├── .gitignore ├── 3rd ├── hiredis-1.0.0.tar.gz ├── libmysqlclient.a ├── libuv-1.34.0.zip ├── lua-5.4.3.tar.gz ├── make_depend.sh ├── mysql-5.7.16-linux-glibc2.5-x86_64.zip ├── protobuf-3.11.1.zip └── sol2-3.2.3.zip ├── CMakeLists.txt ├── README.md ├── cmake ├── use-ccache.cmake ├── use-gold-linker.cmake └── utils.cmake ├── doc ├── code-doc.md └── src-note.md ├── example ├── cpp │ ├── CMakeLists.txt │ ├── createdb.bat │ ├── http_server.cpp │ ├── http_server_ext.cpp │ ├── json_test.cpp │ ├── kcp_client.cpp │ ├── kcp_server.cpp │ ├── mysql_test.cpp │ ├── protobuf_test │ │ └── client │ │ │ ├── msgtest.pb.cc │ │ │ ├── msgtest.pb.h │ │ │ ├── msgtest.proto │ │ │ └── protobuf_client_test.cpp │ ├── redis_test.cpp │ ├── sql.sql │ ├── tcp_client.cpp │ ├── tcp_server.cpp │ └── timer_test.cpp ├── lua │ ├── config.csv │ ├── csv_test.lua │ ├── http_server.lua │ ├── json.lua │ ├── json_test.lua │ ├── kcp_client.lua │ ├── kcp_server.lua │ ├── mysql_test.lua │ ├── protobuf_test │ │ └── server │ │ │ ├── example.lua │ │ │ ├── msgtest.proto │ │ │ ├── person.proto │ │ │ ├── server.lua │ │ │ └── strings.lua │ ├── redis_test.lua │ ├── tcp_client.lua │ ├── tcp_server.lua │ ├── websocket_client │ │ ├── start.html │ │ └── websocket.js │ └── websocket_server.lua └── python │ ├── __pycache__ │ ├── net.cpython-36.pyc │ └── socket_buffer.cpython-36.pyc │ ├── client_test.py │ ├── net.py │ ├── net.pyc │ ├── socket_buffer.py │ └── socket_buffer.pyc ├── src ├── common │ ├── BaseType.h │ ├── ByteBuffer.cpp │ ├── ByteBuffer.h │ ├── ByteConverter.h │ ├── CommonPool.h │ ├── CsvParser.cpp │ ├── CsvParser.h │ ├── Define.h │ ├── EventLoop.cpp │ ├── EventLoop.h │ ├── Heap.cpp │ ├── Heap.h │ ├── HttpParam.cpp │ ├── HttpParam.h │ ├── Objectpool.h │ ├── Platform.h │ ├── PoolObject.h │ ├── Singleton.h │ ├── SpinLock.h │ ├── TQueue.h │ ├── ThreadPool.cpp │ ├── ThreadPool.h │ ├── Timer.cpp │ ├── Timer.h │ ├── Tools.cpp │ ├── Tools.h │ ├── UTimer.h │ ├── XAssert.cpp │ ├── XAssert.h │ ├── XFile.cpp │ ├── XFile.h │ ├── XLog.cpp │ ├── XLog.h │ ├── XTime.cpp │ ├── XTime.h │ ├── base64.cpp │ ├── base64.h │ ├── concurrentqueue │ │ ├── blockingconcurrentqueue.h │ │ ├── concurrentqueue.h │ │ └── lightweightsemaphore.h │ ├── sha1.cpp │ └── sha1.h ├── db │ ├── DBResult.h │ ├── DBThreadPool.cpp │ ├── DBThreadPool.h │ ├── DB_Interface.cpp │ ├── DB_Interface.h │ ├── DB_Interface_mysql.cpp │ ├── DB_Interface_mysql.h │ ├── DB_Interface_redis.cpp │ ├── DB_Interface_redis.h │ ├── MysqlResult.cpp │ ├── MysqlResult.h │ ├── RedisCommand.cpp │ ├── RedisCommand.h │ ├── RedisResult.cpp │ ├── RedisResult.h │ ├── SqlPrepare.cpp │ ├── SqlPrepare.h │ ├── SqlResultSet.cpp │ └── SqlResultSet.h ├── network │ ├── BasePacket.cpp │ ├── BasePacket.h │ ├── HttpConnect.cpp │ ├── HttpConnect.h │ ├── HttpEvent.h │ ├── HttpServer.cpp │ ├── HttpServer.h │ ├── KcpClient.cpp │ ├── KcpClient.h │ ├── KcpEvent.cpp │ ├── KcpEvent.h │ ├── KcpServer.cpp │ ├── KcpServer.h │ ├── KcpSession.cpp │ ├── KcpSession.h │ ├── MessageBuffer.h │ ├── NetClient.cpp │ ├── NetClient.h │ ├── NetConnect.cpp │ ├── NetConnect.h │ ├── NetEvent.cpp │ ├── NetEvent.h │ ├── NetPacket.cpp │ ├── NetPacket.h │ ├── NetServer.cpp │ ├── NetServer.h │ ├── ProtoPacket.h │ ├── TcpClient.cpp │ ├── TcpClient.h │ ├── TcpServer.cpp │ ├── TcpServer.h │ ├── TcpSocket.cpp │ ├── TcpSocket.h │ ├── UdpClient.cpp │ ├── UdpClient.h │ ├── UdpPacket.cpp │ ├── UdpPacket.h │ ├── UdpServer.cpp │ ├── UdpServer.h │ ├── WebSocketConnect.cpp │ ├── WebSocketConnect.h │ ├── WebSocketEvent.cpp │ ├── WebSocketEvent.h │ ├── WebSocketPacket.cpp │ ├── WebSocketPacket.h │ ├── WebSocketServer.cpp │ ├── WebSocketServer.h │ ├── ikcp.cpp │ └── ikcp.h ├── protolua │ ├── CMakeLists.txt │ ├── README.md │ ├── decoder.cpp │ ├── encoder.cpp │ ├── lua51ext.h │ ├── parse.cpp │ ├── protolua.cpp │ └── protolua.h ├── script │ ├── Lua_Base.cpp │ ├── Lua_Common.cpp │ ├── Lua_CsvFile.cpp │ ├── Lua_EventLoop.cpp │ ├── Lua_HttpServer.cpp │ ├── Lua_Json.cpp │ ├── Lua_KcpServer.cpp │ ├── Lua_Mysql.cpp │ ├── Lua_NetServer.cpp │ ├── Lua_Redis.cpp │ ├── Lua_WebSockServer.cpp │ └── main.cpp └── utils │ ├── HttpParser.cpp │ ├── HttpParser.h │ ├── Json.cpp │ ├── Json.h │ ├── JsonReader.cpp │ ├── JsonReader.h │ ├── ParseUrl.cpp │ ├── ParseUrl.h │ ├── api.c │ ├── http.c │ ├── http_parser.cpp │ ├── http_parser.h │ ├── llhttp.c │ └── llhttp.h └── tests ├── allTests.cpp ├── libuv_tests.cpp └── sol2_tests.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Object files 5 | *.o 6 | *.ko 7 | *.obj 8 | *.elf 9 | 10 | # Linker output 11 | *.ilk 12 | *.map 13 | *.exp 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Libraries 20 | *.lib 21 | *.la 22 | *.lo 23 | 24 | # Shared objects (inc. Windows DLLs) 25 | *.dll 26 | *.so 27 | *.so.* 28 | *.dylib 29 | 30 | # Executables 31 | *.exe 32 | *.out 33 | *.app 34 | *.i*86 35 | *.x86_64 36 | *.hex 37 | 38 | # Debug files 39 | *.dSYM/ 40 | *.su 41 | *.idb 42 | *.pdb 43 | 44 | # Kernel Module Compile Results 45 | *.mod* 46 | *.cmd 47 | .tmp_versions/ 48 | modules.order 49 | Module.symvers 50 | Mkfile.old 51 | dkms.conf 52 | 53 | # editor & ide 54 | .vscode/ 55 | 56 | 57 | # build dir 58 | build/ 59 | 60 | # third part dependency 61 | dependencies/ 62 | 63 | 64 | libs/ -------------------------------------------------------------------------------- /3rd/hiredis-1.0.0.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/lua-server/6008c764295d822f82a89ed8d579559bbcf1adfa/3rd/hiredis-1.0.0.tar.gz -------------------------------------------------------------------------------- /3rd/libmysqlclient.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/lua-server/6008c764295d822f82a89ed8d579559bbcf1adfa/3rd/libmysqlclient.a -------------------------------------------------------------------------------- /3rd/libuv-1.34.0.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/lua-server/6008c764295d822f82a89ed8d579559bbcf1adfa/3rd/libuv-1.34.0.zip -------------------------------------------------------------------------------- /3rd/lua-5.4.3.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/lua-server/6008c764295d822f82a89ed8d579559bbcf1adfa/3rd/lua-5.4.3.tar.gz -------------------------------------------------------------------------------- /3rd/make_depend.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo "-- start make depend:" 4 | 5 | SH_DIR=$(dirname `readlink -f $0`) 6 | PACKAGE_DIR=${SH_DIR} 7 | PROJECT_DIR=`dirname ${SH_DIR}` 8 | DEPEND_DIR=${PROJECT_DIR}/dependencies 9 | LIBS_DIR=${PROJECT_DIR}/libs 10 | 11 | LUA_DIR=${DEPEND_DIR}/lua 12 | SOL2_DIR=${DEPEND_DIR}/sol2 13 | LIBUV_DIR=${DEPEND_DIR}/libuv 14 | HIREDIS_DIR=${DEPEND_DIR}/hiredis 15 | MYSQL_DIR=${DEPEND_DIR}/mysql 16 | PROTOBUF_DIR=${DEPEND_DIR}/protobuf 17 | 18 | 19 | LUA_PKG=${PACKAGE_DIR}/lua-5.4.3.tar.gz 20 | SOL2_PKG=${PACKAGE_DIR}/sol2-3.2.3.zip 21 | LIBUV_PKG=${PACKAGE_DIR}/libuv-1.34.0.zip 22 | HIREDIS_PKG=${PACKAGE_DIR}/hiredis-1.0.0.tar.gz 23 | MYSQL_PKG=${PACKAGE_DIR}/mysql-5.7.16-linux-glibc2.5-x86_64.zip 24 | PROTOBUF_PKG=${PACKAGE_DIR}/protobuf-3.11.1.zip 25 | 26 | 27 | 28 | if [ ! -d ${DEPEND_DIR} ] 29 | then 30 | echo "create dependencies dir" 31 | mkdir ${DEPEND_DIR} 32 | fi 33 | 34 | if [ ! -d ${LIBS_DIR} ] 35 | then 36 | echo "create libs dir" 37 | mkdir ${LIBS_DIR} 38 | fi 39 | 40 | 41 | # lua 42 | if [ -d ${LUA_DIR} ] 43 | then 44 | echo "lua ok" 45 | else 46 | echo "lua decompression && compile" 47 | mkdir -p ${LUA_DIR} 48 | tar -xvf ${LUA_PKG} --strip-components 1 -C ${LUA_DIR} 49 | cd ${LUA_DIR} && make -j $(nproc) 50 | cp ${LUA_DIR}/src/liblua.a ${LIBS_DIR} 51 | fi 52 | 53 | 54 | # sol2 55 | if [ -d ${SOL2_DIR} ] 56 | then 57 | echo "sol2 ok" 58 | else 59 | echo "sol2 decompression" 60 | unzip ${SOL2_PKG} -d ${DEPEND_DIR} 61 | mv ${SOL2_DIR}-3.2.3 ${SOL2_DIR} 62 | fi 63 | 64 | 65 | # libuv 66 | if [ -d ${LIBUV_DIR} ] 67 | then 68 | echo "libuv ok" 69 | else 70 | echo "libuv decompression && compile" 71 | unzip ${LIBUV_PKG} -d ${DEPEND_DIR} 72 | mv ${LIBUV_DIR}-1.34.0 ${LIBUV_DIR} 73 | cd ${LIBUV_DIR} 74 | mkdir build && cd build && cmake .. && make -j $(nproc) 75 | cp ${LIBUV_DIR}/build/libuv_a.a ${LIBS_DIR} 76 | fi 77 | 78 | 79 | 80 | # hiredis 81 | if [ -d ${HIREDIS_DIR} ] 82 | then 83 | echo "hiredis ok" 84 | else 85 | echo "hiredis decompression && compile" 86 | mkdir -p ${HIREDIS_DIR} 87 | tar -xvf ${HIREDIS_PKG} --strip-components 1 -C ${HIREDIS_DIR} 88 | cd ${HIREDIS_DIR} && make -j $(nproc) 89 | cp ${HIREDIS_DIR}/libhiredis.a ${LIBS_DIR} 90 | fi 91 | 92 | 93 | # mysql 94 | if [ -d ${MYSQL_DIR} ] 95 | then 96 | echo "mysql ok" 97 | else 98 | echo "mysql header file decompression" 99 | unzip ${MYSQL_PKG} -d ${DEPEND_DIR} 100 | mv ${MYSQL_DIR}-5.7.16-linux-glibc2.5-x86_64 ${MYSQL_DIR} 101 | cp ${PACKAGE_DIR}/libmysqlclient.a ${LIBS_DIR} 102 | fi 103 | 104 | 105 | 106 | # protobuf 107 | cd $SHDIR 108 | if [ -d ${PROTOBUF_DIR} ] 109 | then 110 | echo "protobuf ok" 111 | else 112 | unzip ${PROTOBUF_PKG} -d ${DEPEND_DIR} 113 | mv ${PROTOBUF_DIR}-3.11.1 ${PROTOBUF_DIR} 114 | cd ${PROTOBUF_DIR} && ./autogen.sh && ./configure && make -j$(nproc) 115 | cp ${PROTOBUF_DIR}/src/.libs/libprotobuf.a ${LIBS_DIR} 116 | fi -------------------------------------------------------------------------------- /3rd/mysql-5.7.16-linux-glibc2.5-x86_64.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/lua-server/6008c764295d822f82a89ed8d579559bbcf1adfa/3rd/mysql-5.7.16-linux-glibc2.5-x86_64.zip -------------------------------------------------------------------------------- /3rd/protobuf-3.11.1.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/lua-server/6008c764295d822f82a89ed8d579559bbcf1adfa/3rd/protobuf-3.11.1.zip -------------------------------------------------------------------------------- /3rd/sol2-3.2.3.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/lua-server/6008c764295d822f82a89ed8d579559bbcf1adfa/3rd/sol2-3.2.3.zip -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # lua-server 2 | 3 | 本工程fork自[jwEngine](https://github.com/jwcpp/jwEngine/tree/master),是一个用C++实现的服务器框架。功能包括tcp、udp、kcp、web socket等基本的网络操作模块,mysql、redis等数据库操作模块,以及lua脚本运行模块。可以作为一个轻便、高效的游戏服务器,web接口服务器,其他微服务器等。 4 | 5 | 6 | ## 目录结构 7 | ``` 8 | ├── 3rd // 第三方依赖源码包 9 | ├── cmake // cmake的include文件 10 | ├── doc // 文档 11 | ├── example // 服务器个模块的使用例子 12 | │   ├── cpp 13 | │   ├── lua 14 | │   └── python 15 | ├── libs 16 | ├── src // 源码文件 17 | │   ├── common // 通用模块 18 | │   ├── db // 数据库模块,包括mysql、redis 19 | │   ├── network // 网络模块 20 | │   ├── protolua // protobuf对lua语言的支持模块 21 | │   ├── script // c++对象导入lua环境和lua脚本运行模块 22 | │   └── utils // 工具类库 23 | └── tests // 测试代码,测试框架用的是gtest 24 | ``` 25 | 26 | 27 | ## 第三方依赖 28 | * libuv 29 | 跨平台的异步I/O网络库 30 | * sol2 31 | C++绑定Lua脚本的库,仅由头文件组成,方便集成 32 | * lua 33 | * mysql 34 | * hiredis 35 | Redis的C语言客户端库函数,基本实现了Redis的协议的最小集 36 | * kcp 37 | KCP是一个快速可靠协议,能以比 TCP 浪费 10%-20% 的带宽的代价,换取平均延迟降低 30%-40% 38 | * protobuf 39 | 免费的、开源的跨平台库,用于序列化结构化数据。 40 | 41 | 42 | ## 编译安装 43 | 44 | **步骤一:编译第三方依赖** 45 | 46 | 1. 进入`3rd`目录 47 | 2. 执行`make_depend.sh`脚本文件 48 | 此脚本的作用1.把第三方依赖编译成静态库,并复制到libs目录下 2.复制第三方依赖的include头文件到dependencies目录下 49 | 50 | **步骤二:编译工程源码** 51 | 52 | 此工程的编译工具为cmake,执行以下命令进行编译,编译后的二进制程序为`build/bin/lua-server` 53 | ``` 54 | mkdir build 55 | cd build 56 | cmake && make 57 | ``` 58 | 59 | ## lua-server使用例子 60 | 61 | ### tcp服务器端 62 | 运行`lua-server tcp_server.lua` 63 | 64 | tcp_server.lua源码 65 | ``` 66 | -- init 67 | event_init() 68 | 69 | -- create server 70 | server = NetServer:new() 71 | server.on_accept = function(conn) 72 | local pack = NetPacket:new() 73 | pack:pushString("msg ...") 74 | conn:sendPacket(1, pack) 75 | end 76 | 77 | server.on_close = function(conn) 78 | print("close") 79 | end 80 | 81 | server.on_msg = function(conn, msgtype, pack) 82 | local str = pack:getString() 83 | print(str) 84 | conn:sendPacket(1, pack) 85 | end 86 | 87 | server:listen("127.0.0.1", 3001, false) 88 | 89 | event_run() 90 | ``` 91 | 92 | ### tcp客户端 93 | 运行`lua-server tcp_client.lua` 94 | 95 | tcp_client.lua源码 96 | ``` 97 | event_init() 98 | 99 | -- create server 100 | client = NetClient:new() 101 | client.on_connect = function(conn, argv) 102 | print("on onnect:".. argv) 103 | end 104 | 105 | client.on_close = function(conn) 106 | print("close") 107 | end 108 | 109 | client.on_msg = function(conn, msgtype, pack) 110 | local str = pack:getString() 111 | print(str) 112 | conn:sendPacket(1, pack) 113 | end 114 | 115 | client:connect("127.0.0.1", 3001, false, 1); 116 | 117 | event_run() 118 | ``` 119 | 120 | 121 | ## 其他使用例子说明 122 | 参见`example`目录下的各个模块使用的使用例子 123 | 124 | 125 | 126 | ## 源码文件说明 127 | 参见: [doc/src-note.md](doc/src-note.md) 128 | 129 | 130 | 131 | 132 | 133 | 134 | -------------------------------------------------------------------------------- /cmake/use-ccache.cmake: -------------------------------------------------------------------------------- 1 | option(CCACHE "Use ccache if available" ON) 2 | 3 | find_program(CCACHE_PROGRAM ccache) 4 | message("use-ccache===========") 5 | message("CCACHE:${CCACHE}") 6 | # message("CCACHE_PROGRAM:${CCACHE_PROGRAM}") 7 | if(CCACHE AND CCACHE_PROGRAM) 8 | set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}") 9 | 10 | # message("CMAKE_C_COMPILER:${CMAKE_C_COMPILER}") 11 | # message("CMAKE_CXX_COMPILER:${CMAKE_CXX_COMPILER}") 12 | SET(CMAKE_CXX_COMPILER_ARG1 "${CMAKE_CXX_COMPILER}") 13 | SET(CMAKE_CXX_COMPILER "ccache") 14 | endif() 15 | -------------------------------------------------------------------------------- /cmake/use-gold-linker.cmake: -------------------------------------------------------------------------------- 1 | option(USE_LD_GOLD "Use GNU gold linker" ON) 2 | 3 | message("use-gold-linker===========") 4 | # message("CMAKE_C_COMPILER_ID:${CMAKE_C_COMPILER_ID}") 5 | 6 | message("USE_LD_GOLD:${USE_LD_GOLD}") 7 | 8 | if(USE_LD_GOLD AND "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") 9 | execute_process(COMMAND ${CMAKE_C_COMPILER} -fuse-ld=gold -Wl,--version OUTPUT_VARIABLE stdout ERROR_QUIET) 10 | # message("stdout:${stdout}") 11 | if("${stdout}" MATCHES "GNU gold") 12 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fuse-ld=gold") 13 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fuse-ld=gold") 14 | else() 15 | message(WARNING "GNU gold linker isn't available, using the default system linker.") 16 | endif() 17 | endif() 18 | -------------------------------------------------------------------------------- /cmake/utils.cmake: -------------------------------------------------------------------------------- 1 | #重新定义当前目标的源文件的__FILE__宏 2 | function(redefine_file_macro targetname) 3 | #获取当前目标的所有源文件 4 | get_target_property(source_files "${targetname}" SOURCES) 5 | #遍历源文件 6 | foreach(sourcefile ${source_files}) 7 | #获取当前源文件的编译参数 8 | get_property(defs SOURCE "${sourcefile}" 9 | PROPERTY COMPILE_DEFINITIONS) 10 | #获取当前文件的绝对路径 11 | get_filename_component(filepath "${sourcefile}" ABSOLUTE) 12 | #将绝对路径中的项目路径替换成空,得到源文件相对于项目路径的相对路径 13 | string(REPLACE ${PROJECT_SOURCE_DIR}/ "" relpath ${filepath}) 14 | string(REPLACE ".cpp" "" relpath ${relpath}) 15 | string(REPLACE ".c" "" relpath ${relpath}) 16 | #将我们要加的编译参数(__FILE__定义)添加到原来的编译参数里面 17 | list(APPEND defs "__FILE__=\"${relpath}\"") 18 | #重新设置源文件的编译参数 19 | set_property( 20 | SOURCE "${sourcefile}" 21 | PROPERTY COMPILE_DEFINITIONS ${defs} 22 | ) 23 | endforeach() 24 | endfunction() 25 | -------------------------------------------------------------------------------- /doc/code-doc.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## git tag 4 | 5 | ### cmake_linux 6 | 此标签的编译模式只适用于linux系统,方式如下: 7 | 利用shell脚本把程序依赖包进行解压然后再通过make、cmake编译成.a静态库文件并复制到libs目录下,程序编译的时候再去链接静态库文件 8 | 9 | 10 | 11 | ## 采用cmake方式编译依赖库 12 | 采用cmake方式编译第三方依赖源码,类似于下面的方式 13 | ``` 14 | add_subdirectory(lua) 15 | ... 16 | target_link_libraries( lua_static) 17 | ``` 18 | 19 | 但是第三方依赖库不一定提供相应的CMakeLists文件,若真没有提供的话,还得自己编写,所以比较麻烦。 20 | 不过一般比较常用的库的话通过"库名 + cmake"进行搜索可以搜索到相应的CMakeLists文件以进行cmake的方式编译。 21 | 22 | 以下为本程序中用到的一些库的cmake的编译方式 23 | 24 | - [CMake based build of Lua 5.4.3](https://github.com/walterschell/Lua) 25 | - [CMake build for libuv](https://github.com/jen20/libuv-cmake) 26 | 27 | 28 | -------------------------------------------------------------------------------- /example/cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # tcp 2 | add_executable(tcp_client 3 | tcp_client.cpp) 4 | 5 | target_link_libraries(tcp_client 6 | ${STATIC_LIB_NAME} 7 | Threads::Threads) 8 | 9 | add_executable(tcp_server 10 | tcp_server.cpp) 11 | 12 | target_link_libraries(tcp_server 13 | ${STATIC_LIB_NAME} 14 | Threads::Threads) 15 | 16 | 17 | # kcp 18 | add_executable(kcp_client 19 | kcp_client.cpp) 20 | 21 | target_link_libraries(kcp_client 22 | ${STATIC_LIB_NAME} 23 | Threads::Threads) 24 | 25 | add_executable(kcp_server 26 | kcp_server.cpp) 27 | 28 | target_link_libraries(kcp_server 29 | ${STATIC_LIB_NAME} 30 | Threads::Threads) 31 | 32 | 33 | 34 | # http 35 | add_executable(http_server 36 | http_server.cpp) 37 | 38 | target_link_libraries(http_server 39 | ${STATIC_LIB_NAME} 40 | Threads::Threads) 41 | 42 | add_executable(http_server_ext 43 | http_server_ext.cpp) 44 | 45 | target_link_libraries(http_server_ext 46 | ${STATIC_LIB_NAME} 47 | Threads::Threads) 48 | 49 | 50 | # mysql 51 | add_executable(mysql_test 52 | mysql_test.cpp) 53 | 54 | target_link_libraries(mysql_test 55 | ${STATIC_LIB_NAME} 56 | Threads::Threads) 57 | 58 | # mysql 59 | add_executable(redis_test 60 | redis_test.cpp) 61 | 62 | target_link_libraries(redis_test 63 | ${STATIC_LIB_NAME} 64 | Threads::Threads) 65 | 66 | 67 | 68 | # json_test 69 | add_executable(json_test 70 | json_test.cpp) 71 | 72 | target_link_libraries(json_test 73 | ${STATIC_LIB_NAME} 74 | Threads::Threads) 75 | 76 | 77 | # timer_test 78 | add_executable(timer_test 79 | timer_test.cpp) 80 | 81 | target_link_libraries(timer_test 82 | ${STATIC_LIB_NAME} 83 | Threads::Threads) 84 | 85 | 86 | 87 | # timer_test 88 | add_executable(protobuf_client_test 89 | protobuf_test/client/protobuf_client_test.cpp 90 | protobuf_test/client/msgtest.pb.cc 91 | ) 92 | 93 | target_link_libraries(protobuf_client_test 94 | ${STATIC_LIB_NAME} 95 | Threads::Threads) 96 | -------------------------------------------------------------------------------- /example/cpp/createdb.bat: -------------------------------------------------------------------------------- 1 | mysql -uroot -p111111 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include "HttpServer.h" 8 | #include "EventLoop.h" 9 | 10 | #include 11 | #include "HttpParam.h" 12 | #include "HttpConnect.h" 13 | 14 | const char * html = R"( 15 | 16 |

login

17 |

hello world!

18 |
19 | 20 | 21 | 22 |
23 | 24 | )"; 25 | 26 | 27 | const char * html2 = R"( 28 | 29 | 30 | 31 | 40 | 41 | 42 | 43 | 44 | )"; 45 | 46 | const char * succeed = "" 47 | "" 48 | "" 49 | "

login succeed

" 50 | "" 51 | ""; 52 | 53 | const char * failing = "" 54 | "" 55 | "" 56 | "

login failing

" 57 | "" 58 | ""; 59 | 60 | 61 | #include "XFile.h" 62 | 63 | int main() 64 | { 65 | EventLoop::Instance()->init(); 66 | HttpServer server(EventLoop::Instance()); 67 | server.listen("0.0.0.0", 80); 68 | 69 | server.addGet("/", [](HttpConnect *conn, std::string_view & data) { 70 | conn->autoMsg(html); 71 | /* 72 | std::string s; 73 | XFile::readFile("test.html", s); 74 | conn->sendMsg(s); 75 | */ 76 | }); 77 | 78 | server.addGet("/test", [](HttpConnect *conn, std::string_view & data) { 79 | conn->autoMsg("hello world"); 80 | }); 81 | 82 | server.addPost("/login", [](HttpConnect *conn, std::string_view & data) { 83 | 84 | HttpParam hp(data); 85 | if (hp.getStr("user") == "jw" && hp.getStr("pass") == "1111") 86 | { 87 | conn->autoMsg(succeed); 88 | } 89 | else 90 | { 91 | conn->autoMsg(failing); 92 | } 93 | }); 94 | 95 | EventLoop::Instance()->run(); 96 | return 0; 97 | } -------------------------------------------------------------------------------- /example/cpp/http_server_ext.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "HttpServer.h" 6 | #include "EventLoop.h" 7 | #include "HttpConnect.h" 8 | #include "HttpParser.h" 9 | #include 10 | 11 | class HttpExt 12 | { 13 | public: 14 | void printField(const char* p, int len) 15 | { 16 | std::string_view v(p, len); 17 | std::cout << v <<": "; 18 | } 19 | 20 | void printValue(const char* p, int len) 21 | { 22 | std::string_view v(p, len); 23 | std::cout << v << std::endl; 24 | } 25 | }; 26 | 27 | HttpExt httpext; 28 | 29 | int main() 30 | { 31 | EventLoop::Instance()->init(); 32 | HttpServer server(EventLoop::Instance()); 33 | server.listen("0.0.0.0", 80); 34 | 35 | server.addGet("/", [](HttpConnect* conn, std::string_view& data) { 36 | conn->autoMsg("hello world"); 37 | }); 38 | 39 | HttpSettings* setting = getHttpSettings(); 40 | setting->on_message_begin = [](llhttp_t* http)->int { 41 | http->data = &httpext; 42 | return 0; 43 | }; 44 | 45 | setting->on_header_field = [](llhttp_t* http, const char* at, size_t length)->int { 46 | HttpExt* ext = (HttpExt*)(http->data); 47 | ext->printField(at, length); 48 | return 0; 49 | }; 50 | 51 | setting->on_header_value = [](llhttp_t* http, const char* at, size_t length)->int { 52 | HttpExt* ext = (HttpExt*)(http->data); 53 | ext->printValue(at, length); 54 | return 0; 55 | }; 56 | 57 | EventLoop::Instance()->run(); 58 | return 0; 59 | } -------------------------------------------------------------------------------- /example/cpp/json_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Json.h" 4 | #include "JsonReader.h" 5 | #include 6 | using namespace jwEngine; 7 | 8 | // obj 9 | int main_1() 10 | { 11 | std::string str; 12 | { 13 | JSonObj obj; 14 | obj.setInt("num", 10); 15 | 16 | // array 17 | JArray * j_arr = obj.createArray("arr"); 18 | j_arr->pushInt(12); 19 | j_arr->pushInt(13); 20 | 21 | JArray * array1 = j_arr->createArray(); 22 | array1->pushInt(33); 23 | array1->pushInt(44); 24 | 25 | JSonObj * obj1 = j_arr->createObj(); 26 | obj1->setInt("count", 88); 27 | 28 | JArray * array2 = obj1->createArray("arr2"); 29 | array2->pushInt(123); 30 | array2->pushInt(321); 31 | 32 | // obj 33 | JSonObj * obj2 = obj.createObj("obj"); 34 | obj2->setInt("num", 1); 35 | obj2->setInt("num2",2); 36 | 37 | JSonObj * obj3 = obj2->createObj("obj2"); 38 | obj3->setStr("str", "hello world"); 39 | obj3->setBool("boo", false); 40 | 41 | JArray * array3 = obj3->createArray("array"); 42 | array3->pushBool(true); 43 | array3->pushBool(false); 44 | 45 | obj.write(str); 46 | } 47 | printf("%s\n", str.c_str()); 48 | 49 | return 0; 50 | } 51 | 52 | // array 53 | int main_2() 54 | { 55 | JArray arr; 56 | arr.pushInt(10); 57 | arr.pushInt(20); 58 | 59 | JSonObj * obj = arr.createObj(); 60 | obj->setInt("num", 6); 61 | obj->setInt("count", 0); 62 | 63 | arr.pushBool(false); 64 | 65 | std::string s; 66 | arr.write(s); 67 | printf("%s\n", s.c_str()); 68 | return 0; 69 | } 70 | 71 | // base value 72 | int main_3() 73 | { 74 | JValue value; 75 | value.setInt(10); 76 | printf("%d\n", value.iv); 77 | 78 | value.setStr("hello world"); 79 | printf("%s\n", value.sv.c_str()); 80 | return 0; 81 | } 82 | int main_4() 83 | { 84 | //const char * p = "{\"num\": 11, \"obj\":{\"a\":12, \"b\":13}, \"array\":[1314,520]}"; 85 | const char * p = "[\"haha\", false, null, 20.9, {\"num\":123, \"array\":[1,2,3,4]}]"; 86 | JsonBuff buff(p); 87 | 88 | JBaseObj * jobj = JsonReader::parser(&buff); 89 | if (jobj) 90 | { 91 | std::string str = JsonReader::write(jobj); 92 | std::cout << str << std::endl; 93 | } 94 | else 95 | { 96 | std::cout <<"parser error:" << JsonReader::getError(&buff) << std::endl; 97 | } 98 | return 0; 99 | 100 | } 101 | 102 | 103 | int main() 104 | { 105 | printf("test1---------\n"); 106 | main_1(); 107 | printf("test2---------\n"); 108 | main_2(); 109 | printf("test3---------\n"); 110 | main_3(); 111 | printf("test4---------\n"); 112 | main_4(); 113 | 114 | 115 | return 0; 116 | } -------------------------------------------------------------------------------- /example/cpp/kcp_client.cpp: -------------------------------------------------------------------------------- 1 | #include "KcpClient.h" 2 | #include "KcpServer.h" 3 | #include "EventLoop.h" 4 | #include "KcpEvent.h" 5 | #include "KcpSession.h" 6 | #include "UdpPacket.h" 7 | #include 8 | #include 9 | 10 | class KNetEvent : public KcpEvent 11 | { 12 | public: 13 | virtual KcpSession * createConnect() 14 | { 15 | return new KcpSession(this, 1000); 16 | } 17 | 18 | 19 | virtual void onConnect(KcpSession * conn){ 20 | if (conn) 21 | { 22 | 23 | // 客户端通知连接成功 24 | std::cout << "connect to server success." << std::endl; 25 | 26 | int x = rand() % 100000; 27 | std::string s(std::to_string(x)); 28 | conn->sendMsg(1, s.c_str(), s.length()); 29 | std::cout << "send message to server:" << s << std::endl; 30 | } 31 | }; 32 | virtual void onClose(KcpSession * conn){ 33 | std::cout << "onClose" << std::endl; 34 | }; 35 | 36 | virtual void onMsg(KcpSession * conn, int msgtype, UdpPacket * pack){ 37 | std::string s; 38 | (*pack) >> s; 39 | 40 | printf("receive message from server: %s\n", s.c_str()); 41 | // conn->sendMsg(1, pack); 42 | } 43 | 44 | virtual void onUdpTimeout(KcpSession * s) 45 | { 46 | printf("timeout ..............\n"); 47 | server->closeSession(s); 48 | } 49 | 50 | KcpServer * server; 51 | }; 52 | 53 | //#define UDP_CLIENT_TEST 54 | 55 | int main() 56 | { 57 | srand((int)time(0)); 58 | EventLoop::Instance()->init(); 59 | 60 | //初始化事件循环 61 | KNetEvent eve; 62 | EventLoop::Instance()->init(); 63 | 64 | 65 | KcpClient client(EventLoop::Instance(), &eve); 66 | client.createSession("127.0.0.1", 3001); 67 | 68 | EventLoop::Instance()->run(); 69 | 70 | system("pause"); 71 | return 0; 72 | } -------------------------------------------------------------------------------- /example/cpp/kcp_server.cpp: -------------------------------------------------------------------------------- 1 | #include "KcpClient.h" 2 | #include "KcpServer.h" 3 | #include "EventLoop.h" 4 | #include "KcpEvent.h" 5 | #include "KcpSession.h" 6 | #include "UdpPacket.h" 7 | #include 8 | #include 9 | 10 | class KNetEvent : public KcpEvent 11 | { 12 | public: 13 | virtual KcpSession * createConnect() 14 | { 15 | return new KcpSession(this, 1000); 16 | } 17 | 18 | virtual void onAccept(KcpSession * conn){ 19 | if (conn) 20 | { 21 | // 通知服务器有客户端连入 22 | std::cout << "accept client connect" << std::endl; 23 | } 24 | }; 25 | 26 | virtual void onClose(KcpSession * conn){ 27 | std::cout << "onClose" << std::endl; 28 | }; 29 | 30 | virtual void onMsg(KcpSession * conn, int msgtype, UdpPacket * pack){ 31 | std::string s; 32 | (*pack) >> s; 33 | 34 | printf("receive message from client: %s\n", s.c_str()); 35 | conn->sendMsg(1, pack); 36 | std::cout << "send message to client:" << s << std::endl; 37 | 38 | } 39 | 40 | virtual void onUdpTimeout(KcpSession * s) 41 | { 42 | printf("timeout ..............\n"); 43 | server->closeSession(s); 44 | } 45 | 46 | KcpServer * server; 47 | }; 48 | 49 | //#define UDP_CLIENT_TEST 50 | 51 | int main() 52 | { 53 | srand((int)time(0)); 54 | EventLoop::Instance()->init(); 55 | 56 | //初始化事件循环 57 | KNetEvent eve; 58 | EventLoop::Instance()->init(); 59 | 60 | KcpServer server(EventLoop::Instance(), &eve); 61 | server.start("127.0.0.1", 3001); 62 | eve.server = &server; 63 | 64 | EventLoop::Instance()->run(); 65 | 66 | system("pause"); 67 | return 0; 68 | } -------------------------------------------------------------------------------- /example/cpp/mysql_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "mysql.h" 8 | #include "DB_Interface_mysql.h" 9 | #include "MysqlResult.h" 10 | #include "SqlPrepare.h" 11 | 12 | 13 | const char * HOST = "192.168.1.120"; 14 | const char * DB = "test_db"; 15 | const char * USER = "root"; 16 | const char * PWD = "123456"; 17 | 18 | 19 | void sql_query_1() 20 | { 21 | DBInterfaceMysql mysql(HOST, DB, USER, PWD); 22 | mysql.connect(); 23 | 24 | 25 | MysqlResult result; 26 | mysql.execute(&result, "select * from test"); 27 | 28 | while (result.fetch()) 29 | { 30 | 31 | int id; 32 | int num; 33 | std::string name; 34 | result >> id; 35 | result >> num; 36 | result >> name; 37 | 38 | printf("id:%d, num:%d, name:%s\n", id, num, name.c_str()); 39 | } 40 | } 41 | 42 | #include "SqlResultSet.h" 43 | 44 | void sql_query_2() 45 | { 46 | DBInterfaceMysql mysql(HOST, DB, USER, PWD); 47 | mysql.connect(); 48 | 49 | 50 | SqlPrepare pre("select * from test where id = ?"); 51 | pre.pushInt32(1); 52 | pre.prepare(mysql.mysql()); 53 | 54 | SqlResultSet result; 55 | pre.execute(&result); 56 | 57 | while (result.fetch()) 58 | { 59 | int id = result.getInt32(); 60 | int num = result.getInt32(); 61 | std::string name = result.getString(); 62 | 63 | printf("id:%d, num:%d, name:%s\n", id, num, name.c_str()); 64 | } 65 | } 66 | 67 | #include 68 | #include "DBThreadPool.h" 69 | void sql_query_3() 70 | { 71 | DBConfig config; 72 | config.dbname = DB; 73 | config.pswd = PWD; 74 | config.ip = HOST; 75 | DBThreadPool pool(config); 76 | pool.create(1); 77 | 78 | { 79 | std::shared_ptr pre(new SqlPrepare("select * from test where id = ?")); 80 | pre->pushInt32(1); 81 | 82 | std::shared_ptr task(new DBSqlTask(pre, std::make_shared())); 83 | task->backfunc = [](int errno_, const char* error, std::shared_ptr result) { 84 | 85 | if (errno_ != 0) 86 | { 87 | printf("%s\n", error); 88 | } 89 | else 90 | { 91 | while (result->fetch()) 92 | { 93 | int id = result->getInt32(); 94 | int num = result->getInt32(); 95 | std::string name = result->getString(); 96 | printf("id:%d, num:%d, name:%s\n", id, num, name.c_str()); 97 | } 98 | } 99 | }; 100 | 101 | pool.addTask(task); 102 | } 103 | 104 | 105 | std::this_thread::sleep_for(std::chrono::seconds(3)); 106 | pool.update(); 107 | 108 | } 109 | 110 | #include 111 | int main() 112 | { 113 | MySQL::libraryInit(); 114 | MySQL::threadSafe(); 115 | 116 | std::cout << "sql_query_1****************************" << std::endl; 117 | sql_query_1(); 118 | std::cout << "sql_query_2****************************" << std::endl; 119 | sql_query_2(); 120 | std::cout << "sql_query_3****************************" << std::endl; 121 | sql_query_3(); 122 | 123 | MySQL::libraryEnd(); 124 | 125 | return 0; 126 | } -------------------------------------------------------------------------------- /example/cpp/protobuf_test/client/msgtest.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | message Role 4 | { 5 | int32 id = 1; 6 | string name = 2; 7 | int32 money = 3; 8 | repeated int32 tasks = 4; 9 | } 10 | 11 | message Family 12 | { 13 | string name = 1; 14 | int32 lv = 2; 15 | repeated Role roles = 3; 16 | } -------------------------------------------------------------------------------- /example/cpp/protobuf_test/client/protobuf_client_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "NetEvent.h" 6 | #include "EventLoop.h" 7 | #include "NetClient.h" 8 | #include "NetConnect.h" 9 | #include "NetPacket.h" 10 | #include "ProtoPacket.h" 11 | #include "msgtest.pb.h" 12 | #include 13 | 14 | 15 | class INetEvent : public NetEvent 16 | { 17 | public: 18 | virtual void onConnect(NetConnect * conn, int argv) 19 | { 20 | if (!conn) return; 21 | 22 | Family family; 23 | family.set_name("i family"); 24 | family.set_lv(80); 25 | 26 | Role* role1 = family.add_roles(); 27 | role1->set_id(1000); 28 | role1->set_name("zhangsan"); 29 | role1->set_money(50); 30 | role1->add_tasks(100); 31 | role1->add_tasks(101); 32 | 33 | Role* role2 = family.add_roles(); 34 | role2->set_id(1001); 35 | role2->set_name("lisi"); 36 | role2->set_money(90); 37 | role2->add_tasks(200); 38 | role2->add_tasks(201); 39 | role2->add_tasks(202); 40 | 41 | NetPacket pack; 42 | writeProto(&pack, family); 43 | conn->sendMsg(111, &pack); 44 | }; 45 | virtual void onClose(NetConnect * conn){ 46 | 47 | }; 48 | 49 | virtual void onMsg(NetConnect * conn, int msgtype, NetPacket * pack) 50 | { 51 | Family family; 52 | readProto(pack, family); 53 | 54 | google::protobuf::util::JsonPrintOptions options; 55 | options.add_whitespace = true; 56 | options.always_print_primitive_fields = true; 57 | options.preserve_proto_field_names = true; 58 | 59 | std::string out_str; 60 | google::protobuf::util::MessageToJsonString(family, &out_str, options); 61 | std::cout << out_str << std::endl; 62 | 63 | } 64 | }; 65 | 66 | int main() 67 | { 68 | //初始化事件循环 69 | INetEvent eve; 70 | EventLoop::Instance()->init(); 71 | 72 | NetClient client(EventLoop::Instance(), &eve); 73 | client.connect("127.0.0.1", 3001); 74 | 75 | //开启事件循环 76 | EventLoop::Instance()->run(); 77 | 78 | return 0; 79 | } -------------------------------------------------------------------------------- /example/cpp/sql.sql: -------------------------------------------------------------------------------- 1 | CREATE DATABASE IF NOT EXISTS `test_db` DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_general_ci; 2 | 3 | USE `test_db`; 4 | 5 | CREATE TABLE IF NOT EXISTS `test` ( 6 | `id` int(11) DEFAULT NULL, 7 | `num` int(11) DEFAULT NULL, 8 | `name` varchar(100) DEFAULT NULL 9 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; 10 | 11 | -- ---------------------------- 12 | -- Records of test 13 | -- ---------------------------- 14 | INSERT INTO `test` VALUES ('2', '101', 'lisi'); 15 | INSERT INTO `test` VALUES ('1', '100', 'zhangsan'); -------------------------------------------------------------------------------- /example/cpp/tcp_client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "NetEvent.h" 6 | #include "EventLoop.h" 7 | #include "NetClient.h" 8 | #include "NetServer.h" 9 | #include "Timer.h" 10 | #include "NetConnect.h" 11 | #include "NetPacket.h" 12 | 13 | class INetEvent : public NetEvent 14 | { 15 | public: 16 | virtual void onConnect(NetConnect * conn, int argv){ 17 | if (conn) 18 | { 19 | // 客户端通知连接成功 20 | std::cout << "connect to server success." << std::endl; 21 | } 22 | }; 23 | virtual void onClose(NetConnect * conn){ 24 | std::cout << "onClose" << std::endl; 25 | }; 26 | 27 | virtual void onMsg(NetConnect * conn, int msgtype, NetPacket * pack){ 28 | std::string s; 29 | (*pack) >> s; 30 | 31 | printf("receive message from server: %s\n", s.c_str()); 32 | conn->sendMsg(1, pack); 33 | } 34 | }; 35 | 36 | 37 | 38 | int main() 39 | { 40 | //初始化事件循环 41 | INetEvent eve; 42 | EventLoop::Instance()->init(); 43 | 44 | 45 | NetClient client(EventLoop::Instance(), &eve); 46 | client.connect("127.0.0.1", 3001); 47 | 48 | //开启事件循环 49 | EventLoop::Instance()->run(); 50 | 51 | return 0; 52 | } -------------------------------------------------------------------------------- /example/cpp/tcp_server.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "NetEvent.h" 6 | #include "EventLoop.h" 7 | #include "NetClient.h" 8 | #include "NetServer.h" 9 | #include "Timer.h" 10 | #include "NetConnect.h" 11 | #include "NetPacket.h" 12 | 13 | class INetEvent : public NetEvent 14 | { 15 | public: 16 | virtual void onAccept(NetConnect * conn){ 17 | if (conn) 18 | { 19 | // 服务器通知有客户端连入 20 | std::cout << "accept client connect" << std::endl; 21 | conn->sendMsg(1, "12345", 5); 22 | } 23 | }; 24 | 25 | 26 | virtual void onClose(NetConnect * conn){ 27 | std::cout << "onClose" << std::endl; 28 | }; 29 | 30 | virtual void onMsg(NetConnect * conn, int msgtype, NetPacket * pack){ 31 | std::string s; 32 | (*pack) >> s; 33 | 34 | printf("receive message from client: %s\n", s.c_str()); 35 | } 36 | }; 37 | 38 | 39 | 40 | int main() 41 | { 42 | //初始化事件循环 43 | INetEvent eve; 44 | EventLoop::Instance()->init(); 45 | 46 | 47 | NetServer server(EventLoop::Instance(), &eve); 48 | server.listen("127.0.0.1", 3001); 49 | 50 | 51 | //开启事件循环 52 | EventLoop::Instance()->run(); 53 | 54 | return 0; 55 | } -------------------------------------------------------------------------------- /example/cpp/timer_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "BaseType.h" 5 | #include "Timer.h" 6 | #include "Tools.h" 7 | 8 | 9 | 10 | int main() 11 | { 12 | Timer::init(); 13 | 14 | 15 | Timer timer1; 16 | Timer timer2; 17 | 18 | timer1.start([](){ 19 | printf("--->30\n"); 20 | },30 * 1000); 21 | 22 | timer2.start([](){ 23 | printf("--->10\n"); 24 | }, 10 * 1000, 10 * 1000); 25 | 26 | Timer * timer3 = new Timer; 27 | timer3->start([&](){ 28 | printf("--->20\n"); 29 | 30 | timer3->stop(); 31 | delete timer3; 32 | 33 | 34 | }, 20 * 1000, 1000); 35 | 36 | 37 | while (1) 38 | { 39 | Tools::sleep(10); 40 | Timer::update(); 41 | } 42 | 43 | system("pause"); 44 | return 0; 45 | } -------------------------------------------------------------------------------- /example/lua/config.csv: -------------------------------------------------------------------------------- 1 | 唯一id,名称,值 2 | id,name,value 3 | 1,hello,10 4 | 2,c++,20 5 | 3,engine,30 6 | -------------------------------------------------------------------------------- /example/lua/csv_test.lua: -------------------------------------------------------------------------------- 1 | local csv = CsvParser:new("config.csv", 2, ',') 2 | 3 | for i = 1, csv:row(), 1 do 4 | local id = csv:getInt32(i, "id") 5 | local name = csv:getString(i, "name") 6 | local value = csv:getInt32(i, "value") 7 | print(id.." | ".. name .. " | ".. value) 8 | end -------------------------------------------------------------------------------- /example/lua/http_server.lua: -------------------------------------------------------------------------------- 1 | msg = [[ 2 | 3 |

hello world

4 | 5 | ]] 6 | 7 | event_init() 8 | 9 | server = HttpServer:new() 10 | 11 | server:listen("127.0.0.1", 80, false) 12 | 13 | server:addGet("/", function(conn, data) 14 | 15 | local hp = HttpParam:new(data, '&') 16 | 17 | if hp:find("a") and hp:find("b") then 18 | local a = hp:getStr("a") 19 | 20 | local b = hp:getStr("b") 21 | print(a.."|"..b) 22 | end 23 | 24 | conn:autoMsg(msg, 0) 25 | end) 26 | 27 | 28 | event_run() 29 | -------------------------------------------------------------------------------- /example/lua/json_test.lua: -------------------------------------------------------------------------------- 1 | local str = "{\"num\": 11, \"obj\":{\"a\":12, \"b\":13}, \"array\":[1314,520]}" 2 | local buff = JsonBuff:new(str) 3 | local jobj = json_parser(buff) 4 | if jobj then 5 | -- C++ returns the parent class, need convert to subclass 6 | obj = json_to_obj(jobj) 7 | print("num:" .. obj:getInt("num") .. "\n") 8 | 9 | local str = json_write(jobj, true) 10 | print(str) 11 | else 12 | print("parser error:" .. json_error(buff)) 13 | end 14 | 15 | local json = require "json" 16 | 17 | local tab = json.decode(str) -- json to lua table 18 | local jstr = json.encode(tab) -- lua table to json 19 | print(jstr) -------------------------------------------------------------------------------- /example/lua/kcp_client.lua: -------------------------------------------------------------------------------- 1 | event_init() 2 | 3 | -- create server 4 | client = KcpClient:new() 5 | client.on_connect = function(conn, argv) 6 | print("on onnect:".. argv) 7 | end 8 | 9 | client.on_close = function(conn) 10 | print("close") 11 | end 12 | 13 | count = 0 14 | client.on_msg = function(conn, msgtype, pack) 15 | local str = pack:getString() 16 | --print(str) 17 | conn:sendPacket(1, pack) 18 | count = count + 1 19 | end 20 | 21 | client:createSession("127.0.0.1", 3001, false); 22 | 23 | t = UTimer:new() 24 | t:start(function() 25 | print(count) 26 | count = 0 27 | end, 1000,1000) 28 | 29 | event_run() -------------------------------------------------------------------------------- /example/lua/kcp_server.lua: -------------------------------------------------------------------------------- 1 | -- init 2 | event_init() 3 | 4 | -- create server 5 | server = KcpServer:new() 6 | server.on_accept = function(conn) 7 | local pack = KcpPacket:new() 8 | pack:pushString("hello world, hello c++") 9 | conn:sendPacket(1, pack) 10 | end 11 | 12 | server.on_close = function(conn) 13 | print("close") 14 | end 15 | 16 | server.on_msg = function(conn, msgtype, pack) 17 | local str = pack:getString() 18 | --print(str) 19 | conn:sendPacket(1, pack) 20 | end 21 | 22 | server:start("127.0.0.1", 3001, false) 23 | 24 | event_run() -------------------------------------------------------------------------------- /example/lua/mysql_test.lua: -------------------------------------------------------------------------------- 1 | local config = DBConfig:new() 2 | config.device = "mysql" 3 | config.ip = "192.168.1.120" 4 | config.dbname = "test_db" 5 | config.user = "root" 6 | config.pswd = "123456" 7 | config.port = 3306 8 | 9 | mysql_library_init() 10 | mysql_thread_safe() 11 | 12 | pool = DBThreadPool:new(config) 13 | pool:create(1) 14 | 15 | func = function(errno, err, result) 16 | if errno ~= 0 then 17 | print(err) 18 | return 19 | end 20 | 21 | while(result:fetch()) 22 | do 23 | local id = result:getInt32() 24 | local num = result:getInt32() 25 | local name = result:getString() 26 | 27 | local str = "id:" .. id .. ", num:" .. num .. ", name:" .. name 28 | -- errorLog(str) 29 | print(str) 30 | end 31 | end 32 | 33 | function exec() 34 | local sql = SqlCommand:new("select * from test where id = ?") 35 | sql:pushInt32(1) 36 | sql:addToPool(pool, func) 37 | end 38 | 39 | event_init() 40 | 41 | exec() 42 | 43 | timer = UTimer:new() 44 | timer:start(function () 45 | pool:update() 46 | end, 10, 10) 47 | 48 | event_run() 49 | 50 | mysql_library_end() -------------------------------------------------------------------------------- /example/lua/protobuf_test/server/example.lua: -------------------------------------------------------------------------------- 1 | 2 | proto.parse("person.proto") 3 | 4 | local person = { 5 | name = "jinjiazh", 6 | id = 10001, 7 | email = "jinjiazh@qq.com", 8 | phones = { 9 | {number = "183****0402", type = PhoneType.HOME}, 10 | {number = "186****9470", type = PhoneType.WORK}, 11 | }, 12 | scores = { 13 | ["Chinese"] = 82, 14 | ["Maths"] = 98, 15 | ["English"] = 88, 16 | } 17 | } 18 | 19 | local data = proto.encode("Person", person) 20 | local clone = proto.decode("Person", data) 21 | 22 | local data = proto.pack("Person", person.name, person.id, person.email, person.phones, person.scores) 23 | local name, id, email, phones, scores = proto.unpack("Person", data) 24 | 25 | require "strings" 26 | print("data = "..b2string(data)) 27 | print("clone = "..t2string(clone)) 28 | print("name = "..name) 29 | print("id = "..id) 30 | print("email = "..email) 31 | print("phones = "..t2string(phones)) 32 | print("scores = "..t2string(scores)) -------------------------------------------------------------------------------- /example/lua/protobuf_test/server/msgtest.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | message Role 4 | { 5 | int32 id = 1; 6 | string name = 2; 7 | int32 money = 3; 8 | repeated int32 tasks = 4; 9 | } 10 | 11 | message Family 12 | { 13 | string name = 1; 14 | int32 lv = 2; 15 | repeated Role roles = 3; 16 | } -------------------------------------------------------------------------------- /example/lua/protobuf_test/server/person.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | message Person { 4 | string name = 1; 5 | int32 id = 2; 6 | string email = 3; 7 | 8 | enum PhoneType { 9 | MOBILE = 0; 10 | HOME = 1; 11 | WORK = 2; 12 | } 13 | 14 | message PhoneNumber { 15 | string number = 1; 16 | PhoneType type = 2; 17 | } 18 | 19 | repeated PhoneNumber phones = 4; 20 | map scores = 5; 21 | } -------------------------------------------------------------------------------- /example/lua/protobuf_test/server/server.lua: -------------------------------------------------------------------------------- 1 | 2 | require "strings" 3 | 4 | proto.parse("msgtest.proto") 5 | 6 | 7 | -- init 8 | event_init() 9 | 10 | -- create server 11 | server = NetServer:new() 12 | server.on_accept = function(conn) 13 | 14 | end 15 | 16 | server.on_close = function(conn) 17 | 18 | end 19 | 20 | server.on_msg = function(conn, msgtype, pack) 21 | -- 从二进制数据解析出实际消息 22 | 23 | local family = proto.decode("Family", pack:readData()) 24 | 25 | print("family = "..t2string(family)) 26 | 27 | local data = proto.encode("Family", family) 28 | conn:sendMsg(111, data); 29 | end 30 | 31 | server:listen("127.0.0.1", 3001, false) 32 | 33 | event_run() -------------------------------------------------------------------------------- /example/lua/protobuf_test/server/strings.lua: -------------------------------------------------------------------------------- 1 | b2string = function(value) 2 | if type(value) ~= 'string' then 3 | return tostring(value) 4 | end 5 | 6 | local s = '' 7 | for i = 1, string.len(value) do 8 | b = string.byte(value, i) 9 | if b < 16 then 10 | s = s .. string.format("0%X ", b) 11 | else 12 | s = s .. string.format("%X ", b) 13 | end 14 | end 15 | return s 16 | end 17 | 18 | t2string = function(value, layer) 19 | if type(value) ~= 'table' then 20 | return tostring(value) 21 | end 22 | layer = layer or 1 23 | local s = '{\n' 24 | for k, v in pairs(value) do 25 | s = s..string.rep(' ', layer) 26 | if type(k) == 'string' then 27 | s = s..k 28 | else 29 | s = s..'[' 30 | s = s..tostring(k) 31 | s = s..']' 32 | end 33 | s = s..' = ' 34 | if type(v) == 'table' then 35 | s = s..t2string(v, layer + 1) 36 | elseif type(v) == 'string' then 37 | s = s..string.format("%q",v) 38 | else 39 | s = s..tostring(v) 40 | end 41 | s = s..',\n' 42 | end 43 | s = s..string.rep(' ', layer - 1) 44 | s = s..'}' 45 | return s 46 | end -------------------------------------------------------------------------------- /example/lua/redis_test.lua: -------------------------------------------------------------------------------- 1 | local config = DBConfig:new() 2 | config.device = "redis" 3 | config.ip = "127.0.0.1" 4 | config.port = 6379 5 | 6 | pool = DBThreadPool:new(config) 7 | pool:create(1) 8 | 9 | func = function(errno, err, result) 10 | if errno ~= 0 then 11 | print(err) 12 | return 13 | end 14 | 15 | while(result:fetch()) 16 | do 17 | local str = result:getString() 18 | -- errorLog(str) 19 | print(str) 20 | end 21 | end 22 | 23 | function exec() 24 | local command = RedisCommand:new("lrange") 25 | command:pushString("t1") 26 | command:pushString("0") 27 | command:pushString("10") 28 | command:addToPool(pool, func) 29 | end 30 | 31 | exec() 32 | event_init() 33 | 34 | timer = UTimer:new() 35 | timer:start(function () 36 | pool:update() 37 | end, 10, 10) 38 | 39 | event_run() -------------------------------------------------------------------------------- /example/lua/tcp_client.lua: -------------------------------------------------------------------------------- 1 | event_init() 2 | 3 | -- create server 4 | client = NetClient:new() 5 | client.on_connect = function(conn, argv) 6 | print("on onnect:".. argv) 7 | end 8 | 9 | client.on_close = function(conn) 10 | print("close") 11 | end 12 | 13 | client.on_msg = function(conn, msgtype, pack) 14 | local str = pack:getString() 15 | print(str) 16 | conn:sendPacket(1, pack) 17 | end 18 | 19 | client:connect("127.0.0.1", 3001, false, 1); 20 | 21 | event_run() -------------------------------------------------------------------------------- /example/lua/tcp_server.lua: -------------------------------------------------------------------------------- 1 | -- init 2 | event_init() 3 | 4 | -- create server 5 | server = NetServer:new() 6 | server.on_accept = function(conn) 7 | local pack = NetPacket:new() 8 | pack:pushString("msg ...") 9 | conn:sendPacket(1, pack) 10 | end 11 | 12 | server.on_close = function(conn) 13 | print("close") 14 | end 15 | 16 | server.on_msg = function(conn, msgtype, pack) 17 | local str = pack:getString() 18 | print(str) 19 | conn:sendPacket(1, pack) 20 | end 21 | 22 | server:listen("127.0.0.1", 3001, false) 23 | 24 | event_run() -------------------------------------------------------------------------------- /example/lua/websocket_client/start.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

run websocket

4 | 5 | 6 | -------------------------------------------------------------------------------- /example/lua/websocket_client/websocket.js: -------------------------------------------------------------------------------- 1 | var ws = new WebSocket("ws://localhost:8080"); 2 | ws.onopen = function() 3 | { 4 | var pos = 0; 5 | var msg = "你好 jwEngine"; 6 | var buff = new ArrayBuffer(4 + (msg.length + 1) + 4); 7 | var dv = new DataView(buff); 8 | dv.setInt32(pos, 110, true); 9 | pos += 4; 10 | for (var i=0; i { 28 | var str = "" 29 | var buff = reader.result; 30 | var dv = new DataView(buff); 31 | // c++ char* end is 0 32 | for (var i=0; i < evt.data.size - 1; i++) 33 | { 34 | str += String.fromCharCode(dv.getUint8(i, true)); 35 | } 36 | alert(str) 37 | }; 38 | }; 39 | 40 | ws.onclose = function() 41 | { 42 | alert("close"); 43 | }; 44 | -------------------------------------------------------------------------------- /example/lua/websocket_server.lua: -------------------------------------------------------------------------------- 1 | -- init 2 | event_init() 3 | 4 | -- create server 5 | server = WebSocketServer:new() 6 | server.on_accept = function(conn) 7 | print("connect") 8 | end 9 | 10 | server.on_close = function(conn) 11 | print("close") 12 | end 13 | 14 | server.on_msg = function(conn, pack) 15 | print(pack:getInt32()) 16 | print(utf8_gbk(pack:getString())) 17 | print(pack:getInt32()) 18 | 19 | local retpak = WebSocketPacket:new() 20 | retpak:pushString('hello client') 21 | conn:sendPacket(retpak) 22 | end 23 | 24 | server:listen("127.0.0.1", 8080, false) 25 | 26 | event_run() -------------------------------------------------------------------------------- /example/python/__pycache__/net.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/lua-server/6008c764295d822f82a89ed8d579559bbcf1adfa/example/python/__pycache__/net.cpython-36.pyc -------------------------------------------------------------------------------- /example/python/__pycache__/socket_buffer.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/lua-server/6008c764295d822f82a89ed8d579559bbcf1adfa/example/python/__pycache__/socket_buffer.cpython-36.pyc -------------------------------------------------------------------------------- /example/python/client_test.py: -------------------------------------------------------------------------------- 1 | import socket_buffer 2 | import net 3 | import time 4 | 5 | def onMsg(type, buff): 6 | print("------------------->"+str(type)) 7 | rpack = socket_buffer.NetPacket() 8 | rpack.receive(buff) 9 | print(rpack.getInt32()) 10 | print(rpack.getString()) 11 | print(rpack.getInt16()) 12 | 13 | client = net.TcpClient("127.0.0.1", 3001) 14 | client.set_on_msg(onMsg) 15 | client.start() 16 | 17 | pack = socket_buffer.NetPacket() 18 | pack.pushString("abcdefg") 19 | pack.pushInt32(1314) 20 | pack.pushString("jwEngine") 21 | pack.pushInt32(520) 22 | pack.setHead(100011) 23 | 24 | client.send(pack.getSendData()) 25 | 26 | 27 | while True: 28 | time.sleep(0.1) 29 | client.update() 30 | 31 | 32 | client.close() -------------------------------------------------------------------------------- /example/python/net.py: -------------------------------------------------------------------------------- 1 | import threading 2 | import queue 3 | import struct 4 | import socket 5 | import time 6 | 7 | HEAD_SIZE = 8 8 | class TcpClientBase(threading.Thread): 9 | def __init__(self, ip, port): 10 | threading.Thread.__init__(self) 11 | 12 | self.socket = None 13 | self.ip = ip 14 | self.port = port 15 | 16 | self.sends = queue.Queue() 17 | self.cursend = None 18 | self.sendpos = 0 19 | 20 | self.reads = queue.Queue() 21 | self.curread = bytearray() 22 | self.readpos = 0 23 | 24 | def connect(self): 25 | self.socket = socket.socket() 26 | try: 27 | self.socket.connect((self.ip, self.port)) 28 | except ConnectionRefusedError: 29 | self.socket.close() 30 | self.socket = None 31 | 32 | if self.socket: 33 | self.socket.setblocking(False) 34 | 35 | def __startRecv(self, size): 36 | try: 37 | recvdata = self.socket.recv(size) 38 | except BlockingIOError: 39 | recvdata = None 40 | except: 41 | return -1 42 | 43 | if recvdata: 44 | self.curread += recvdata 45 | self.readpos += len(recvdata) 46 | return 0 47 | 48 | def __handleRead(self): 49 | ret = 0 50 | if self.readpos < HEAD_SIZE: 51 | ret = self.__startRecv(HEAD_SIZE - self.readpos) 52 | 53 | if self.readpos >= HEAD_SIZE: 54 | bodylen = struct.unpack_from('i', self.curread, 0)[0] 55 | if self.readpos >= HEAD_SIZE + bodylen: 56 | self.reads.put(self.curread) 57 | self.curread = bytearray() 58 | self.readpos = 0 59 | else: 60 | ret = self.__startRecv(HEAD_SIZE + bodylen - self.readpos) 61 | return ret 62 | 63 | 64 | def __handleWrite(self): 65 | if self.cursend is None and not self.sends.empty(): 66 | self.cursend = self.sends.get_nowait() 67 | if self.cursend is None: 68 | return 69 | 70 | sendsize = self.socket.send(self.cursend[self.sendpos:]) 71 | if sendsize > 0: 72 | self.sendpos += sendsize 73 | if self.sendpos == len(self.cursend): 74 | self.sendpos = 0 75 | self.cursend = None 76 | 77 | def run(self): 78 | while True: 79 | if self.socket: 80 | self.__handleWrite() 81 | ret = self.__handleRead() 82 | if ret < 0: 83 | self.socket = None 84 | else: 85 | time.sleep(1) 86 | print('Reconnect...') 87 | self.connect() 88 | 89 | 90 | def send(self, buff): 91 | self.sends.put(buff) 92 | 93 | def getBuff(self): 94 | if self.reads.empty(): 95 | return None 96 | return self.reads.get_nowait() 97 | 98 | def close(self): 99 | if self.socket: 100 | self.socket.close() 101 | 102 | 103 | 104 | class TcpClient(TcpClientBase): 105 | def __init__(self, ip, port): 106 | TcpClientBase.__init__(self, ip, port) 107 | self.on_msg = None 108 | 109 | def set_on_msg(self, func): 110 | self.on_msg = func 111 | 112 | def start(self): 113 | TcpClientBase.connect(self) 114 | # start thread 115 | TcpClientBase.start(self) 116 | 117 | def update(self): 118 | if self.on_msg is None: 119 | return 120 | 121 | buff = self.getBuff() 122 | if buff is None: 123 | return 124 | 125 | msgid = struct.unpack_from('i', buff, 4)[0] 126 | self.on_msg(msgid, buff) 127 | -------------------------------------------------------------------------------- /example/python/net.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/lua-server/6008c764295d822f82a89ed8d579559bbcf1adfa/example/python/net.pyc -------------------------------------------------------------------------------- /example/python/socket_buffer.py: -------------------------------------------------------------------------------- 1 | import struct 2 | 3 | class BaseBuffer: 4 | def __init__(self, size): 5 | self.rpos = 0 6 | self.wpos = size 7 | self.buff = bytearray(size) 8 | 9 | def write(self, fmt, value, size): 10 | self.buff += struct.pack(fmt,value) 11 | self.wpos += size 12 | 13 | def read(self, fmt, size): 14 | ret = struct.unpack_from(fmt,self.buff, self.rpos) 15 | self.rpos += size 16 | return ret 17 | 18 | def pushInt8(self, value): 19 | self.write('b',value, 1) 20 | def pushUint8(self, value): 21 | self.write('B',value, 1) 22 | def pushInt16(self, value): 23 | self.write('h',value, 2) 24 | def pushUint16(self, value): 25 | self.write('H',value, 2) 26 | def pushInt32(self, value): 27 | self.write('i',value, 4) 28 | def pushUint32(self, value): 29 | self.write('I',value, 4) 30 | def pushInt64(self, value): 31 | self.write('q',value, 8) 32 | def pushUint64(self, value): 33 | self.write('Q',value, 8) 34 | def pushFloat(self, value): 35 | self.write('f',value, 4) 36 | def pushDouble(self, value): 37 | self.write('d',value, 8) 38 | def pushString(self, value): 39 | value += '\0' 40 | self.buff += value.encode('utf-8') 41 | self.wpos += len(value) 42 | 43 | def getInt8(self): 44 | return self.read('b', 1)[0] 45 | def getUint8(self): 46 | return self.read('B', 1)[0] 47 | def getInt16(self): 48 | return self.read('h', 2)[0] 49 | def getUint16(self): 50 | return self.read('H', 2)[0] 51 | def getInt32(self): 52 | return self.read('i', 4)[0] 53 | def getUint32(self): 54 | return self.read('I', 4)[0] 55 | def getInt64(self): 56 | return self.read('q', 8)[0] 57 | def getUint64(self): 58 | return self.read('Q', 8)[0] 59 | def getFloat(self): 60 | return self.read('f', 4)[0] 61 | def getDouble(self): 62 | return self.read('d', 8)[0] 63 | def getString(self): 64 | slen = 0 65 | for i in range(len(self.buff) - self.rpos): 66 | char_ = self.buff[self.rpos + i] 67 | if char_ == 0: 68 | break 69 | slen += 1 70 | by = self.buff[self.rpos: self.rpos + slen] 71 | self.rpos += (slen + 1) 72 | return by.decode() 73 | 74 | class NetPacket(BaseBuffer): 75 | def __init__(self): 76 | BaseBuffer.__init__(self, 8) 77 | 78 | def receive(self, buff): 79 | self.rpos = 8 80 | self.wpos = len(buff) 81 | self.buff = buff 82 | 83 | def setHead(self, msgtype): 84 | struct.pack_into('I',self.buff,0, self.wpos - 8) 85 | struct.pack_into('I',self.buff,4,msgtype) 86 | 87 | def getSendData(self): 88 | return self.buff 89 | 90 | def getSendSize(self): 91 | return self.wpos -------------------------------------------------------------------------------- /example/python/socket_buffer.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/lua-server/6008c764295d822f82a89ed8d579559bbcf1adfa/example/python/socket_buffer.pyc -------------------------------------------------------------------------------- /src/common/BaseType.h: -------------------------------------------------------------------------------- 1 | #ifndef BASETYPE_H 2 | #define BASETYPE_H 3 | 4 | #include "stdint.h" 5 | 6 | typedef int8_t int8; 7 | typedef uint8_t uint8; 8 | 9 | typedef int16_t int16; 10 | typedef uint16_t uint16; 11 | 12 | typedef int32_t int32; 13 | typedef uint32_t uint32; 14 | 15 | typedef int64_t int64; 16 | typedef uint64_t uint64; 17 | 18 | 19 | 20 | #endif 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/common/ByteBuffer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "ByteBuffer.h" 3 | #include "CommonPool.h" 4 | 5 | // constructor 6 | ByteBuffer::ByteBuffer() : _rpos(0), _wpos(0) 7 | { 8 | _storage = createBuffer(); 9 | _storage->reserve(DEFAULT_SIZE); 10 | } 11 | 12 | ByteBuffer::ByteBuffer(size_t reserve) : _rpos(0), _wpos(0) 13 | { 14 | _storage = createBuffer(); 15 | _storage->reserve(reserve); 16 | } 17 | 18 | ByteBuffer::ByteBuffer(ByteBuffer&& buf) : _rpos(buf._rpos), _wpos(buf._wpos) 19 | { 20 | _storage = createBuffer(); 21 | swapBuffer(buf); 22 | } 23 | 24 | ByteBuffer::ByteBuffer(ByteBuffer const& right) : _rpos(right._rpos), _wpos(right._wpos) 25 | { 26 | _storage = createBuffer(); 27 | *_storage = *right._storage; 28 | } 29 | 30 | ByteBuffer& ByteBuffer::operator=(ByteBuffer const& right) 31 | { 32 | if (this != &right) 33 | { 34 | _rpos = right._rpos; 35 | _wpos = right._wpos; 36 | *_storage = *right._storage; 37 | } 38 | 39 | return *this; 40 | } 41 | 42 | ByteBuffer& ByteBuffer::operator=(ByteBuffer&& right) 43 | { 44 | if (this != &right) 45 | { 46 | _rpos = right._rpos; 47 | _wpos = right._wpos; 48 | swapBuffer(right); 49 | } 50 | 51 | return *this; 52 | } 53 | 54 | ByteBuffer::~ByteBuffer() { 55 | if(_storage) CommPool::reclaim(_storage); 56 | } 57 | 58 | CBuffer* ByteBuffer::createBuffer() 59 | { 60 | return CommPool::create(); 61 | } 62 | void ByteBuffer::swapBuffer(ByteBuffer& right) 63 | { 64 | CBuffer* tmp = _storage; 65 | _storage = right._storage; 66 | right._storage = tmp; 67 | } 68 | 69 | ByteBuffer& ByteBuffer::operator>>(float& value) 70 | { 71 | value = read(); 72 | return *this; 73 | } 74 | 75 | ByteBuffer& ByteBuffer::operator>>(double& value) 76 | { 77 | value = read(); 78 | return *this; 79 | } 80 | 81 | void ByteBuffer::append(const uint8 *src, size_t cnt) 82 | { 83 | _storage->insert(_storage->begin() + _wpos, src, src + cnt); 84 | _wpos += cnt; 85 | } 86 | 87 | void ByteBuffer::put(size_t pos, const uint8 *src, size_t cnt) 88 | { 89 | std::memcpy(&(*_storage)[pos], src, cnt); 90 | } 91 | -------------------------------------------------------------------------------- /src/common/ByteConverter.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008-2019 TrinityCore 3 | * Copyright (C) 2005-2009 MaNGOS 4 | * 5 | * This program is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License as published by the 7 | * Free Software Foundation; either version 2 of the License, or (at your 8 | * option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, but WITHOUT 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 | * more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along 16 | * with this program. If not, see . 17 | */ 18 | 19 | #ifndef TRINITY_BYTECONVERTER_H 20 | #define TRINITY_BYTECONVERTER_H 21 | 22 | /** ByteConverter reverse your byte order. This is use 23 | for cross platform where they have different endians. 24 | */ 25 | 26 | #include "Define.h" 27 | #include "BaseType.h" 28 | #include 29 | 30 | namespace ByteConverter 31 | { 32 | template 33 | inline void convert(char *val) 34 | { 35 | std::swap(*val, *(val + T - 1)); 36 | convert(val + 1); 37 | } 38 | 39 | template<> inline void convert<0>(char *) { } 40 | template<> inline void convert<1>(char *) { } // ignore central byte 41 | 42 | template inline void apply(T *val) 43 | { 44 | convert((char *)(val)); 45 | } 46 | } 47 | 48 | #if TRINITY_ENDIAN == TRINITY_BIGENDIAN 49 | template inline void EndianConvert(T& val) { ByteConverter::apply(&val); } 50 | template inline void EndianConvertReverse(T&) { } 51 | template inline void EndianConvertPtr(void* val) { ByteConverter::apply(val); } 52 | template inline void EndianConvertPtrReverse(void*) { } 53 | #else 54 | template inline void EndianConvert(T&) { } 55 | template inline void EndianConvertReverse(T& val) { ByteConverter::apply(&val); } 56 | template inline void EndianConvertPtr(void*) { } 57 | template inline void EndianConvertPtrReverse(void* val) { ByteConverter::apply(val); } 58 | #endif 59 | 60 | template void EndianConvert(T*); // will generate link error 61 | template void EndianConvertReverse(T*); // will generate link error 62 | 63 | inline void EndianConvert(uint8&) { } 64 | inline void EndianConvert(int8&) { } 65 | inline void EndianConvertReverse(uint8&) { } 66 | inline void EndianConvertReverse(int8&) { } 67 | 68 | #endif -------------------------------------------------------------------------------- /src/common/CommonPool.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/lua-server/6008c764295d822f82a89ed8d579559bbcf1adfa/src/common/CommonPool.h -------------------------------------------------------------------------------- /src/common/CsvParser.cpp: -------------------------------------------------------------------------------- 1 | #include "CsvParser.h" 2 | #include 3 | #include "XLog.h" 4 | 5 | 6 | CsvParser::CsvParser(const char * file, int startline, char sep) : 7 | _sep(sep) 8 | { 9 | std::string line; 10 | 11 | std::ifstream ifile(file); 12 | if (ifile.is_open()) 13 | { 14 | int row = 0; 15 | while (ifile.good()) 16 | { 17 | getline(ifile, line); 18 | if (line == "") 19 | continue; 20 | 21 | if (startline && --startline) 22 | continue; 23 | 24 | row++; 25 | if (row == 1) 26 | { 27 | parseHeader(line); 28 | } 29 | else 30 | { 31 | parseContent(line); 32 | } 33 | } 34 | ifile.close(); 35 | } 36 | else 37 | { 38 | ERROR_LOG("Failed to open %s", file); 39 | } 40 | } 41 | 42 | 43 | CsvParser::~CsvParser() 44 | { 45 | } 46 | 47 | void CsvParser::parseHeader(std::string & line) 48 | { 49 | std::stringstream ss(line); 50 | std::string item; 51 | 52 | while (std::getline(ss, item, _sep)) 53 | _header.push_back(item); 54 | } 55 | 56 | void CsvParser::parseContent(std::string & line) 57 | { 58 | std::stringstream ss(line); 59 | std::string item; 60 | 61 | CsvRow csvrow; 62 | while (std::getline(ss, item, _sep)) 63 | csvrow.push(item); 64 | 65 | _content.push_back(csvrow); 66 | } 67 | 68 | int CsvParser::row() 69 | { 70 | return _content.size(); 71 | } -------------------------------------------------------------------------------- /src/common/CsvParser.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | # include 4 | #include 5 | 6 | class CsvRow 7 | { 8 | public: 9 | unsigned int size(void) const{ return _values.size(); } 10 | void push(const std::string & title){ _values.push_back(title); } 11 | 12 | template 13 | const T getValue(int idx, T defvalue = T()) const 14 | { 15 | T res = defvalue; 16 | std::stringstream ss; 17 | ss << _values[idx]; 18 | ss >> res; 19 | return res; 20 | } 21 | private: 22 | std::vector _values; 23 | }; 24 | 25 | class CsvParser 26 | { 27 | public: 28 | CsvParser(const char * file, int startline = 1, char sep = '\t'); 29 | ~CsvParser(); 30 | 31 | template 32 | const T getValue(int row, std::string name, T defvalue = T()) const 33 | { 34 | for (unsigned int i = 0; i < _header.size();++i) 35 | { 36 | if (name == _header[i]) 37 | { 38 | const CsvRow & csvrow = _content[row - 1]; 39 | T ret = csvrow.getValue(i, defvalue); 40 | return ret; 41 | } 42 | } 43 | 44 | return T(); 45 | } 46 | 47 | int row(); 48 | 49 | protected: 50 | void parseHeader(std::string & line); 51 | void parseContent(std::string & line); 52 | private: 53 | const char _sep; 54 | std::vector _header; 55 | std::vector _content; 56 | }; 57 | 58 | -------------------------------------------------------------------------------- /src/common/Define.h: -------------------------------------------------------------------------------- 1 | #ifndef _DEFINE_H_ 2 | #define _DEFINE_H_ 3 | 4 | #include "Platform.h" 5 | 6 | #ifdef SYSTEM_WIN 7 | #include 8 | #endif 9 | 10 | #define TRINITY_BIGENDIAN 1 11 | 12 | 13 | 14 | #endif -------------------------------------------------------------------------------- /src/common/EventLoop.cpp: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | 3 | void EventLoop::init() 4 | { 5 | mLoop = uv_default_loop(); 6 | } 7 | 8 | int EventLoop::run() 9 | { 10 | return uv_run(mLoop, UV_RUN_DEFAULT); 11 | } 12 | 13 | void EventLoop::stop() 14 | { 15 | uv_stop(mLoop); 16 | } 17 | 18 | void EventLoop::exit() 19 | { 20 | uv_loop_delete(mLoop); 21 | mLoop = NULL; 22 | } 23 | 24 | uv_loop_t * EventLoop::getLoop() 25 | { 26 | return mLoop; 27 | } -------------------------------------------------------------------------------- /src/common/EventLoop.h: -------------------------------------------------------------------------------- 1 | #ifndef EVENT_LOOP_H 2 | #define EVENT_LOOP_H 3 | 4 | #include "libuv/include/uv.h" 5 | #include "Singleton.h" 6 | 7 | class EventLoop : public Singleton 8 | { 9 | public: 10 | void init(); 11 | 12 | int run(); 13 | void stop(); 14 | void exit(); 15 | uv_loop_t* getLoop(); 16 | 17 | private: 18 | uv_loop_t* mLoop; 19 | }; 20 | 21 | 22 | #endif -------------------------------------------------------------------------------- /src/common/Heap.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2013, Ben Noordhuis 2 | * 3 | * Permission to use, copy, modify, and/or distribute this software for any 4 | * purpose with or without fee is hereby granted, provided that the above 5 | * copyright notice and this permission notice appear in all copies. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | */ 15 | 16 | #ifndef HEAP_H_ 17 | #define HEAP_H_ 18 | 19 | #include /* NULL */ 20 | 21 | namespace Heap 22 | { 23 | struct heap_node { 24 | struct heap_node* left; 25 | struct heap_node* right; 26 | struct heap_node* parent; 27 | }; 28 | 29 | /* A binary min heap. The usual properties hold: the root is the lowest 30 | * element in the set, the height of the tree is at most log2(nodes) and 31 | * it's always a complete binary tree. 32 | * 33 | * The heap function try hard to detect corrupted tree nodes at the cost 34 | * of a minor reduction in performance. Compile with -DNDEBUG to disable. 35 | */ 36 | struct heap { 37 | struct heap_node* min; 38 | unsigned int nelts; 39 | }; 40 | 41 | /* Return non-zero if a < b. */ 42 | typedef int(*heap_compare_fn)(const struct heap_node* a, const struct heap_node* b); 43 | 44 | 45 | class CHeap{ 46 | public: 47 | /* Public functions. */ 48 | static void heap_init(struct heap* heap); 49 | static struct heap_node* heap_min(const struct heap* heap); 50 | static void heap_insert(struct heap* heap, 51 | struct heap_node* newnode, heap_compare_fn less_than); 52 | static void heap_remove(struct heap* heap, struct heap_node* node, heap_compare_fn less_than); 53 | static void heap_dequeue(struct heap* heap, heap_compare_fn less_than); 54 | 55 | private: 56 | static void heap_node_swap(struct heap* heap, 57 | struct heap_node* parent, 58 | struct heap_node* child); 59 | }; 60 | }; 61 | 62 | #endif /* UV_SRC_HEAP_H_ */ 63 | -------------------------------------------------------------------------------- /src/common/HttpParam.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "HttpParam.h" 6 | 7 | HttpParam::HttpParam(std::string_view str_v, char cut) 8 | { 9 | std::vector equal; 10 | splite(str_v, equal, cut); 11 | 12 | for (auto it = equal.begin();it!= equal.end(); ++it) 13 | { 14 | std::string_view & sub = (*it); 15 | 16 | std::vector kys; 17 | splite(sub, kys, '='); 18 | 19 | if (kys.size() == 2) 20 | { 21 | params[kys[0]] = kys[1]; 22 | } 23 | } 24 | } 25 | 26 | 27 | void HttpParam::splite(std::string_view str_view, std::vector & vec_str, char cut) 28 | { 29 | std::string::size_type pos1 = 0, pos2; 30 | while ((pos2 = str_view.find(cut, pos1)) != std::string_view::npos) 31 | { 32 | vec_str.push_back(str_view.substr(pos1, pos2 - pos1)); 33 | pos1 = pos2 + 1; 34 | } 35 | vec_str.push_back(str_view.substr(pos1)); 36 | } 37 | 38 | bool HttpParam::find(std::string_view key) 39 | { 40 | return params.find(key) != params.end(); 41 | } 42 | 43 | std::string_view HttpParam::getStr(std::string_view key) 44 | { 45 | return params[key]; 46 | } 47 | 48 | int HttpParam::getInt(std::string_view key) 49 | { 50 | std::string si(params[key]); 51 | return std::stoi(si); 52 | } 53 | 54 | float HttpParam::getFloat(std::string_view key) 55 | { 56 | std::string sf(params[key]); 57 | return std::stof(sf); 58 | } -------------------------------------------------------------------------------- /src/common/HttpParam.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /************************************************************************ 3 | * @file HttpParam.h 4 | * @brief Parse HTTP parameters 5 | * @author jiangwang 6 | * @data 2020-5-21 7 | * @version 0.1 8 | ************************************************************************/ 9 | 10 | class HttpParam 11 | { 12 | public: 13 | HttpParam(std::string_view str_v, char cut = '&'); 14 | 15 | static void splite(std::string_view str_view, std::vector & vec_str, char cut = '&'); 16 | 17 | bool find(std::string_view key); 18 | std::string_view getStr(std::string_view key); 19 | int getInt(std::string_view key); 20 | float getFloat(std::string_view key); 21 | 22 | private: 23 | std::map params; 24 | }; 25 | 26 | -------------------------------------------------------------------------------- /src/common/Objectpool.h: -------------------------------------------------------------------------------- 1 | #ifndef _OBJECT_POOL_H 2 | #define _OBJECT_POOL_H 3 | 4 | #include 5 | #include 6 | #include "XAssert.h" 7 | 8 | template< typename T> 9 | class ObjectPool 10 | { 11 | typedef std::list OBJECTS; 12 | 13 | public: 14 | ObjectPool(int32 maxfreecount = 0x200) : 15 | max_free(maxfreecount), obj_count_(0) 16 | { 17 | 18 | } 19 | 20 | ~ObjectPool(){ 21 | destroy(); 22 | } 23 | 24 | void init(int32 count) 25 | { 26 | max_free = count; 27 | } 28 | 29 | void destroy() 30 | { 31 | typename OBJECTS::iterator iter = objects_.begin(); 32 | for (; iter != objects_.end(); ++iter) 33 | { 34 | (*iter)->setEnabledPoolObject(false); 35 | delete (*iter); 36 | } 37 | 38 | objects_.clear(); 39 | obj_count_ = 0; 40 | } 41 | 42 | T* createObject() 43 | { 44 | if (obj_count_ > 0) 45 | { 46 | T* t = *objects_.begin(); 47 | objects_.pop_front(); 48 | --obj_count_; 49 | t->setEnabledPoolObject(true); 50 | return t; 51 | } 52 | 53 | T* t = newObj(); 54 | t->setEnabledPoolObject(true); 55 | return t; 56 | } 57 | 58 | virtual T * newObj() 59 | { 60 | return new T; 61 | } 62 | 63 | void reclaimObject(T* obj) 64 | { 65 | if (obj == NULL) 66 | { 67 | return; 68 | } 69 | if (!obj->isEnabledPoolObject()) 70 | { 71 | XAssert(0, "The object is already in the pool"); 72 | return; 73 | } 74 | 75 | obj->setEnabledPoolObject(false); 76 | if (obj_count_ >= max_free) 77 | { 78 | delete obj; 79 | } 80 | else 81 | { 82 | objects_.push_back(obj); 83 | ++obj_count_; 84 | } 85 | } 86 | 87 | int32 getObjCount(){ return obj_count_; } 88 | OBJECTS & getObjs() { return objects_; } 89 | private: 90 | int32 max_free; 91 | int32 obj_count_; 92 | OBJECTS objects_; 93 | }; 94 | 95 | 96 | #endif -------------------------------------------------------------------------------- /src/common/Platform.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/lua-server/6008c764295d822f82a89ed8d579559bbcf1adfa/src/common/Platform.h -------------------------------------------------------------------------------- /src/common/PoolObject.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //include body 4 | #define INCLUDE_POOL_OBJECT\ 5 | public:\ 6 | bool isEnabledPoolObject() const{ return isEnabledPoolObject_; }\ 7 | void setEnabledPoolObject(bool v){ isEnabledPoolObject_ = v; }\ 8 | private:\ 9 | bool isEnabledPoolObject_ = true; 10 | 11 | class PoolObject 12 | { 13 | INCLUDE_POOL_OBJECT 14 | }; -------------------------------------------------------------------------------- /src/common/Singleton.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef SRC_UTILS_SINGLETON_H_ 3 | #define SRC_UTILS_SINGLETON_H_ 4 | 5 | template 6 | class Singleton 7 | { 8 | public: 9 | static T* Instance() { 10 | static T _instance; 11 | return &_instance; 12 | } 13 | 14 | protected: 15 | // Disable compiler generated code to prevent default constuction/destruction 16 | // and copy/assignment semantics. 17 | Singleton(){} 18 | ~Singleton(){} 19 | Singleton(Singleton const&){} 20 | Singleton& operator=(Singleton const&){} 21 | }; 22 | 23 | 24 | #endif // SRC_UTILS_SINGLETON_H_ 25 | -------------------------------------------------------------------------------- /src/common/SpinLock.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class SpinLock 6 | { 7 | public: 8 | explicit SpinLock() 9 | { 10 | flag.clear(); 11 | } 12 | 13 | ~SpinLock() 14 | { 15 | } 16 | 17 | void lock() 18 | { 19 | while (flag.test_and_set(std::memory_order_acquire)) 20 | ; 21 | } 22 | 23 | bool try_lock() 24 | { 25 | if (flag.test_and_set(std::memory_order_acquire)) 26 | { 27 | return false; 28 | } 29 | 30 | return true; 31 | } 32 | 33 | void unlock() 34 | { 35 | flag.clear(std::memory_order_release); 36 | } 37 | 38 | protected: 39 | mutable std::atomic_flag flag;// = ATOMIC_FLAG_INIT; 40 | 41 | private: 42 | SpinLock& operator=(const SpinLock& src); 43 | }; -------------------------------------------------------------------------------- /src/common/TQueue.h: -------------------------------------------------------------------------------- 1 | #ifndef X_QUEUE_H 2 | #define X_QUEUE_H 3 | 4 | #include "concurrentqueue/concurrentqueue.h" 5 | 6 | /* 7 | 8 | using namespace moodycamel; 9 | 10 | ReaderWriterQueue q(100); // Reserve space for at least 100 elements up front 11 | 12 | q.enqueue(17); // Will allocate memory if the queue is full 13 | bool succeeded = q.try_enqueue(18); // Will only succeed if the queue has an empty slot (never allocates) 14 | assert(succeeded); 15 | 16 | int number; 17 | succeeded = q.try_dequeue(number); // Returns false if the queue was empty 18 | 19 | assert(succeeded && number == 17); 20 | 21 | // You can also peek at the front item of the queue (consumer only) 22 | int* front = q.peek(); 23 | assert(*front == 18); 24 | succeeded = q.try_dequeue(number); 25 | assert(succeeded && number == 18); 26 | front = q.peek(); 27 | assert(front == nullptr); // Returns nullptr if the queue was empty 28 | 29 | */ 30 | 31 | template 32 | class TQueue 33 | { 34 | public: 35 | TQueue(int maxSize = 15) : 36 | mqueue(maxSize) 37 | { 38 | 39 | } 40 | void push(const T& object) 41 | { 42 | mqueue.enqueue(object); 43 | } 44 | 45 | bool tryPop(T& object) 46 | { 47 | return mqueue.try_dequeue(object); 48 | } 49 | 50 | private: 51 | moodycamel::ConcurrentQueue mqueue; 52 | }; 53 | 54 | #endif -------------------------------------------------------------------------------- /src/common/ThreadPool.cpp: -------------------------------------------------------------------------------- 1 | #include "ThreadPool.h" 2 | #include 3 | 4 | using namespace Thread; 5 | 6 | Task::~Task() 7 | { 8 | 9 | } 10 | 11 | CThread::CThread(ThreadPool * pool) : 12 | _pool(pool), 13 | _thread(CThread::backfunc, this) 14 | { 15 | //_thread.detach(); 16 | } 17 | 18 | CThread::~CThread() 19 | { 20 | 21 | } 22 | 23 | void CThread::backfunc(CThread * t) 24 | { 25 | std::this_thread::sleep_for(std::chrono::milliseconds(10)); 26 | t->onStart(); 27 | while (t->_isrun) 28 | { 29 | TaskPtr task = t->_pool->popWaitTask(); 30 | if (task) 31 | { 32 | t->run(task); 33 | t->_pool->_completeTasks.push(task); 34 | } 35 | else 36 | { 37 | std::this_thread::sleep_for(std::chrono::milliseconds(1)); 38 | } 39 | } 40 | t->onEnd(); 41 | } 42 | 43 | void CThread::stop() 44 | { 45 | _isrun = false; 46 | _thread.join(); 47 | } 48 | 49 | void CThread::run(TaskPtr task) 50 | { 51 | task->process(); 52 | }; 53 | 54 | ThreadPool::ThreadPool() 55 | { 56 | 57 | } 58 | 59 | 60 | ThreadPool::~ThreadPool() 61 | { 62 | exit(); 63 | } 64 | 65 | void ThreadPool::create(int count) 66 | { 67 | for (int i = 0; i < count; ++i) 68 | { 69 | CThread * t = createThread(); 70 | if (t) 71 | { 72 | _threads.push_back(t); 73 | } 74 | } 75 | } 76 | void ThreadPool::exit() 77 | { 78 | for (CThread * t : _threads) 79 | { 80 | t->stop(); 81 | deleteThread(t); 82 | } 83 | 84 | _threads.clear(); 85 | } 86 | 87 | void ThreadPool::addTask(TaskPtr task) 88 | { 89 | _waitTasks.push(task); 90 | } 91 | 92 | TaskPtr ThreadPool::popWaitTask() 93 | { 94 | TaskPtr task; 95 | if (!_waitTasks.tryPop(task)) 96 | return NULL; 97 | return task; 98 | } 99 | 100 | void ThreadPool::update() 101 | { 102 | TaskPtr task; 103 | if (!_completeTasks.tryPop(task)) 104 | return; 105 | 106 | task->complete(); 107 | completeTask(task); 108 | } -------------------------------------------------------------------------------- /src/common/ThreadPool.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include "TQueue.h" 6 | 7 | namespace Thread 8 | { 9 | class Task 10 | { 11 | public: 12 | virtual ~Task(); 13 | virtual void process() = 0; 14 | virtual void complete() = 0; 15 | }; 16 | 17 | typedef std::shared_ptr TaskPtr; 18 | 19 | class ThreadPool; 20 | class CThread 21 | { 22 | public: 23 | CThread(ThreadPool * pool); 24 | virtual ~CThread(); 25 | static void backfunc(CThread * t); 26 | void stop(); 27 | 28 | virtual void run(TaskPtr task); 29 | 30 | protected: 31 | virtual void onStart() {}; 32 | virtual void onEnd() {}; 33 | 34 | protected: 35 | ThreadPool * _pool; 36 | std::thread _thread; 37 | std::atomic _isrun{ true }; 38 | }; 39 | 40 | class ThreadPool 41 | { 42 | friend CThread; 43 | public: 44 | ThreadPool(); 45 | virtual ~ThreadPool(); 46 | 47 | void create(int count); 48 | void exit(); 49 | 50 | void addTask(TaskPtr task); 51 | void update(); 52 | protected: 53 | virtual CThread* createThread() = 0; 54 | virtual void deleteThread(CThread * t) 55 | { 56 | delete t; 57 | } 58 | virtual void completeTask(TaskPtr task) = 0; 59 | private: 60 | TaskPtr popWaitTask(); 61 | 62 | private: 63 | std::vector _threads; 64 | TQueue _waitTasks; 65 | TQueue _completeTasks; 66 | }; 67 | } 68 | 69 | -------------------------------------------------------------------------------- /src/common/Timer.cpp: -------------------------------------------------------------------------------- 1 | #include "Timer.h" 2 | #include "XTime.h" 3 | 4 | struct Heap::heap Timer::gRootHeap; 5 | 6 | Timer::Timer() 7 | { 8 | m_node = (TimerNode *)malloc(sizeof(TimerNode)); 9 | m_node->user = this; 10 | } 11 | 12 | Timer::~Timer() 13 | { 14 | if (m_node) 15 | { 16 | m_node->user = NULL; 17 | 18 | stop(); 19 | free(m_node); 20 | 21 | m_node = NULL; 22 | } 23 | } 24 | 25 | 26 | /*static */ void Timer::init() 27 | { 28 | Heap::CHeap::heap_init(&gRootHeap); 29 | } 30 | /*static */ void Timer::update() 31 | { 32 | for (int i = 0; i < 10; ++i) 33 | { 34 | TimerNode * node = (TimerNode *)Heap::CHeap::heap_min(&gRootHeap); 35 | if (node) 36 | { 37 | Timer * timer = (Timer *)node->user; 38 | if (XTime::iclock() >= timer->m_time) 39 | { 40 | Heap::CHeap::heap_remove(&gRootHeap, (struct Heap::heap_node *)node, (Heap::heap_compare_fn)compare_fn); 41 | timer->m_time = 0; 42 | if (timer->m_repeat > 0) 43 | { 44 | timer->m_time = timer->m_repeat + XTime::iclock(); 45 | Heap::CHeap::heap_insert(&gRootHeap, (struct Heap::heap_node *)node, (Heap::heap_compare_fn)compare_fn); 46 | } 47 | 48 | timer->m_cb(); 49 | } 50 | else 51 | { 52 | break; 53 | } 54 | } 55 | else 56 | { 57 | break; 58 | } 59 | } 60 | } 61 | 62 | void Timer::start(std::function cb, uint64_t timeout, uint64_t repeat) 63 | { 64 | m_cb = cb; 65 | m_time = timeout + XTime::iclock(); 66 | m_repeat = repeat; 67 | Heap::CHeap::heap_insert(&gRootHeap, (struct Heap::heap_node *)m_node, (Heap::heap_compare_fn)compare_fn); 68 | } 69 | void Timer::stop() 70 | { 71 | if (m_time == 0) 72 | return; 73 | 74 | m_time = 0; 75 | Heap::CHeap::heap_remove(&gRootHeap, (struct Heap::heap_node *)m_node, (Heap::heap_compare_fn)compare_fn); 76 | } 77 | 78 | int Timer::compare_fn(const struct Heap::heap_node* a, const struct Heap::heap_node* b) 79 | { 80 | TimerNode * node_a = (TimerNode *)a; 81 | TimerNode * node_b = (TimerNode *)b; 82 | 83 | Timer * timer_a = (Timer *)node_a->user; 84 | Timer * timer_b = (Timer *)node_b->user; 85 | 86 | if (timer_a->m_time < timer_b->m_time) 87 | return 1; 88 | else if (timer_b->m_time < timer_a->m_time) 89 | return 0; 90 | 91 | /* 92 | if (a->start_id < b->start_id) 93 | return 1; 94 | if (b->start_id < a->start_id) 95 | return 0; 96 | */ 97 | 98 | return 0; 99 | } -------------------------------------------------------------------------------- /src/common/Timer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Heap.h" 4 | #include "BaseType.h" 5 | #include 6 | 7 | class Timer 8 | { 9 | struct TimerNode 10 | { 11 | struct Heap::heap_node m_node; 12 | void * user = NULL; 13 | }; 14 | 15 | //typedef void(*close_timer_cb)(TimerNode* timernode); 16 | 17 | public: 18 | Timer(); 19 | ~Timer(); 20 | 21 | static void init(); 22 | static void update(); 23 | 24 | void start(std::function cb, uint64_t timeout, uint64_t repeat = 0); 25 | void stop(); 26 | 27 | private: 28 | static int compare_fn(const struct Heap::heap_node* a, const struct Heap::heap_node* b); 29 | 30 | private: 31 | TimerNode * m_node = NULL; 32 | uint32 m_time = 0; 33 | uint32 m_repeat = 0; 34 | std::function m_cb; 35 | 36 | static struct Heap::heap gRootHeap; 37 | }; 38 | 39 | -------------------------------------------------------------------------------- /src/common/Tools.cpp: -------------------------------------------------------------------------------- 1 | #include "Tools.h" 2 | #include 3 | #include 4 | #include "Define.h" 5 | #include 6 | 7 | void Tools::encrypt(char * buf, char * key) 8 | { 9 | char * p = buf; 10 | char * pKey = key; 11 | 12 | unsigned int bufLen = strlen(buf); 13 | unsigned int keyLen = strlen(pKey); 14 | 15 | for (unsigned int i = 0; i < bufLen; i++) 16 | { 17 | *p ^= pKey[i % keyLen]; 18 | p++; 19 | } 20 | } 21 | 22 | std::string Tools::format(const char * format, ...) 23 | { 24 | va_list vl; 25 | va_start(vl, format); 26 | 27 | int len = vsnprintf(NULL, 0, format, vl); 28 | std::string s("", len + 1); 29 | char * buff = (char *)s.data(); 30 | vsprintf(buff, format, vl); 31 | 32 | va_end(vl); 33 | 34 | return s; 35 | } 36 | 37 | 38 | void Tools::sleep(int ms) 39 | { 40 | #if defined(SYSTEM_WIN) 41 | Sleep(ms); 42 | #else 43 | ::usleep(ms * 1000); 44 | #endif 45 | } 46 | 47 | unsigned long Tools::getCurrentThreadID() 48 | { 49 | #if defined(SYSTEM_WIN) 50 | return GetCurrentThreadId(); 51 | #else 52 | return pthread_self(); 53 | #endif 54 | } 55 | 56 | 57 | int Tools::binarySearch(int arr[], int len, int findX) 58 | { 59 | int left = 0; int right = len - 1; 60 | while (left <= right) { 61 | int middle = (left + right) / 2; 62 | if (findX == arr[middle]) return middle; 63 | if (findX > arr[middle])left = middle + 1; 64 | else right = middle - 1; 65 | } 66 | 67 | return -1; 68 | } 69 | 70 | #ifdef SYSTEM_LINUX 71 | 72 | #include 73 | 74 | static int iconv_convert(const char *src_str, size_t src_len, char *dst_str, size_t dst_len, const char * from_charset = "gbk", const char * to_charset = "utf8") 75 | { 76 | iconv_t cd; 77 | char **pin = (char **)&src_str; 78 | char **pout = &dst_str; 79 | 80 | cd = iconv_open(to_charset, from_charset); 81 | if (cd == 0) 82 | return -1; 83 | memset(dst_str, 0, dst_len); 84 | if (iconv(cd, pin, &src_len, pout, &dst_len) == -1) 85 | return -1; 86 | iconv_close(cd); 87 | 88 | return 0; 89 | } 90 | 91 | #endif 92 | 93 | std::string Tools::gbkToUtf8(const char *src_str) 94 | { 95 | std::string strTemp; 96 | #ifdef SYSTEM_WIN 97 | int len = MultiByteToWideChar(CP_ACP, 0, src_str, -1, NULL, 0); 98 | wchar_t* wstr = new wchar_t[len + 1]; 99 | memset(wstr, 0, len + 1); 100 | MultiByteToWideChar(CP_ACP, 0, src_str, -1, wstr, len); 101 | len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL); 102 | char* str = new char[len + 1]; 103 | memset(str, 0, len + 1); 104 | WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, len, NULL, NULL); 105 | strTemp = str; 106 | if (wstr) delete[] wstr; 107 | if (str) delete[] str; 108 | 109 | #else 110 | char dst_gbk[1024] = { 0 }; 111 | iconv_convert(src_str, strlen(src_str), dst_gbk, sizeof(dst_gbk), "gbk", "utf8"); 112 | strTemp = dst_gbk; 113 | 114 | #endif 115 | 116 | return strTemp; 117 | } 118 | 119 | std::string Tools::utf8ToGbk(const char *src_str) 120 | { 121 | std::string strTemp; 122 | #ifdef SYSTEM_WIN 123 | int len = MultiByteToWideChar(CP_UTF8, 0, src_str, -1, NULL, 0); 124 | wchar_t* wszGBK = new wchar_t[len + 1]; 125 | memset(wszGBK, 0, len * 2 + 2); 126 | MultiByteToWideChar(CP_UTF8, 0, src_str, -1, wszGBK, len); 127 | len = WideCharToMultiByte(CP_ACP, 0, wszGBK, -1, NULL, 0, NULL, NULL); 128 | char* szGBK = new char[len + 1]; 129 | memset(szGBK, 0, len + 1); 130 | WideCharToMultiByte(CP_ACP, 0, wszGBK, -1, szGBK, len, NULL, NULL); 131 | strTemp = szGBK; 132 | if (wszGBK) delete[] wszGBK; 133 | if (szGBK) delete[] szGBK; 134 | 135 | #else 136 | char dst_gbk[1024] = { 0 }; 137 | iconv_convert(src_str, strlen(src_str), dst_gbk, sizeof(dst_gbk), "utf8", "gbk"); 138 | strTemp = dst_gbk; 139 | 140 | #endif 141 | return strTemp; 142 | } 143 | 144 | int Tools::charCount(char * pStr, char c) 145 | { 146 | int nCount = 0; 147 | 148 | char* pTemp = pStr; 149 | while (*pTemp != '\0') 150 | { 151 | if (*pTemp == c) 152 | { 153 | nCount += 1; 154 | } 155 | 156 | pTemp += 1; 157 | } 158 | 159 | return nCount; 160 | } 161 | 162 | void Tools::srand(unsigned int t) 163 | { 164 | ::srand(t); 165 | } 166 | 167 | int Tools::random(int begin, int end) 168 | { 169 | int value; 170 | #ifdef SYSTEM_WIN 171 | value = rand() % (end - begin + 1); 172 | #else 173 | value = ::random() % (end - begin + 1); 174 | #endif 175 | 176 | return value + begin; 177 | } -------------------------------------------------------------------------------- /src/common/Tools.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | class Tools 5 | { 6 | public: 7 | static void encrypt(char * buf, char * key); 8 | static std::string format(const char * format, ...); 9 | static void sleep(int ms); 10 | static unsigned long getCurrentThreadID(); 11 | static int binarySearch(int arr[], int len, int findX); 12 | static std::string gbkToUtf8(const char *src_str); 13 | static std::string utf8ToGbk(const char *src_str); 14 | static int charCount(char * pStr, char c); 15 | static void srand(unsigned int); 16 | static int random(int begin, int end); 17 | }; 18 | 19 | -------------------------------------------------------------------------------- /src/common/UTimer.h: -------------------------------------------------------------------------------- 1 | #ifndef UV_TIMER_H 2 | #define UV_TIMER_H 3 | 4 | #include "EventLoop.h" 5 | #include 6 | 7 | class UTimer 8 | { 9 | public: 10 | UTimer() 11 | { 12 | m_timer = (uv_timer_t *)malloc(sizeof(uv_timer_t)); 13 | m_timer->data = this; 14 | uv_timer_init(EventLoop::Instance()->getLoop(), m_timer); 15 | } 16 | 17 | ~UTimer() 18 | { 19 | uv_close((uv_handle_t *)m_timer, [](uv_handle_t* handle){ 20 | free(handle); 21 | }); 22 | } 23 | 24 | void start(std::function cb, uint64_t timeout, uint64_t repeat = 0) 25 | { 26 | m_cb = cb; 27 | uv_timer_start(m_timer, timer_cb, timeout, repeat); 28 | } 29 | 30 | void stop() 31 | { 32 | uv_timer_stop(m_timer); 33 | } 34 | 35 | private: 36 | 37 | static void timer_cb(uv_timer_t* handle) 38 | { 39 | UTimer * timer = (UTimer *)handle->data; 40 | timer->m_cb(); 41 | } 42 | 43 | private: 44 | uv_timer_t * m_timer; 45 | std::function m_cb; 46 | 47 | /* 48 | uv_timer_t m_timer; 49 | (This is the wrong approach) 50 | 51 | class Test 52 | { 53 | void go() 54 | { 55 | timer.start([&]() 56 | { 57 | delete this; // m_timer Object is released 58 | }1000); 59 | } 60 | 61 | Timer timer; 62 | } 63 | */ 64 | }; 65 | 66 | #endif -------------------------------------------------------------------------------- /src/common/XAssert.cpp: -------------------------------------------------------------------------------- 1 | #include "XAssert.h" 2 | #include 3 | #include 4 | #include 5 | 6 | void IAssert(char const* file, int line, char const* function, char const* message, char const* format, ...) 7 | { 8 | va_list args; 9 | va_start(args, format); 10 | 11 | fprintf(stderr, "\n%s:%i in %s ASSERTION FAILED:\n %s ", file, line, function, message); 12 | vfprintf(stderr, format, args); 13 | fprintf(stderr, "\n"); 14 | fflush(stderr); 15 | 16 | va_end(args); 17 | *((volatile int*)NULL) = 0; 18 | exit(1); 19 | } -------------------------------------------------------------------------------- /src/common/XAssert.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void IAssert(char const* file, int line, char const* function, char const* message, char const* format, ...); 4 | 5 | #define XAssert(cond, ...) do { if (!(cond)) IAssert(__FILE__, __LINE__, __FUNCTION__, #cond, ##__VA_ARGS__); } while(0) -------------------------------------------------------------------------------- /src/common/XFile.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/lua-server/6008c764295d822f82a89ed8d579559bbcf1adfa/src/common/XFile.cpp -------------------------------------------------------------------------------- /src/common/XFile.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | class XFile 7 | { 8 | public: 9 | XFile(); 10 | ~XFile(); 11 | 12 | static bool isExist(const char * dir); 13 | static int mkdir(const char * dir); 14 | // Delete empty directory 15 | static int rmdir(const char * dir); 16 | static int createDirectory(const char * dir); 17 | static int writeFile(const char * file, const char * content); 18 | static int readFile(const char * file, std::string & str); 19 | // Read by line 20 | static int readFile(const char *file, std::vector & vec_str); 21 | static int remove(const char * file); 22 | // Walk through all the files in the directory 23 | static int listFiles(const char * dir, std::vector & vec_file); 24 | }; 25 | 26 | -------------------------------------------------------------------------------- /src/common/XLog.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/lua-server/6008c764295d822f82a89ed8d579559bbcf1adfa/src/common/XLog.cpp -------------------------------------------------------------------------------- /src/common/XLog.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "SpinLock.h" 6 | 7 | #define LOG_MAX_SIZE 1073741824 8 | 9 | enum LogLevel 10 | { 11 | LL_INFO, 12 | LL_WARNING, 13 | LL_ERROR, 14 | }; 15 | 16 | class XLog 17 | { 18 | class AutoLock; 19 | public: 20 | XLog(); 21 | ~XLog(); 22 | 23 | void init(const char * rootdir, const char * childdir); 24 | void setMaxsize(unsigned int size){ maxsize = size; } 25 | void writeLog(int level, const char * filename, const char * func, int line, const char * format, ...); 26 | private: 27 | void writeFile(int level, const char * filename, const char * func, int line, const char * logstr); 28 | void closefile(); 29 | void print(int level, std::string& str); 30 | private: 31 | FILE * file; 32 | std::string logdir; 33 | std::string childdir; 34 | std::string currdir; 35 | int writeday; 36 | unsigned int maxsize; 37 | unsigned int currsize; 38 | SpinLock _lock; 39 | }; 40 | 41 | class LogStream 42 | { 43 | public: 44 | LogStream(XLog * log, int level, const char * filename, const char * func, int line); 45 | ~LogStream(); 46 | 47 | template 48 | LogStream & operator << (T value) 49 | { 50 | stream << value; 51 | return *this; 52 | } 53 | private: 54 | std::stringstream stream; 55 | XLog * _log; 56 | int _level; 57 | std::string _filename; 58 | std::string _func; 59 | int _line; 60 | }; 61 | 62 | extern XLog commonlog; 63 | 64 | #define INIT_LOG(rootdir, childdir) commonlog.init(rootdir, childdir) 65 | 66 | #define INFO_LOG(...) commonlog.writeLog(LL_INFO , __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__) 67 | #define WARNING_LOG(...) commonlog.writeLog(LL_WARNING, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__) 68 | #define ERROR_LOG(...) commonlog.writeLog(LL_ERROR, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__) 69 | #define XLOG(level) LogStream(&commonlog, level, __FILE__, __FUNCTION__, __LINE__) 70 | #define XLOG_IF(condition, level) if(condition)\ 71 | LogStream(&commonlog, level, __FILE__, __FUNCTION__, __LINE__) 72 | 73 | -------------------------------------------------------------------------------- /src/common/XTime.cpp: -------------------------------------------------------------------------------- 1 | #include "XTime.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | #ifdef SYSTEM_WIN 9 | 10 | int gettimeofday(struct timeval *tp, void *tzp) 11 | { 12 | time_t clock; 13 | struct tm tm; 14 | SYSTEMTIME wtm; 15 | GetLocalTime(&wtm); 16 | tm.tm_year = wtm.wYear - 1900; 17 | tm.tm_mon = wtm.wMonth - 1; 18 | tm.tm_mday = wtm.wDay; 19 | tm.tm_hour = wtm.wHour; 20 | tm.tm_min = wtm.wMinute; 21 | tm.tm_sec = wtm.wSecond; 22 | tm.tm_isdst = -1; 23 | clock = mktime(&tm); 24 | tp->tv_sec = static_cast(clock); 25 | tp->tv_usec = wtm.wMilliseconds * 1000; 26 | return (0); 27 | } 28 | #endif // PLATFORM_WINDOWS 29 | 30 | 31 | bool XTime::isLeapYear(int year) 32 | { 33 | return (year % 4 == 0 && ((year % 400 == 0) || (year % 100 != 0))); 34 | } 35 | 36 | int XTime::yearMonthDays(int year, int month) 37 | { 38 | switch (month) 39 | { 40 | case 1: 41 | case 3: 42 | case 5: 43 | case 7: 44 | case 8: 45 | case 10: 46 | case 12: 47 | return 31; 48 | case 4: 49 | case 6: 50 | case 9: 51 | case 11: 52 | return 30; 53 | case 2: 54 | //Need to consider a leap year in February 55 | return isLeapYear(year) ? 29 : 28; 56 | default: 57 | return 0; 58 | } 59 | } 60 | 61 | 62 | const struct tm * XTime::getTMStruct() 63 | { 64 | time_t _currt = time(NULL); 65 | return std::localtime(&_currt); 66 | } 67 | 68 | std::string XTime::format(const char * fmt) 69 | { 70 | char buf[256] = { 0 }; 71 | if (0 == strftime(buf, 63, fmt, getTMStruct())) { 72 | buf[0] = '\0'; 73 | } 74 | return std::string(buf); 75 | } 76 | 77 | time_t XTime::getTime(struct tm * tm_) 78 | { 79 | return std::mktime(tm_); 80 | } 81 | 82 | void XTime::getTimeval(struct timeval * tp) 83 | { 84 | gettimeofday(tp, NULL); 85 | } 86 | 87 | // msec 88 | int64 XTime::milliStamp() 89 | { 90 | struct timeval tv; 91 | getTimeval(&tv); 92 | return tv.tv_sec * 1000 + tv.tv_usec / 1000; 93 | } 94 | 95 | // usec 96 | int64 XTime::microStamp() 97 | { 98 | struct timeval tv; 99 | getTimeval(&tv); 100 | return tv.tv_sec * 1000000 + tv.tv_usec; 101 | } 102 | 103 | // sec 104 | time_t XTime::stamp() 105 | { 106 | struct timeval tv; 107 | getTimeval(&tv); 108 | return tv.tv_sec; 109 | } 110 | 111 | uint32 XTime::iclock() 112 | { 113 | return (uint32)((double)std::clock() / CLOCKS_PER_SEC * 1000); 114 | } -------------------------------------------------------------------------------- /src/common/XTime.h: -------------------------------------------------------------------------------- 1 |  2 | #ifndef XTIME_H 3 | #define XTIME_H 4 | 5 | #include 6 | #include 7 | #include "Platform.h" 8 | #include "BaseType.h" 9 | 10 | #ifdef SYSTEM_WIN 11 | #include 12 | #else 13 | #include 14 | #endif // PLATFORM_WINDOWS 15 | 16 | 17 | class XTime 18 | { 19 | public: 20 | // leap year 21 | static bool isLeapYear(int year); 22 | static int yearMonthDays(int year, int month); 23 | 24 | static const struct tm * getTMStruct(); 25 | static time_t getTime(struct tm * tm_); 26 | static std::string format(const char * fmt = "%Y-%m-%d %H:%M:%S"); 27 | 28 | static void getTimeval(struct timeval * tp); 29 | // msec 30 | static int64 milliStamp(); 31 | // usec 32 | static int64 microStamp(); 33 | // sec 34 | static time_t stamp(); 35 | 36 | static uint32 iclock(); 37 | }; 38 | 39 | #endif -------------------------------------------------------------------------------- /src/common/base64.cpp: -------------------------------------------------------------------------------- 1 | #include "base64.h" 2 | #include 3 | 4 | static const std::string base64_chars = 5 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 6 | "abcdefghijklmnopqrstuvwxyz" 7 | "0123456789+/"; 8 | 9 | 10 | static inline bool is_base64(unsigned char c) { 11 | return (isalnum(c) || (c == '+') || (c == '/')); 12 | } 13 | 14 | std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) { 15 | std::string ret; 16 | int i = 0; 17 | int j = 0; 18 | unsigned char char_array_3[3]; 19 | unsigned char char_array_4[4]; 20 | 21 | while (in_len--) { 22 | char_array_3[i++] = *(bytes_to_encode++); 23 | if (i == 3) { 24 | char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; 25 | char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); 26 | char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); 27 | char_array_4[3] = char_array_3[2] & 0x3f; 28 | 29 | for(i = 0; (i <4) ; i++) 30 | ret += base64_chars[char_array_4[i]]; 31 | i = 0; 32 | } 33 | } 34 | 35 | if (i) 36 | { 37 | for(j = i; j < 3; j++) 38 | char_array_3[j] = '\0'; 39 | 40 | char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; 41 | char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); 42 | char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); 43 | char_array_4[3] = char_array_3[2] & 0x3f; 44 | 45 | for (j = 0; (j < i + 1); j++) 46 | ret += base64_chars[char_array_4[j]]; 47 | 48 | while((i++ < 3)) 49 | ret += '='; 50 | 51 | } 52 | 53 | return ret; 54 | 55 | } 56 | 57 | std::string base64_decode(std::string const& encoded_string) { 58 | size_t in_len = encoded_string.size(); 59 | int i = 0; 60 | int j = 0; 61 | int in_ = 0; 62 | unsigned char char_array_4[4], char_array_3[3]; 63 | std::string ret; 64 | 65 | while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) { 66 | char_array_4[i++] = encoded_string[in_]; in_++; 67 | if (i ==4) { 68 | for (i = 0; i <4; i++) 69 | char_array_4[i] = base64_chars.find(char_array_4[i]); 70 | 71 | char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); 72 | char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); 73 | char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; 74 | 75 | for (i = 0; (i < 3); i++) 76 | ret += char_array_3[i]; 77 | i = 0; 78 | } 79 | } 80 | 81 | if (i) { 82 | for (j = i; j <4; j++) 83 | char_array_4[j] = 0; 84 | 85 | for (j = 0; j <4; j++) 86 | char_array_4[j] = base64_chars.find(char_array_4[j]); 87 | 88 | char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); 89 | char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); 90 | char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; 91 | 92 | for (j = 0; (j < i - 1); j++) ret += char_array_3[j]; 93 | } 94 | 95 | return ret; 96 | } 97 | -------------------------------------------------------------------------------- /src/common/base64.h: -------------------------------------------------------------------------------- 1 | #ifndef _BASE64_H_ 2 | #define _BASE64_H_ 3 | #include 4 | 5 | std::string base64_encode(unsigned char const* , unsigned int len); 6 | std::string base64_decode(std::string const& s); 7 | #endif 8 | -------------------------------------------------------------------------------- /src/common/sha1.h: -------------------------------------------------------------------------------- 1 | #ifndef _SHA1_H_ 2 | #define _SHA1_H_ 3 | 4 | class SHA1 5 | { 6 | 7 | public: 8 | 9 | SHA1(); 10 | virtual ~SHA1(); 11 | 12 | /* 13 | * Re-initialize the class 14 | */ 15 | void Reset(); 16 | 17 | /* 18 | * Returns the message digest 19 | */ 20 | bool Result(unsigned *message_digest_array); 21 | 22 | /* 23 | * Provide input to SHA1 24 | */ 25 | void Input(const unsigned char *message_array, 26 | unsigned length); 27 | void Input(const char *message_array, 28 | unsigned length); 29 | void Input(unsigned char message_element); 30 | void Input(char message_element); 31 | SHA1& operator<<(const char *message_array); 32 | SHA1& operator<<(const unsigned char *message_array); 33 | SHA1& operator<<(const char message_element); 34 | SHA1& operator<<(const unsigned char message_element); 35 | 36 | private: 37 | 38 | /* 39 | * Process the next 512 bits of the message 40 | */ 41 | void ProcessMessageBlock(); 42 | 43 | /* 44 | * Pads the current message block to 512 bits 45 | */ 46 | void PadMessage(); 47 | 48 | /* 49 | * Performs a circular left shift operation 50 | */ 51 | inline unsigned CircularShift(int bits, unsigned word); 52 | 53 | unsigned H[5]; // Message digest buffers 54 | 55 | unsigned Length_Low; // Message length in bits 56 | unsigned Length_High; // Message length in bits 57 | 58 | unsigned char Message_Block[64]; // 512-bit message blocks 59 | int Message_Block_Index; // Index into message block array 60 | 61 | bool Computed; // Is the digest computed? 62 | bool Corrupted; // Is the message digest corruped? 63 | 64 | }; 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /src/db/DBResult.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | class DBResult 3 | { 4 | public: 5 | DBResult() {}; 6 | virtual ~DBResult() {}; 7 | virtual bool isEmpty() = 0; 8 | virtual bool fetch() = 0; 9 | virtual uint32 getRowCount() = 0; 10 | virtual uint32 getFieldsCount() = 0; 11 | 12 | virtual const char * getData(int & len) = 0; 13 | virtual const char * getData() = 0; 14 | 15 | }; 16 | 17 | -------------------------------------------------------------------------------- /src/db/DBThreadPool.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "BaseType.h" 4 | #include "mysql.h" 5 | #include "DB_Interface_mysql.h" 6 | #include "hiredis.h" 7 | #include "DB_Interface_redis.h" 8 | #include "SqlPrepare.h" 9 | #include 10 | #include "DBThreadPool.h" 11 | 12 | 13 | DBTask::DBTask() 14 | { 15 | 16 | } 17 | 18 | DBTask::~DBTask() 19 | { 20 | } 21 | 22 | void DBTask::dbi(DB_Interface * dbi) 23 | { 24 | _dbi = dbi; 25 | } 26 | 27 | //------------------------------------------------ 28 | 29 | DBSqlTask::DBSqlTask(std::shared_ptr pre, std::shared_ptr result): 30 | _pre(pre), _result(result) 31 | { 32 | 33 | } 34 | 35 | DBSqlTask::~DBSqlTask() 36 | { 37 | 38 | } 39 | 40 | void DBSqlTask::process() 41 | { 42 | _ret = _pre->prepare(static_cast(_dbi)->mysql()); 43 | DBResult* result = (DBResult*)(_result.get()); 44 | if (_ret >= 0) _ret = _pre->execute(result); 45 | if (_ret < 0) 46 | { 47 | _errno = _dbi->getErrno(); 48 | _error = _dbi->getError(); 49 | } 50 | } 51 | 52 | void DBSqlTask::complete() 53 | { 54 | const char* str = NULL; 55 | if (_ret < 0) str = _error.c_str(); 56 | if (backfunc) 57 | { 58 | backfunc(_errno, str, _result); 59 | backfunc = nullptr; 60 | } 61 | } 62 | 63 | //------------------------------------------------ 64 | 65 | DBRedisTask::DBRedisTask(std::shared_ptr command, std::shared_ptr result) 66 | { 67 | _command = command; 68 | _result = result; 69 | } 70 | 71 | DBRedisTask::~DBRedisTask() 72 | { 73 | 74 | } 75 | 76 | void DBRedisTask::process() 77 | { 78 | DBResult* result = (DBResult*)(_result.get()); 79 | _ret = static_cast(_dbi)->execute(_command.get(), result); 80 | if (_ret < 0) 81 | { 82 | _errno = _dbi->getErrno(); 83 | _error = _dbi->getError(); 84 | } 85 | } 86 | 87 | void DBRedisTask::complete() 88 | { 89 | const char* str = NULL; 90 | if (_ret < 0) str = _error.c_str(); 91 | if (backfunc) 92 | { 93 | backfunc(_errno, str, _result); 94 | backfunc = nullptr; 95 | } 96 | } 97 | 98 | //------------------------------------------------ 99 | 100 | DBThread::DBThread(ThreadPool * pool): 101 | CThread(pool) 102 | { 103 | m_db = NULL; 104 | } 105 | 106 | DBThread::~DBThread() 107 | { 108 | 109 | } 110 | 111 | void DBThread::onStart() 112 | { 113 | DBThreadPool * pool = static_cast(_pool); 114 | 115 | const DBConfig * config = pool->getConfig(); 116 | if (config->device == "mysql") 117 | { 118 | m_db = new DBInterfaceMysql(config->ip.c_str(), config->dbname.c_str(), config->user.c_str(), config->pswd.c_str(), config->port); 119 | } 120 | else 121 | { 122 | m_db = new DBInterfaceRedis(config->ip.c_str(), config->port); 123 | } 124 | 125 | m_db->connect(); 126 | } 127 | 128 | void DBThread::onEnd() 129 | { 130 | if (m_db) 131 | { 132 | delete m_db; 133 | } 134 | } 135 | 136 | void DBThread::run(TaskPtr task) 137 | { 138 | static_cast(task.get())->dbi(m_db); 139 | CThread::run(task); 140 | } 141 | 142 | DBThreadPool::DBThreadPool(DBConfig config) 143 | { 144 | m_config = config; 145 | } 146 | 147 | DBThreadPool::~DBThreadPool() 148 | { 149 | 150 | } 151 | 152 | CThread* DBThreadPool::createThread() 153 | { 154 | return new DBThread(this); 155 | } 156 | 157 | void DBThreadPool::deleteThread(CThread * t) 158 | { 159 | delete t; 160 | } 161 | 162 | void DBThreadPool::completeTask(TaskPtr task) 163 | { 164 | } 165 | 166 | const DBConfig * DBThreadPool::getConfig() 167 | { 168 | return &m_config; 169 | } 170 | -------------------------------------------------------------------------------- /src/db/DBThreadPool.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /************************************************************************ 4 | * @file DBThreadPool.h 5 | * @brief mysql thread pool 6 | * @author jiangwang 7 | * @data 2020-3-25 8 | * @version 0.1 9 | ************************************************************************/ 10 | 11 | #include "ThreadPool.h" 12 | using namespace Thread; 13 | 14 | struct DBConfig 15 | { 16 | std::string device = "mysql"; // mysql or redis 17 | std::string ip = "local"; 18 | unsigned int port = 3306; 19 | std::string dbname; 20 | std::string user = "root"; 21 | std::string pswd; 22 | }; 23 | 24 | class DB_Interface; 25 | class RedisCommand; 26 | class RedisResult; 27 | class SqlPrepare; 28 | class SqlResultSet; 29 | 30 | class DBTask : public Task 31 | { 32 | public: 33 | DBTask(); 34 | ~DBTask(); 35 | 36 | void dbi(DB_Interface * dbi); 37 | 38 | protected: 39 | DB_Interface * _dbi; 40 | int _ret; 41 | int32 _errno = 0; 42 | std::string _error; 43 | }; 44 | 45 | class DBSqlTask : public DBTask 46 | { 47 | public: 48 | DBSqlTask(std::shared_ptr pre, std::shared_ptr result); 49 | ~DBSqlTask(); 50 | 51 | virtual void process(); 52 | virtual void complete(); 53 | public: 54 | std::function)> backfunc; 55 | private: 56 | std::shared_ptr _pre; 57 | std::shared_ptr _result; 58 | }; 59 | 60 | class DBRedisTask : public DBTask 61 | { 62 | public: 63 | DBRedisTask(std::shared_ptr command, std::shared_ptr result); 64 | ~DBRedisTask(); 65 | 66 | virtual void process(); 67 | virtual void complete(); 68 | public: 69 | std::function)> backfunc; 70 | private: 71 | std::shared_ptr _command; 72 | std::shared_ptr _result; 73 | }; 74 | 75 | class DBThread : public CThread 76 | { 77 | public: 78 | DBThread(ThreadPool * pool); 79 | ~DBThread(); 80 | virtual void onStart(); 81 | virtual void onEnd(); 82 | 83 | virtual void run(TaskPtr task); 84 | 85 | private: 86 | DB_Interface * m_db; 87 | }; 88 | 89 | class DBThreadPool : public ThreadPool 90 | { 91 | public: 92 | DBThreadPool(DBConfig config); 93 | ~DBThreadPool(); 94 | virtual CThread* createThread(); 95 | virtual void deleteThread(CThread * t); 96 | virtual void completeTask(TaskPtr task); 97 | 98 | const DBConfig * getConfig(); 99 | 100 | private: 101 | DBConfig m_config; 102 | }; 103 | 104 | -------------------------------------------------------------------------------- /src/db/DB_Interface.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "DB_Interface.h" 3 | 4 | DB_Interface::DB_Interface(const char * ip, unsigned int port): 5 | m_ip(ip), 6 | m_port(port) 7 | { 8 | 9 | } 10 | 11 | DB_Interface::~DB_Interface() 12 | { 13 | 14 | } -------------------------------------------------------------------------------- /src/db/DB_Interface.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /************************************************************************ 4 | * @file DB_Interface.h 5 | * @brief db interface 6 | * @author jiangwang 7 | * @data 2020-3-31 8 | * @version 0.1 9 | ************************************************************************/ 10 | 11 | class DBResult; 12 | class DB_Interface 13 | { 14 | public: 15 | DB_Interface(const char * ip, unsigned int port); 16 | virtual ~DB_Interface(); 17 | 18 | public: 19 | virtual bool connect() = 0; 20 | virtual bool detach() = 0; 21 | virtual int execute(DBResult * result, const char * cmd, int len = 0) = 0; 22 | virtual const char * getError() = 0; 23 | virtual int getErrno() = 0; 24 | virtual bool ping() = 0; 25 | protected: 26 | std::string m_ip; 27 | unsigned int m_port; 28 | }; -------------------------------------------------------------------------------- /src/db/DB_Interface_mysql.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "mysql.h" 5 | #include "DB_Interface_mysql.h" 6 | #include "XLog.h" 7 | #include "MysqlResult.h" 8 | #include "SqlPrepare.h" 9 | 10 | DBInterfaceMysql::DBInterfaceMysql(const char * host, const char * dbname, const char * user, const char * pswd, unsigned int port): 11 | m_dbname(dbname), 12 | m_user(user), 13 | m_pswd(pswd), 14 | DB_Interface(host, port) 15 | { 16 | if (!(mMysql_ = mysql_init(nullptr))) 17 | { 18 | ERROR_LOG("mysql init error!!"); 19 | } 20 | } 21 | 22 | DBInterfaceMysql::~DBInterfaceMysql() 23 | { 24 | detach(); 25 | } 26 | 27 | bool DBInterfaceMysql::connect() 28 | { 29 | if (mysql_options(mMysql_, MYSQL_SET_CHARSET_NAME, "utf8")) 30 | { 31 | ERROR_LOG("mysql_options(MYSQL_SET_CHARSET_NAME) Errno:%d failed: %s", getErrno(), getError()); 32 | return false; 33 | } 34 | 35 | my_bool reconnect = 1; 36 | if (mysql_options(mMysql_, MYSQL_OPT_RECONNECT, &reconnect)) 37 | { 38 | ERROR_LOG("mysql_options(MYSQL_OPT_RECONNECT) Errno:%d failed: %s", getErrno(), getError()); 39 | return false; 40 | } 41 | 42 | if (!mysql_real_connect(mMysql_, m_ip.c_str(), m_user.c_str(), m_pswd.c_str(), m_dbname.c_str(), m_port, NULL, 0)) 43 | { 44 | ERROR_LOG("mysql_real_connect Errno:%d error: %s", getErrno(), getError()); 45 | return false; 46 | } 47 | 48 | return true; 49 | } 50 | 51 | bool DBInterfaceMysql::detach() 52 | { 53 | ::mysql_close(mMysql_); 54 | return true; 55 | } 56 | 57 | int DBInterfaceMysql::execute(DBResult * result, const char * cmd, int len) 58 | { 59 | int nResult = mysql_real_query(mMysql_, cmd, (len <= 0 ? strlen(cmd) : len)); 60 | if (nResult != 0) 61 | { 62 | ERROR_LOG("mysql_real_query Errno:%d error: %s", getErrno(), getError()); 63 | return -1; 64 | } 65 | 66 | MYSQL_RES * pResult = mysql_store_result(mMysql_); 67 | 68 | /* 69 | if (pResult) 70 | { 71 | uint32 nrows = (uint32)mysql_num_rows(pResult); 72 | uint32 nfields = (uint32)mysql_num_fields(pResult); 73 | 74 | MYSQL_ROW arow; 75 | while ((arow = mysql_fetch_row(pResult)) != NULL) 76 | { 77 | unsigned long *lengths = mysql_fetch_lengths(pResult); 78 | 79 | for (uint32 i = 0; i < nfields; ++i) 80 | { 81 | // arow[i], lengths[i] 82 | } 83 | } 84 | 85 | //mysql_free_result(pResult); 86 | } 87 | else 88 | { 89 | 90 | } 91 | */ 92 | 93 | static_cast(result)->setResult(pResult); 94 | 95 | return 0; 96 | } 97 | 98 | const char * DBInterfaceMysql::getError() 99 | { 100 | return mysql_error(mMysql_); 101 | } 102 | 103 | int DBInterfaceMysql::getErrno() 104 | { 105 | return mysql_errno(mMysql_); 106 | } 107 | 108 | bool DBInterfaceMysql::ping() { 109 | return mysql_ping(mMysql_) == 0; 110 | } 111 | 112 | MYSQL * DBInterfaceMysql::mysql() { 113 | return mMysql_; 114 | } 115 | 116 | 117 | namespace MySQL 118 | { 119 | int threadSafe() 120 | { 121 | return mysql_thread_safe(); 122 | } 123 | void libraryInit() 124 | { 125 | mysql_library_init(-1, nullptr, nullptr); 126 | } 127 | void libraryEnd() 128 | { 129 | mysql_library_end(); 130 | } 131 | char const* getLibraryVersion() 132 | { 133 | return MYSQL_SERVER_VERSION; 134 | } 135 | }; -------------------------------------------------------------------------------- /src/db/DB_Interface_mysql.h: -------------------------------------------------------------------------------- 1 | #ifndef DB_INTERFACE_MYSQL_H 2 | #define DB_INTERFACE_MYSQL_H 3 | 4 | #include "DB_Interface.h" 5 | 6 | class MysqlResult; 7 | class SqlPrepare; 8 | class DBInterfaceMysql : public DB_Interface 9 | { 10 | public: 11 | DBInterfaceMysql(const char * host, const char * dbname, const char * user, const char * pswd = "", unsigned int port = 3306); 12 | ~DBInterfaceMysql(); 13 | 14 | virtual bool connect(); 15 | virtual bool detach(); 16 | virtual int execute(DBResult * result, const char * cmd, int len = 0); 17 | 18 | virtual const char * getError(); 19 | virtual int getErrno(); 20 | virtual bool ping(); 21 | 22 | MYSQL * mysql(); 23 | 24 | protected: 25 | 26 | std::string m_dbname; 27 | std::string m_user; 28 | std::string m_pswd; 29 | //MYSQL mMysql_; mMysql_字段如果不放在最后的位置的话,当BDInterfaceMysql构造时调用mysql_init(&mMysql_)的时候,会破坏mMysql_字段下面的其他字段的内存,从而造成段错误 30 | // 目前将MYSQL字段放到了最后的位置,不知道还会有其他的隐患没有。后来知道了,析构的时候会报段错误。 31 | //后来改成MYSQL * mMysql_;这种指针的形式了,由mysql的库在堆上分配内存,上面出现的段错误就不会再发生了。 32 | MYSQL * mMysql_; 33 | }; 34 | 35 | namespace MySQL 36 | { 37 | int threadSafe(); 38 | void libraryInit(); 39 | void libraryEnd(); 40 | char const* getLibraryVersion(); 41 | }; 42 | 43 | #endif -------------------------------------------------------------------------------- /src/db/DB_Interface_redis.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "hiredis.h" 5 | #include "DB_Interface_redis.h" 6 | #include "XLog.h" 7 | #include "RedisResult.h" 8 | #include 9 | #include "RedisCommand.h" 10 | 11 | DBInterfaceRedis::DBInterfaceRedis(const char * ip, unsigned int port): 12 | DB_Interface(ip, port) 13 | { 14 | m_context = NULL; 15 | } 16 | 17 | DBInterfaceRedis::~DBInterfaceRedis() 18 | { 19 | detach(); 20 | } 21 | 22 | bool DBInterfaceRedis::connect() 23 | { 24 | redisContext* c = redisConnect(m_ip.c_str(), (int)m_port); 25 | if (c == nullptr || c->err) 26 | { 27 | ERROR_LOG("DBInterfaceRedis::attach: errno=%d, error=%s\n", c->err, c->errstr); 28 | 29 | redisFree(c); 30 | return false; 31 | } 32 | 33 | // TODO command: auth password 34 | // TODO command: select idx 35 | 36 | m_context = c; 37 | return true; 38 | } 39 | 40 | bool DBInterfaceRedis::detach() 41 | { 42 | 43 | if (m_context) 44 | { 45 | /* Disconnects and frees the context */ 46 | redisFree(m_context); 47 | m_context = NULL; 48 | } 49 | 50 | return true; 51 | } 52 | 53 | int DBInterfaceRedis::execute(DBResult * result, const char * cmd, int len) 54 | { 55 | redisReply *pRedisReply = (redisReply*)redisCommand(m_context, cmd); 56 | if (m_context->err) 57 | { 58 | ERROR_LOG("DBInterfaceRedis::query: cmd=%s, errno=%d, error=%s\n", cmd, m_context->err, m_context->errstr); 59 | return -1; 60 | } 61 | //freeReplyObject(pRedisReply); 62 | 63 | static_cast(result)->setResult(pRedisReply); 64 | return 0; 65 | } 66 | 67 | const char * DBInterfaceRedis::getError() 68 | { 69 | if (m_context == NULL) 70 | return "pRedisContext_ is NULL"; 71 | 72 | return m_context->errstr; 73 | } 74 | 75 | int DBInterfaceRedis::getErrno() 76 | { 77 | if (m_context == NULL) 78 | return 0; 79 | 80 | return m_context->err; 81 | } 82 | 83 | bool DBInterfaceRedis::ping() 84 | { 85 | if (!m_context) 86 | return false; 87 | 88 | redisReply* pRedisReply = (redisReply*)redisCommand(m_context, "ping"); 89 | 90 | if (NULL == pRedisReply) 91 | { 92 | ERROR_LOG("DBInterfaceRedis::ping: errno=%d, error=%s\n", 93 | m_context->err, m_context->errstr); 94 | 95 | return false; 96 | } 97 | 98 | if (!(pRedisReply->type == REDIS_REPLY_STATUS && strcmp(pRedisReply->str, "PONG") == 0)) 99 | { 100 | ERROR_LOG("DBInterfaceRedis::ping: errno=%d, error=%s\n", 101 | m_context->err, pRedisReply->str); 102 | 103 | freeReplyObject(pRedisReply); 104 | return false; 105 | } 106 | printf("PING: %s\n", pRedisReply->str); 107 | freeReplyObject(pRedisReply); 108 | return true; 109 | } 110 | 111 | int DBInterfaceRedis::execute(RedisCommand * command, DBResult * result) 112 | { 113 | std::vector temp; 114 | redisReply *pRedisReply = NULL; 115 | 116 | if (command->length() > 1) 117 | { 118 | pRedisReply = (redisReply*)redisCommandArgv(m_context, command->length(), command->argv(temp), command->argvlen()); 119 | } 120 | else 121 | { 122 | pRedisReply = (redisReply*)redisCommand(m_context, command->tostr()); 123 | } 124 | 125 | if (m_context->err) 126 | { 127 | return -1; 128 | } 129 | //freeReplyObject(pRedisReply); 130 | 131 | static_cast(result)->setResult(pRedisReply); 132 | return 0; 133 | } -------------------------------------------------------------------------------- /src/db/DB_Interface_redis.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /************************************************************************ 3 | * @file DB_Interface_redis.h 4 | * @brief db interface redis 5 | * @author jiangwang 6 | * @data 2020-3-31 7 | * @version 0.1 8 | ************************************************************************/ 9 | 10 | #include "DB_Interface.h" 11 | class RedisCommand; 12 | class DBInterfaceRedis : public DB_Interface 13 | { 14 | public: 15 | DBInterfaceRedis(const char * ip, unsigned int port); 16 | ~DBInterfaceRedis(); 17 | 18 | virtual bool connect(); 19 | virtual bool detach(); 20 | virtual int execute(DBResult * result, const char * cmd, int len = 0); 21 | virtual const char * getError(); 22 | virtual int getErrno(); 23 | virtual bool ping(); 24 | 25 | int execute(RedisCommand * command, DBResult * result); 26 | 27 | protected: 28 | redisContext * m_context; 29 | }; 30 | 31 | -------------------------------------------------------------------------------- /src/db/MysqlResult.cpp: -------------------------------------------------------------------------------- 1 | #include "MysqlResult.h" 2 | 3 | MysqlResult::MysqlResult() 4 | { 5 | pResult = NULL; 6 | pos = 0; 7 | lengths = NULL; 8 | } 9 | 10 | MysqlResult::~MysqlResult() 11 | { 12 | if (pResult) 13 | { 14 | mysql_free_result(pResult); 15 | } 16 | } 17 | 18 | void MysqlResult::setResult(MYSQL_RES * result) { 19 | pResult = result; 20 | if (result) 21 | lengths = mysql_fetch_lengths(pResult); 22 | else 23 | lengths = NULL; 24 | } 25 | 26 | bool MysqlResult::isEmpty() 27 | { 28 | return pResult == NULL; 29 | } 30 | 31 | bool MysqlResult::fetch() { 32 | pos = 0; 33 | return (aRow = mysql_fetch_row(pResult)) != NULL; 34 | } 35 | 36 | uint32 MysqlResult::getRowCount() { 37 | return (uint32)mysql_num_rows(pResult); 38 | } 39 | 40 | uint32 MysqlResult::getFieldsCount() { 41 | return (uint32)mysql_num_fields(pResult); 42 | } 43 | 44 | const char * MysqlResult::getData(int & len) { 45 | len = lengths[pos]; 46 | return aRow[pos++]; 47 | } 48 | 49 | const char * MysqlResult::getData() { 50 | return aRow[pos++]; 51 | } -------------------------------------------------------------------------------- /src/db/MysqlResult.h: -------------------------------------------------------------------------------- 1 | #ifndef DB_RESULT_H 2 | #define DB_RESULT_H 3 | 4 | #include "mysql.h" 5 | #include "XLog.h" 6 | #include "BaseType.h" 7 | #include 8 | #include "DBResult.h" 9 | 10 | class MysqlResult : public DBResult 11 | { 12 | public: 13 | MysqlResult(); 14 | ~MysqlResult(); 15 | 16 | void setResult(MYSQL_RES * result); 17 | 18 | virtual bool isEmpty(); 19 | virtual bool fetch(); 20 | virtual uint32 getRowCount(); 21 | virtual uint32 getFieldsCount(); 22 | 23 | virtual const char * getData(int & len); 24 | virtual const char * getData(); 25 | 26 | template 27 | MysqlResult & operator >> (T & t) 28 | { 29 | if (pos >= getFieldsCount()) 30 | { 31 | ERROR_LOG("mysql row count upper limit"); 32 | return *this; 33 | } 34 | std::istringstream ins(aRow[pos]); 35 | ins >> t; 36 | pos++; 37 | return *this; 38 | } 39 | 40 | private: 41 | 42 | MYSQL_RES * pResult; 43 | MYSQL_ROW aRow; 44 | uint32 pos; 45 | unsigned long *lengths; 46 | }; 47 | 48 | #endif -------------------------------------------------------------------------------- /src/db/RedisCommand.cpp: -------------------------------------------------------------------------------- 1 | #include "BaseType.h" 2 | #include 3 | #include 4 | #include "RedisCommand.h" 5 | #include "BasePacket.h" 6 | 7 | RedisCommand::RedisCommand(const char *cmd) 8 | { 9 | append((const uint8*)cmd, strlen(cmd)); 10 | } 11 | void RedisCommand::pushInt8(int8 value) 12 | { 13 | pushValue(value); 14 | } 15 | void RedisCommand::pushUint8(uint8 value) 16 | { 17 | pushValue(value); 18 | } 19 | void RedisCommand::pushInt16(int16 value) 20 | { 21 | pushValue(value); 22 | } 23 | void RedisCommand::pushUint16(uint16 value) 24 | { 25 | pushValue(value); 26 | } 27 | void RedisCommand::pushInt32(int32 value) 28 | { 29 | pushValue(value); 30 | } 31 | void RedisCommand::pushUint32(uint32 value) 32 | { 33 | pushValue(value); 34 | } 35 | void RedisCommand::pushInt64(int64 value) 36 | { 37 | pushValue(value); 38 | } 39 | void RedisCommand::pushUint64(uint64 value) 40 | { 41 | pushValue(value); 42 | } 43 | void RedisCommand::pushFloat(float value) 44 | { 45 | pushValue(value); 46 | } 47 | void RedisCommand::pushDouble(double value) 48 | { 49 | pushValue(value); 50 | } 51 | void RedisCommand::pushString(std::string value) 52 | { 53 | append((const uint8*)value.c_str(), value.size()); 54 | } 55 | void RedisCommand::pushBlob(BasePacket * packet) 56 | { 57 | append((const uint8*)packet->contents(), packet->writePos()); 58 | } 59 | 60 | void RedisCommand::pushData(std::string_view sv) 61 | { 62 | append((const uint8*)sv.data(), sv.size()); 63 | } 64 | 65 | void RedisCommand::append(const uint8 * p, int len) 66 | { 67 | std::vector vec; 68 | vec.insert(vec.begin(), p, p + len); 69 | 70 | m_param.push_back(vec); 71 | m_len.push_back(len); 72 | } 73 | 74 | int RedisCommand::length() 75 | { 76 | return m_len.size(); 77 | } 78 | const char ** RedisCommand::argv(std::vector & vec) 79 | { 80 | for (uint32 i = 0; i < m_param.size(); ++i) 81 | { 82 | vec.push_back((char *)(m_param[i].data())); 83 | } 84 | 85 | return (const char **)(vec.data()); 86 | } 87 | const size_t * RedisCommand::argvlen() 88 | { 89 | return (size_t *)m_len.data(); 90 | } 91 | 92 | const char * RedisCommand::tostr() 93 | { 94 | m_param[0].push_back(0); 95 | const char * ret = (const char *)(m_param[0].data()); 96 | return ret; 97 | } -------------------------------------------------------------------------------- /src/db/RedisCommand.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /************************************************************************ 3 | * @file RedisCommand.h 4 | * @brief redis command param 5 | * @author jiangwang 6 | * @data 2020-4-2 7 | * @version 0.1 8 | ************************************************************************/ 9 | 10 | class BasePacket; 11 | class RedisCommand 12 | { 13 | public: 14 | RedisCommand(const char *cmd); 15 | // push 16 | void pushInt8(int8 value); 17 | void pushUint8(uint8 value); 18 | void pushInt16(int16 value); 19 | void pushUint16(uint16 value); 20 | void pushInt32(int32 value); 21 | void pushUint32(uint32 value); 22 | void pushInt64(int64 value); 23 | void pushUint64(uint64 value); 24 | void pushFloat(float value); 25 | void pushDouble(double value); 26 | void pushString(std::string value); 27 | void pushBlob(BasePacket * packet); 28 | void pushData(std::string_view sv); // lua call 29 | 30 | template 31 | void pushValue(T t) 32 | { 33 | append((const uint8 *)&t, sizeof(t)); 34 | } 35 | 36 | int length(); 37 | const char ** argv(std::vector & vec); 38 | const size_t * argvlen(); 39 | const char * tostr(); 40 | 41 | private: 42 | void append(const uint8 * p, int len); 43 | 44 | private: 45 | std::vector> m_param; 46 | // void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen); 47 | // 因为redisCommandArgv最后一个参数是size_t类型的,所以m_len的类型为size_t,若为int类型的话在返回(size_t *)m_len.data()的时候由于 48 | // 类型转换的问题会导致redisCommandArgv()函数调用失败 49 | std::vector m_len; 50 | }; 51 | 52 | -------------------------------------------------------------------------------- /src/db/RedisResult.cpp: -------------------------------------------------------------------------------- 1 | #include "RedisResult.h" 2 | #include "hiredis.h" 3 | #include "BasePacket.h" 4 | #include 5 | 6 | RedisResult::RedisResult() 7 | { 8 | m_reply = NULL; 9 | pos = 0; 10 | } 11 | 12 | RedisResult::~RedisResult() 13 | { 14 | if(m_reply) 15 | freeReplyObject(m_reply); 16 | } 17 | 18 | void RedisResult::setResult(redisReply * result) 19 | { 20 | m_reply = result; 21 | } 22 | 23 | bool RedisResult::isEmpty() 24 | { 25 | return !(m_reply && (m_reply->str || m_reply->elements > 0)); 26 | } 27 | bool RedisResult::fetch() 28 | { 29 | if (pos >= getRowCount()) 30 | return false; 31 | return true; 32 | } 33 | 34 | uint32 RedisResult::getRowCount() 35 | { 36 | return m_reply->str ? 1 : m_reply->elements; 37 | } 38 | 39 | uint32 RedisResult::getFieldsCount() 40 | { 41 | return getRowCount(); 42 | } 43 | 44 | const char * RedisResult::getData(int & len) 45 | { 46 | const char * str; 47 | // key or list 48 | if (m_reply->str) 49 | { 50 | len = m_reply->len; 51 | str = m_reply->str; 52 | } 53 | else 54 | { 55 | len = m_reply->element[pos]->len; 56 | str = m_reply->element[pos]->str; 57 | } 58 | 59 | pos++; 60 | return str; 61 | } 62 | const char * RedisResult::getData() 63 | { 64 | const char * str; 65 | if (m_reply->str) 66 | { 67 | str = m_reply->str; 68 | } 69 | else 70 | { 71 | str = m_reply->element[pos]->str; 72 | } 73 | pos++; 74 | return str; 75 | } 76 | 77 | RedisResult &RedisResult::operator>>(std::string& value) 78 | { 79 | if (pos >= getFieldsCount()) 80 | { 81 | ERROR_LOG("redis row count upper limit"); 82 | return *this; 83 | } 84 | 85 | // string 86 | std::istringstream ins(m_reply->str ? m_reply->str : m_reply->element[pos]->str); 87 | ins >> value; 88 | 89 | pos++; 90 | return *this; 91 | } 92 | 93 | int RedisResult::readBlob(BasePacket * packet) 94 | { 95 | int len; 96 | const char * pdata = getData(len); 97 | if (len > 0) 98 | { 99 | packet->append((const uint8 *)pdata, len); 100 | } 101 | return len; 102 | } 103 | 104 | std::string_view RedisResult::getStream() 105 | { 106 | int len; 107 | const char * p = getData(len); 108 | return std::string_view(p, len); 109 | } -------------------------------------------------------------------------------- /src/db/RedisResult.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /************************************************************************ 3 | * @file RedisResult.h 4 | * @brief redis result 5 | * @author jiangwang 6 | * @data 2020-3-31 7 | * @version 0.1 8 | ************************************************************************/ 9 | 10 | #include "XLog.h" 11 | #include "BaseType.h" 12 | #include "DBResult.h" 13 | #include 14 | 15 | class BasePacket; 16 | struct redisReply; 17 | class RedisResult : public DBResult 18 | { 19 | public: 20 | RedisResult(); 21 | ~RedisResult(); 22 | void setResult(redisReply * result); 23 | 24 | virtual bool isEmpty(); 25 | virtual bool fetch(); 26 | virtual uint32 getRowCount(); 27 | virtual uint32 getFieldsCount(); 28 | 29 | virtual const char * getData(int & len); 30 | virtual const char * getData(); 31 | 32 | // base type 33 | template 34 | RedisResult & operator >> (T & t) 35 | { 36 | if (pos >= getFieldsCount()) 37 | { 38 | ERROR_LOG("redis row count upper limit"); 39 | return *this; 40 | } 41 | 42 | // blob 43 | const char * p = m_reply->str ? m_reply->str : m_reply->element[pos]->str; 44 | std::memcpy(&t, p, sizeof(t)); 45 | 46 | pos++; 47 | return *this; 48 | } 49 | 50 | // string type 51 | RedisResult &operator>>(std::string& value); 52 | int readBlob(BasePacket * packet); 53 | std::string_view getStream(); 54 | private: 55 | redisReply * m_reply; 56 | uint32 pos; 57 | }; 58 | 59 | -------------------------------------------------------------------------------- /src/db/SqlPrepare.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /************************************************************************ 3 | * @file SqlPrepare.h 4 | * @brief sql prepare 5 | * @author jiangwang 6 | * @data 2020-3-23 7 | * @version 0.1 8 | ************************************************************************/ 9 | 10 | class BasePacket; 11 | class DBResult; 12 | class SqlPrepare 13 | { 14 | public: 15 | SqlPrepare(const char * sqlstr); 16 | ~SqlPrepare(); 17 | 18 | void clear(); 19 | 20 | // push 21 | void pushInt8(int8 value); 22 | void pushUint8(uint8 value); 23 | void pushInt16(int16 value); 24 | void pushUint16(uint16 value); 25 | void pushInt32(int32 value); 26 | void pushUint32(uint32 value); 27 | void pushInt64(int64 value); 28 | void pushUint64(uint64 value); 29 | void pushFloat(float value); 30 | void pushDouble(double value); 31 | void pushString(std::string value); 32 | void pushBlob(BasePacket * packet); 33 | void pushData(std::string_view sv); // lua call 34 | 35 | void write(void* pData, int len); 36 | 37 | int prepare(MYSQL * mysql); 38 | int execute(DBResult* result); 39 | protected: 40 | bool _query(MYSQL_RES** pResult); 41 | private: 42 | int m_count; 43 | std::string m_sql; 44 | MYSQL_STMT * m_stmt; 45 | MYSQL_BIND * m_paramBind; 46 | unsigned long * m_paramLengths; 47 | 48 | private: 49 | int m_widx; // write 50 | }; -------------------------------------------------------------------------------- /src/db/SqlResultSet.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | class SqlField 8 | { 9 | public: 10 | SqlField() 11 | { 12 | m_buff = NULL; 13 | m_len = 0; 14 | } 15 | 16 | ~SqlField() 17 | { 18 | if (m_buff) 19 | { 20 | delete[] m_buff; 21 | } 22 | } 23 | 24 | void make(const char* pdata, int len) 25 | { 26 | m_len = len; 27 | m_buff = new char[len]; 28 | memcpy(m_buff, pdata, len); 29 | } 30 | 31 | bool isEmpty() 32 | { 33 | return !m_buff; 34 | } 35 | 36 | const char* data() { return m_buff; } 37 | int length() { return m_len; } 38 | 39 | template 40 | T getValue() 41 | { 42 | T val; 43 | memcpy(&val, m_buff, sizeof(T)); 44 | return val; 45 | } 46 | 47 | private: 48 | char* m_buff; 49 | int m_len; 50 | }; 51 | 52 | #include 53 | #include "BaseType.h" 54 | #include "DBResult.h" 55 | 56 | class BasePacket; 57 | class SqlResultSet : public DBResult 58 | { 59 | public: 60 | SqlResultSet(); 61 | ~SqlResultSet(); 62 | 63 | void setResult(MYSQL_STMT* stmt, MYSQL_RES* pResult, uint64 pRowCount, uint32 pFieldCount); 64 | virtual bool fetch(); 65 | virtual bool isEmpty(); 66 | virtual uint32 getRowCount(); 67 | virtual uint32 getFieldsCount(); 68 | virtual const char* getData(int& len); 69 | virtual const char* getData(); 70 | 71 | SqlField* getField(int idx); 72 | bool emptyField(int idx); 73 | 74 | int8 getInt8(); 75 | uint8 getUint8(); 76 | int16 getInt16(); 77 | uint16 getUint16(); 78 | int32 getInt32(); 79 | uint32 getUint32(); 80 | int64 getInt64(); 81 | uint64 getUint64(); 82 | float getFloat(); 83 | double getDouble(); 84 | std::string getString(); 85 | int readBlob(BasePacket* packet); 86 | std::string_view getStrview(); // lua call 87 | 88 | protected: 89 | bool _fetch(MYSQL_STMT * stmt); 90 | private: 91 | std::vector m_fields; 92 | int64 m_currRowIdx; 93 | int32 m_currColIdx; 94 | int64 m_rowCount; 95 | int32 m_fieldCount; 96 | }; 97 | 98 | -------------------------------------------------------------------------------- /src/network/BasePacket.cpp: -------------------------------------------------------------------------------- 1 | #include "BasePacket.h" 2 | 3 | 4 | BasePacket::BasePacket() 5 | { 6 | // Polymorphism cannot be implemented in constructors 7 | zero(); 8 | } 9 | 10 | BasePacket::~BasePacket() 11 | { 12 | } 13 | 14 | 15 | void BasePacket::zero() 16 | { 17 | rpos(0); 18 | wpos(0); 19 | this->storage().resize(0); 20 | } 21 | 22 | void BasePacket::release() 23 | { 24 | 25 | } 26 | 27 | void BasePacket::moveData(BasePacket * packet) 28 | { 29 | rpos(packet->rpos()); 30 | wpos(packet->wpos()); 31 | swapBuffer(*packet); 32 | packet->zero(); 33 | } 34 | 35 | void BasePacket::shrink(int isize) 36 | { 37 | // shrink_to_fit() 38 | // swap() 39 | 40 | if (_storage->capacity() > isize) 41 | { 42 | std::vector vec; 43 | vec.reserve(isize); 44 | _storage->swap(vec); 45 | } 46 | } 47 | 48 | int32 BasePacket::getHeadSize() 49 | { 50 | return 0; 51 | } 52 | 53 | int32 BasePacket::getBodySize() 54 | { 55 | return wpos() - getHeadSize(); 56 | } 57 | 58 | const char * BasePacket::getBodyData() 59 | { 60 | return (const char*)(contents() + getHeadSize()); 61 | } 62 | 63 | const char * BasePacket::readPointer() 64 | { 65 | return (const char *)(contents() + _rpos); 66 | } 67 | 68 | void BasePacket::setWriteSize(int size) 69 | { 70 | size += getHeadSize(); 71 | _storage->resize(size); 72 | wpos(size); 73 | } 74 | 75 | int32 BasePacket::activeSize() 76 | { 77 | return _wpos - _rpos; 78 | } 79 | 80 | std::string_view BasePacket::readData() 81 | { 82 | return std::string_view(readPointer(), activeSize()); 83 | } 84 | 85 | void BasePacket::writeData(std::string_view sv) 86 | { 87 | append(sv.data(), sv.size()); 88 | } 89 | 90 | // message head mark length 91 | int32 BasePacket::getMarkLen() 92 | { 93 | return 0; 94 | } 95 | 96 | int BasePacket::getMsgType() 97 | { 98 | return 0; 99 | } 100 | 101 | bool BasePacket::isHeadFull() 102 | { 103 | return false; 104 | } 105 | 106 | // send msg call 107 | int32 BasePacket::sendSize() 108 | { 109 | return wpos(); 110 | } 111 | 112 | char * BasePacket::sendStream() 113 | { 114 | return (char *)contents(); 115 | } 116 | 117 | int BasePacket::readPos() 118 | { 119 | return rpos(); 120 | } 121 | 122 | int BasePacket::writePos() 123 | { 124 | return wpos(); 125 | } 126 | 127 | //------->get 128 | int8 BasePacket::getInt8() { 129 | return popValue(); 130 | } 131 | uint8 BasePacket::getUint8() { 132 | return popValue(); 133 | } 134 | int16 BasePacket::getInt16() { 135 | return popValue(); 136 | } 137 | uint16 BasePacket::getUint16() { 138 | return popValue(); 139 | } 140 | int32 BasePacket::getInt32() { 141 | return popValue(); 142 | } 143 | uint32 BasePacket::getUint32() { 144 | return popValue(); 145 | } 146 | int64 BasePacket::getInt64() { 147 | return popValue(); 148 | } 149 | uint64 BasePacket::getUint64() { 150 | return popValue(); 151 | } 152 | float BasePacket::getFloat() { 153 | return popValue(); 154 | } 155 | double BasePacket::getDouble() { 156 | return popValue(); 157 | } 158 | std::string BasePacket::getString() { 159 | return popValue(); 160 | } 161 | 162 | 163 | //------->push 164 | void BasePacket::pushInt8(int8 value) { 165 | *this << value; 166 | } 167 | void BasePacket::pushUint8(uint8 value) { 168 | *this << value; 169 | } 170 | void BasePacket::pushInt16(int16 value) { 171 | *this << value; 172 | } 173 | void BasePacket::pushUint16(uint16 value) { 174 | *this << value; 175 | } 176 | void BasePacket::pushInt32(int32 value) { 177 | *this << value; 178 | } 179 | void BasePacket::pushUint32(uint32 value) { 180 | *this << value; 181 | } 182 | void BasePacket::pushInt64(int64 value) { 183 | *this << value; 184 | } 185 | void BasePacket::pushUint64(uint64 value) { 186 | *this << value; 187 | } 188 | void BasePacket::pushFloat(float value) { 189 | *this << value; 190 | } 191 | void BasePacket::pushDouble(double value) { 192 | *this << value; 193 | } 194 | void BasePacket::pushString(std::string value) { 195 | *this << value; 196 | } -------------------------------------------------------------------------------- /src/network/BasePacket.h: -------------------------------------------------------------------------------- 1 | /************************************************************************ 2 | * @file BasePacket.h 3 | * @brief Network packet base class 4 | * @author jiangwang 5 | * @data 2019-1-15 6 | * @version 0.1 7 | ************************************************************************/ 8 | 9 | #pragma once 10 | 11 | #include "ByteBuffer.h" 12 | #include "PoolObject.h" 13 | 14 | class BasePacket : public ByteBuffer 15 | { 16 | public: 17 | BasePacket(); 18 | ~BasePacket(); 19 | 20 | virtual void zero(); 21 | virtual void release(); 22 | virtual void moveData(BasePacket * packet); 23 | void shrink(int isize); 24 | 25 | virtual int32 getHeadSize(); 26 | int32 getBodySize(); 27 | const char * getBodyData(); 28 | const char * readPointer(); 29 | void setWriteSize(int size); 30 | int32 activeSize(); 31 | // lua call blob 32 | std::string_view readData(); 33 | void writeData(std::string_view sv); 34 | 35 | // read msg call 36 | virtual int32 getMarkLen(); // message head mark length 37 | virtual int getMsgType(); 38 | virtual bool isHeadFull(); 39 | 40 | // send msg call 41 | virtual int32 sendSize(); 42 | virtual char * sendStream(); 43 | 44 | int readPos(); 45 | int writePos(); 46 | public: 47 | 48 | //------->get 49 | int8 getInt8(); 50 | uint8 getUint8(); 51 | int16 getInt16(); 52 | uint16 getUint16(); 53 | int32 getInt32(); 54 | uint32 getUint32(); 55 | int64 getInt64(); 56 | uint64 getUint64(); 57 | float getFloat(); 58 | double getDouble(); 59 | std::string getString(); 60 | 61 | //------->push 62 | void pushInt8(int8 value); 63 | void pushUint8(uint8 value); 64 | void pushInt16(int16 value); 65 | void pushUint16(uint16 value); 66 | void pushInt32(int32 value); 67 | void pushUint32(uint32 value); 68 | void pushInt64(int64 value); 69 | void pushUint64(uint64 value); 70 | void pushFloat(float value); 71 | void pushDouble(double value); 72 | void pushString(std::string value); 73 | protected: 74 | 75 | template 76 | T popValue() { 77 | T t; 78 | *this >> t; 79 | return t; 80 | } 81 | 82 | template 83 | T getValue(uint32 pos){ 84 | T value; 85 | std::memcpy(&value, &(*_storage)[pos], sizeof(T)); 86 | EndianConvert(value); 87 | 88 | return value; 89 | } 90 | 91 | template 92 | void setValue(uint32 pos, T t){ 93 | put(pos, t); 94 | } 95 | 96 | INCLUDE_POOL_OBJECT 97 | }; 98 | 99 | -------------------------------------------------------------------------------- /src/network/HttpConnect.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /************************************************************************ 3 | * @file HttpConnect.h 4 | * @brief HttpConnect 5 | * @author jiangwang 6 | * @data 2020-5-20 7 | * @version 0.1 8 | ************************************************************************/ 9 | 10 | #include "TcpSocket.h" 11 | #include "HttpEvent.h" 12 | #include "PoolObject.h" 13 | #include "HttpParser.h" 14 | #include 15 | 16 | enum http_content_type 17 | { 18 | hct_text_html , //HTML��ʽ 19 | hct_text_plain, //���ı���ʽ 20 | hct_text_xml, //XML��ʽ 21 | hct_text_json, //json��ʽ 22 | hct_image_gif, //gifͼƬ��ʽ 23 | hct_image_jpeg, //jpgͼƬ��ʽ 24 | hct_image_png, //pngͼƬ��ʽ 25 | 26 | }; 27 | 28 | class BasePacket; 29 | class MessageBuffer; 30 | class HttpConnect : public TcpSocket 31 | { 32 | public: 33 | HttpConnect(); 34 | ~HttpConnect(); 35 | 36 | void zero(); 37 | void setEvent(HttpEvent * e) { m_event = e; } 38 | void sendMsg(const char* msg, int32 len); 39 | // lua call 40 | void sendData(std::string_view sv); 41 | void autoMsg(std::string_view sv, enum http_content_type type = hct_text_html); 42 | static const char *getContentTypeStr(enum http_content_type type); 43 | protected: 44 | virtual void on_msgbuffer(MessageBuffer * buffer); 45 | virtual void on_clsesocket(); 46 | virtual void on_writecomplete(); 47 | 48 | private: 49 | void complete(); 50 | 51 | private: 52 | HttpEvent * m_event = NULL; 53 | BasePacket * m_readPacket; 54 | HttpParser m_parser; 55 | const char * m_content; 56 | int m_residue; 57 | 58 | INCLUDE_POOL_OBJECT 59 | }; 60 | 61 | -------------------------------------------------------------------------------- /src/network/HttpEvent.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /************************************************************************ 3 | * @file HttpEvent.h 4 | * @brief HttpEvent 5 | * @author jiangwang 6 | * @data 2020-5-20 7 | * @version 0.1 8 | ************************************************************************/ 9 | 10 | class HttpConnect; 11 | class HttpParser; 12 | class HttpEvent 13 | { 14 | public: 15 | virtual void onClose(HttpConnect *conn) = 0; 16 | 17 | virtual void onGet(HttpConnect* conn, std::string_view& path, std::string_view& data) = 0; 18 | virtual void onPost(HttpConnect* conn, std::string_view& path, std::string_view& data) = 0; 19 | virtual void onOther(HttpConnect* conn, HttpParser * parser) = 0; 20 | }; 21 | -------------------------------------------------------------------------------- /src/network/HttpServer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "HttpServer.h" 5 | #include "HttpConnect.h" 6 | #include "CommonPool.h" 7 | 8 | HttpServer::HttpServer(EventLoop * loop): 9 | TcpServer(loop) 10 | { 11 | 12 | } 13 | 14 | TcpSocket * HttpServer::createSocket() 15 | { 16 | HttpConnect * conn = CommPool::create(); 17 | conn->setEvent(this); 18 | return conn; 19 | } 20 | 21 | void HttpServer::onSocket(TcpSocket * connect) 22 | { 23 | 24 | } 25 | 26 | void HttpServer::onClose(HttpConnect *conn) 27 | { 28 | CommPool::reclaim(conn); 29 | } 30 | 31 | void HttpServer::onGet(HttpConnect* conn, std::string_view& path, std::string_view& data) 32 | { 33 | std::string spath(path); 34 | auto it = m_get.find(spath); 35 | if (it != m_get.end()) 36 | { 37 | (it->second)(conn, data); 38 | } 39 | } 40 | 41 | void HttpServer::onPost(HttpConnect* conn, std::string_view& path, std::string_view& data) 42 | { 43 | std::string spath(path); 44 | auto it = m_post.find(spath); 45 | if (it != m_post.end()) 46 | { 47 | (it->second)(conn, data); 48 | } 49 | } 50 | void HttpServer::onOther(HttpConnect* conn, HttpParser* parser) 51 | { 52 | if (m_other) m_other(conn, parser); 53 | } 54 | 55 | void HttpServer::addGet(const char * name, std::function back) 56 | { 57 | m_get[name] = back; 58 | } 59 | void HttpServer::addPost(const char * name, std::function back) 60 | { 61 | m_post[name] = back; 62 | } 63 | 64 | void HttpServer::setOther(std::function back) 65 | { 66 | m_other = back; 67 | } -------------------------------------------------------------------------------- /src/network/HttpServer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "TcpServer.h" 3 | #include "HttpEvent.h" 4 | 5 | class EventLoop; 6 | class HttpServer : public TcpServer, public HttpEvent 7 | { 8 | public: 9 | HttpServer(EventLoop * loop); 10 | void addGet(const char * name, std::function back); 11 | void addPost(const char * name, std::function back); 12 | void setOther(std::function back); 13 | protected: 14 | virtual TcpSocket * createSocket(); 15 | virtual void onSocket(TcpSocket * connect); 16 | virtual void onClose(HttpConnect *conn); 17 | virtual void onGet(HttpConnect* conn, std::string_view& path, std::string_view& data); 18 | virtual void onPost(HttpConnect* conn, std::string_view& path, std::string_view& data); 19 | virtual void onOther(HttpConnect* conn, HttpParser* parser); 20 | 21 | private: 22 | std::map> m_get; 23 | std::map> m_post; 24 | std::function m_other; 25 | }; 26 | 27 | -------------------------------------------------------------------------------- /src/network/KcpClient.cpp: -------------------------------------------------------------------------------- 1 | #include "KcpClient.h" 2 | #include "KcpEvent.h" 3 | #include "KcpSession.h" 4 | 5 | 6 | KcpClient::KcpClient(EventLoop * loop, KcpEvent * event_): 7 | UdpClient(loop), 8 | __m_kcpEvent(event_) 9 | { 10 | } 11 | 12 | 13 | KcpClient::~KcpClient() 14 | { 15 | } 16 | 17 | 18 | void KcpClient::createSession(const char * server_ip, int server_port, bool ipv6) 19 | { 20 | connect(server_ip, server_port, ipv6); 21 | 22 | uint8 msg[SESSION_PACKET_SIZE]; 23 | *(uint32 *)msg = 0; 24 | *(uint8 *)(msg + 4) = SETUP_SESSION_CODE; 25 | writeToServer((char *)msg, SESSION_PACKET_SIZE); 26 | } 27 | 28 | void KcpClient::closeSession(KcpSession * session) 29 | { 30 | std::map::iterator it = __m_mapSessions.find(session->getSessionId()); 31 | if (it != __m_mapSessions.end()) 32 | { 33 | __m_mapSessions.erase(session->getSessionId()); 34 | release(session); 35 | } 36 | } 37 | 38 | void KcpClient::onMessage(const sockaddr * addr, const char * buff, ssize_t len) 39 | { 40 | uint32 conv = ikcp_getconv((const void *)buff); 41 | unsigned char code = *(unsigned char*)(buff + 4); 42 | if (len == SESSION_PACKET_SIZE && conv > 0 && code == SETUP_SESSION_CODE) 43 | { 44 | KcpSession * session = __m_kcpEvent->createConnect(); 45 | uint32 ms = __m_kcpEvent->onKcp(session->init(conv, addr, &_udp)); 46 | session->start(ms); 47 | __m_mapSessions[conv] = session; 48 | __m_kcpEvent->onConnect(session); 49 | 50 | } 51 | else 52 | { 53 | std::map::iterator it = __m_mapSessions.find(conv); 54 | if (it != __m_mapSessions.end()) 55 | { 56 | KcpSession * session = it->second; 57 | if (session->recv(buff, len) == 0) { 58 | session->updateKcp(); 59 | }else{ 60 | release(session); 61 | __m_mapSessions.erase(it); 62 | } 63 | } 64 | } 65 | 66 | } 67 | 68 | void KcpClient::release(KcpSession * session) 69 | { 70 | session->destory(); 71 | session->over(); 72 | __m_kcpEvent->onClose(session); 73 | __m_kcpEvent->destroyConnect(session); 74 | } -------------------------------------------------------------------------------- /src/network/KcpClient.h: -------------------------------------------------------------------------------- 1 | /************************************************************************ 2 | * @file KcpClient.h 3 | * @brief kcp client 4 | * @author jiangwang 5 | * @data 2019-12-13 6 | * @version 0.1 7 | ************************************************************************/ 8 | 9 | #pragma once 10 | 11 | #include "UdpClient.h" 12 | #include "BaseType.h" 13 | #include 14 | 15 | class KcpEvent; 16 | class EventLoop; 17 | class KcpSession; 18 | class KcpClient : public UdpClient 19 | { 20 | public: 21 | KcpClient(EventLoop * loop, KcpEvent * event_); 22 | ~KcpClient(); 23 | 24 | void createSession(const char * server_ip, int server_port, bool ipv6 = false); 25 | void closeSession(KcpSession * session); 26 | 27 | protected: 28 | virtual void onMessage(const sockaddr * addr, const char * buff, ssize_t len); 29 | 30 | private: 31 | void release(KcpSession * session); 32 | private: 33 | KcpEvent * __m_kcpEvent; 34 | std::map __m_mapSessions; 35 | }; 36 | 37 | -------------------------------------------------------------------------------- /src/network/KcpEvent.cpp: -------------------------------------------------------------------------------- 1 | #include "KcpEvent.h" 2 | #include 3 | #include "KcpSession.h" 4 | 5 | KcpEvent::KcpEvent() 6 | { 7 | } 8 | 9 | 10 | KcpEvent::~KcpEvent() 11 | { 12 | } 13 | 14 | KcpSession * KcpEvent::createConnect() 15 | { 16 | return new KcpSession(this, 30 * 1000); 17 | } 18 | 19 | void KcpEvent::destroyConnect(KcpSession * conn) 20 | { 21 | if (conn) 22 | delete conn; 23 | } 24 | 25 | int KcpEvent::onKcp(void* kcp) 26 | { 27 | ikcpcb* _kcp = static_cast(kcp); 28 | // int ikcp_wndsize(ikcpcb *kcp, int sndwnd, int rcvwnd); 29 | ikcp_nodelay(_kcp, 1, 10, 2, 1); 30 | // return update millisecond 31 | return 10; 32 | } -------------------------------------------------------------------------------- /src/network/KcpEvent.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/lua-server/6008c764295d822f82a89ed8d579559bbcf1adfa/src/network/KcpEvent.h -------------------------------------------------------------------------------- /src/network/KcpServer.cpp: -------------------------------------------------------------------------------- 1 | #include "KcpServer.h" 2 | #include "ikcp.h" 3 | #include "KcpSession.h" 4 | #include "KcpEvent.h" 5 | 6 | uint32 gSessionid = 0; 7 | 8 | KcpServer::KcpServer(EventLoop * loop, KcpEvent * event_): 9 | UdpServer(loop), 10 | __m_kcpEvent(event_) 11 | { 12 | } 13 | 14 | 15 | KcpServer::~KcpServer() 16 | { 17 | } 18 | 19 | void KcpServer::closeSession(KcpSession * session) 20 | { 21 | std::map::iterator it = __m_mapSessions.find(session->getSessionId()); 22 | if (it != __m_mapSessions.end()) 23 | { 24 | __m_mapSessions.erase(session->getSessionId()); 25 | release(session); 26 | } 27 | } 28 | 29 | void KcpServer::shutdown() 30 | { 31 | uv_close((uv_handle_t *)&_m_udp, NULL); 32 | } 33 | 34 | void KcpServer::onMessage(const sockaddr * addr, const char * buff, ssize_t len) 35 | { 36 | if (len <= 0) 37 | { 38 | return; 39 | } 40 | 41 | uint32 conv = ikcp_getconv((const void *)buff); 42 | unsigned char code = *(unsigned char*)(buff + 4); 43 | if (len == SESSION_PACKET_SIZE && conv == 0 && code == SETUP_SESSION_CODE) 44 | { 45 | gSessionid++; 46 | 47 | 48 | //create new session 49 | KcpSession * session = __m_kcpEvent->createConnect(); 50 | uint32 ms = __m_kcpEvent->onKcp(session->init(gSessionid, addr, &_m_udp)); 51 | session->start(ms); 52 | __m_mapSessions[gSessionid] = session; 53 | 54 | //send to client 55 | uint8 msg[SESSION_PACKET_SIZE]; 56 | *(uint32 *)msg = gSessionid; 57 | *(uint8 *)(msg + 4) = SETUP_SESSION_CODE; 58 | uv_buf_t uvbuff = uv_buf_init((char *)msg, len); 59 | uv_udp_try_send(&_m_udp, &uvbuff, 1, addr); 60 | 61 | __m_kcpEvent->onAccept(session); 62 | } 63 | else 64 | { 65 | std::map::iterator it = __m_mapSessions.find(conv); 66 | if (it != __m_mapSessions.end()) 67 | { 68 | KcpSession * session = it->second; 69 | if (session->recv(buff, len) == 0){ 70 | session->updateKcp(); 71 | }else{ 72 | release(session); 73 | __m_mapSessions.erase(it); 74 | } 75 | } 76 | } 77 | } 78 | 79 | void KcpServer::release(KcpSession * session) 80 | { 81 | session->destory(); 82 | session->over(); 83 | __m_kcpEvent->onClose(session); 84 | __m_kcpEvent->destroyConnect(session); 85 | } -------------------------------------------------------------------------------- /src/network/KcpServer.h: -------------------------------------------------------------------------------- 1 | /************************************************************************ 2 | * @file KcpServer.h 3 | * @brief kcp server 4 | * @author jiangwang 5 | * @data 2019-12-12 6 | * @version 0.1 7 | ************************************************************************/ 8 | 9 | #pragma once 10 | 11 | #include "UdpServer.h" 12 | #include 13 | #include "BaseType.h" 14 | 15 | class KcpEvent; 16 | class EventLoop; 17 | class KcpSession; 18 | class KcpServer : public UdpServer 19 | { 20 | public: 21 | KcpServer(EventLoop * loop, KcpEvent * event_); 22 | ~KcpServer(); 23 | 24 | void closeSession(KcpSession * session); 25 | void shutdown(); 26 | 27 | protected: 28 | virtual void onMessage(const sockaddr * addr, const char * buff, ssize_t len); 29 | 30 | private: 31 | void release(KcpSession * session); 32 | private: 33 | KcpEvent * __m_kcpEvent; 34 | std::map __m_mapSessions; 35 | }; 36 | 37 | -------------------------------------------------------------------------------- /src/network/KcpSession.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/lua-server/6008c764295d822f82a89ed8d579559bbcf1adfa/src/network/KcpSession.cpp -------------------------------------------------------------------------------- /src/network/KcpSession.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/lua-server/6008c764295d822f82a89ed8d579559bbcf1adfa/src/network/KcpSession.h -------------------------------------------------------------------------------- /src/network/MessageBuffer.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __MESSAGEBUFFER_H_ 3 | #define __MESSAGEBUFFER_H_ 4 | 5 | #include 6 | #include 7 | 8 | #define MESSAGE_BUFFER_SIZE 4096 9 | 10 | class MessageBuffer 11 | { 12 | typedef std::vector::size_type size_type; 13 | 14 | public: 15 | MessageBuffer() : _wpos(0), _rpos(0), _storage() 16 | { 17 | _storage.resize(MESSAGE_BUFFER_SIZE); 18 | } 19 | 20 | explicit MessageBuffer(std::size_t initialSize) : _wpos(0), _rpos(0), _storage() 21 | { 22 | _storage.resize(initialSize); 23 | } 24 | 25 | MessageBuffer(MessageBuffer const& right) : _wpos(right._wpos), _rpos(right._rpos), _storage(right._storage) 26 | { 27 | } 28 | 29 | MessageBuffer(MessageBuffer&& right) : _wpos(right._wpos), _rpos(right._rpos), _storage(right.Move()) { } 30 | 31 | void Reset() 32 | { 33 | _wpos = 0; 34 | _rpos = 0; 35 | } 36 | 37 | void Resize(size_type bytes) 38 | { 39 | _storage.resize(bytes); 40 | } 41 | 42 | size_type GetWpos(){ return _wpos; } 43 | size_type GetRpos(){ return _rpos; } 44 | 45 | uint8* GetBasePointer() { return _storage.data(); } 46 | 47 | uint8* GetReadPointer() { return GetBasePointer() + _rpos; } 48 | 49 | uint8* GetWritePointer() { return GetBasePointer() + _wpos; } 50 | 51 | void ReadCompleted(size_type bytes) { _rpos += bytes; } 52 | 53 | void WriteCompleted(size_type bytes) { _wpos += bytes; } 54 | 55 | size_type GetActiveSize() const { return _wpos - _rpos; } 56 | 57 | size_type GetRemainingSpace() const { return _storage.size() - _wpos; } 58 | 59 | size_type GetBufferSize() const { return _storage.size(); } 60 | 61 | // Discards inactive data 62 | void Normalize() 63 | { 64 | if (_rpos) 65 | { 66 | if (_rpos != _wpos) 67 | memmove(GetBasePointer(), GetReadPointer(), GetActiveSize()); 68 | _wpos -= _rpos; 69 | _rpos = 0; 70 | } 71 | } 72 | 73 | // Ensures there's "some" free space, make sure to call Normalize() before this 74 | void EnsureFreeSpace() 75 | { 76 | // resize buffer if it's already full 77 | if (GetRemainingSpace() == 0) 78 | _storage.resize(_storage.size() * 3 / 2); 79 | } 80 | 81 | void Write(void const* data, std::size_t size) 82 | { 83 | if (size) 84 | { 85 | memcpy(GetWritePointer(), data, size); 86 | WriteCompleted(size); 87 | } 88 | } 89 | 90 | std::vector&& Move() 91 | { 92 | _wpos = 0; 93 | _rpos = 0; 94 | return std::move(_storage); 95 | } 96 | 97 | MessageBuffer& operator=(MessageBuffer const& right) 98 | { 99 | if (this != &right) 100 | { 101 | _wpos = right._wpos; 102 | _rpos = right._rpos; 103 | _storage = right._storage; 104 | } 105 | 106 | return *this; 107 | } 108 | 109 | MessageBuffer& operator=(MessageBuffer&& right) 110 | { 111 | if (this != &right) 112 | { 113 | _wpos = right._wpos; 114 | _rpos = right._rpos; 115 | _storage = right.Move(); 116 | } 117 | 118 | return *this; 119 | } 120 | 121 | private: 122 | size_type _wpos; 123 | size_type _rpos; 124 | std::vector _storage; 125 | }; 126 | 127 | #endif /* __MESSAGEBUFFER_H_ */ -------------------------------------------------------------------------------- /src/network/NetClient.cpp: -------------------------------------------------------------------------------- 1 | #include "NetClient.h" 2 | #include "NetConnect.h" 3 | #include "NetEvent.h" 4 | 5 | 6 | NetClient::NetClient(EventLoop * loop, NetEvent * nevent) : 7 | TcpClient(loop), 8 | _netevent(nevent) 9 | { 10 | 11 | } 12 | 13 | NetClient::~NetClient(){ 14 | 15 | } 16 | 17 | 18 | TcpSocket * NetClient::createSocket() 19 | { 20 | NetConnect * conn = _netevent->createConnect(); 21 | return (TcpSocket *)conn; 22 | } 23 | 24 | void NetClient::onSocket(TcpSocket * conn, int argv) 25 | { 26 | _netevent->onConnect((NetConnect *)conn, argv); 27 | } -------------------------------------------------------------------------------- /src/network/NetClient.h: -------------------------------------------------------------------------------- 1 | #ifndef TCP_CLIENT_H 2 | #define TCP_CLIENT_H 3 | 4 | 5 | #include "TcpClient.h" 6 | 7 | class NetEvent; 8 | class NetClient : public TcpClient 9 | { 10 | 11 | public: 12 | NetClient(EventLoop * loop, NetEvent * nevent); 13 | 14 | ~NetClient(); 15 | 16 | protected: 17 | virtual TcpSocket * createSocket(); 18 | virtual void onSocket(TcpSocket * conn, int argv); 19 | 20 | private: 21 | NetEvent * _netevent; 22 | }; 23 | 24 | #endif -------------------------------------------------------------------------------- /src/network/NetConnect.cpp: -------------------------------------------------------------------------------- 1 | #include "NetConnect.h" 2 | #include "NetPacket.h" 3 | #include "CommonPool.h" 4 | #include "NetEvent.h" 5 | 6 | NetConnect::NetConnect(NetEvent * nevent,uint32 buffersize) : 7 | _netevent(nevent), 8 | TcpSocket(buffersize), 9 | mReadPacket(NULL) 10 | { 11 | } 12 | 13 | NetConnect::~NetConnect() 14 | { 15 | if (mReadPacket) 16 | { 17 | recyclePacket(mReadPacket); 18 | mReadPacket = NULL; 19 | } 20 | } 21 | 22 | void NetConnect::on_msgbuffer(MessageBuffer * buffer) 23 | { 24 | while (buffer->GetActiveSize() > 0) 25 | { 26 | if (!mReadPacket) 27 | { 28 | //create packet obj 29 | mReadPacket = createPacket(); 30 | mReadPacket->wpos(0); 31 | } 32 | 33 | //read head 34 | if (mReadPacket->isHeadFull() == false) 35 | { 36 | uint32 rlen = mReadPacket->readHead(buffer->GetReadPointer(), buffer->GetActiveSize()); 37 | buffer->ReadCompleted(rlen); 38 | } 39 | else 40 | { 41 | //read body 42 | int32 needsize = mReadPacket->getMarkLen() + MSG_HEAD_SIZE - mReadPacket->wpos(); 43 | if (needsize > 0) 44 | { 45 | int32 wsize = buffer->GetActiveSize() >= needsize ? needsize : buffer->GetActiveSize(); 46 | if (wsize > 0) 47 | { 48 | mReadPacket->append(buffer->GetReadPointer(), wsize); 49 | buffer->ReadCompleted(wsize); 50 | } 51 | } 52 | 53 | //new packet 54 | if (mReadPacket->wpos() == mReadPacket->getMarkLen() + MSG_HEAD_SIZE) 55 | { 56 | _netevent->onMsg(this, mReadPacket->getMsgType(), mReadPacket); 57 | 58 | // recycle packet, todo 优化成mReadPacket的内存重复利用 59 | recyclePacket(mReadPacket); 60 | mReadPacket = NULL; 61 | } 62 | } 63 | }//while 64 | } 65 | void NetConnect::on_clsesocket() 66 | { 67 | _netevent->onClose(this); 68 | _netevent->destroyConnect(this); 69 | } 70 | 71 | 72 | void NetConnect::sendMsg(uint32 msgtype, NetPacket * pack) 73 | { 74 | NetPacket * packet = createPacket(); 75 | packet->moveData(pack); 76 | packet->writeHead(msgtype); 77 | 78 | TcpSocket::write(packet); 79 | } 80 | 81 | void NetConnect::sendMsg(uint32 msgtype, const char* msg, uint32 len) 82 | { 83 | 84 | NetPacket *pack = createPacket(); 85 | 86 | pack->append(msg, len); 87 | pack->writeHead(msgtype); 88 | 89 | TcpSocket::write(pack); 90 | } 91 | 92 | 93 | NetPacket* NetConnect::createPacket() 94 | { 95 | return new NetPacket; 96 | } -------------------------------------------------------------------------------- /src/network/NetConnect.h: -------------------------------------------------------------------------------- 1 | #ifndef NET_CONNECT_H 2 | #define NET_CONNECT_H 3 | 4 | #include "TcpSocket.h" 5 | 6 | class NetPacket; 7 | class NetEvent; 8 | class NetConnect : public TcpSocket 9 | { 10 | public: 11 | NetConnect(NetEvent * nevent, uint32 buffersize = MESSAGE_BUFFER_SIZE); 12 | 13 | ~NetConnect(); 14 | 15 | // write data to socket 16 | void sendMsg(uint32 msgtype, NetPacket * pack); 17 | void sendMsg(uint32 msgtype, const char * msg, uint32 len); 18 | // lua call 19 | void sendPacket(uint32 msgtype, NetPacket * pack) { sendMsg(msgtype, pack);} 20 | void sendData(uint32 msgtype, std::string_view view) { sendMsg(msgtype, view.data(), view.size()); } 21 | 22 | protected: 23 | NetPacket* createPacket(); 24 | //virtual void recyclePacket(BasePacket* pack); 25 | 26 | virtual void on_msgbuffer(MessageBuffer * buffer); 27 | virtual void on_clsesocket(); 28 | private: 29 | NetPacket * mReadPacket; 30 | NetEvent * _netevent; 31 | }; 32 | 33 | #endif -------------------------------------------------------------------------------- /src/network/NetEvent.cpp: -------------------------------------------------------------------------------- 1 | #include "NetEvent.h" 2 | #include "NetConnect.h" 3 | 4 | NetEvent::NetEvent() 5 | { 6 | 7 | } 8 | 9 | NetEvent::~NetEvent() 10 | { 11 | 12 | } 13 | 14 | NetConnect * NetEvent::createConnect() 15 | { 16 | return new NetConnect(this, MESSAGE_BUFFER_SIZE); 17 | } 18 | 19 | void NetEvent::destroyConnect(NetConnect * conn) 20 | { 21 | if (conn) 22 | { 23 | delete conn; 24 | } 25 | } -------------------------------------------------------------------------------- /src/network/NetEvent.h: -------------------------------------------------------------------------------- 1 | #ifndef NET_EVENT_H 2 | #define NET_EVENT_H 3 | 4 | class NetConnect; 5 | class NetPacket; 6 | 7 | class NetEvent 8 | { 9 | public: 10 | NetEvent(); 11 | virtual ~NetEvent(); 12 | 13 | virtual NetConnect * createConnect(); 14 | virtual void destroyConnect(NetConnect * conn); 15 | 16 | virtual void onAccept(NetConnect * conn){}; 17 | virtual void onConnect(NetConnect * conn, int argv){}; 18 | virtual void onClose(NetConnect * conn){}; 19 | virtual void onMsg(NetConnect * conn, int msgtype, NetPacket * pack){}; 20 | 21 | }; 22 | 23 | #endif -------------------------------------------------------------------------------- /src/network/NetPacket.cpp: -------------------------------------------------------------------------------- 1 | #include "NetPacket.h" 2 | 3 | NetPacket::NetPacket() 4 | { 5 | zero(); 6 | } 7 | 8 | void NetPacket::zero() 9 | { 10 | this->_storage->resize(MSG_HEAD_SIZE); 11 | _wpos = MSG_HEAD_SIZE; 12 | _rpos = MSG_HEAD_SIZE; 13 | } 14 | 15 | int32 NetPacket::getHeadSize() 16 | { 17 | return MSG_HEAD_SIZE; 18 | } 19 | int32 NetPacket::getMarkLen() 20 | { 21 | // message head mark length 22 | return getValue(MSG_LEN_POS); 23 | } 24 | 25 | int NetPacket::getMsgType() 26 | { 27 | return getValue(MSG_TYPE_POS); 28 | } 29 | 30 | bool NetPacket::isHeadFull() 31 | { 32 | return wpos() >= MSG_HEAD_SIZE; 33 | } 34 | 35 | // send msg call 36 | int32 NetPacket::sendSize() 37 | { 38 | return wpos(); 39 | } 40 | char * NetPacket::sendStream() 41 | { 42 | return (char *)contents(); 43 | } 44 | 45 | void NetPacket::writeHead(int msgtype) 46 | { 47 | setValue(MSG_LEN_POS, getBodySize()); 48 | setValue(MSG_TYPE_POS, msgtype); 49 | } 50 | 51 | uint32 NetPacket::readHead(const uint8 * p, uint32 size) 52 | { 53 | int rsize = MSG_HEAD_SIZE - wpos(); 54 | if (rsize <= 0) 55 | { 56 | return 0; 57 | } 58 | 59 | rsize = size >= rsize ? rsize : size; 60 | 61 | put(wpos(), p, rsize); 62 | _wpos += rsize; 63 | 64 | return rsize; 65 | } -------------------------------------------------------------------------------- /src/network/NetPacket.h: -------------------------------------------------------------------------------- 1 | #ifndef MSG_PACKET_H 2 | #define MSG_PACKET_H 3 | 4 | #include "BasePacket.h" 5 | 6 | #define MSG_LEN_POS 0 7 | #define MSG_TYPE_POS sizeof(uint32) 8 | #define MSG_HEAD_SIZE (sizeof(uint32) + sizeof(uint32)) 9 | 10 | // packet head( msglen:uint32, msgtype:uint32 ) 11 | class NetPacket : public BasePacket 12 | { 13 | 14 | public: 15 | NetPacket(); 16 | 17 | virtual void zero(); 18 | virtual int32 getHeadSize(); 19 | 20 | // read msg call 21 | virtual int32 getMarkLen(); // message head mark length 22 | virtual int getMsgType(); 23 | virtual bool isHeadFull(); 24 | 25 | // send msg call 26 | virtual int32 sendSize(); 27 | virtual char * sendStream(); 28 | 29 | void writeHead(int msgtype); 30 | uint32 readHead(const uint8 * p, uint32 size); 31 | }; 32 | 33 | #endif -------------------------------------------------------------------------------- /src/network/NetServer.cpp: -------------------------------------------------------------------------------- 1 | #include "NetServer.h" 2 | #include "NetConnect.h" 3 | #include "NetEvent.h" 4 | 5 | NetServer::NetServer(EventLoop * loop, NetEvent * nevent) : 6 | TcpServer(loop), 7 | _netevent(nevent) 8 | { 9 | } 10 | 11 | TcpSocket * NetServer::createSocket() 12 | { 13 | NetConnect * conn = _netevent->createConnect(); 14 | return (TcpSocket *)conn; 15 | } 16 | 17 | void NetServer::onSocket(TcpSocket * connect) 18 | { 19 | _netevent->onAccept((NetConnect *)connect); 20 | } -------------------------------------------------------------------------------- /src/network/NetServer.h: -------------------------------------------------------------------------------- 1 | #ifndef NET_SERVER_H 2 | #define NET_SERVER_H 3 | 4 | #include "TcpServer.h" 5 | 6 | class NetConnect; 7 | class NetEvent; 8 | class NetServer : public TcpServer 9 | { 10 | public: 11 | NetServer(EventLoop * loop, NetEvent * nevent); 12 | 13 | protected: 14 | 15 | virtual TcpSocket * createSocket(); 16 | virtual void onSocket(TcpSocket * connect); 17 | 18 | private: 19 | NetEvent * _netevent; 20 | }; 21 | 22 | #endif -------------------------------------------------------------------------------- /src/network/ProtoPacket.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | template 4 | void readProto(T* buff, MSG & msg) 5 | { 6 | const char * data = buff->getBodyData(); 7 | msg.ParseFromArray((const void*)data, buff->getBodySize()); 8 | } 9 | 10 | template 11 | void writeProto(T* buff, MSG & msg) 12 | { 13 | int size = msg.ByteSizeLong(); 14 | buff->setWriteSize(size); 15 | const char* data = buff->getBodyData(); 16 | msg.SerializeToArray((void *)data, size); 17 | } -------------------------------------------------------------------------------- /src/network/TcpClient.cpp: -------------------------------------------------------------------------------- 1 | #include "TcpClient.h" 2 | #include "XLog.h" 3 | #include "EventLoop.h" 4 | 5 | TcpClient::TcpClient(EventLoop * loop) : 6 | mLoop(loop->getLoop()) 7 | { 8 | 9 | } 10 | 11 | 12 | TcpClient::~TcpClient() 13 | { 14 | } 15 | 16 | int TcpClient::connect(const char * ip, int port, bool ipv6, int argv) 17 | { 18 | struct user_connect : public uv_connect_t 19 | { 20 | TcpSocket * conn; 21 | int argv; 22 | }; 23 | 24 | user_connect * user_conn = new user_connect; 25 | user_conn->conn = createSocket(); 26 | user_conn->data = this; //data type is void* 27 | user_conn->argv = argv; 28 | 29 | uv_tcp_init(mLoop, user_conn->conn->getUvTcp()); 30 | 31 | sockaddr_storage iaddr; 32 | if (ipv6) { 33 | uv_ip6_addr(ip, port, (sockaddr_in6*)&iaddr); 34 | } 35 | else { 36 | uv_ip4_addr(ip, port, (sockaddr_in*)&iaddr); 37 | } 38 | 39 | return uv_tcp_connect(user_conn, user_conn->conn->getUvTcp(), (sockaddr*)&iaddr, 40 | [](uv_connect_t* req, int status) { 41 | user_connect *user_conn = (user_connect*)req; 42 | TcpClient * self = (TcpClient *)user_conn->data; 43 | 44 | if (status < 0) { 45 | uv_close((uv_handle_t*)(user_conn->conn->getUvTcp()), NULL); 46 | self->onSocket(NULL, user_conn->argv); //通过第一个参数让user判断是否连接成功 47 | } 48 | else { 49 | user_conn->conn->on_read_start(); 50 | self->onSocket(user_conn->conn, user_conn->argv); 51 | } 52 | 53 | delete user_conn; 54 | }); 55 | } -------------------------------------------------------------------------------- /src/network/TcpClient.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "TcpSocket.h" 4 | 5 | class EventLoop; 6 | class TcpClient 7 | { 8 | public: 9 | TcpClient(EventLoop * loop); 10 | virtual ~TcpClient(); 11 | 12 | virtual int connect(const char * ip, int port, bool ipv6 = false, int argv = 0); 13 | 14 | protected: 15 | virtual TcpSocket * createSocket() = 0; 16 | virtual void onSocket(TcpSocket * conn, int argv) = 0; 17 | protected: 18 | uv_loop_t * mLoop; 19 | }; 20 | 21 | -------------------------------------------------------------------------------- /src/network/TcpServer.cpp: -------------------------------------------------------------------------------- 1 | #include "XLog.h" 2 | #include "TcpServer.h" 3 | #include "EventLoop.h" 4 | 5 | TcpServer::TcpServer(EventLoop * loop) : 6 | mLoop(loop->getLoop()) 7 | { 8 | m_uv_tcp.data = this; 9 | uv_tcp_init(mLoop, &m_uv_tcp); 10 | } 11 | 12 | TcpServer::~TcpServer() 13 | { 14 | 15 | } 16 | 17 | int TcpServer::listen(const char * ip, int port, bool ipv6) 18 | { 19 | 20 | /* 21 | #ifdef USE_IPV6_ADDR 22 | struct sockaddr_in6 mAddr; 23 | uv_ip6_addr(ip, port, &mAddr); 24 | #else 25 | struct sockaddr_in mAddr; 26 | uv_ip4_addr(ip, port, &mAddr); 27 | #endif 28 | */ 29 | sockaddr_storage iaddr; 30 | if (ipv6) { 31 | uv_ip6_addr(ip, port, (sockaddr_in6*)&iaddr); 32 | } 33 | else { 34 | uv_ip4_addr(ip, port, (sockaddr_in*)&iaddr); 35 | } 36 | 37 | uv_tcp_bind(&m_uv_tcp, (const struct sockaddr*)&iaddr, 0); 38 | return uv_listen((uv_stream_t*)&m_uv_tcp, DEFAULT_BACKLOG, on_new_connection); 39 | } 40 | 41 | void TcpServer::shutdown() 42 | { 43 | uv_close((uv_handle_s *)&m_uv_tcp, [](uv_handle_t* handle){ 44 | 45 | }); 46 | } 47 | 48 | void TcpServer::on_new_connection(uv_stream_t *server, int status) 49 | { 50 | if (status < 0) { 51 | ERROR_LOG("New connection error %s\n", uv_strerror(status)); 52 | return; 53 | } 54 | 55 | TcpServer * self = (TcpServer *)server->data; //构造函数时设置data为自己 56 | // new connect 57 | TcpSocket * connect = self->createSocket(); 58 | connect->clear(); 59 | connect->init_uv_tcp(self->mLoop); 60 | if (connect->accept(server) == 0) { 61 | 62 | connect->on_read_start(); 63 | self->onSocket(connect); 64 | } 65 | else { 66 | uv_close((uv_handle_t*)connect->getUvTcp(), NULL); 67 | ERROR_LOG("New connection close %s\n", uv_strerror(status)); 68 | delete connect; 69 | } 70 | } -------------------------------------------------------------------------------- /src/network/TcpServer.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/lua-server/6008c764295d822f82a89ed8d579559bbcf1adfa/src/network/TcpServer.h -------------------------------------------------------------------------------- /src/network/TcpSocket.h: -------------------------------------------------------------------------------- 1 | #ifndef CONNECT_H 2 | #define CONNECT_H 3 | 4 | #define SOCKET_BUFFER_SIZE 65536 5 | 6 | #include "BaseType.h" 7 | #include "libuv/include/uv.h" 8 | #include "MessageBuffer.h" 9 | #include 10 | 11 | 12 | class TcpSocketBase 13 | { 14 | public: 15 | TcpSocketBase(uint32 buffersize = MESSAGE_BUFFER_SIZE); 16 | virtual ~TcpSocketBase(); 17 | 18 | int init_uv_tcp(uv_loop_t * loop){ return uv_tcp_init(loop, getUvTcp()); } 19 | int accept(uv_stream_t *server){ return uv_accept(server, (uv_stream_t*)getUvTcp()); } 20 | 21 | void clear(); 22 | void close(); 23 | void on_read_start(); 24 | int write(const uv_buf_t * buf, uint32 size); 25 | 26 | //static void createConnect(uv_loop_t * loop, const char * ip, int port, std::function &)> cb, bool ipv6 = false); 27 | 28 | std::string localIP() const; 29 | int localPort() const; 30 | std::string remoteIP() const; 31 | int remotePort() const; 32 | uv_tcp_t* getUvTcp() { return &m_uv_tcp; } 33 | 34 | protected: 35 | 36 | virtual void on_msgbuffer(MessageBuffer * buffer){}; 37 | virtual void on_clsesocket(){}; 38 | virtual void on_writecomplete(){}; 39 | 40 | private: 41 | 42 | static void alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf); 43 | static void echo_read(uv_stream_t *tcp, ssize_t nread, const uv_buf_t *buf); 44 | static void on_uv_close(uv_handle_t* handle); 45 | static void echo_write(uv_write_t *req, int status); 46 | 47 | private: 48 | uv_tcp_t m_uv_tcp; 49 | uv_write_t m_write_t; 50 | MessageBuffer mBuffer; 51 | }; 52 | 53 | #include 54 | #include 55 | class BasePacket; 56 | class TcpSocket : public TcpSocketBase 57 | { 58 | public: 59 | TcpSocket(uint32 buffersize = MESSAGE_BUFFER_SIZE); 60 | ~TcpSocket(); 61 | 62 | virtual void zero(); 63 | virtual void release(); 64 | 65 | void setUserdata(void* userdata) { _userdata = userdata; } 66 | void* getUserdata() { return _userdata; } 67 | void setUsernum(uint64 num) { _userdata = (void*)num; } 68 | uint64 getUsernum() { return (uint64)_userdata; } 69 | protected: 70 | 71 | void write(BasePacket * packet); 72 | 73 | BasePacket* createPacket(); 74 | virtual void recyclePacket(BasePacket * packet); 75 | virtual void on_writecomplete(); 76 | private: 77 | bool isSending(); 78 | void send_top_msg(); 79 | private: 80 | std::vector mSending; 81 | std::list mSendPackets; 82 | 83 | void* _userdata; 84 | }; 85 | 86 | 87 | #endif -------------------------------------------------------------------------------- /src/network/UdpClient.cpp: -------------------------------------------------------------------------------- 1 | #include "UdpClient.h" 2 | #include "EventLoop.h" 3 | #include "XLog.h" 4 | 5 | UdpClient::UdpClient(EventLoop * loop) 6 | { 7 | _udp.data = this; 8 | uv_udp_init(loop->getLoop(), &_udp); 9 | } 10 | 11 | 12 | UdpClient::~UdpClient() 13 | { 14 | } 15 | 16 | /* 17 | int UdpClient::connect(const char * server_ip, int server_port, int port, bool ipv6) 18 | { 19 | int err_code = 0; 20 | 21 | //sockaddr_storage _server_addr; 22 | if (ipv6) 23 | err_code = uv_ip6_addr(server_ip, server_port, (sockaddr_in6 *)&_server_addr); 24 | else 25 | err_code = uv_ip4_addr(server_ip, server_port, (sockaddr_in *)&_server_addr); 26 | 27 | if (err_code < 0) 28 | { 29 | ERROR_LOG("uv_ip4_addr error %s\n", uv_strerror(err_code)); 30 | return -1; 31 | } 32 | 33 | sockaddr_storage _listen_addr; 34 | if (ipv6) 35 | err_code = uv_ip6_addr("0.0.0.0", port, (sockaddr_in6 *)&_listen_addr); 36 | else 37 | err_code = uv_ip4_addr("0.0.0.0", port, (sockaddr_in *)&_listen_addr); 38 | 39 | if (err_code < 0) 40 | { 41 | ERROR_LOG("uv_ip4_addr error %s\n", uv_strerror(err_code)); 42 | return -2; 43 | } 44 | 45 | err_code = uv_udp_bind(&_udp, (sockaddr *)&_listen_addr, 0); 46 | if (err_code < 0) 47 | { 48 | ERROR_LOG("uv_udp_bind error %s\n", uv_strerror(err_code)); 49 | return -3; 50 | } 51 | err_code = uv_udp_recv_start(&_udp, UdpClient::alloc_buffer, UdpClient::on_read); 52 | if (err_code < 0) 53 | { 54 | ERROR_LOG("uv_udp_recv_start error %s\n", uv_strerror(err_code)); 55 | return -4; 56 | } 57 | 58 | return 0; 59 | } 60 | */ 61 | 62 | int UdpClient::connect(const char * server_ip, int server_port, bool ipv6) 63 | { 64 | int err_code = 0; 65 | 66 | //sockaddr_storage _server_addr; 67 | if (ipv6) 68 | err_code = uv_ip6_addr(server_ip, server_port, (sockaddr_in6 *)&_server_addr); 69 | else 70 | err_code = uv_ip4_addr(server_ip, server_port, (sockaddr_in *)&_server_addr); 71 | 72 | if (err_code < 0) 73 | { 74 | ERROR_LOG("uv_ip4_addr error %s\n", uv_strerror(err_code)); 75 | return -1; 76 | } 77 | 78 | err_code = uv_udp_recv_start(&_udp, UdpClient::alloc_buffer, UdpClient::on_read); 79 | if (err_code < 0) 80 | { 81 | ERROR_LOG("uv_udp_recv_start error %s\n", uv_strerror(err_code)); 82 | return -2; 83 | } 84 | 85 | return 0; 86 | } 87 | 88 | void UdpClient::alloc_buffer(uv_handle_t * handle, size_t suggested_size, uv_buf_t * buf) 89 | { 90 | static const int bufflen = 65536; 91 | static char buff[bufflen]; 92 | 93 | buf->base = buff; 94 | buf->len = bufflen; 95 | } 96 | 97 | void UdpClient::on_read(uv_udp_t * handle, ssize_t nread, const uv_buf_t * rcvbuf, const sockaddr * addr, unsigned flags) 98 | { 99 | UdpClient * self = static_cast(handle->data); 100 | do 101 | { 102 | if (nread <= 0) 103 | { 104 | break; 105 | } 106 | 107 | self->onMessage(addr, rcvbuf->base, nread); 108 | 109 | } while (false); 110 | } 111 | 112 | int UdpClient::writeToServer(char * buff, int len) 113 | { 114 | uv_buf_t msg = uv_buf_init(buff, len); 115 | int send_len = uv_udp_try_send(&_udp, &msg, 1, (const struct sockaddr*)&_server_addr); 116 | return send_len; 117 | } -------------------------------------------------------------------------------- /src/network/UdpClient.h: -------------------------------------------------------------------------------- 1 | /************************************************************************ 2 | * @file UdpClient.h 3 | * @brief udp client 4 | * @author jiangwang 5 | * @data 2019-12-12 6 | * @version 0.1 7 | ************************************************************************/ 8 | 9 | #pragma once 10 | #include "libuv/include/uv.h" 11 | 12 | class EventLoop; 13 | class UdpClient 14 | { 15 | public: 16 | UdpClient(EventLoop * loop); 17 | virtual ~UdpClient(); 18 | 19 | //int connect(const char * server_ip, int server_port, int port, bool ipv6 = false); 20 | int connect(const char * server_ip, int server_port, bool ipv6 = false); 21 | int writeToServer(char * buff, int len); 22 | 23 | protected: 24 | virtual void onMessage(const sockaddr * addr, const char * buff, ssize_t len) = 0; 25 | 26 | private: 27 | static void alloc_buffer(uv_handle_t * handle, size_t suggested_size, uv_buf_t * buf); 28 | static void on_read(uv_udp_t * handle, ssize_t nread, const uv_buf_t * rcvbuf, const sockaddr * addr, unsigned flags); 29 | 30 | protected: 31 | uv_udp_t _udp; 32 | sockaddr_storage _server_addr; 33 | }; 34 | 35 | -------------------------------------------------------------------------------- /src/network/UdpPacket.cpp: -------------------------------------------------------------------------------- 1 | #include "UdpPacket.h" 2 | 3 | 4 | UdpPacket::UdpPacket() 5 | { 6 | zero(); 7 | } 8 | 9 | 10 | UdpPacket::~UdpPacket() 11 | { 12 | } 13 | 14 | void UdpPacket::zero() 15 | { 16 | this->_storage->resize(UDP_PACK_HEAD_SIZE); 17 | _wpos = UDP_PACK_HEAD_SIZE; 18 | _rpos = UDP_PACK_HEAD_SIZE; 19 | } 20 | 21 | int32 UdpPacket::getHeadSize() 22 | { 23 | return UDP_PACK_HEAD_SIZE; 24 | } 25 | 26 | void UdpPacket::initSize(int s) 27 | { 28 | if (s > size()) 29 | { 30 | this->_storage->resize(s); 31 | } 32 | } 33 | 34 | int UdpPacket::getMsgType() 35 | { 36 | return getValue(0); 37 | } 38 | 39 | void UdpPacket::writeHead(int msgtype) 40 | { 41 | put(0, msgtype); 42 | } 43 | 44 | void UdpPacket::writeComplete(uint32 size) 45 | { 46 | _wpos += size; 47 | } 48 | 49 | int32 UdpPacket::getMarkLen() 50 | { 51 | // udp There is no need to mark the length 52 | return 0; 53 | } 54 | 55 | // send msg call 56 | int32 UdpPacket::sendSize() 57 | { 58 | return wpos(); 59 | } 60 | 61 | char * UdpPacket::sendStream() 62 | { 63 | return (char *)contents(); 64 | } -------------------------------------------------------------------------------- /src/network/UdpPacket.h: -------------------------------------------------------------------------------- 1 | /************************************************************************ 2 | * @file UdpPacket.h 3 | * @brief udp message packet 4 | * @author jiangwang 5 | * @data 2019-12-12 6 | * @version 0.1 7 | ************************************************************************/ 8 | 9 | #pragma once 10 | 11 | #include "BasePacket.h" 12 | 13 | #define UDP_PACK_HEAD_SIZE sizeof(uint32) 14 | 15 | class UdpPacket : public BasePacket 16 | { 17 | public: 18 | UdpPacket(); 19 | ~UdpPacket(); 20 | 21 | virtual void zero(); 22 | virtual int32 getHeadSize(); 23 | void initSize(int size); 24 | 25 | // read msg call 26 | virtual int32 getMarkLen(); // message head mark length 27 | virtual int getMsgType(); 28 | 29 | // send msg call 30 | virtual int32 sendSize(); 31 | virtual char * sendStream(); 32 | 33 | void writeHead(int msgtype); 34 | void writeComplete(uint32 size); 35 | }; 36 | 37 | -------------------------------------------------------------------------------- /src/network/UdpServer.cpp: -------------------------------------------------------------------------------- 1 | #include "UdpServer.h" 2 | #include "EventLoop.h" 3 | #include "XLog.h" 4 | 5 | UdpServer::UdpServer(EventLoop * loop) 6 | { 7 | _m_udp.data = this; 8 | uv_udp_init(loop->getLoop(), &_m_udp); 9 | } 10 | 11 | 12 | UdpServer::~UdpServer() 13 | { 14 | } 15 | 16 | int UdpServer::start(const char * ip, int port, bool ipv6) 17 | { 18 | 19 | sockaddr_storage iaddr; 20 | if (ipv6) { 21 | uv_ip6_addr(ip, port, (sockaddr_in6*)&iaddr); 22 | } 23 | else { 24 | uv_ip4_addr(ip, port, (sockaddr_in*)&iaddr); 25 | } 26 | 27 | int errcode = uv_udp_bind(&_m_udp, (const struct sockaddr *)&iaddr, UV_UDP_REUSEADDR); 28 | if (errcode) 29 | { 30 | ERROR_LOG("uv_udp_bind error %s\n", uv_strerror(errcode)); 31 | return -1; 32 | } 33 | 34 | errcode = uv_udp_recv_start(&_m_udp, alloc_buffer, on_read); 35 | if (errcode) 36 | { 37 | ERROR_LOG("uv_udp_recv_start error %s\n", uv_strerror(errcode)); 38 | return -1; 39 | } 40 | 41 | return 0; 42 | } 43 | 44 | void UdpServer::alloc_buffer(uv_handle_t * handle, size_t suggested_size, uv_buf_t * buf) 45 | { 46 | static const int bufflen = 65536; 47 | static char buff[bufflen]; 48 | 49 | buf->base = buff; 50 | buf->len = bufflen; 51 | 52 | } 53 | 54 | void UdpServer::on_read(uv_udp_t * handle, ssize_t nread, const uv_buf_t * rcvbuf, const sockaddr * addr, unsigned flags) 55 | { 56 | UdpServer * server = (UdpServer *)handle->data; 57 | server->onMessage(addr, rcvbuf->base, nread); 58 | } -------------------------------------------------------------------------------- /src/network/UdpServer.h: -------------------------------------------------------------------------------- 1 | /************************************************************************ 2 | * @file UdpServer.h 3 | * @brief udp server 4 | * @author jiangwang 5 | * @data 2019-12-12 6 | * @version 0.1 7 | ************************************************************************/ 8 | 9 | #pragma once 10 | #include "libuv/include/uv.h" 11 | 12 | class EventLoop; 13 | class UdpServer 14 | { 15 | public: 16 | UdpServer(EventLoop * loop); 17 | virtual ~UdpServer(); 18 | 19 | int start(const char * ip, int port, bool ipv6 = false); 20 | 21 | protected: 22 | virtual void onMessage(const sockaddr * addr, const char * buff, ssize_t len) = 0; 23 | 24 | private: 25 | static void alloc_buffer(uv_handle_t * handle, size_t suggested_size, uv_buf_t * buf); 26 | static void on_read(uv_udp_t * handle, ssize_t nread, const uv_buf_t * rcvbuf, const sockaddr * addr, unsigned flags); 27 | 28 | protected: 29 | uv_udp_t _m_udp; 30 | }; 31 | 32 | -------------------------------------------------------------------------------- /src/network/WebSocketConnect.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/lua-server/6008c764295d822f82a89ed8d579559bbcf1adfa/src/network/WebSocketConnect.h -------------------------------------------------------------------------------- /src/network/WebSocketEvent.cpp: -------------------------------------------------------------------------------- 1 | #include "WebSocketEvent.h" 2 | #include "WebSocketConnect.h" 3 | 4 | 5 | WebSocketEvent::WebSocketEvent() 6 | { 7 | } 8 | 9 | 10 | WebSocketEvent::~WebSocketEvent() 11 | { 12 | } 13 | 14 | 15 | WebSocketConnect * WebSocketEvent::createConnect() 16 | { 17 | return new WebSocketConnect(this); 18 | } 19 | 20 | void WebSocketEvent::destroyConnect(WebSocketConnect * conn) 21 | { 22 | if (conn) 23 | delete conn; 24 | } -------------------------------------------------------------------------------- /src/network/WebSocketEvent.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/lua-server/6008c764295d822f82a89ed8d579559bbcf1adfa/src/network/WebSocketEvent.h -------------------------------------------------------------------------------- /src/network/WebSocketPacket.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/lua-server/6008c764295d822f82a89ed8d579559bbcf1adfa/src/network/WebSocketPacket.cpp -------------------------------------------------------------------------------- /src/network/WebSocketPacket.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/lua-server/6008c764295d822f82a89ed8d579559bbcf1adfa/src/network/WebSocketPacket.h -------------------------------------------------------------------------------- /src/network/WebSocketServer.cpp: -------------------------------------------------------------------------------- 1 | #include "WebSocketServer.h" 2 | #include "WebSocketEvent.h" 3 | 4 | 5 | WebSocketServer::WebSocketServer(EventLoop * loop, WebSocketEvent * wevent): 6 | TcpServer(loop), 7 | __m_event(wevent) 8 | { 9 | } 10 | 11 | 12 | WebSocketServer::~WebSocketServer() 13 | { 14 | } 15 | 16 | 17 | TcpSocket * WebSocketServer::createSocket() 18 | { 19 | return (TcpSocket *)__m_event->createConnect(); 20 | } 21 | 22 | void WebSocketServer::onSocket(TcpSocket * connect) 23 | { 24 | __m_event->onAccept((WebSocketConnect *)connect); 25 | } -------------------------------------------------------------------------------- /src/network/WebSocketServer.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunxvming/lua-server/6008c764295d822f82a89ed8d579559bbcf1adfa/src/network/WebSocketServer.h -------------------------------------------------------------------------------- /src/protolua/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.1) 2 | project(protolua) 3 | 4 | add_definitions(-std=c++11) 5 | aux_source_directory(. DIR_SRCS) 6 | file(GLOB_RECURSE DIR_INCS *.h *.hpp) 7 | source_group("Include Files" FILES ${DIR_INCS}) 8 | 9 | if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang") 10 | set(CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS "${CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS} -undefined dynamic_lookup") 11 | endif() 12 | 13 | IF (CMAKE_SYSTEM_NAME MATCHES "Linux" OR CMAKE_SYSTEM_NAME MATCHES "Darwin") 14 | add_library(${PROJECT_NAME} SHARED ${DIR_SRCS} ${DIR_INCS}) 15 | target_link_libraries(${PROJECT_NAME} libprotobuf) 16 | ELSE () 17 | add_library(${PROJECT_NAME} SHARED ${DIR_SRCS} ${DIR_INCS}) 18 | target_link_libraries(${PROJECT_NAME} lua-${LUA_VERSION} libprotobuf) 19 | ENDIF (CMAKE_SYSTEM_NAME MATCHES "Linux" OR CMAKE_SYSTEM_NAME MATCHES "Darwin") 20 | 21 | 22 | include_directories(../) 23 | include_directories(../thirdparty/lua-${LUA_VERSION}/src) 24 | include_directories(../thirdparty/protobuf/src) 25 | add_dependencies(${PROJECT_NAME} lua-${LUA_VERSION} libprotobuf) 26 | -------------------------------------------------------------------------------- /src/protolua/README.md: -------------------------------------------------------------------------------- 1 | Protocol Buffers for lua 2 | =================================================== 3 | 4 | https://github.com/jinjiazhang/protolua/ -------------------------------------------------------------------------------- /src/protolua/lua51ext.h: -------------------------------------------------------------------------------- 1 | #ifndef _JINJIAZHANG_PROTOVER_H_ 2 | #define _JINJIAZHANG_PROTOVER_H_ 3 | 4 | #include 5 | #include "lua.hpp" 6 | 7 | #ifndef lua_toint64 8 | #define lua_toint64 lua_toint64 9 | #endif 10 | 11 | #ifndef lua_pushint64 12 | #define lua_pushint64 lua_pushint64 13 | #endif 14 | 15 | inline int lua_geti(lua_State *L, int idx, lua_Integer n) 16 | { 17 | lua_pushinteger(L, n); 18 | lua_gettable(L, idx); 19 | return lua_gettop(L); 20 | } 21 | 22 | inline void lua_seti(lua_State *L, int idx, lua_Integer n) 23 | { 24 | lua_pushinteger(L, n); 25 | lua_insert(L, -2); 26 | lua_settable(L, idx - 1); 27 | } 28 | 29 | inline int lua_absindex(lua_State *L, int idx) 30 | { 31 | if (idx <= 0 && idx > LUA_REGISTRYINDEX) 32 | idx = lua_gettop(L) + idx + 1; 33 | return idx; 34 | } 35 | 36 | inline lua_Integer luaL_len(lua_State *L, int idx) 37 | { 38 | return luaL_getn(L, idx); 39 | } 40 | 41 | inline void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup) { 42 | luaL_checkstack(L, nup, "too many upvalues"); 43 | for (; l->name != NULL; l++) { /* fill the table with given functions */ 44 | int i; 45 | for (i = 0; i < nup; i++) /* copy upvalues to the top */ 46 | lua_pushvalue(L, -nup); 47 | lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ 48 | lua_setfield(L, -(nup + 2), l->name); 49 | } 50 | lua_pop(L, nup); /* remove upvalues */ 51 | } 52 | 53 | inline long long lua_toint64(lua_State *L, int idx) 54 | { 55 | if (lua_type(L, idx) == LUA_TSTRING) 56 | { 57 | return atoll(lua_tostring(L, idx)); 58 | } 59 | return (long long)lua_tonumber(L, idx); 60 | } 61 | 62 | inline void lua_pushint64(lua_State *L, long long value) 63 | { 64 | // because of #define LUA_NUMBER_FMT "%.14g" 65 | if (abs(value) > 99999999999999) 66 | { 67 | char str[32]; 68 | lua_pushstring(L, _i64toa(value, str, 10)); 69 | return; 70 | } 71 | 72 | lua_pushnumber(L, (lua_Number)value); 73 | } 74 | 75 | #endif -------------------------------------------------------------------------------- /src/protolua/protolua.cpp: -------------------------------------------------------------------------------- 1 | #include "protolua.h" 2 | 3 | using namespace google::protobuf; 4 | using namespace google::protobuf::compiler; 5 | 6 | void proto_init(lua_State* L); 7 | bool proto_reload(lua_State* L); 8 | 9 | // ret = proto.parse("preson.proto") 10 | static int parse(lua_State *L) 11 | { 12 | assert(lua_gettop(L) == 1); 13 | luaL_checktype(L, 1, LUA_TSTRING); 14 | const char* file = lua_tostring(L, 1); 15 | if (!proto_parse(file, L)) 16 | { 17 | proto_error("proto.parse fail, file=%s", file); 18 | lua_pushboolean(L, false); 19 | return 1; 20 | } 21 | 22 | lua_pushboolean(L, true); 23 | return 1; 24 | } 25 | 26 | // is_exist = proto.exist("Person") 27 | static int exist(lua_State *L) 28 | { 29 | assert(lua_gettop(L) == 1); 30 | luaL_checktype(L, 1, LUA_TSTRING); 31 | const char* proto = lua_tostring(L, 1); 32 | if (!g_importer->pool()->FindMessageTypeByName(proto)) 33 | { 34 | lua_pushboolean(L, 0); 35 | } 36 | else 37 | { 38 | lua_pushboolean(L, 1); 39 | } 40 | return 1; 41 | } 42 | 43 | // person = proto.create("Person") 44 | static int create(lua_State *L) 45 | { 46 | assert(lua_gettop(L) == 1); 47 | luaL_checktype(L, 1, LUA_TSTRING); 48 | const char* proto = lua_tostring(L, 1); 49 | if (!proto_create(proto, L)) 50 | { 51 | proto_error("proto.create fail, proto=%s", proto); 52 | return 0; 53 | } 54 | 55 | return lua_gettop(L) - 1; 56 | } 57 | 58 | // data = proto.encode("Person", person) 59 | static int encode(lua_State *L) 60 | { 61 | assert(lua_gettop(L) == 2); 62 | luaL_checktype(L, 1, LUA_TSTRING); 63 | luaL_checktype(L, 2, LUA_TTABLE); 64 | const char* proto = lua_tostring(L, 1); 65 | if (!proto_encode(proto, L, 2, 0, 0)) 66 | { 67 | proto_error("proto.encode fail, proto=%s", proto); 68 | return 0; 69 | } 70 | 71 | return lua_gettop(L) - 2; 72 | } 73 | 74 | // person = proto.decode("Person", data) 75 | static int decode(lua_State *L) 76 | { 77 | assert(lua_gettop(L) == 2); 78 | size_t size = 0; 79 | luaL_checktype(L, 1, LUA_TSTRING); 80 | const char* proto = lua_tostring(L, 1); 81 | luaL_checktype(L, 2, LUA_TSTRING); 82 | const char* data = lua_tolstring(L, 2, &size); 83 | if (!proto_decode(proto, L, data, size)) 84 | { 85 | proto_error("proto.decode fail, proto=%s", proto); 86 | return 0; 87 | } 88 | 89 | return lua_gettop(L) - 2; 90 | } 91 | 92 | // data = proto.pack("Person", name, id, email) 93 | static int pack(lua_State *L) 94 | { 95 | assert(lua_gettop(L) >= 1); 96 | int stack = lua_gettop(L); 97 | luaL_checktype(L, 1, LUA_TSTRING); 98 | const char* proto = lua_tostring(L, 1); 99 | if (!proto_pack(proto, L, 2, stack, 0, 0)) 100 | { 101 | proto_error("proto.pack fail, proto=%s", proto); 102 | return 0; 103 | } 104 | 105 | return lua_gettop(L) - stack; 106 | } 107 | 108 | // name, id, email = proto.unpack("Person", data) 109 | static int unpack(lua_State *L) 110 | { 111 | assert(lua_gettop(L) == 2); 112 | size_t size = 0; 113 | luaL_checktype(L, 1, LUA_TSTRING); 114 | const char* proto = lua_tostring(L, 1); 115 | const char* data = lua_tolstring(L, 2, &size); 116 | if (!proto_unpack(proto, L, data, size)) 117 | { 118 | proto_error("proto.unpack fail, proto=%s", proto); 119 | return 0; 120 | } 121 | 122 | return lua_gettop(L) - 2; 123 | } 124 | 125 | // proto.reload() 126 | static int reload(lua_State *L) 127 | { 128 | if (!proto_reload(L)) 129 | { 130 | lua_pushboolean(L, false); 131 | return 1; 132 | } 133 | 134 | lua_pushboolean(L, true); 135 | return 1; 136 | } 137 | 138 | static const struct luaL_Reg protoLib[]={ 139 | {"parse", parse}, 140 | {"exist", exist}, 141 | {"create", create}, 142 | {"encode", encode}, 143 | {"decode", decode}, 144 | {"pack", pack}, 145 | {"unpack", unpack}, 146 | {"reload", reload}, 147 | {NULL, NULL} 148 | }; 149 | 150 | int luaopen_protolua(lua_State* L) 151 | { 152 | proto_init(L); 153 | lua_newtable(L); 154 | luaL_setfuncs(L, protoLib, 0); 155 | lua_setglobal(L, "proto"); 156 | return 0; 157 | } 158 | -------------------------------------------------------------------------------- /src/protolua/protolua.h: -------------------------------------------------------------------------------- 1 | #ifndef _JINJIAZHANG_PROTOLUA_H_ 2 | #define _JINJIAZHANG_PROTOLUA_H_ 3 | 4 | #include "lua.hpp" 5 | 6 | #if LUA_VERSION_NUM == 501 7 | #include "lua51ext.h" 8 | #endif 9 | 10 | #include "google/protobuf/dynamic_message.h" 11 | #include "google/protobuf/compiler/importer.h" 12 | 13 | #ifdef _JINJIAZHANG_PROTOLOG_H_ 14 | #define proto_trace(fmt, ...) log_trace(fmt, __VA_ARGS__) 15 | #define proto_debug(fmt, ...) log_debug(fmt, __VA_ARGS__) 16 | #define proto_info(fmt, ...) log_info(fmt, __VA_ARGS__) 17 | #define proto_warn(fmt, ...) log_warn(fmt, __VA_ARGS__) 18 | #define proto_error(fmt, ...) log_error(fmt, __VA_ARGS__) 19 | #define proto_fatal(fmt, ...) log_fatal(fmt, __VA_ARGS__) 20 | #else 21 | #define proto_trace(fmt, ...) printf("[trace]" fmt "\n", __VA_ARGS__) 22 | #define proto_debug(fmt, ...) printf("[debug]" fmt "\n", __VA_ARGS__) 23 | #define proto_info(fmt, ...) printf("[info]" fmt "\n", __VA_ARGS__) 24 | #define proto_warn(fmt, ...) printf("[warn]" fmt "\n", __VA_ARGS__) 25 | #define proto_error(fmt, ...) printf("[error]" fmt "\n", __VA_ARGS__) 26 | #define proto_fatal(fmt, ...) printf("[fatal]" fmt "\n", __VA_ARGS__) 27 | #endif 28 | 29 | #ifndef lua_toint64 30 | #define lua_toint64 lua_tointeger 31 | #endif 32 | 33 | #ifndef lua_pushint64 34 | #define lua_pushint64 lua_pushinteger 35 | #endif 36 | 37 | #ifdef _WIN32 38 | #define PROTO_API extern "C" __declspec(dllexport) 39 | #else 40 | #define PROTO_API extern "C" 41 | #endif 42 | 43 | #define PROTO_DO(exp) { if(!(exp)) return false; } 44 | #define PROTO_ASSERT(exp) { if(!(exp)) return false; } 45 | 46 | bool proto_parse(const char* file, lua_State* L); 47 | bool proto_create(const char* proto, lua_State* L); 48 | bool proto_encode(const char* proto, lua_State* L, int index, char* output, size_t* size); 49 | bool proto_decode(const char* proto, lua_State* L, const char* input, size_t size); 50 | bool proto_pack(const char* proto, lua_State* L, int start, int end, char* output, size_t* size); 51 | bool proto_unpack(const char* proto, lua_State* L, const char* input, size_t size); 52 | 53 | extern google::protobuf::compiler::Importer* g_importer; 54 | extern google::protobuf::DynamicMessageFactory* g_factory; 55 | 56 | #endif -------------------------------------------------------------------------------- /src/script/Lua_Base.cpp: -------------------------------------------------------------------------------- 1 | #include "sol/sol.hpp" 2 | #include "TcpSocket.h" 3 | #include "BasePacket.h" 4 | #include "ByteBuffer.h" 5 | #include "CommonPool.h" 6 | 7 | void init_buffer_pool(int count) 8 | { 9 | CommPool::init(count); 10 | } 11 | 12 | void luabind_basepacket(sol::state & lua) 13 | { 14 | lua["init_buffer_pool"] = &init_buffer_pool; 15 | 16 | lua.new_usertype("BasePacket", 17 | "getInt8", &BasePacket::getInt8, 18 | "getUint8", &BasePacket::getUint8, 19 | "getInt16", &BasePacket::getInt16, 20 | "getUint16", &BasePacket::getUint16, 21 | "getInt32", &BasePacket::getInt32, 22 | "getUint32", &BasePacket::getUint32, 23 | "getInt64", &BasePacket::getInt64, 24 | "getUint64", &BasePacket::getUint64, 25 | "getFloat", &BasePacket::getFloat, 26 | "getDouble", &BasePacket::getDouble, 27 | "getString", &BasePacket::getString, 28 | 29 | "pushInt8", &BasePacket::pushInt8, 30 | "pushUint8", &BasePacket::pushUint8, 31 | "pushInt16", &BasePacket::pushInt16, 32 | "pushUint16", &BasePacket::pushUint16, 33 | "pushInt32", &BasePacket::pushInt32, 34 | "pushUint32", &BasePacket::pushUint32, 35 | "pushInt64", &BasePacket::pushInt64, 36 | "pushUint64", &BasePacket::pushUint64, 37 | "pushFloat", &BasePacket::pushFloat, 38 | "pushDouble", &BasePacket::pushDouble, 39 | "pushString", &BasePacket::pushString, 40 | 41 | "moveData", & BasePacket::moveData, 42 | "wpos", &BasePacket::writePos, 43 | "rpos", &BasePacket::readPos, 44 | "readData", &BasePacket::readData, 45 | "writeData", &BasePacket::writeData); 46 | 47 | 48 | lua.new_usertype("TcpSocket", 49 | "close", &TcpSocket::close, 50 | "localIP", &TcpSocket::localIP, 51 | "localPort", &TcpSocket::localPort, 52 | "remoteIP", &TcpSocket::remoteIP, 53 | "remotePort", &TcpSocket::remotePort, 54 | "setUserdata", &TcpSocket::setUserdata, 55 | "getUserdata", &TcpSocket::getUserdata, 56 | "setUsernum", &TcpSocket::setUsernum, 57 | "getUsernum", &TcpSocket::getUsernum); 58 | } -------------------------------------------------------------------------------- /src/script/Lua_Common.cpp: -------------------------------------------------------------------------------- 1 | #include "sol/sol.hpp" 2 | #include "UTimer.h" 3 | #include "XLog.h" 4 | #include "Tools.h" 5 | #include "XFile.h" 6 | #include "XTime.h" 7 | 8 | class Lua_XLog 9 | { 10 | public: 11 | static void info_log(const char * log) { INFO_LOG(log); } 12 | static void warning_log(const char * log) { WARNING_LOG(log); } 13 | static void error_log(const char * log) { ERROR_LOG(log); } 14 | }; 15 | 16 | void luabind_common(sol::state & lua) 17 | { 18 | // file 19 | lua["writeFile"] = &XFile::writeFile; 20 | lua["isExist"] = &XFile::isExist; 21 | lua["mkdir"] = &XFile::mkdir; 22 | lua["rmdir"] = &XFile::rmdir; 23 | lua["createDir"] = &XFile::createDirectory; 24 | 25 | // log 26 | lua["infoLog"] = &Lua_XLog::info_log; 27 | lua["warningLog"] = &Lua_XLog::warning_log; 28 | lua["errorLog"] = &Lua_XLog::error_log; 29 | 30 | // timer 31 | lua.new_usertype("UTimer", 32 | "start", &UTimer::start, 33 | "stop", &UTimer::stop); 34 | 35 | // tool 36 | lua["sleep"] = &Tools::sleep; 37 | lua["gbk_utf8"] = &Tools::gbkToUtf8; 38 | lua["utf8_gbk"] = &Tools::utf8ToGbk; 39 | lua["srand"] = &Tools::srand; 40 | lua["random"] = &Tools::random; 41 | 42 | // time 43 | lua["isLeapYear"] = &XTime::isLeapYear; 44 | lua["yearMonthDays"] = &XTime::yearMonthDays; 45 | lua["milliStamp"] = &XTime::milliStamp; 46 | lua["microStamp"] = &XTime::microStamp; 47 | lua["stamp"] = &XTime::stamp; 48 | lua["iclock"] = &XTime::iclock; 49 | } -------------------------------------------------------------------------------- /src/script/Lua_CsvFile.cpp: -------------------------------------------------------------------------------- 1 | #include "sol/sol.hpp" 2 | #include "CsvParser.h" 3 | #include 4 | #include "BaseType.h" 5 | 6 | class Lua_CsvParser : public CsvParser 7 | { 8 | public: 9 | Lua_CsvParser(const char * file, int startline = 1, char sep = '\t'): 10 | CsvParser(file, startline, sep) 11 | { 12 | 13 | } 14 | 15 | //------->get 16 | int8 getInt8(int row, const char * name) { return getValue (row, name); } 17 | uint8 getUint8(int row, const char * name) { return getValue (row, name); } 18 | int16 getInt16(int row, const char * name) { return getValue (row, name); } 19 | uint16 getUint16(int row, const char * name) { return getValue (row, name); } 20 | int32 getInt32(int row, const char * name) { return getValue (row, name); } 21 | uint32 getUint32(int row, const char * name) { return getValue (row, name); } 22 | int64 getInt64(int row, const char * name) { return getValue (row, name); } 23 | uint64 getUint64(int row, const char * name) { return getValue (row, name); } 24 | float getFloat(int row, const char * name) { return getValue (row, name); } 25 | double getDouble(int row, const char * name) { return getValue (row, name); } 26 | std::string getString(int row, const char * name) { return getValue (row, name); } 27 | }; 28 | 29 | void luabind_csvpar(sol::state & lua) 30 | { 31 | lua.new_usertype("CsvParser", 32 | sol::constructors(), 33 | "getInt8", &Lua_CsvParser::getInt8, 34 | "getUint8", &Lua_CsvParser::getUint8, 35 | "getInt16", &Lua_CsvParser::getInt16, 36 | "getUint16", &Lua_CsvParser::getUint16, 37 | "getInt32", &Lua_CsvParser::getInt32, 38 | "getUint32", &Lua_CsvParser::getUint32, 39 | "getInt64", &Lua_CsvParser::getInt64, 40 | "getUint64", &Lua_CsvParser::getUint64, 41 | "getFloat", &Lua_CsvParser::getFloat, 42 | "getDouble", &Lua_CsvParser::getDouble, 43 | "getString", &Lua_CsvParser::getString, 44 | 45 | "row", &Lua_CsvParser::row); 46 | } -------------------------------------------------------------------------------- /src/script/Lua_EventLoop.cpp: -------------------------------------------------------------------------------- 1 | #include "EventLoop.h" 2 | #include "sol/sol.hpp" 3 | 4 | /* 5 | class EventLoop : public Singleton 6 | { 7 | public: 8 | void init(); 9 | 10 | int run(); 11 | void stop(); 12 | void exit(); 13 | uv_loop_t* getLoop(); 14 | 15 | private: 16 | uv_loop_t* mLoop; 17 | }; 18 | */ 19 | 20 | 21 | class Lua_EventLoop 22 | { 23 | public: 24 | static void init() { EventLoop::Instance()->init(); } 25 | static void run() { EventLoop::Instance()->run(); } 26 | static void stop() { EventLoop::Instance()->stop(); } 27 | static void exit() { EventLoop::Instance()->exit(); } 28 | }; 29 | 30 | 31 | 32 | void luabind_eventloop(sol::state & lua) 33 | { 34 | //lua["eventobj"] = EventLoop::Instance(); 35 | lua["event_init"] = &Lua_EventLoop::init; 36 | lua["event_run"] = &Lua_EventLoop::run; 37 | lua["event_stop"] = &Lua_EventLoop::stop; 38 | lua["event_exit"] = &Lua_EventLoop::exit; 39 | } -------------------------------------------------------------------------------- /src/script/Lua_HttpServer.cpp: -------------------------------------------------------------------------------- 1 | #include "sol/sol.hpp" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "HttpParam.h" 8 | #include "HttpServer.h" 9 | #include "HttpConnect.h" 10 | #include "EventLoop.h" 11 | 12 | class Lua_HttpServer : public HttpServer 13 | { 14 | public: 15 | Lua_HttpServer() : 16 | HttpServer(EventLoop::Instance()) 17 | { 18 | 19 | } 20 | }; 21 | 22 | void luabind_httpserver(sol::state & lua) 23 | { 24 | lua.new_usertype("HttpParam", 25 | sol::constructors(), 26 | "find", &HttpParam::find, 27 | "getStr", &HttpParam::getStr, 28 | "getInt", &HttpParam::getInt, 29 | "getFloat", &HttpParam::getFloat); 30 | 31 | lua.new_usertype("HttpConnect", 32 | sol::base_classes, sol::bases(), 33 | "sendMsg", &HttpConnect::sendData, 34 | "autoMsg", &HttpConnect::autoMsg); 35 | 36 | lua.new_usertype("HttpServer", 37 | "listen", &Lua_HttpServer::listen, 38 | "shutdown", &Lua_HttpServer::shutdown, 39 | "addGet", &Lua_HttpServer::addGet, 40 | "addPost", &Lua_HttpServer::addPost); 41 | } -------------------------------------------------------------------------------- /src/script/Lua_Json.cpp: -------------------------------------------------------------------------------- 1 | #include "sol/sol.hpp" 2 | #include "Json.h" 3 | #include "JsonReader.h" 4 | 5 | using namespace jwEngine; 6 | 7 | JValue * json_to_value(JBaseObj * obj) 8 | { 9 | return static_cast(obj); 10 | } 11 | 12 | JArray * json_to_array(JBaseObj * obj) 13 | { 14 | return static_cast(obj); 15 | } 16 | 17 | JSonObj * json_to_obj(JBaseObj * obj) 18 | { 19 | return static_cast(obj); 20 | } 21 | 22 | void luabind_json(sol::state & lua) 23 | { 24 | 25 | lua["json_to_value"] = &json_to_value; 26 | lua["json_to_array"] = &json_to_array; 27 | lua["json_to_obj"] = &json_to_obj; 28 | lua["json_parser"] = &JsonReader::parser; 29 | lua["json_error"] = &JsonReader::getError; 30 | lua["json_write"] = &JsonReader::write; 31 | 32 | lua.new_usertype("JBaseObj", 33 | "type", &JBaseObj::type); 34 | 35 | lua.new_usertype("JValue", 36 | sol::base_classes, sol::bases(), 37 | "setInt", &JValue::setInt, 38 | "setFloat", &JValue::setFloat, 39 | "setStr", &JValue::setStr, 40 | "setBool", &JValue::setBool, 41 | "setNull", &JValue::setNull); 42 | 43 | lua.new_usertype("JArray", 44 | sol::base_classes, sol::bases(), 45 | "pushInt", &JArray::pushInt, 46 | "pushFloat", &JArray::pushFloat, 47 | "pushStr", &JArray::pushStr, 48 | "pushBool", &JArray::pushBool, 49 | "pushNull", &JArray::pushNull, 50 | 51 | "getInt", &JArray::getInt, 52 | "getFloat", &JArray::getFloat, 53 | "getStr", &JArray::getStr, 54 | "getBool", &JArray::getBool, 55 | "isNull", &JArray::isNull, 56 | 57 | "setInt", &JArray::setInt, 58 | "setFloat", &JArray::setFloat, 59 | "setStr", &JArray::setStr, 60 | "setBool", &JArray::setBool, 61 | "setNull", &JArray::setNull, 62 | 63 | "createArray", &JArray::createArray, 64 | "createObj", &JArray::createObj, 65 | "getJsonObj", &JArray::getJsonObj, 66 | 67 | "remove", &JArray::remove, 68 | "size", &JArray::size); 69 | 70 | lua.new_usertype("JSonObj", 71 | sol::base_classes, sol::bases(), 72 | "getInt", &JSonObj::getInt, 73 | "getFloat", &JSonObj::getFloat, 74 | "getStr", &JSonObj::getStr, 75 | "getBool", &JSonObj::getBool, 76 | "isNull", &JSonObj::isNull, 77 | 78 | "setInt", &JSonObj::setInt, 79 | "setFloat", &JSonObj::setFloat, 80 | "setStr", &JSonObj::setStr, 81 | "setBool", &JSonObj::setBool, 82 | "setNull", &JSonObj::setNull, 83 | 84 | "createArray", &JSonObj::createArray, 85 | "createObj", &JSonObj::createObj, 86 | "getJsonObj", &JSonObj::getJsonObj, 87 | 88 | "remove", &JSonObj::remove); 89 | 90 | 91 | lua.new_usertype ("JsonBuff", 92 | sol::constructors()); 93 | } -------------------------------------------------------------------------------- /src/script/Lua_KcpServer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "sol/sol.hpp" 3 | 4 | #include "KcpEvent.h" 5 | #include "KcpClient.h" 6 | #include "KcpServer.h" 7 | #include "UdpPacket.h" 8 | #include "KcpSession.h" 9 | #include "EventLoop.h" 10 | 11 | class Lua_KcpServer : public KcpServer, public KcpEvent 12 | { 13 | public: 14 | Lua_KcpServer() : 15 | KcpServer(EventLoop::Instance(), this) 16 | { 17 | 18 | } 19 | 20 | protected: 21 | 22 | 23 | virtual void onAccept(KcpSession * conn) { 24 | on_accept(conn); 25 | }; 26 | virtual void onClose(KcpSession * conn) { 27 | on_close(conn); 28 | }; 29 | virtual void onMsg(KcpSession * conn, int msgtype, UdpPacket * pack) { 30 | on_msg(conn, msgtype, pack); 31 | }; 32 | 33 | public: 34 | std::function on_accept; 35 | std::function on_close; 36 | std::function on_msg; 37 | }; 38 | 39 | class Lua_KcpClient : public KcpClient, public KcpEvent 40 | { 41 | public: 42 | Lua_KcpClient() : 43 | KcpClient(EventLoop::Instance(), this) 44 | { 45 | 46 | } 47 | 48 | protected: 49 | 50 | virtual void onConnect(KcpSession * conn) { 51 | on_connect(conn); 52 | }; 53 | virtual void onClose(KcpSession * conn) { 54 | on_close(conn); 55 | }; 56 | virtual void onMsg(KcpSession * conn, int msgtype, UdpPacket * pack) { 57 | on_msg(conn, msgtype, pack); 58 | }; 59 | 60 | public: 61 | std::function on_connect; 62 | std::function on_close; 63 | std::function on_msg; 64 | }; 65 | 66 | 67 | void luabind_kcpserver(sol::state & lua) 68 | { 69 | 70 | lua.new_usertype("KcpSession", 71 | "sendPacket", &KcpSession::sendPacket, 72 | "sendMsg", &KcpSession::sendData, 73 | "flushKcp", &KcpSession::flushKcp, 74 | "getSessionId", &KcpSession::getSessionId); 75 | 76 | lua.new_usertype("KcpClient", 77 | //sol::constructors(), 78 | "createSession", &Lua_KcpClient::createSession, 79 | "closeSession", &Lua_KcpClient::closeSession, 80 | "on_connect", &Lua_KcpClient::on_connect, 81 | "on_close", &Lua_KcpClient::on_close, 82 | "on_msg", &Lua_KcpClient::on_msg); 83 | 84 | lua.new_usertype("KcpServer", 85 | //sol::constructors(), 86 | "start", &Lua_KcpServer::start, 87 | "closeSession", &Lua_KcpServer::closeSession, 88 | "shutdown", &Lua_KcpServer::shutdown, 89 | "on_accept", &Lua_KcpServer::on_accept, 90 | "on_close", &Lua_KcpServer::on_close, 91 | "on_msg", &Lua_KcpServer::on_msg); 92 | 93 | lua.new_usertype("KcpPacket", 94 | sol::base_classes, sol::bases()); 95 | } -------------------------------------------------------------------------------- /src/script/Lua_NetServer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "sol/sol.hpp" 3 | 4 | #include "NetEvent.h" 5 | #include "NetClient.h" 6 | #include "NetServer.h" 7 | #include "NetPacket.h" 8 | #include "NetConnect.h" 9 | #include "EventLoop.h" 10 | 11 | class Lua_NetServer : public NetServer, public NetEvent 12 | { 13 | public: 14 | Lua_NetServer() : 15 | NetServer(EventLoop::Instance(), this) 16 | { 17 | 18 | } 19 | 20 | protected: 21 | 22 | 23 | virtual void onAccept(NetConnect * conn) { 24 | on_accept(conn); 25 | }; 26 | virtual void onClose(NetConnect * conn) { 27 | on_close(conn); 28 | }; 29 | virtual void onMsg(NetConnect * conn, int msgtype, NetPacket * pack) { 30 | on_msg(conn, msgtype, pack); 31 | }; 32 | 33 | public: 34 | std::function on_accept; 35 | std::function on_close; 36 | std::function on_msg; 37 | }; 38 | 39 | class Lua_NetClient : public NetClient, public NetEvent 40 | { 41 | public: 42 | Lua_NetClient(): 43 | NetClient(EventLoop::Instance(), this) 44 | { 45 | 46 | } 47 | 48 | protected: 49 | 50 | virtual void onConnect(NetConnect * conn, int argv) { 51 | on_connect(conn, argv); 52 | }; 53 | virtual void onClose(NetConnect * conn) { 54 | on_close(conn); 55 | }; 56 | virtual void onMsg(NetConnect * conn, int msgtype, NetPacket * pack) { 57 | on_msg(conn, msgtype, pack); 58 | }; 59 | 60 | public: 61 | std::function on_connect; 62 | std::function on_close; 63 | std::function on_msg; 64 | }; 65 | 66 | void luabind_netserver(sol::state & lua) 67 | { 68 | lua.new_usertype("NetConnect", 69 | sol::base_classes, sol::bases(), 70 | "sendPacket", &NetConnect::sendPacket, 71 | "sendMsg", &NetConnect::sendData); 72 | 73 | lua.new_usertype("NetClient", 74 | //sol::constructors(), 75 | "connect", &Lua_NetClient::connect, 76 | "on_connect", &Lua_NetClient::on_connect, 77 | "on_close", &Lua_NetClient::on_close, 78 | "on_msg", &Lua_NetClient::on_msg); 79 | 80 | lua.new_usertype("NetServer", 81 | //sol::constructors(), 82 | "listen", &Lua_NetServer::listen, 83 | "shutdown", &Lua_NetServer::shutdown, 84 | "on_accept", &Lua_NetServer::on_accept, 85 | "on_close", &Lua_NetServer::on_close, 86 | "on_msg", &Lua_NetServer::on_msg); 87 | 88 | lua.new_usertype("NetPacket", 89 | sol::base_classes, sol::bases()); 90 | } -------------------------------------------------------------------------------- /src/script/Lua_WebSockServer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "sol/sol.hpp" 3 | 4 | #include "WebSocketEvent.h" 5 | #include "WebSocketServer.h" 6 | #include "WebSocketPacket.h" 7 | #include "WebSocketConnect.h" 8 | #include "EventLoop.h" 9 | 10 | class Lua_WebSocketServer : public WebSocketServer, public WebSocketEvent 11 | { 12 | public: 13 | Lua_WebSocketServer() : 14 | WebSocketServer(EventLoop::Instance(), this) 15 | { 16 | 17 | } 18 | 19 | protected: 20 | 21 | 22 | virtual void onAccept(WebSocketConnect * conn) { 23 | on_accept(conn); 24 | }; 25 | virtual void onClose(WebSocketConnect * conn) { 26 | on_close(conn); 27 | }; 28 | virtual void onMsg(WebSocketConnect * conn, WebSocketPacket * pack) { 29 | on_msg(conn, pack); 30 | }; 31 | 32 | public: 33 | std::function on_accept; 34 | std::function on_close; 35 | std::function on_msg; 36 | }; 37 | 38 | void luabind_websocket(sol::state & lua) 39 | { 40 | lua.new_usertype("WebSocketConnect", 41 | sol::base_classes, sol::bases(), 42 | "sendPacket", &WebSocketConnect::sendPacket, 43 | "sendMsg", &WebSocketConnect::sendData); 44 | 45 | lua.new_usertype("WebSocketServer", 46 | "listen", &Lua_WebSocketServer::listen, 47 | "shutdown", &Lua_WebSocketServer::shutdown, 48 | "on_accept", &Lua_WebSocketServer::on_accept, 49 | "on_close", &Lua_WebSocketServer::on_close, 50 | "on_msg", &Lua_WebSocketServer::on_msg); 51 | 52 | lua.new_usertype("WebSocketPacket", 53 | sol::base_classes, sol::bases()); 54 | } -------------------------------------------------------------------------------- /src/script/main.cpp: -------------------------------------------------------------------------------- 1 | extern "C" { 2 | #include "lua.h" 3 | #include "lauxlib.h" 4 | #include "lualib.h" 5 | } 6 | 7 | #include 8 | #include 9 | 10 | #include "sol/sol.hpp" 11 | 12 | 13 | extern void luabind_basepacket(sol::state & lua); 14 | extern void luabind_netserver(sol::state & lua); 15 | extern void luabind_kcpserver(sol::state & lua); 16 | extern void luabind_websocket(sol::state & lua); 17 | extern void luabind_eventloop(sol::state & lua); 18 | extern void luabind_httpserver(sol::state & lua); 19 | extern void luabind_mysql(sol::state & lua); 20 | extern void luabind_redis(sol::state & lua); 21 | extern void luabind_common(sol::state & lua); 22 | extern void luabind_csvpar(sol::state & lua); 23 | extern void luabind_json(sol::state & lua); 24 | 25 | extern int luaopen_protolua(lua_State* L); 26 | 27 | int main(int argc, char* argv[]) 28 | { 29 | sol::state lua; 30 | lua.open_libraries(); 31 | 32 | // bind c++ && lua 33 | luabind_basepacket(lua); 34 | luabind_netserver(lua); 35 | luabind_kcpserver(lua); 36 | luabind_websocket(lua); 37 | luabind_eventloop(lua); 38 | luabind_httpserver(lua); 39 | luabind_mysql(lua); 40 | luabind_redis(lua); 41 | luabind_common(lua); 42 | luabind_csvpar(lua); 43 | luabind_json(lua); 44 | 45 | luaopen_protolua(lua.lua_state()); 46 | 47 | if (luaL_dofile(lua.lua_state(), argv[1]) == 1) { 48 | if (lua_isstring(lua.lua_state(), -1)) { 49 | printf("load lua file error:%s\n", lua_tostring(lua.lua_state(), -1)); 50 | } 51 | } 52 | 53 | system("pause"); 54 | return 0; 55 | } -------------------------------------------------------------------------------- /src/utils/HttpParser.cpp: -------------------------------------------------------------------------------- 1 | #include "HttpParser.h" 2 | 3 | HttpSettings::HttpSettings() 4 | { 5 | llhttp_settings_init(this); 6 | 7 | this->on_url = [](llhttp_t* _, const char* at, size_t length)->int { 8 | HttpParser* parser = (HttpParser*)(_); 9 | return parser->getUrl()->parse(at, length); 10 | }; 11 | } 12 | 13 | HttpSettings http_settings; 14 | 15 | HttpSettings* getHttpSettings() 16 | { 17 | return &http_settings; 18 | } 19 | 20 | HttpParser::HttpParser() 21 | { 22 | 23 | } 24 | 25 | void HttpParser::zero() 26 | { 27 | llhttp_init(this, HTTP_REQUEST, &http_settings); 28 | } 29 | 30 | #include 31 | bool HttpParser::parser(const char* buf, int len) 32 | { 33 | enum llhttp_errno err = llhttp_execute(this, buf, len); 34 | if (err != HPE_OK) 35 | { 36 | fprintf(stderr, "Parse error: %s %s\n", llhttp_errno_name(err), llhttp_t::reason); 37 | return false; 38 | } 39 | 40 | return true; 41 | } 42 | -------------------------------------------------------------------------------- /src/utils/HttpParser.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "llhttp.h" 4 | #include "ParseUrl.h" 5 | 6 | // 7 | struct HttpSettings : public llhttp_settings_t 8 | { 9 | public: 10 | HttpSettings(); 11 | }; 12 | 13 | HttpSettings* getHttpSettings(); 14 | 15 | class HttpParser : public llhttp_t 16 | { 17 | public: 18 | HttpParser(); 19 | void zero(); 20 | 21 | bool parser(const char* buf, int len); 22 | uint64_t contentLen() { return llhttp_t::content_length; } 23 | uint8_t method() { return llhttp_t::method; } 24 | bool isClose() { return llhttp_should_keep_alive(this) == 0; } 25 | ParseUrl* getUrl() { return &m_url; } 26 | llhttp_t* getParser() { return this; } 27 | private: 28 | ParseUrl m_url; 29 | }; 30 | 31 | -------------------------------------------------------------------------------- /src/utils/Json.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace jwEngine 8 | { 9 | enum eJOSN_TYPE 10 | { 11 | eJ_INT, // int 12 | eJ_FLOAT, // float 13 | eJ_NULL, // null 14 | eJ_STRING,// string 15 | eJ_BOOL, // bool 16 | eJ_ARRAY, // array 17 | eJ_OBJ, // obj 18 | }; 19 | class JBaseObj 20 | { 21 | public: 22 | JBaseObj(); 23 | virtual ~JBaseObj(); 24 | 25 | int type = eJ_NULL; // eJOSN_TYPE 26 | 27 | virtual void write(std::string & str, bool layout = true, int depth = 0) = 0; 28 | }; 29 | 30 | // base value 31 | class JValue: public JBaseObj 32 | { 33 | public: 34 | JValue(); 35 | ~JValue(); 36 | void setInt(int v); 37 | void setFloat(float v); 38 | void setStr(const char * v); 39 | void setBool(bool v); 40 | void setNull(); 41 | 42 | virtual void write(std::string & str, bool layout = true, int depth = 0); 43 | 44 | public: 45 | union 46 | { 47 | int iv; 48 | float fv; 49 | bool bv; 50 | }; 51 | std::string sv; 52 | }; 53 | 54 | class JSonObj; 55 | class JsonReader; 56 | 57 | // array type 58 | class JArray: public JBaseObj 59 | { 60 | friend JsonReader; 61 | public: 62 | JArray(); 63 | ~JArray(); 64 | 65 | void pushInt(int v); 66 | void pushFloat(float v); 67 | void pushStr(const char * v); 68 | void pushBool(bool v); 69 | void pushNull(); 70 | 71 | int getInt(int idx); 72 | float getFloat(int idx); 73 | bool getBool(int idx); 74 | const char * getStr(int idx); 75 | bool isNull(int idx); 76 | 77 | void setInt(int idx, int v); 78 | void setFloat(int idx, float v); 79 | void setStr(int idx, const char * v); 80 | void setBool(int idx, bool v); 81 | void setNull(int idx); 82 | 83 | void remove(int idx); 84 | 85 | int size(); 86 | JArray * createArray(); 87 | JSonObj * createObj(); 88 | JBaseObj * getJsonObj(int idx); 89 | 90 | virtual void write(std::string & str, bool layout = true, int depth = 0); 91 | private: 92 | std::vector items; 93 | }; 94 | 95 | class JSonObj : public JBaseObj 96 | { 97 | friend JsonReader; 98 | public: 99 | JSonObj(); 100 | ~JSonObj(); 101 | 102 | int getInt(std::string key); 103 | float getFloat(std::string key); 104 | bool getBool(std::string key); 105 | const char * getStr(std::string key); 106 | bool isNull(std::string key); 107 | 108 | void setInt(std::string key, int v); 109 | void setFloat(std::string key, float v); 110 | void setStr(std::string key, const char * v); 111 | void setBool(std::string key, bool v); 112 | void setNull(std::string key); 113 | 114 | void remove(std::string key); 115 | 116 | JArray * createArray(std::string key); 117 | JSonObj * createObj(std::string key); 118 | JBaseObj * getJsonObj(std::string key); 119 | 120 | virtual void write(std::string & str, bool layout = true, int depth = 0); 121 | 122 | private: 123 | std::map maps; 124 | }; 125 | } -------------------------------------------------------------------------------- /src/utils/JsonReader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace jwEngine 6 | { 7 | class JBaseObj; 8 | class JsonReader; 9 | class JsonBuff 10 | { 11 | friend JsonReader; 12 | public: 13 | JsonBuff(const char *str) { p = (char *)str; } 14 | ~JsonBuff() { if (obj != nullptr) { delete obj; obj = nullptr; } } 15 | 16 | // delete function 17 | JsonBuff(JsonBuff &) = delete; 18 | void operator =(JsonBuff &) = delete; 19 | 20 | const char *skip() { while (p && *p && (unsigned char)*p <= 32) p++; return p; } 21 | const char *curr() { return p; } 22 | const char *go(int len = 1) { p += len; return p; } 23 | private: 24 | char * p; 25 | JBaseObj * obj = nullptr; 26 | }; 27 | 28 | class JsonReader 29 | { 30 | public: 31 | 32 | JsonReader & operator | (JsonReader & r) { 33 | return *this; 34 | } 35 | 36 | //read 37 | static JBaseObj * parser(JsonBuff * buff); 38 | static std::string getError(JsonBuff * buff); 39 | 40 | static std::string write(JBaseObj * obj,bool layout = true); 41 | private: 42 | static bool readStr(std::string & outstr, JsonBuff * buff); 43 | static JBaseObj * readBase(JsonBuff * buff); 44 | static JBaseObj * readArray(JsonBuff * buff); 45 | static JBaseObj * readObj(JsonBuff * buff); 46 | static JBaseObj * reader(JsonBuff * buff); 47 | }; 48 | } -------------------------------------------------------------------------------- /src/utils/ParseUrl.cpp: -------------------------------------------------------------------------------- 1 | #include "ParseUrl.h" 2 | #include "http_parser.h" 3 | #include 4 | 5 | ParseUrl::ParseUrl() 6 | { 7 | m_buff = NULL; 8 | m_url = (struct http_parser_url*)malloc(sizeof(struct http_parser_url)); 9 | http_parser_url_init(m_url); 10 | } 11 | 12 | ParseUrl::~ParseUrl() 13 | { 14 | if (m_url) { 15 | free(m_url); 16 | m_url = NULL; 17 | } 18 | } 19 | 20 | int ParseUrl::parse(const char* buf, int len) 21 | { 22 | m_buff = buf; 23 | return http_parser_parse_url(buf, len, 0, m_url); 24 | } 25 | 26 | bool ParseUrl::haveParam() 27 | { 28 | return ((m_url->field_set & (1 << UF_QUERY)) != 0); 29 | } 30 | 31 | std::string_view ParseUrl::getPath() 32 | { 33 | return std::string_view(m_buff + m_url->field_data[UF_PATH].off, m_url->field_data[UF_PATH].len); 34 | } 35 | std::string_view ParseUrl::getParam() 36 | { 37 | return std::string_view(m_buff + m_url->field_data[UF_QUERY].off, m_url->field_data[UF_QUERY].len); 38 | } -------------------------------------------------------------------------------- /src/utils/ParseUrl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct http_parser_url; 6 | class ParseUrl 7 | { 8 | public: 9 | ParseUrl(); 10 | ~ParseUrl(); 11 | 12 | int parse(const char * buf, int len); 13 | bool haveParam(); 14 | std::string_view getPath(); 15 | std::string_view getParam(); 16 | 17 | private: 18 | struct http_parser_url * m_url; 19 | const char * m_buff; 20 | }; -------------------------------------------------------------------------------- /tests/allTests.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char **argv) { 4 | ::testing::InitGoogleTest(&argc, argv); 5 | return RUN_ALL_TESTS(); 6 | } 7 | -------------------------------------------------------------------------------- /tests/libuv_tests.cpp: -------------------------------------------------------------------------------- 1 | #define XCTEST 2 | 3 | #include 4 | #include 5 | #include 6 | #include "uv.h" 7 | 8 | TEST(libuv, hello_world) 9 | { 10 | 11 | uv_loop_t *loop = static_cast(malloc(sizeof(uv_loop_t))); 12 | uv_loop_init(loop); 13 | 14 | printf("Now quitting.\n"); 15 | uv_run(loop, UV_RUN_DEFAULT); 16 | 17 | uv_loop_close(loop); 18 | free(loop); 19 | 20 | } 21 | 22 | 23 | -------------------------------------------------------------------------------- /tests/sol2_tests.cpp: -------------------------------------------------------------------------------- 1 | #define XCTEST 2 | 3 | extern "C" { 4 | #include "lua.h" 5 | #include "lauxlib.h" 6 | #include "lualib.h" 7 | } 8 | 9 | #include 10 | #include 11 | 12 | 13 | 14 | 15 | struct vars { 16 | int boop = 0; 17 | }; 18 | 19 | 20 | TEST(sol2, lua_dofile) 21 | { 22 | 23 | sol::state lua; 24 | lua.open_libraries(); 25 | 26 | if (luaL_dostring (lua.lua_state(), "print('hello world')") == 1) { 27 | if (lua_isstring(lua.lua_state(), -1)) { 28 | printf("luaL_dostring error:%s\n", lua_tostring(lua.lua_state(), -1)); 29 | } 30 | } 31 | 32 | } 33 | 34 | 35 | TEST(sol2, call_lua_function) 36 | { 37 | 38 | sol::state lua; 39 | int x = 0; 40 | lua.set_function("beep", [&x]{ ++x; }); 41 | lua.script("beep()"); 42 | EXPECT_EQ(x, 1); 43 | 44 | } 45 | 46 | 47 | TEST(sol2, new_usertype) 48 | { 49 | sol::state lua; 50 | lua.new_usertype("vars", "boop", &vars::boop); 51 | lua.script("beep = vars.new()\n" 52 | "beep.boop = 1"); 53 | EXPECT_EQ(lua.get("beep").boop, 1); 54 | 55 | } --------------------------------------------------------------------------------