├── .DS_Store ├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── demo.c ├── examples ├── .DS_Store ├── codebuffer.c ├── tcp │ ├── tcp_client.c │ └── tcp_server.c └── udp │ ├── udp_client.c │ └── udp_server.c ├── include ├── mr_buffer.h ├── mr_code.h ├── mr_mem.h ├── mr_socket.h ├── mrsocket.h └── socket_info.h ├── mrsocket ├── .DS_Store ├── CMakeLists.txt ├── atomic.h ├── mr_config.h ├── mr_mem.c ├── mr_mem.h ├── mr_slist.h ├── mr_socket.c ├── mr_socket.h ├── mrsocket.h ├── socket_epoll.h ├── socket_info.h ├── socket_kqueue.h ├── socket_poll.h ├── socket_select.h ├── socket_server.c ├── socket_server.h ├── spinlock.h └── win │ ├── atomic.h │ ├── spinlock.h │ ├── winconfig.h │ ├── winport.c │ ├── winport.h │ ├── winsocket.c │ ├── winsocket.h │ └── winsocketdef.h └── mrtool ├── .DS_Store ├── CMakeLists.txt ├── mr_buffer.c ├── mr_buffer.h ├── mr_code.h ├── mr_time.h └── mrtool.h /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skynetlua/mushroom/c1a10c03bcba1c5a529c5d36acd831982ccc5a90/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | /demo 3 | /bin 4 | /lib -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #CMake最低版本号要求 2 | CMAKE_MINIMUM_REQUIRED(VERSION 2.8) 3 | 4 | set(APP_NAME tutorial) 5 | 6 | PROJECT(${APP_NAME}) 7 | 8 | MESSAGE(STATUS "PROJECT_SOURCE_DIR: ${PROJECT_SOURCE_DIR}") 9 | MESSAGE(STATUS "PROJECT_BINARY_DIR: ${PROJECT_BINARY_DIR}") 10 | 11 | if(WIN32) 12 | else() 13 | #SET(CMAKE_BUILE_TYPE DEBUG) 14 | #SET(CMAKE_C_FLAGS_DEBUG "-g -Wall") 15 | SET(CMAKE_C_FLAGS "-g -Wall") 16 | endif() 17 | 18 | file(COPY "${PROJECT_SOURCE_DIR}/mrtool/mr_buffer.h" DESTINATION "${PROJECT_SOURCE_DIR}/include") 19 | file(COPY "${PROJECT_SOURCE_DIR}/mrtool/mr_code.h" DESTINATION "${PROJECT_SOURCE_DIR}/include") 20 | 21 | file(COPY "${PROJECT_SOURCE_DIR}/mrsocket/mr_mem.h" DESTINATION "${PROJECT_SOURCE_DIR}/include") 22 | file(COPY "${PROJECT_SOURCE_DIR}/mrsocket/mr_socket.h" DESTINATION "${PROJECT_SOURCE_DIR}/include") 23 | file(COPY "${PROJECT_SOURCE_DIR}/mrsocket/socket_info.h" DESTINATION "${PROJECT_SOURCE_DIR}/include") 24 | file(COPY "${PROJECT_SOURCE_DIR}/mrsocket/mrsocket.h" DESTINATION "${PROJECT_SOURCE_DIR}/include") 25 | 26 | SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib CACHE PATH "Single directory for all static libraries.") 27 | SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib CACHE PATH "Single directory for all dynamic libraries.") 28 | SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin CACHE PATH "Single directory for all executable.") 29 | 30 | SET(LIBMRSOCKET mrsocket) 31 | SET(LIBMRTOOL mrtool) 32 | 33 | include_directories(${PROJECT_SOURCE_DIR}/${LIBMRSOCKET}) 34 | add_subdirectory(${PROJECT_SOURCE_DIR}/${LIBMRSOCKET}) 35 | 36 | include_directories(${PROJECT_SOURCE_DIR}/${LIBMRTOOL}) 37 | add_subdirectory(${PROJECT_SOURCE_DIR}/${LIBMRTOOL}) 38 | 39 | if(WIN32) 40 | link_libraries(ws2_32) 41 | else() 42 | link_libraries(pthread) 43 | endif() 44 | 45 | 46 | #demo 47 | add_executable(demo demo.c) 48 | target_link_libraries(demo ${LIBMRSOCKET} ${LIBMRTOOL}) 49 | 50 | 51 | #examples文件夹的测试例子 52 | #demo例子 53 | #客户端 54 | #add_executable(demo_client examples/demo/demo_client.c) 55 | #target_link_libraries(demo_client ${LIBMRSOCKET} ${LIBMRTOOL}) 56 | #服务端 57 | #add_executable(demo_server examples/demo/demo_server.c) 58 | #target_link_libraries(demo_server ${LIBMRSOCKET} ${LIBMRTOOL}) 59 | 60 | #tcp例子 61 | #tcp客户端 62 | add_executable(tcp_client examples/tcp/tcp_client.c) 63 | target_link_libraries(tcp_client ${LIBMRSOCKET} ${LIBMRTOOL}) 64 | #tcp服务端 65 | add_executable(tcp_server examples/tcp/tcp_server.c) 66 | target_link_libraries(tcp_server ${LIBMRSOCKET} ${LIBMRTOOL}) 67 | 68 | #udp例子 69 | #udp客户端 70 | add_executable(udp_client examples/udp/udp_client.c) 71 | target_link_libraries(udp_client ${LIBMRSOCKET} ${LIBMRTOOL}) 72 | #udp服务端 73 | add_executable(udp_server examples/udp/udp_server.c) 74 | target_link_libraries(udp_server ${LIBMRSOCKET} ${LIBMRTOOL}) 75 | 76 | 77 | #codebuffer 78 | #add_executable(codebuffer examples/codebuffer.c) 79 | #target_link_libraries(codebuffer ${LIBMRSOCKET} ${LIBMRTOOL}) 80 | 81 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # mushroom 2 | 废弃,请使用OpenSocket项目,在win32支持IOCP 请见https://github.com/openlinyou/opensocket 3 | ## 介绍 4 | 5G、大数据浪潮来袭。对设备与设备的通信提出了更高要求。为此开发了这个高性能高并发的网络框架。 5 | 6 | mushroom是一个高性能的跨全平台的socket网络框架。 7 | 8 | mushroom支持TCP、UDP通信,让客户端非常容易创建并发网络链接,可以让手机快速创建上万条链接,甚至可以让手机作为服务器,被上万客户端连接。 9 | mushroom还有另外一个分支mushroom-kcp,mushroom-kcp在UDP的基础上,加上kcp协议,让拥堵的网络环境消息交互变得更及时。同时,它也支持p2p连接,让成千上万设备互相通信。 10 | 11 | mushroom之所以如此强大,是因为它的网络模块来自服务端框架skynet,纯C语言开发,使用epoll,kqueue, select等事件复用技术。 12 | mushroom专门为跨平台设计,所有平台只有一个api,cmake构建工程,只有几个源代码文件,非常容易在vs和xcode下调试,支持linux,macos,win,android,ios等操作系统。在国内有众多依托skynet框架的游戏产品在运行,而mushroom的网络模块来自skynet,因此,它的稳定性已经得到很好保障。 13 | 14 | ## 软件架构 15 | mushroom的网络模块来自skynet,采用事件复用技术,linux和安卓采用epoll,macox和iOS采用kqueue,win采用select。使用C语言开发,基本支持绝大多数操作系统。 16 | 17 | mushroom内部只有一条线程运行,该线程堵塞监听所有的io事件,并把各种io事件进行划分成各类消息。mushroom线程接收到io事件后,会立刻把该消息添加到消息队列,消息队列缓存此消息,等待业务线程派发。消息队列通过原子锁保证数据安全和效率。逻辑业务线程通过轮询方式频繁调用update函数,把各种消息通过回调函数派发给业务线程。 18 | 19 | mushroom内部有如下消息:"start","close","open","accept","error","exit","udp","warning"等。业务层无需处理这些事件,mushroom内部会把消息转换成对应的回调函数。 20 | 21 | ## mushroom流水线 22 | mushroom内部只有一条线程,简称事件线程;调用mushroom的api的线程,就叫业务线程。业务线程请求socket业务通过管道通知事件线程。事件线程从管道接收该socket业务并进行立刻处理,处理完后把消息发送到消息队列进行缓存,等待业务线程获取。业务线程通过轮询的方式获取消息,并通过消息调用对于的回调函数,回到业务线程。 23 | 24 | 1. 创建socket。业务线程通过mushroom提供的api,直接创建socket,然后通过管道把该socket的fd发送到mushroom的线程。在mushroom线程监听到该管道io事件,通过管道接收该fd。最后发送open消息,告诉业务层(业务层监听回调函数)socket创建成功 25 | 2. 启动socket。socket创建后,因为没有加入到io事件中,不会工作,需要进行start操作,把该socket加入到io系统事件中。业务线程执行mushroom提供的start函数,业务线程通过管道发该请求发到mushroom线程,mushroom线程接收到消息后,把该socket的fd加入到系统的IO事件中,并向业务层发送start消息。 26 | 3. 发送数据。业务线程直接通过mushroom提供的接口,直接调用write函数发送数据,如果socket的发送缓冲已满,就会把剩余的数据通过管道发到mushroom线程,mushroom线程监听到发送缓冲有空位,就会把剩余的数据发送完毕。 27 | 4. 接收数据。mushroom线程监听到read事件,就会立刻进行读取数据操作,然后发送data消息,并附上网络数据,告诉业务层。 28 | 29 | ## 项目源代码结构 30 | mushroom源代码如下: 31 | ```c 32 | examples //测试例子。tcp和upd的测试例子 33 | mrsocket //mushroom的全部源代码。 34 | mrtool //辅助工具,方便处理网络数据包和二进制数据读取 35 | demo_client.c //客户端测试例子 36 | demo_server.c //服务端测试例子 37 | CMakeLists.txt //cmake文件 38 | ``` 39 | 在mrsocket/socket_poll.h头文件描述了怎样选择事件复用技术。 40 | ```C 41 | #if defined(__linux__) 42 | #include "socket_epoll.h" 43 | #elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined (__NetBSD__) 44 | #include "socket_kqueue.h" 45 | #else 46 | #include "socket_select.h" 47 | #endif 48 | ``` 49 | 如果不是linux和unix系统,就缺省选择select作为事件复用技术。 50 | 整个项目的源代码文件只有几个,可以手动把源代码添加到自己的项目中。非win系统,除了win文件夹之外,其他源文件加入即可。 51 | 52 | 此网络框架是针对linux系统设计的,对于win系统,mushroom进行了处理,为win环境提供一套linux的接口,源代码中的win文件夹就是提供这个功能。 53 | 54 | mushroom可以通过cmake快速生成各个平台的静态库。通过cmake构建工程,编译运行后,就会在主目录生成include和lib两个文件夹。里面提供了静态库需要的头文件和静态库文件。 55 | 56 | ## 安装教程 57 | 1. 环境准备 58 | cmake构建工具,linux系统需要gcc编译器,window需要vs2017,macos/ios需要xcode,安卓需要ndk。 59 | 2. 可以通过git工具下载源代码。 60 | ``` 61 | git clone https://github.com/skynetlua/mushroom.git 62 | ``` 63 | 3. 创建build目录 64 | 在shell终端 65 | ``` 66 | cd xxx存放的文件夹/mushroom 67 | mkdir build;cd ./build 68 | ``` 69 | 4. 用cmake构建工程 70 | 以linux为例子,在shell终端,在上述/build下, 71 | ``` 72 | cmake ../ 73 | ``` 74 | 在win和macos中,cmake有可视化工具,鼠标点击即可构建。 75 | 在win系统,vs2017(其他版本未测试过)上可编译运行,通过cmake也可以导出xcode工程。 76 | 若macos,cmake可能存在找不到编译器的情况,执行下列命令即可 77 | ``` 78 | #macosx cmake 79 | sudo xcode-select --switch /Applications/Xcode.app/ 80 | ``` 81 | 5. 编译项目 82 | 以linux为例,使用make命令,就完成编译。 83 | ``` 84 | make 85 | ``` 86 | 编译完成后。在mushroom目录下会生成三个文件夹。bin、include和lib。直接把include和lib导入到工程就可以使用mushroom框架。bin文件夹内含一些测试程序。 87 | 88 | ## 简单的实例 89 | 。客户端和服务端写到一起。客户端(boy)邀请服务器(girl)吃饭。 90 | ```C 91 | #include 92 | #include 93 | #include 94 | #include "mrsocket.h" 95 | #include "mrtool.h" 96 | 97 | int server_fd = 0; 98 | int client_fd = 0; 99 | int timer_count = 0; 100 | int invite_count = 0; 101 | 102 | //服务器监听session id 103 | const int server_session_id = 1; 104 | //服务器中与客户端连接的session id 105 | const int accept_session_id = 2; 106 | //客户端的session id 107 | const int client_session_id = 3; 108 | 109 | static void handle_data(uintptr_t uid, int fd, char* data, int size) 110 | { 111 | int session_id = (int)uid; 112 | if (client_session_id == session_id) 113 | { 114 | printf("[boy]接收到服务端消息 fd = %d, data = %s \n", fd, data); 115 | if (data[0] == 2) 116 | { 117 | char msg[128] = "\3那你要出来吃饭吗?"; 118 | mr_socket_send(fd, msg, sizeof(msg)); 119 | } 120 | } 121 | else if (accept_session_id == session_id) 122 | { 123 | printf("[girl]接收到客户端消息 fd = %d, data = %s \n", fd, data); 124 | if (data[0] == 1) 125 | { 126 | char msg[128] = "\2还没呢,你真贴心。^_^"; 127 | mr_socket_send(fd, msg, sizeof(msg)); 128 | } 129 | else if (data[0] == 3) 130 | { 131 | char msg[128] = "\4讨厌。才刚认识呢!我们先聊聊嘛"; 132 | mr_socket_send(fd, msg, sizeof(msg)); 133 | mr_socket_close((uintptr_t)session_id, fd); 134 | printf("[girl]拒绝邀约,关闭客户端\n"); 135 | } 136 | } 137 | else 138 | { 139 | assert(0); 140 | } 141 | } 142 | 143 | static void handle_connect(uintptr_t uid, int fd, char* data, int size) 144 | { 145 | int session_id = (int)uid; 146 | if (server_session_id == session_id) 147 | { 148 | assert(server_fd == fd); 149 | printf("[server]服务器监听启动成功 data =%s, size = %d \n", data, size); 150 | } 151 | else if (client_session_id == session_id) 152 | { 153 | assert(client_fd == fd); 154 | printf("\n[boy]客户端连接服务器启动成功 data =%s, size = %d \n", data, size); 155 | char msg[128] = "\1靓女,你吃饭了吗?"; 156 | mr_socket_send(fd, msg, sizeof(msg)); 157 | printf("[boy]开始第%d次邀请妹纸\n", ++invite_count); 158 | } 159 | else if (accept_session_id == session_id) 160 | { 161 | printf("[girl]客户端连接服务器成功 data =%s, size = %d \n", data, size); 162 | } 163 | else 164 | { 165 | assert(0); 166 | } 167 | } 168 | 169 | static void handle_close(uintptr_t uid, int fd, char* data, int size) 170 | { 171 | int session_id = (int)uid; 172 | if (client_session_id == session_id) 173 | { 174 | printf("[boy]连接关闭 fd = %d, data=%s, size = %d \n", fd, data, size); 175 | //等3秒,再预约 176 | client_fd = 0; 177 | timer_count = 3000; 178 | } 179 | else if (accept_session_id == session_id) 180 | { 181 | printf("[girl]连接关闭 fd = %d, data=%s, size = %d \n", fd, data, size); 182 | } 183 | } 184 | 185 | static void handle_error(uintptr_t uid, int fd, char* data, int size) 186 | { 187 | int session_id = (int)uid; 188 | printf("发生错误 session_id = %d, fd = %d, data=%s, size = %d \n", session_id, fd, data, size); 189 | } 190 | 191 | static void handle_warning(uintptr_t uid, int fd, char* data, int size) 192 | { 193 | int session_id = (int)uid; 194 | printf("发生警告 session_id = %d, fd = %d, data=%s, size = %d \n", session_id, fd, data, size); 195 | } 196 | 197 | void handle_accept(uintptr_t uid, int fd, char* data, int size, int apt_fd) 198 | { 199 | int session_id = (int)uid; 200 | assert(session_id == server_session_id); 201 | 202 | char* addr = malloc(size+1); 203 | memset((void*)addr, 0, sizeof(addr)); 204 | memcpy(addr, data, size); 205 | printf("[server]监听到新的链接addr=%s, apt_fd=%d \n", addr, apt_fd); 206 | free(addr); 207 | 208 | mr_socket_start((uintptr_t)accept_session_id, apt_fd); 209 | printf("[girl]接受与客户端连接 apt_fd =%d\n", apt_fd); 210 | } 211 | 212 | int main(int argc, char* argv[]) 213 | { 214 | //初始化mushroom(只能初始化一次) 215 | mr_socket_init(); 216 | //设置回调函数 217 | //配置socket数据包回调函数 218 | mr_set_handle_data(handle_data); 219 | //配置socket链接回调函数 220 | mr_set_handle_connect(handle_connect); 221 | //配置socket关闭回调函数 222 | mr_set_handle_close(handle_close); 223 | //配置socket发生错误回调函数 224 | mr_set_handle_error(handle_error); 225 | //配置socket发生警告回调函数 226 | mr_set_handle_warning(handle_warning); 227 | //配置socket监听到新连接回调函数 228 | mr_set_handle_accept(handle_accept); 229 | 230 | //启动mushroom,并启动线程监听和接收数据包 231 | mr_socket_run(); 232 | printf("[mushroom]mushroom启动成功\n"); 233 | //启动服务器监听 234 | server_fd = mr_socket_listen((uintptr_t)server_session_id, "0.0.0.0", 8080, 64); 235 | if (server_fd < 0) { 236 | printf("[server]mr_socket_listen faild server_fd = %d\n", server_fd); 237 | assert(0); 238 | } 239 | mr_socket_start((uintptr_t)server_session_id, server_fd); 240 | printf("[server]启动监听0.0.0.0:8080 server_fd = %d\n", server_fd); 241 | //启动连接服务器 242 | client_fd = mr_socket_connect((uintptr_t)client_session_id, "127.0.0.1", 8080); 243 | if (client_fd < 0) 244 | { 245 | printf("[boy]连接失败 faild client_fd = %d\n", client_fd); 246 | assert(0); 247 | } 248 | printf("[boy]启动连接服务器 client_fd = %d\n", client_fd); 249 | while(1) 250 | { 251 | //业务线程循环检测是否有网络消息,有网络消息,就会通过回调函数返回 252 | mr_socket_update(); 253 | mr_sleep(1); 254 | 255 | if (timer_count == 0) 256 | { 257 | if (client_fd == 0) 258 | //断线重连服务器 259 | client_fd = mr_socket_connect((uintptr_t)client_session_id, "127.0.0.1", 8080); 260 | } 261 | else 262 | { 263 | timer_count--; 264 | if (timer_count<0) 265 | timer_count = 0; 266 | } 267 | } 268 | //销毁mushroo线程,并释放相应内存 269 | mr_socket_free(); 270 | return 0; 271 | } 272 | ``` 273 | 274 | 275 | -------------------------------------------------------------------------------- /demo.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include "mrsocket.h" 6 | #include "mrtool.h" 7 | 8 | int server_fd = 0; 9 | int client_fd = 0; 10 | int timer_count = 0; 11 | int invite_count = 0; 12 | 13 | //服务器监听session id 14 | const int server_session_id = 1; 15 | //服务器中与客户端连接的session id 16 | const int accept_session_id = 2; 17 | //客户端的session id 18 | const int client_session_id = 3; 19 | 20 | static void handle_data(uintptr_t uid, int fd, char* data, int size) 21 | { 22 | int session_id = (int)uid; 23 | if (client_session_id == session_id) 24 | { 25 | printf("[boy]receive server msg fd = %d, data = %s \n", fd, data); 26 | if (data[0] == 2) 27 | { 28 | char msg[128] = "\3have a dinner?"; 29 | mr_socket_send(fd, msg, sizeof(msg)); 30 | } 31 | } 32 | else if (accept_session_id == session_id) 33 | { 34 | printf("[girl]receive client msg fd = %d, data = %s \n", fd, data); 35 | if (data[0] == 1) 36 | { 37 | char msg[128] = "\2final,thank you^_^"; 38 | mr_socket_send(fd, msg, sizeof(msg)); 39 | } 40 | else if (data[0] == 3) 41 | { 42 | char msg[128] = "\4I don't know you"; 43 | mr_socket_send(fd, msg, sizeof(msg)); 44 | mr_socket_close((uintptr_t)session_id, fd); 45 | printf("[girl]refuse,close client\n"); 46 | } 47 | } 48 | else 49 | { 50 | assert(0); 51 | } 52 | } 53 | 54 | static void handle_connect(uintptr_t uid, int fd, char* data, int size) 55 | { 56 | int session_id = (int)uid; 57 | if (server_session_id == session_id) 58 | { 59 | assert(server_fd == fd); 60 | printf("[server]server listen success. data =%s, size = %d \n", data, size); 61 | } 62 | else if (client_session_id == session_id) 63 | { 64 | assert(client_fd == fd); 65 | printf("\n[boy]client connect server success. data =%s, size = %d \n", data, size); 66 | char msg[128] = "\1girl,how are you?"; 67 | mr_socket_send(fd, msg, sizeof(msg)); 68 | printf("[boy]invite girl %d times\n", ++invite_count); 69 | } 70 | else if (accept_session_id == session_id) 71 | { 72 | printf("[girl]client connect server success data =%s, size = %d \n", data, size); 73 | } 74 | else 75 | { 76 | assert(0); 77 | } 78 | } 79 | 80 | static void handle_close(uintptr_t uid, int fd, char* data, int size) 81 | { 82 | int session_id = (int)uid; 83 | if (client_session_id == session_id) 84 | { 85 | printf("[boy]connect close fd = %d, data=%s, size = %d \n", fd, data, size); 86 | //等3秒,再预约 87 | client_fd = 0; 88 | timer_count = 3000; 89 | } 90 | else if (accept_session_id == session_id) 91 | { 92 | printf("[girl]connect close fd = %d, data=%s, size = %d \n", fd, data, size); 93 | } 94 | } 95 | 96 | static void handle_error(uintptr_t uid, int fd, char* data, int size) 97 | { 98 | int session_id = (int)uid; 99 | printf("error session_id = %d, fd = %d, data=%s, size = %d \n", session_id, fd, data, size); 100 | } 101 | 102 | static void handle_warning(uintptr_t uid, int fd, char* data, int size) 103 | { 104 | int session_id = (int)uid; 105 | printf("warning session_id = %d, fd = %d, data=%s, size = %d \n", session_id, fd, data, size); 106 | } 107 | 108 | void handle_accept(uintptr_t uid, int fd, char* data, int size, int apt_fd) 109 | { 110 | int session_id = (int)uid; 111 | assert(session_id == server_session_id); 112 | 113 | char* addr = malloc(size+1); 114 | memset((void*)addr, 0, sizeof(addr)); 115 | memcpy(addr, data, size); 116 | printf("[server]listen new connect addr=%s, apt_fd=%d \n", addr, apt_fd); 117 | free(addr); 118 | 119 | mr_socket_start((uintptr_t)accept_session_id, apt_fd); 120 | printf("[girl]accept client apt_fd =%d\n", apt_fd); 121 | } 122 | 123 | int main(int argc, char* argv[]) 124 | { 125 | //初始化mushroom(只能初始化一次) 126 | mr_socket_init(); 127 | //设置回调函数 128 | //配置socket数据包回调函数 129 | mr_set_handle_data(handle_data); 130 | //配置socket链接回调函数 131 | mr_set_handle_connect(handle_connect); 132 | //配置socket关闭回调函数 133 | mr_set_handle_close(handle_close); 134 | //配置socket发生错误回调函数 135 | mr_set_handle_error(handle_error); 136 | //配置socket发生警告回调函数 137 | mr_set_handle_warning(handle_warning); 138 | //配置socket监听到新连接回调函数 139 | mr_set_handle_accept(handle_accept); 140 | 141 | //启动mushroom,并启动线程监听和接收数据包 142 | mr_socket_run(); 143 | printf("[mushroom]mushroom start success\n"); 144 | //启动服务器监听 145 | server_fd = mr_socket_listen((uintptr_t)server_session_id, "0.0.0.0", 8080, 64); 146 | if (server_fd < 0) { 147 | printf("[server]mr_socket_listen faild server_fd = %d\n", server_fd); 148 | assert(0); 149 | } 150 | mr_socket_start((uintptr_t)server_session_id, server_fd); 151 | printf("[server]listen:0.0.0.0:8080 server_fd = %d\n", server_fd); 152 | //启动连接服务器 153 | client_fd = mr_socket_connect((uintptr_t)client_session_id, "127.0.0.1", 8080); 154 | if (client_fd < 0) 155 | { 156 | printf("[boy]connect faild client_fd = %d\n", client_fd); 157 | assert(0); 158 | } 159 | printf("[boy]connect server client_fd = %d\n", client_fd); 160 | while(1) 161 | { 162 | //业务线程循环检测是否有网络消息,有网络消息,就会通过回调函数返回 163 | mr_socket_update(); 164 | mr_sleep(1); 165 | 166 | if (timer_count == 0) 167 | { 168 | if (client_fd == 0) 169 | //断线重连服务器 170 | client_fd = mr_socket_connect((uintptr_t)client_session_id, "127.0.0.1", 8080); 171 | } 172 | else 173 | { 174 | timer_count--; 175 | if (timer_count<0) 176 | timer_count = 0; 177 | } 178 | } 179 | //销毁mushroo线程,并释放相应内存 180 | mr_socket_free(); 181 | return 0; 182 | } 183 | -------------------------------------------------------------------------------- /examples/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skynetlua/mushroom/c1a10c03bcba1c5a529c5d36acd831982ccc5a90/examples/.DS_Store -------------------------------------------------------------------------------- /examples/codebuffer.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "mrsocket.h" 9 | 10 | 11 | int main(int argc, char* argv[]) 12 | { 13 | mr_mem_detect(0xFFFF); 14 | 15 | struct mr_buffer* buffer = mr_buffer_create(4); 16 | 17 | char* txt = "hello world!"; 18 | int snd_id = 0; 19 | for (; snd_id < 100; ++snd_id) 20 | { 21 | char tmp[128] = {0}; 22 | char* ptr = tmp; 23 | uint32_t id = 16888; 24 | ptr = mr_encode32u(ptr, id); 25 | uint32_t time = mr_clock(); 26 | ptr = mr_encode32u(ptr, time); 27 | ptr = mr_encode32u(ptr, snd_id); 28 | 29 | short txtlen = (short)strlen(txt); 30 | ptr = mr_encode16u(ptr, txtlen); 31 | memcpy(ptr, txt, txtlen); 32 | 33 | mr_buffer_write_push(buffer, tmp, ptr-tmp+txtlen); 34 | 35 | mr_buffer_write_pack(buffer); 36 | char* snddata = buffer->write_data; 37 | int sndsize = buffer->write_len; 38 | mr_buffer_read_push(buffer, snddata, sndsize); 39 | } 40 | 41 | int rcv_id = 0; 42 | while(1){ 43 | int ret = mr_buffer_read_pack(buffer); 44 | if (ret > 0){ 45 | const char* ptr = buffer->read_data; 46 | int read_len = buffer->read_len; 47 | 48 | uint32_t id = 0; 49 | ptr = mr_decode32u(ptr, &id); 50 | assert(id == 16888); 51 | 52 | uint32_t sndtime = 0; 53 | ptr = mr_decode32u(ptr, &sndtime); 54 | uint32_t curtime = mr_clock(); 55 | printf("delta_time:%d\n", curtime-sndtime); 56 | 57 | uint32_t snd_id = 0; 58 | ptr = mr_decode32u(ptr, &snd_id); 59 | assert(rcv_id == snd_id); 60 | rcv_id++; 61 | 62 | unsigned short txtlen = 0; 63 | ptr = mr_decode16u(ptr, &txtlen); 64 | char tmp[128] = {0}; 65 | memcpy(tmp, ptr, txtlen); 66 | assert(memcmp(tmp, txt, txtlen) == 0); 67 | 68 | assert(read_len == (ptr-buffer->read_data)+txtlen); 69 | } 70 | else { 71 | break; 72 | } 73 | } 74 | 75 | mr_buffer_free(buffer); 76 | 77 | mr_mem_info(); 78 | return 0; 79 | } 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /examples/tcp/tcp_client.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "mrsocket.h" 8 | #include "mrtool.h" 9 | 10 | struct User{ 11 | int id; 12 | int type; 13 | int fd; 14 | int snd_id; 15 | int rcv_id; 16 | struct mr_buffer* buffer; 17 | }; 18 | 19 | 20 | #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) 21 | //60 connections 22 | #define TEST_CLIENT_NUM 60 23 | #else 24 | //1000 connections 25 | #define TEST_CLIENT_NUM 1000 26 | //Yes,1000 socket connect sever 27 | #endif 28 | #define TEST_SERVER_IP "127.0.0.1" 29 | // #define TEST_SERVER_IP "192.168.188.224" 30 | #define TEST_SERVER_PORT 8765 31 | struct User* clientUsers[TEST_CLIENT_NUM] = {0}; 32 | 33 | 34 | struct User* create_user(){ 35 | struct User* user = (struct User*)malloc(sizeof(struct User)); 36 | user->buffer = mr_buffer_create(4); 37 | return user; 38 | } 39 | 40 | void destroy_user(struct User* user){ 41 | mr_buffer_free(user->buffer); 42 | free(user); 43 | } 44 | 45 | 46 | static void client_handle_data(uintptr_t uid, int fd, char* data, int size) 47 | { 48 | printf("client_handle_data uid = %d, fd = %d, size = %d \n", (int)uid, fd, size); 49 | struct User* user = (struct User*)uid; 50 | struct mr_buffer* buffer = user->buffer; 51 | mr_buffer_read_push(buffer, data, size); 52 | int ret = mr_buffer_read_pack(buffer); 53 | if (ret > 0){ 54 | const char* ptr = buffer->read_data; 55 | uint32_t id = 0; 56 | ptr = mr_decode32u(ptr, &id); 57 | uint32_t send_time = 0; 58 | ptr = mr_decode32u(ptr, &send_time); 59 | uint32_t rcv_id = 0; 60 | ptr = mr_decode32u(ptr, &rcv_id); 61 | assert(user->rcv_id == rcv_id); 62 | user->rcv_id++; 63 | 64 | uint32_t cur_time = mr_clock(); 65 | printf("[client]id = %d, rcv_id=%d, costtime = %d \n", id, rcv_id, cur_time-send_time); 66 | assert(id%2 == 1); 67 | 68 | char* enptr = buffer->read_data; 69 | enptr = mr_encode32u(enptr, ++id); 70 | enptr = mr_encode32u(enptr, cur_time); 71 | enptr = mr_encode32u(enptr, (uint32_t)user->snd_id); 72 | user->snd_id++; 73 | 74 | mr_buffer_write_push(buffer, buffer->read_data, buffer->read_len); 75 | mr_buffer_write_pack(buffer); 76 | int ret = mr_socket_send(fd, buffer->write_data, buffer->write_len); 77 | if (ret < 0) 78 | { 79 | printf("[client]mr_socket_send faild ret = %d\n", ret); 80 | } 81 | } 82 | } 83 | 84 | static void client_handle_connect(uintptr_t uid, int fd, char* data, int size) 85 | { 86 | printf("client_handle_connect uid = %d, fd = %d, data =%s, size = %d \n", (int)uid, fd, data, size); 87 | 88 | struct User* user = (struct User*)uid; 89 | user->snd_id = 0; 90 | user->rcv_id = 0; 91 | //100KB data 92 | char tmp[1024*100] = {0}; 93 | // snprintf(tmp, 2048, "send data hello world"); 94 | memset(tmp, 97, sizeof(tmp)-1); 95 | char* ptr = tmp; 96 | 97 | uint32_t id = 0; 98 | ptr = mr_encode32u(ptr, id); 99 | uint32_t time = mr_clock(); 100 | ptr = mr_encode32u(ptr, time); 101 | ptr = mr_encode32u(ptr, (uint32_t)user->snd_id); 102 | user->snd_id++; 103 | 104 | struct mr_buffer* buffer = user->buffer; 105 | mr_buffer_write_push(buffer, tmp, sizeof(tmp)); 106 | mr_buffer_write_pack(buffer); 107 | int ret = mr_socket_send(fd, buffer->write_data, buffer->write_len); 108 | if (ret < 0) 109 | { 110 | printf("mr_socket_send faild ret = %d\n", ret); 111 | } 112 | } 113 | 114 | static void client_handle_close(uintptr_t uid, int fd, char* data, int size) 115 | { 116 | printf("client_handle_close uid = %d, fd = %d, data=%s, size = %d \n", (int)uid, fd, data, size); 117 | } 118 | 119 | static void client_handle_error(uintptr_t uid, int fd, char* data, int size) 120 | { 121 | printf("client_handle_error uid = %d, fd = %d, data=%s, size = %d \n", (int)uid, fd, data, size); 122 | } 123 | 124 | static void client_handle_warning(uintptr_t uid, int fd, char* data, int size) 125 | { 126 | printf("client_handle_warning uid = %d, fd = %d, data=%s, size = %d \n", (int)uid, fd, data, size); 127 | } 128 | 129 | int main(int argc, char* argv[]) 130 | { 131 | mr_socket_init(); 132 | mr_socket_run(); 133 | 134 | mr_set_handle_data(client_handle_data); 135 | mr_set_handle_connect(client_handle_connect); 136 | mr_set_handle_close(client_handle_close); 137 | mr_set_handle_error(client_handle_error); 138 | mr_set_handle_warning(client_handle_warning); 139 | 140 | int i = 0; 141 | for (i = 0; i < TEST_CLIENT_NUM; ++i) 142 | { 143 | struct User* user = create_user(); 144 | user->id = i; 145 | uintptr_t uid = (uintptr_t)user; 146 | int fd = mr_socket_connect(uid, TEST_SERVER_IP, TEST_SERVER_PORT); 147 | if (fd < 0) 148 | { 149 | printf("mr_socket_connect faild fd = %d\n", fd); 150 | assert(0); 151 | } 152 | printf("mr_socket_connect id=%d, uid=%ld, fd =%d \n", user->id, uid, fd); 153 | user->fd = fd; 154 | clientUsers[i] = user; 155 | } 156 | printf("start success\n"); 157 | while(1) 158 | { 159 | mr_socket_update(); 160 | mr_sleep(1); 161 | } 162 | 163 | i = 0; 164 | for (; i < TEST_CLIENT_NUM; ++i) 165 | { 166 | if (clientUsers[i]) 167 | { 168 | destroy_user(clientUsers[i]); 169 | clientUsers[i] = NULL; 170 | } 171 | } 172 | mr_socket_free(); 173 | return 0; 174 | } 175 | -------------------------------------------------------------------------------- /examples/tcp/tcp_server.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "mrsocket.h" 8 | #include "mrtool.h" 9 | 10 | struct User{ 11 | int id; 12 | int type; 13 | int fd; 14 | int snd_id; 15 | int rcv_id; 16 | struct mr_buffer* buffer; 17 | }; 18 | 19 | #define TEST_SERVER_IP "0.0.0.0" 20 | #define TEST_SERVER_PORT 8765 21 | 22 | struct User* serverUser = NULL; 23 | struct User* clientUsers[0xffff] = {0}; 24 | 25 | struct User* create_user(){ 26 | struct User* user = (struct User*)malloc(sizeof(struct User)); 27 | user->buffer = mr_buffer_create(4); 28 | return user; 29 | } 30 | 31 | void destroy_user(struct User* user){ 32 | mr_buffer_free(user->buffer); 33 | free(user); 34 | } 35 | 36 | void server_handle_data(uintptr_t uid, int fd, char* data, int size) 37 | { 38 | printf("[main]server_handle_data uid =%d \n", (int)uid); 39 | 40 | struct User* user = (struct User*)uid; 41 | struct mr_buffer* buffer = user->buffer; 42 | mr_buffer_read_push(buffer, data, size); 43 | int ret = mr_buffer_read_pack(buffer); 44 | if (ret > 0){ 45 | const char* ptr = buffer->read_data; 46 | uint32_t id = 0; 47 | ptr = mr_decode32u(ptr, &id); 48 | uint32_t send_time = 0; 49 | ptr = mr_decode32u(ptr, &send_time); 50 | 51 | uint32_t cur_time = mr_clock(); 52 | printf("[server]id = %d, costtime = %d \n", id, cur_time-send_time); 53 | 54 | assert(id%2 == 0); 55 | char* enptr = buffer->read_data; 56 | enptr = mr_encode32u(enptr, ++id); 57 | 58 | mr_buffer_write_push(buffer, buffer->read_data, buffer->read_len); 59 | mr_buffer_write_pack(buffer); 60 | int ret = mr_socket_send(fd, buffer->write_data, buffer->write_len); 61 | if (ret < 0){ 62 | printf("[server]server_handle_data faild ret = %d\n", ret); 63 | } 64 | } 65 | } 66 | 67 | void server_handle_close(uintptr_t uid, int fd, char* data, int size) 68 | { 69 | printf("server_handle_close uid=%d\n", (int)uid); 70 | struct User* user = (struct User*)uid; 71 | if (user == serverUser){ 72 | 73 | }else{ 74 | int i = 0; 75 | for (; i < 0xffff; ++i) 76 | { 77 | if (clientUsers[i] == user) 78 | { 79 | clientUsers[i] = NULL; 80 | destroy_user(user); 81 | return; 82 | } 83 | } 84 | } 85 | } 86 | 87 | void server_handle_accept(uintptr_t uid, int fd, char* data, int size, int apt_fd) 88 | { 89 | printf("server_handle_accept uid=%d, fd=%d, data=%s, size=%d, apt_fd=%d \n", (int)uid, fd, data, size, apt_fd); 90 | int i = 0; 91 | for (; i < 0xffff; ++i) 92 | { 93 | if (!clientUsers[i]) 94 | { 95 | struct User* user = create_user(); 96 | clientUsers[i] = user; 97 | mr_socket_start((uintptr_t)user, apt_fd); 98 | return; 99 | } 100 | } 101 | //too many client. refuse connect; 102 | mr_socket_close(uid, apt_fd); 103 | } 104 | 105 | void server_handle_error(uintptr_t uid, int fd, char* data, int size) 106 | { 107 | printf("server_handle_error uid = %d, fd = %d, data = %s, size=%d \n", (int)uid, fd, data, size); 108 | } 109 | 110 | void server_handle_warning(uintptr_t uid, int fd, char* data, int size) 111 | { 112 | printf("server_handle_warning uid = %d, fd = %d, data = %s, size=%d \n", (int)uid, fd, data, size); 113 | } 114 | 115 | int main(int argc, char* argv[]) 116 | { 117 | mr_socket_init(); 118 | mr_socket_run(); 119 | 120 | mr_set_handle_data(server_handle_data); 121 | mr_set_handle_close(server_handle_close); 122 | mr_set_handle_accept(server_handle_accept); 123 | mr_set_handle_error(server_handle_error); 124 | mr_set_handle_warning(server_handle_warning); 125 | 126 | struct User* user = create_user(); 127 | serverUser = user; 128 | 129 | int server_fd = mr_socket_listen((uintptr_t)user, TEST_SERVER_IP, TEST_SERVER_PORT, 64); 130 | if (server_fd < 0) { 131 | printf("mr_socket_listen faild server_fd = %d\n", server_fd); 132 | assert(0); 133 | } 134 | mr_socket_start((uintptr_t)user, server_fd); 135 | printf("[main]start server\n"); 136 | while(1){ 137 | mr_socket_update(); 138 | mr_sleep(1); 139 | } 140 | 141 | int i = 0; 142 | for (; i < 0xffff; ++i){ 143 | if (clientUsers[i]){ 144 | destroy_user(clientUsers[i]); 145 | clientUsers[i] = NULL; 146 | } 147 | } 148 | destroy_user(user); 149 | serverUser = NULL; 150 | mr_socket_free(); 151 | return 0; 152 | } 153 | 154 | -------------------------------------------------------------------------------- /examples/udp/udp_client.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "mrsocket.h" 8 | #include "mrtool.h" 9 | 10 | struct User{ 11 | int id; 12 | int type; 13 | int fd; 14 | int snd_id; 15 | int rcv_id; 16 | struct mr_buffer* buffer; 17 | }; 18 | 19 | 20 | #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) 21 | //60 connections 22 | #define TEST_CLIENT_NUM 60 23 | #else 24 | //1000 connections 25 | #define TEST_CLIENT_NUM 1000 26 | //Yes,1000 socket connect sever 27 | #endif 28 | #define TEST_SERVER_IP "127.0.0.1" 29 | // #define TEST_SERVER_IP "192.168.188.224" 30 | #define TEST_SERVER_PORT 8765 31 | struct User* clientUsers[TEST_CLIENT_NUM] = {0}; 32 | 33 | 34 | struct User* create_user(){ 35 | struct User* user = (struct User*)malloc(sizeof(struct User)); 36 | user->buffer = mr_buffer_create(4); 37 | return user; 38 | } 39 | 40 | void destroy_user(struct User* user){ 41 | mr_buffer_free(user->buffer); 42 | free(user); 43 | } 44 | 45 | void client_handle_udp(uintptr_t uid, int fd, char* data, int size, char* address) 46 | { 47 | char udp_addr[256]; 48 | mr_socket_udp_address(address, udp_addr, sizeof(udp_addr)); 49 | 50 | char* tmp = (char*)malloc(size+1); 51 | memset(tmp, 0, size + 1); 52 | memcpy(tmp, data, size); 53 | printf("client_handle_udp[%s] uid=%d fd =%d buffer=%s sz=%d ud=%d\n", udp_addr, (int)uid, fd, tmp, (int)strlen(tmp), size); 54 | 55 | //mr_sleep(100); 56 | 57 | static int _sid = 1; 58 | char sbuffer[2048] = {0}; 59 | snprintf(sbuffer, 2048, "send data hello world sid=%d", _sid++); 60 | int ret = mr_socket_udp_send(fd, address, sbuffer, (int)strlen(sbuffer)); 61 | if (ret < 0){ 62 | printf("mr_socket_udp_send faild ret = %d\n", ret); 63 | } 64 | } 65 | 66 | 67 | int main(int argc, char* argv[]) 68 | { 69 | mr_socket_init(); 70 | mr_socket_run(); 71 | 72 | mr_set_handle_udp(client_handle_udp); 73 | 74 | int i = 0; 75 | for (; i < TEST_CLIENT_NUM; ++i){ 76 | struct User* user = create_user(); 77 | user->id = i; 78 | int fd = mr_socket_udp((uintptr_t)user, NULL, 0); 79 | if (fd < 0){ 80 | printf("mr_socket_udp faild fd = %d\n", fd); 81 | } 82 | mr_socket_udp_connect(fd, TEST_SERVER_IP, TEST_SERVER_PORT); 83 | 84 | char buffer[2048] = {0}; 85 | snprintf(buffer, 2048, "udp test send data hello world"); 86 | int ret = mr_socket_send(fd, buffer, (int)strlen(buffer)); 87 | if (ret < 0) 88 | { 89 | printf("mr_socket_send faild ret = %d\n", ret); 90 | } 91 | user->fd = fd; 92 | clientUsers[i] = user; 93 | } 94 | while(1) 95 | { 96 | mr_socket_update(); 97 | mr_sleep(1); 98 | } 99 | 100 | i = 0; 101 | for (; i < TEST_CLIENT_NUM; ++i){ 102 | if (clientUsers[i]){ 103 | destroy_user(clientUsers[i]); 104 | clientUsers[i] = NULL; 105 | } 106 | } 107 | mr_socket_free(); 108 | 109 | return 0; 110 | } 111 | 112 | -------------------------------------------------------------------------------- /examples/udp/udp_server.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "mrsocket.h" 8 | #include "mrtool.h" 9 | 10 | struct User{ 11 | int id; 12 | int type; 13 | int fd; 14 | int snd_id; 15 | int rcv_id; 16 | struct mr_buffer* buffer; 17 | }; 18 | 19 | #define TEST_SERVER_IP "0.0.0.0" 20 | #define TEST_SERVER_PORT 8765 21 | 22 | void server_handle_udp(uintptr_t uid, int fd, char* data, int size, char* address) 23 | { 24 | // struct User* user = (struct User*)uid; 25 | 26 | char udp_addr[256]; 27 | mr_socket_udp_address(address, udp_addr, sizeof(udp_addr)); 28 | 29 | char* tmp = (char*)malloc(size+1); 30 | memset(tmp, 0, size + 1); 31 | memcpy(tmp, data, size); 32 | printf("server_handle_udp[%s] uid=%d fd =%d buffer=%s sz=%d ud=%d\n", udp_addr, (int)uid, fd, tmp, (int)strlen(tmp), size); 33 | 34 | 35 | int ret = mr_socket_udp_send(fd, address, data, size); 36 | if (ret < 0){ 37 | printf("server_handle_udp faild ret = %d\n", ret); 38 | } 39 | } 40 | 41 | int main(int argc, char* argv[]) 42 | { 43 | mr_socket_init(); 44 | mr_socket_run(); 45 | 46 | mr_set_handle_udp(server_handle_udp); 47 | 48 | struct User* user = (struct User*)malloc(sizeof(struct User)); 49 | int server_fd = mr_socket_udp((uintptr_t)user, TEST_SERVER_IP, TEST_SERVER_PORT); 50 | if (server_fd < 0) 51 | { 52 | printf("mr_socket_udp faild server_fd = %d\n", server_fd); 53 | } 54 | while(1) 55 | { 56 | mr_socket_update(); 57 | mr_sleep(1); 58 | } 59 | free(user); 60 | return 0; 61 | } 62 | 63 | -------------------------------------------------------------------------------- /include/mr_buffer.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __mr_buffer_h__ 3 | #define __mr_buffer_h__ 4 | 5 | #include 6 | #include 7 | 8 | struct mr_buffer { 9 | int head_len; 10 | 11 | int pack_len; 12 | 13 | size_t read_size; 14 | size_t read_offset; 15 | struct mr_buffer_node *read_head; 16 | struct mr_buffer_node *read_tail; 17 | 18 | int read_len; 19 | int read_cap; 20 | char* read_data; 21 | 22 | size_t write_size; 23 | // size_t write_offset; 24 | struct mr_buffer_node *write_head; 25 | struct mr_buffer_node *write_tail; 26 | 27 | int write_len; 28 | int write_cap; 29 | char* write_data; 30 | }; 31 | 32 | 33 | #define mr_buffer_size(buffer) (buffer)->size 34 | 35 | // static inline size_t mr_buffer_size(struct mr_buffer* buffer){ 36 | // return buffer->size; 37 | // } 38 | 39 | struct mr_buffer* mr_buffer_create(int head_len); 40 | void mr_buffer_free(struct mr_buffer* buffer); 41 | int mr_buffer_read_push(struct mr_buffer* buffer, char* msg, size_t len); 42 | int mr_buffer_read_header(struct mr_buffer* buffer, size_t len); 43 | int mr_buffer_read(struct mr_buffer* buffer, char* data, int len); 44 | int mr_buffer_read_pack(struct mr_buffer* buffer); 45 | 46 | 47 | int mr_buffer_write_push(struct mr_buffer* buffer, char* msg, size_t len); 48 | int mr_buffer_write_pack(struct mr_buffer* buffer); 49 | 50 | // int mr_buffer_write_pack(struct mr_buffer* buffer, char* data, size_t len); 51 | 52 | 53 | #endif -------------------------------------------------------------------------------- /include/mr_code.h: -------------------------------------------------------------------------------- 1 | #ifndef mr_code_h 2 | #define mr_code_h 3 | 4 | #include 5 | 6 | #ifndef DATA_BIG_ENDIAN 7 | #ifdef _BIG_ENDIAN_ 8 | #if _BIG_ENDIAN_ 9 | #define DATA_BIG_ENDIAN 1 10 | #endif 11 | #endif 12 | #ifndef DATA_BIG_ENDIAN 13 | #if defined(__hppa__) || \ 14 | defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \ 15 | (defined(__MIPS__) && defined(__MIPSEB__)) || \ 16 | defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) || \ 17 | defined(__sparc__) || defined(__powerpc__) || \ 18 | defined(__mc68000__) || defined(__s390x__) || defined(__s390__) 19 | #define DATA_BIG_ENDIAN 1 20 | #endif 21 | #endif 22 | #ifndef DATA_BIG_ENDIAN 23 | #define DATA_BIG_ENDIAN 0 24 | #endif 25 | #endif 26 | 27 | 28 | static inline char *mr_encode8u(char *p, unsigned char c){ 29 | *(unsigned char*)p++ = c; 30 | return p; 31 | } 32 | 33 | static inline const char *mr_decode8u(const char *p, unsigned char *c){ 34 | *c = *(unsigned char*)p++; 35 | return p; 36 | } 37 | 38 | static inline char *mr_encode16u(char *p, unsigned short w){ 39 | #if DATA_BIG_ENDIAN 40 | *(unsigned char*)(p + 0) = (w & 255); 41 | *(unsigned char*)(p + 1) = (w >> 8); 42 | #else 43 | *(unsigned short*)(p) = w; 44 | #endif 45 | p += 2; 46 | return p; 47 | } 48 | 49 | static inline const char *mr_decode16u(const char *p, unsigned short *w) 50 | { 51 | #if DATA_BIG_ENDIAN 52 | *w = *(const unsigned char*)(p + 1); 53 | *w = *(const unsigned char*)(p + 0) + (*w << 8); 54 | #else 55 | *w = *(const unsigned short*)p; 56 | #endif 57 | p += 2; 58 | return p; 59 | } 60 | 61 | static inline char *mr_encode32u(char *p, uint32_t l) 62 | { 63 | #if DATA_BIG_ENDIAN 64 | *(unsigned char*)(p + 0) = (unsigned char)((l >> 0) & 0xff); 65 | *(unsigned char*)(p + 1) = (unsigned char)((l >> 8) & 0xff); 66 | *(unsigned char*)(p + 2) = (unsigned char)((l >> 16) & 0xff); 67 | *(unsigned char*)(p + 3) = (unsigned char)((l >> 24) & 0xff); 68 | #else 69 | *(uint32_t*)p = l; 70 | #endif 71 | p += 4; 72 | return p; 73 | } 74 | 75 | static inline const char *mr_decode32u(const char *p, uint32_t *l) 76 | { 77 | #if DATA_BIG_ENDIAN 78 | *l = *(const unsigned char*)(p + 3); 79 | *l = *(const unsigned char*)(p + 2) + (*l << 8); 80 | *l = *(const unsigned char*)(p + 1) + (*l << 8); 81 | *l = *(const unsigned char*)(p + 0) + (*l << 8); 82 | #else 83 | *l = *(const uint32_t*)p; 84 | #endif 85 | p += 4; 86 | return p; 87 | } 88 | 89 | static inline char *mr_encode64u(char *p, uint64_t l) 90 | { 91 | #if DATA_BIG_ENDIAN 92 | *(unsigned char*)(p + 0) = (unsigned char)((l >> 0) & 0xff); 93 | *(unsigned char*)(p + 1) = (unsigned char)((l >> 8) & 0xff); 94 | *(unsigned char*)(p + 2) = (unsigned char)((l >> 16) & 0xff); 95 | *(unsigned char*)(p + 3) = (unsigned char)((l >> 24) & 0xff); 96 | *(unsigned char*)(p + 0) = (unsigned char)((l >> 32) & 0xff); 97 | *(unsigned char*)(p + 1) = (unsigned char)((l >> 40) & 0xff); 98 | *(unsigned char*)(p + 2) = (unsigned char)((l >> 48) & 0xff); 99 | *(unsigned char*)(p + 3) = (unsigned char)((l >> 56) & 0xff); 100 | #else 101 | *(uint64_t*)p = l; 102 | #endif 103 | p += 8; 104 | return p; 105 | } 106 | 107 | static inline const char *mr_decode64u(const char *p, uint64_t *l) 108 | { 109 | #if DATA_BIG_ENDIAN 110 | *l = *(const unsigned char*)(p + 7); 111 | *l = *(const unsigned char*)(p + 6) + (*l << 8); 112 | *l = *(const unsigned char*)(p + 5) + (*l << 8); 113 | *l = *(const unsigned char*)(p + 4) + (*l << 8); 114 | *l = *(const unsigned char*)(p + 3) + (*l << 8); 115 | *l = *(const unsigned char*)(p + 2) + (*l << 8); 116 | *l = *(const unsigned char*)(p + 1) + (*l << 8); 117 | *l = *(const unsigned char*)(p + 0) + (*l << 8); 118 | #else 119 | *l = *(const uint64_t*)p; 120 | #endif 121 | p += 8; 122 | return p; 123 | } 124 | 125 | 126 | #endif 127 | 128 | -------------------------------------------------------------------------------- /include/mr_mem.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __mr_mem_h__ 3 | #define __mr_mem_h__ 4 | 5 | #include 6 | #include 7 | 8 | void * mr_mem_malloc(size_t sz); 9 | void mr_mem_free(void *ptr); 10 | 11 | 12 | struct mr_mem_info { 13 | uint32_t uid; 14 | uint32_t mem; 15 | struct mem_info* next; 16 | }; 17 | 18 | struct mr_mem_info* mr_mem_info(void); 19 | void mr_mem_detect(uint32_t max_uid); 20 | void mr_mem_check(uint32_t uid); 21 | struct mr_mem_info* mr_mem_check_info(void); 22 | 23 | size_t mr_get_used_memory(void); 24 | size_t mr_get_memory_block(void); 25 | 26 | 27 | #endif -------------------------------------------------------------------------------- /include/mr_socket.h: -------------------------------------------------------------------------------- 1 | #ifndef mr_socket_h 2 | #define mr_socket_h 3 | 4 | #include "socket_info.h" 5 | 6 | typedef void (*mr_callback4)(uintptr_t, int, char*, int); 7 | typedef void (*mr_callback5)(uintptr_t, int, char*, int, int); 8 | typedef void (*mr_udp_callback)(uintptr_t, int, char*, int, char*); 9 | 10 | //callback 11 | void mr_set_handle_data(mr_callback4 cb); 12 | void mr_set_handle_connect(mr_callback4 cb); 13 | void mr_set_handle_close(mr_callback4 cb); 14 | void mr_set_handle_accept(mr_callback5 cb); 15 | void mr_set_handle_error(mr_callback4 cb); 16 | void mr_set_handle_warning(mr_callback4 cb); 17 | void mr_set_handle_udp(mr_udp_callback cb); 18 | 19 | void mr_socket_run(void); 20 | void mr_socket_update(void); 21 | 22 | void mr_socket_init(void); 23 | void mr_socket_exit(void); 24 | void mr_socket_free(void); 25 | 26 | int mr_socket_send(int fd, void* buffer, int sz); 27 | int mr_socket_send_lowpriority(int fd, void* buffer, int sz); 28 | void mr_socket_nodelay(int fd); 29 | 30 | //tcp part 31 | int mr_socket_listen(uintptr_t uid, const char* host, int port, int backlog); 32 | int mr_socket_connect(uintptr_t uid, const char* host, int port); 33 | int mr_socket_bind(uintptr_t uid, int fd); 34 | void mr_socket_close(uintptr_t uid, int fd); 35 | void mr_socket_shutdown(uintptr_t uid, int fd); 36 | void mr_socket_start(uintptr_t uid, int fd); 37 | 38 | //udp part 39 | int mr_socket_udp(uintptr_t uid, const char* addr, int port); 40 | int mr_socket_udp_connect(int fd, const char* addr, int port); 41 | int mr_socket_udp_send(int fd, const char* address, const void* buffer, int sz); 42 | int mr_socket_udp_address(const char* address, char* udp_addr, int len); 43 | 44 | struct socket_info * mr_socket_info(void); 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /include/mrsocket.h: -------------------------------------------------------------------------------- 1 | #ifndef mrsocket_h 2 | #define mrsocket_h 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | //#include "mr_time.h" 9 | //#include "mr_buffer.h" 10 | //#include "mr_code.h" 11 | #include "mr_socket.h" 12 | 13 | #ifdef __cplusplus 14 | } 15 | #endif 16 | 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /include/socket_info.h: -------------------------------------------------------------------------------- 1 | #ifndef socket_info_h 2 | #define socket_info_h 3 | 4 | #define SOCKET_INFO_UNKNOWN 0 5 | #define SOCKET_INFO_LISTEN 1 6 | #define SOCKET_INFO_TCP 2 7 | #define SOCKET_INFO_UDP 3 8 | #define SOCKET_INFO_BIND 4 9 | 10 | #include 11 | 12 | struct socket_info { 13 | int id; 14 | int type; 15 | uint64_t opaque; 16 | uint64_t read; 17 | uint64_t write; 18 | uint64_t rtime; 19 | uint64_t wtime; 20 | int64_t wbuffer; 21 | char name[128]; 22 | struct socket_info *next; 23 | }; 24 | 25 | struct socket_info * socket_info_create(struct socket_info *last); 26 | void socket_info_release(struct socket_info *); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /mrsocket/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skynetlua/mushroom/c1a10c03bcba1c5a529c5d36acd831982ccc5a90/mrsocket/.DS_Store -------------------------------------------------------------------------------- /mrsocket/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set(LIB_HEADER 3 | atomic.h 4 | socket_info.h 5 | socket_poll.h 6 | spinlock.h 7 | socket_epoll.h 8 | socket_kqueue.h 9 | socket_select.h 10 | socket_server.h 11 | mr_slist.h 12 | mr_socket.h 13 | mr_config.h 14 | ) 15 | 16 | set(LIB_SRC 17 | socket_server.c 18 | mr_socket.c 19 | mr_mem.c 20 | ) 21 | 22 | #mr_time.h 23 | #mr_buffer.h 24 | #mr_code.h 25 | #mr_buffer.c 26 | 27 | if(WIN32) 28 | 29 | list(APPEND LIB_HEADER win/spinlock.h) 30 | list(APPEND LIB_HEADER win/winsocket.h) 31 | list(APPEND LIB_HEADER win/winsocketdef.h) 32 | list(APPEND LIB_HEADER win/atomic.h) 33 | list(APPEND LIB_HEADER win/winport.h) 34 | 35 | list(APPEND LIB_SRC win/winport.c) 36 | list(APPEND LIB_SRC win/winsocket.c) 37 | 38 | link_libraries(ws2_32) 39 | 40 | else() 41 | 42 | link_libraries(pthread) 43 | 44 | endif() 45 | 46 | list(APPEND LIB_SRC ${LIB_HEADER}) 47 | 48 | add_library(mrsocket STATIC ${LIB_SRC}) 49 | 50 | -------------------------------------------------------------------------------- /mrsocket/atomic.h: -------------------------------------------------------------------------------- 1 | #ifndef SKYNET_ATOMIC_H 2 | #define SKYNET_ATOMIC_H 3 | 4 | #define ATOM_CAS(ptr, oval, nval) __sync_bool_compare_and_swap(ptr, oval, nval) 5 | #define ATOM_CAS_POINTER(ptr, oval, nval) __sync_bool_compare_and_swap(ptr, oval, nval) 6 | #define ATOM_INC(ptr) __sync_add_and_fetch(ptr, 1) 7 | #define ATOM_FINC(ptr) __sync_fetch_and_add(ptr, 1) 8 | #define ATOM_DEC(ptr) __sync_sub_and_fetch(ptr, 1) 9 | #define ATOM_FDEC(ptr) __sync_fetch_and_sub(ptr, 1) 10 | #define ATOM_ADD(ptr,n) __sync_add_and_fetch(ptr, n) 11 | #define ATOM_SUB(ptr,n) __sync_sub_and_fetch(ptr, n) 12 | #define ATOM_AND(ptr,n) __sync_and_and_fetch(ptr, n) 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /mrsocket/mr_config.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __mr_config_h__ 3 | #define __mr_config_h__ 4 | 5 | #include "mr_mem.h" 6 | 7 | #define MALLOC mr_mem_malloc 8 | #define FREE mr_mem_free 9 | 10 | 11 | #define MAX_SOCKET_P 16 12 | 13 | #endif -------------------------------------------------------------------------------- /mrsocket/mr_mem.c: -------------------------------------------------------------------------------- 1 | 2 | #include "mr_mem.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) 9 | #include "win/winport.h" 10 | #include "win/atomic.h" 11 | #include "win/spinlock.h" 12 | #else 13 | #include "atomic.h" 14 | #include "spinlock.h" 15 | #endif 16 | 17 | #define MEMORY_ALLOCTAG 0x20190429 18 | #define MEMORY_FREETAG 0x0badf00d 19 | 20 | // #define MEMORY_CHECK 21 | struct mem_cookie { 22 | uint32_t uid; 23 | uint32_t dogtag; 24 | }; 25 | 26 | #define PREFIX_SIZE sizeof(struct mem_cookie) 27 | 28 | static size_t _used_memory = 0; 29 | static size_t _memory_block = 0; 30 | 31 | static uint32_t _uid = 0; 32 | static uint32_t _max_uid = 0; 33 | static uint32_t* uid_mems = NULL; 34 | static uint32_t* check_mems = NULL; 35 | 36 | static struct mr_mem_info* _head = NULL; 37 | static struct mr_mem_info* _tail = NULL; 38 | static struct spinlock* info_lock = NULL; 39 | 40 | 41 | void push_mem_info(struct mr_mem_info* info){ 42 | if(info_lock == NULL){ 43 | info_lock = (struct spinlock*)malloc(sizeof(struct spinlock)); 44 | spinlock_init(info_lock); 45 | } 46 | spinlock_lock(info_lock); 47 | info->next = NULL; 48 | if (_head == NULL){ 49 | _head = info; 50 | _tail = info; 51 | }else{ 52 | _tail->next = info; 53 | _tail = info; 54 | } 55 | spinlock_unlock(info_lock); 56 | } 57 | 58 | struct mr_mem_info* mr_mem_check_info(void){ 59 | if(info_lock == NULL){ 60 | return NULL; 61 | } 62 | struct mr_mem_info* info; 63 | spinlock_lock(info_lock); 64 | info = _head; 65 | _head = NULL; 66 | _tail = NULL; 67 | spinlock_unlock(info_lock); 68 | return info; 69 | } 70 | 71 | static void* fill_prefix(char* ptr, size_t size) { 72 | struct mem_cookie *p = (struct mem_cookie *)(ptr + size - sizeof(struct mem_cookie)); 73 | uint32_t uid = ATOM_INC(&_uid); 74 | memcpy(&p->uid, &uid, sizeof(uid)); 75 | if (uid < _max_uid){ 76 | uid_mems[uid] = (uint32_t)size; 77 | if (check_mems[uid]){ 78 | struct mr_mem_info* info = (struct mr_mem_info*)malloc(sizeof(struct mr_mem_info)); 79 | info->uid = uid; 80 | info->mem = uid_mems[uid]; 81 | info->next = NULL; 82 | push_mem_info(info); 83 | } 84 | } 85 | uint32_t dogtag = MEMORY_ALLOCTAG; 86 | memcpy(&p->dogtag, &dogtag, sizeof(dogtag)); 87 | 88 | ATOM_ADD(&_used_memory, (int)size); 89 | ATOM_INC(&_memory_block); 90 | *((size_t*)ptr) = size; 91 | return ptr+sizeof(size_t); 92 | } 93 | 94 | inline static void* clean_prefix(char* ptr) { 95 | ptr -= sizeof(size_t); 96 | size_t size = *((size_t*)ptr); 97 | struct mem_cookie *p = (struct mem_cookie *)(ptr + size - sizeof(struct mem_cookie)); 98 | uint32_t uid; 99 | memcpy(&uid, &p->uid, sizeof(uid)); 100 | if (uid < _max_uid){ 101 | if (check_mems[uid]) { 102 | struct mr_mem_info* info = (struct mr_mem_info*)malloc(sizeof(struct mr_mem_info)); 103 | info->uid = uid; 104 | info->mem = uid_mems[uid]; 105 | info->next = NULL; 106 | push_mem_info(info); 107 | } 108 | uid_mems[uid] = 0; 109 | } 110 | uint32_t dogtag; 111 | memcpy(&dogtag, &p->dogtag, sizeof(dogtag)); 112 | if (dogtag == MEMORY_FREETAG) { 113 | fprintf(stderr, "xmalloc: double free in :%d\n", uid); 114 | } 115 | assert(dogtag == MEMORY_ALLOCTAG); 116 | dogtag = MEMORY_FREETAG; 117 | memcpy(&p->dogtag, &dogtag, sizeof(dogtag)); 118 | 119 | ATOM_SUB(&_used_memory, (int)size); 120 | ATOM_DEC(&_memory_block); 121 | return ptr; 122 | } 123 | 124 | void * mr_mem_malloc(size_t sz){ 125 | if (_max_uid == 0){ 126 | return malloc(sz); 127 | } 128 | size_t size = sz + PREFIX_SIZE+sizeof(size_t); 129 | void* ptr = malloc(size); 130 | return fill_prefix(ptr, size); 131 | } 132 | 133 | void mr_mem_free(void *ptr){ 134 | if (ptr == NULL) return; 135 | if (_max_uid == 0){ 136 | free(ptr); 137 | return; 138 | } 139 | void* rawptr = clean_prefix(ptr); 140 | free(rawptr); 141 | } 142 | 143 | struct mr_mem_info* mr_mem_info(void){ 144 | if (_max_uid > 0){ 145 | size_t size = 0; 146 | struct mr_mem_info* head = NULL; 147 | struct mr_mem_info* tail = NULL; 148 | uint32_t uid = 0; 149 | for (; uid < _max_uid; ++uid){ 150 | if(uid_mems[uid]){ 151 | struct mr_mem_info* info = (struct mr_mem_info*)malloc(sizeof(struct mr_mem_info)); 152 | info->uid = uid; 153 | info->mem = uid_mems[uid]; 154 | info->next = NULL; 155 | if (head == NULL){ 156 | head = info; 157 | tail = info; 158 | }else{ 159 | tail->next = info; 160 | tail = info; 161 | } 162 | } 163 | } 164 | return head; 165 | } 166 | // printf("mr_mem_info used_memory=%ldkb, memory_block=%ld \n", _used_memory>>10, _memory_block); 167 | } 168 | 169 | size_t mr_get_used_memory(void){ 170 | return _used_memory; 171 | } 172 | 173 | size_t mr_get_memory_block(void){ 174 | return _memory_block; 175 | } 176 | 177 | void mr_mem_detect(uint32_t max_uid){ 178 | assert(_max_uid == 0); 179 | _max_uid = max_uid; 180 | uid_mems = (uint32_t*)malloc(sizeof(uint32_t)*max_uid); 181 | memset(uid_mems, 0, sizeof(uint32_t)*max_uid); 182 | check_mems = (uint32_t*)malloc(sizeof(uint32_t)*max_uid); 183 | memset(check_mems, 0, sizeof(uint32_t)*max_uid); 184 | } 185 | 186 | void mr_mem_check(uint32_t uid){ 187 | check_mems[uid] = 1; 188 | } 189 | 190 | -------------------------------------------------------------------------------- /mrsocket/mr_mem.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __mr_mem_h__ 3 | #define __mr_mem_h__ 4 | 5 | #include 6 | #include 7 | 8 | void * mr_mem_malloc(size_t sz); 9 | void mr_mem_free(void *ptr); 10 | 11 | 12 | struct mr_mem_info { 13 | uint32_t uid; 14 | uint32_t mem; 15 | struct mem_info* next; 16 | }; 17 | 18 | struct mr_mem_info* mr_mem_info(void); 19 | void mr_mem_detect(uint32_t max_uid); 20 | void mr_mem_check(uint32_t uid); 21 | struct mr_mem_info* mr_mem_check_info(void); 22 | 23 | size_t mr_get_used_memory(void); 24 | size_t mr_get_memory_block(void); 25 | 26 | 27 | #endif -------------------------------------------------------------------------------- /mrsocket/mr_slist.h: -------------------------------------------------------------------------------- 1 | #ifndef mr_slist_h 2 | #define mr_slist_h 3 | 4 | #include 5 | #include 6 | #include "mr_config.h" 7 | 8 | struct mr_slist_node 9 | { 10 | struct mr_slist_node* next; 11 | }; 12 | 13 | struct mr_slist 14 | { 15 | struct mr_slist_node head; 16 | struct mr_slist_node *tail; 17 | }; 18 | 19 | #define mr_slist_is_empty(list) ((list)->head.next == NULL) 20 | 21 | #define mr_slist_free(list) if((list) != NULL){FREE(list);} 22 | 23 | #define mr_slist_link(list, node) \ 24 | (list)->tail->next = (node);\ 25 | (list)->tail = (node);\ 26 | (node)->next = NULL 27 | 28 | // static inline void mr_slist_free(struct mr_slist* list){ 29 | // if (list != NULL) FREE(list); 30 | // } 31 | 32 | // static inline void mr_slist_link(struct mr_slist *list, struct mr_slist_node *node) { 33 | // list->tail->next = node; 34 | // list->tail = node; 35 | // node->next = NULL; 36 | // } 37 | 38 | static inline struct mr_slist* mr_slist_create(void) { 39 | struct mr_slist* list = (struct mr_slist*)MALLOC(sizeof(struct mr_slist)); 40 | memset(list, 0, sizeof(struct mr_slist)); 41 | return list; 42 | } 43 | 44 | static inline struct mr_slist_node* mr_slist_clear(struct mr_slist *list) { 45 | struct mr_slist_node * ret = list->head.next; 46 | list->head.next = NULL; 47 | list->tail = &(list->head); 48 | return ret; 49 | } 50 | 51 | 52 | #endif 53 | 54 | -------------------------------------------------------------------------------- /mrsocket/mr_socket.c: -------------------------------------------------------------------------------- 1 | 2 | #include "mr_socket.h" 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) 11 | #include "win/winport.h" 12 | #include "win/spinlock.h" 13 | #else 14 | #include 15 | #include 16 | #include 17 | #include "spinlock.h" 18 | #endif 19 | 20 | #include "socket_server.h" 21 | #include "mr_slist.h" 22 | #include "mr_config.h" 23 | 24 | #define MR_SOCKET_TYPE_DATA 1 25 | #define MR_SOCKET_TYPE_CONNECT 2 26 | #define MR_SOCKET_TYPE_CLOSE 3 27 | #define MR_SOCKET_TYPE_ERROR 4 28 | #define MR_SOCKET_TYPE_WARNING 5 29 | #define MR_SOCKET_TYPE_COUNT 6 30 | #define MR_SOCKET_TYPE_ACCEPT 7 31 | #define MR_SOCKET_TYPE_UDP 8 32 | 33 | struct mr_socket { 34 | struct mr_slist msg_list; 35 | struct spinlock list_lock; 36 | mr_callback4 cbs[MR_SOCKET_TYPE_COUNT]; 37 | mr_callback5 apt_bc; 38 | mr_udp_callback udpcb; 39 | pthread_t thread; 40 | uint8_t thread_run; 41 | }; 42 | 43 | struct mr_message { 44 | struct mr_slist_node node; 45 | int type; 46 | int fd; 47 | uintptr_t uid; 48 | int ud; 49 | char* buffer; 50 | int size; 51 | char* option; 52 | // char* info; 53 | }; 54 | 55 | static struct socket_server * SOCKET_SERVER = NULL; 56 | static struct mr_socket * MR_SOCKET = NULL; 57 | 58 | static void mr_handle_data(uintptr_t uid, int fd, char* data, int size){ 59 | printf("[mr_socket]mr_handle_data uid=%d fd=%d size=%d data=%s \n", (int)uid, fd, size, data); 60 | } 61 | static void mr_handle_connect(uintptr_t uid, int fd, char* data, int size){ 62 | printf("[mr_socket]mr_handle_connect uid=%d fd=%d size=%d data=%s \n", (int)uid, fd, size, data); 63 | } 64 | static void mr_handle_close(uintptr_t uid, int fd, char* data, int size){ 65 | printf("[mr_socket]mr_handle_close uid=%d fd=%d size=%d data=%s \n", (int)uid, fd, size, data); 66 | } 67 | static void mr_handle_accept(uintptr_t uid, int fd, char* data, int size, int apt_fd){ 68 | printf("[mr_socket]mr_handle_accept uid=%d fd =%d accept_fd=%d data=%s\n", (int)uid, fd, apt_fd, data); 69 | mr_socket_start(uid, apt_fd); 70 | } 71 | static void mr_handle_error(uintptr_t uid, int fd, char* data, int size){ 72 | printf("[mr_socket]mr_handle_error uid=%d fd=%d size=%d data=%s \n", (int)uid, fd, size, data); 73 | } 74 | static void mr_handle_warning(uintptr_t uid, int fd, char* data, int size){ 75 | printf("[mr_socket]mr_handle_warning uid=%d fd=%d size=%d data=%s \n", (int)uid, fd, size, data); 76 | } 77 | static void mr_handle_udp(uintptr_t uid, int fd, char* data, int size, char* address){ 78 | char udp_addr[256]; 79 | mr_socket_udp_address(address, udp_addr, sizeof(udp_addr)); 80 | 81 | char* tmp = (char*)malloc(size+1); 82 | memset(tmp, 0, size + 1); 83 | memcpy(tmp, data, size); 84 | printf("[mr_socket]mr_handle_udp[%s] uid=%d fd=%d size=%d data=%s \n", udp_addr, (int)uid, fd, size, tmp); 85 | } 86 | 87 | void mr_socket_init(void) { 88 | assert(!SOCKET_SERVER); 89 | // SOCKET_SERVER = socket_server_create(skynet_now()); 90 | SOCKET_SERVER = socket_server_create(0); 91 | 92 | MR_SOCKET = (struct mr_socket*)MALLOC(sizeof(struct mr_socket)); 93 | memset(MR_SOCKET, 0, sizeof(struct mr_socket)); 94 | mr_slist_clear(&MR_SOCKET->msg_list); 95 | spinlock_init(&MR_SOCKET->list_lock); 96 | 97 | mr_callback4* cbs = MR_SOCKET->cbs; 98 | cbs[MR_SOCKET_TYPE_DATA] = mr_handle_data; 99 | cbs[MR_SOCKET_TYPE_CONNECT] = mr_handle_connect; 100 | cbs[MR_SOCKET_TYPE_CLOSE] = mr_handle_close; 101 | cbs[MR_SOCKET_TYPE_ERROR] = mr_handle_error; 102 | cbs[MR_SOCKET_TYPE_WARNING] = mr_handle_warning; 103 | MR_SOCKET->apt_bc = mr_handle_accept; 104 | MR_SOCKET->udpcb = mr_handle_udp; 105 | } 106 | 107 | void mr_set_handle_data(mr_callback4 cb){ 108 | assert(SOCKET_SERVER && cb); 109 | MR_SOCKET->cbs[MR_SOCKET_TYPE_DATA] = cb; 110 | } 111 | void mr_set_handle_connect(mr_callback4 cb){ 112 | assert(SOCKET_SERVER && cb); 113 | MR_SOCKET->cbs[MR_SOCKET_TYPE_CONNECT] = cb; 114 | } 115 | void mr_set_handle_close(mr_callback4 cb){ 116 | assert(SOCKET_SERVER && cb); 117 | MR_SOCKET->cbs[MR_SOCKET_TYPE_CLOSE] = cb; 118 | } 119 | void mr_set_handle_accept(mr_callback5 cb){ 120 | assert(SOCKET_SERVER && cb); 121 | MR_SOCKET->apt_bc = cb; 122 | } 123 | void mr_set_handle_error(mr_callback4 cb){ 124 | assert(SOCKET_SERVER && cb); 125 | MR_SOCKET->cbs[MR_SOCKET_TYPE_ERROR] = cb; 126 | } 127 | void mr_set_handle_warning(mr_callback4 cb){ 128 | assert(SOCKET_SERVER && cb); 129 | MR_SOCKET->cbs[MR_SOCKET_TYPE_WARNING] = cb; 130 | } 131 | void mr_set_handle_udp(mr_udp_callback cb){ 132 | assert(SOCKET_SERVER && cb); 133 | MR_SOCKET->udpcb = cb; 134 | } 135 | 136 | void mr_socket_clear(void) { 137 | assert(MR_SOCKET); 138 | if (!mr_slist_is_empty(&MR_SOCKET->msg_list)){ 139 | struct mr_slist_node* node; 140 | 141 | spinlock_lock(&MR_SOCKET->list_lock); 142 | node = mr_slist_clear(&MR_SOCKET->msg_list); 143 | spinlock_unlock(&MR_SOCKET->list_lock); 144 | 145 | struct mr_message* msg; 146 | while(node){ 147 | msg = (struct mr_message*)node; 148 | node = node->next; 149 | if (msg->buffer){ 150 | FREE(msg->buffer); 151 | } 152 | FREE(msg); 153 | } 154 | } 155 | } 156 | 157 | void mr_socket_free(void) { 158 | assert(SOCKET_SERVER); 159 | 160 | MR_SOCKET->thread_run = 0; 161 | pthread_join(MR_SOCKET->thread, NULL); 162 | 163 | socket_server_release(SOCKET_SERVER); 164 | SOCKET_SERVER = NULL; 165 | 166 | mr_socket_clear(); 167 | spinlock_destroy(&MR_SOCKET->list_lock); 168 | FREE(MR_SOCKET); 169 | MR_SOCKET = NULL; 170 | } 171 | 172 | void mr_socket_update(void){ 173 | assert(SOCKET_SERVER); 174 | // socket_server_updatetime(SOCKET_SERVER, skynet_now()); 175 | if (mr_slist_is_empty(&MR_SOCKET->msg_list)){ 176 | return; 177 | } 178 | struct mr_slist_node* node; 179 | spinlock_lock(&MR_SOCKET->list_lock); 180 | node = mr_slist_clear(&MR_SOCKET->msg_list); 181 | spinlock_unlock(&MR_SOCKET->list_lock); 182 | 183 | assert(node != NULL); 184 | struct mr_message* msg; 185 | char* buffer; 186 | while(node){ 187 | msg = (struct mr_message*)node; 188 | node = node->next; 189 | buffer = msg->buffer == NULL?"":msg->buffer; 190 | if (msg->type == MR_SOCKET_TYPE_UDP) { 191 | MR_SOCKET->udpcb(msg->uid, msg->fd, buffer, msg->size, msg->option); 192 | }else if (msg->type == MR_SOCKET_TYPE_ACCEPT) { 193 | MR_SOCKET->apt_bc(msg->uid, msg->fd, msg->buffer, msg->size, msg->ud); 194 | }else{ 195 | MR_SOCKET->cbs[msg->type](msg->uid, msg->fd, msg->buffer, msg->size); 196 | } 197 | if (msg->buffer){ 198 | FREE(msg->buffer); 199 | } 200 | FREE(msg); 201 | } 202 | } 203 | 204 | static void forward_message(int type, bool padding, struct socket_message * result) { 205 | struct mr_message* msg = (struct mr_message*)MALLOC(sizeof(struct mr_message)); 206 | msg->type = type; 207 | msg->fd = result->id; 208 | msg->ud = result->ud; 209 | msg->uid = result->opaque; 210 | if (padding){ 211 | if (result->data){ 212 | size_t msg_sz = strlen(result->data); 213 | if (msg_sz > 128){ 214 | msg_sz = 128; 215 | } 216 | msg->size = msg_sz+1; 217 | msg->buffer = (char*)MALLOC(msg->size); 218 | memset(msg->buffer, 0, msg->size); 219 | memcpy(msg->buffer, result->data, msg->size); 220 | }else{ 221 | msg->buffer = NULL; 222 | msg->size = 0; 223 | } 224 | }else{ 225 | msg->buffer = result->data; 226 | msg->size = result->ud; 227 | if (msg->type == MR_SOCKET_TYPE_UDP) { 228 | msg->option = msg->buffer + msg->ud; 229 | } 230 | msg->ud = 0; 231 | } 232 | 233 | spinlock_lock(&MR_SOCKET->list_lock); 234 | mr_slist_link(&MR_SOCKET->msg_list, (struct mr_slist_node*)msg); 235 | spinlock_unlock(&MR_SOCKET->list_lock); 236 | } 237 | 238 | int mr_socket_poll(void) { 239 | struct socket_server *ss = SOCKET_SERVER; 240 | assert(ss); 241 | struct socket_message result; 242 | int more = 1; 243 | int type = socket_server_poll(ss, &result, &more); 244 | switch (type) { 245 | case SOCKET_EXIT: 246 | return 0; 247 | case SOCKET_DATA: 248 | forward_message(MR_SOCKET_TYPE_DATA, false, &result); 249 | break; 250 | case SOCKET_CLOSE: 251 | forward_message(MR_SOCKET_TYPE_CLOSE, false, &result); 252 | break; 253 | case SOCKET_OPEN: 254 | forward_message(MR_SOCKET_TYPE_CONNECT, true, &result); 255 | break; 256 | case SOCKET_ERR: 257 | forward_message(MR_SOCKET_TYPE_ERROR, true, &result); 258 | break; 259 | case SOCKET_ACCEPT: 260 | forward_message(MR_SOCKET_TYPE_ACCEPT, true, &result); 261 | break; 262 | case SOCKET_UDP: 263 | forward_message(MR_SOCKET_TYPE_UDP, false, &result); 264 | break; 265 | case SOCKET_WARNING: 266 | forward_message(MR_SOCKET_TYPE_WARNING, false, &result); 267 | break; 268 | default: 269 | if (type != -1){ 270 | fprintf(stderr, "Unknown socket message type %d.\n",type); 271 | } 272 | return -1; 273 | } 274 | if (more) { 275 | return -1; 276 | } 277 | return 1; 278 | } 279 | 280 | static void *thread_socket(void* p) { 281 | int r; 282 | while (MR_SOCKET->thread_run) { 283 | r = mr_socket_poll(); 284 | if (r==0) break; 285 | } 286 | mr_socket_clear(); 287 | return NULL; 288 | } 289 | 290 | void mr_socket_run(void){ 291 | MR_SOCKET->thread_run = 1; 292 | int ret = pthread_create(&MR_SOCKET->thread, NULL, (void *)&thread_socket, NULL); 293 | if (ret != 0) { 294 | fprintf(stderr, "Create thread failed"); 295 | exit(1); 296 | } 297 | } 298 | 299 | int mr_socket_send(int fd, void* buffer, int sz) { 300 | char* sbuffer = (char*)MALLOC(sz); 301 | memcpy(sbuffer, buffer, sz); 302 | return socket_server_send(SOCKET_SERVER, fd, sbuffer, sz); 303 | } 304 | 305 | int mr_socket_send_lowpriority(int fd, void* buffer, int sz) { 306 | char* sbuffer = (char*)MALLOC(sz); 307 | memcpy(sbuffer, buffer, sz); 308 | return socket_server_send_lowpriority(SOCKET_SERVER, fd, sbuffer, sz); 309 | } 310 | 311 | void mr_socket_nodelay(int fd) { 312 | socket_server_nodelay(SOCKET_SERVER, fd); 313 | } 314 | 315 | int mr_socket_listen(uintptr_t uid, const char* host, int port, int backlog) { 316 | return socket_server_listen(SOCKET_SERVER, uid, host, port, backlog); 317 | } 318 | 319 | int mr_socket_connect(uintptr_t uid, const char *host, int port) { 320 | return socket_server_connect(SOCKET_SERVER, uid, host, port); 321 | } 322 | 323 | int mr_socket_bind(uintptr_t uid, int fd) { 324 | return socket_server_bind(SOCKET_SERVER, uid, fd); 325 | } 326 | 327 | void mr_socket_close(uintptr_t uid, int fd) { 328 | socket_server_close(SOCKET_SERVER, uid, fd); 329 | } 330 | 331 | void mr_socket_shutdown(uintptr_t uid, int fd) { 332 | socket_server_shutdown(SOCKET_SERVER, uid, fd); 333 | } 334 | 335 | void mr_socket_start(uintptr_t uid, int fd) { 336 | socket_server_start(SOCKET_SERVER, uid, fd); 337 | } 338 | 339 | int mr_socket_udp(uintptr_t uid, const char* addr, int port) { 340 | return socket_server_udp(SOCKET_SERVER, uid, addr, port); 341 | } 342 | 343 | int mr_socket_udp_connect(int fd, const char* addr, int port) { 344 | return socket_server_udp_connect(SOCKET_SERVER, fd, addr, port); 345 | } 346 | 347 | int mr_socket_udp_send(int fd, const char* address, const void *buffer, int sz) { 348 | char* sbuffer = (char*)MALLOC(sz); 349 | memcpy(sbuffer, buffer, sz); 350 | return socket_server_udp_send(SOCKET_SERVER, fd, (const struct socket_udp_address*)address, sbuffer, sz); 351 | } 352 | 353 | int mr_socket_udp_address(const char* address, char* udp_addr, int len){ 354 | if (!address){ 355 | return -1; 356 | } 357 | int type = address[0]; 358 | int family; 359 | switch(type) { 360 | case PROTOCOL_UDP: 361 | family = AF_INET; 362 | break; 363 | case PROTOCOL_UDPv6: 364 | family = AF_INET6; 365 | break; 366 | default: 367 | return -1; 368 | } 369 | uint16_t port = 0; 370 | memcpy(&port, address+1, sizeof(uint16_t)); 371 | port = ntohs(port); 372 | const void * addrptr = address+3; 373 | char strptr[256] = {0}; 374 | if (!inet_ntop(family, addrptr, strptr, sizeof(strptr))) { 375 | return -1; 376 | } 377 | snprintf(udp_addr, len, "%s:%d", strptr, port); 378 | return 0; 379 | } 380 | 381 | struct socket_info *mr_socket_info(void) { 382 | return socket_server_info(SOCKET_SERVER); 383 | } 384 | -------------------------------------------------------------------------------- /mrsocket/mr_socket.h: -------------------------------------------------------------------------------- 1 | #ifndef mr_socket_h 2 | #define mr_socket_h 3 | 4 | #include "socket_info.h" 5 | 6 | typedef void (*mr_callback4)(uintptr_t, int, char*, int); 7 | typedef void (*mr_callback5)(uintptr_t, int, char*, int, int); 8 | typedef void (*mr_udp_callback)(uintptr_t, int, char*, int, char*); 9 | 10 | //callback 11 | void mr_set_handle_data(mr_callback4 cb); 12 | void mr_set_handle_connect(mr_callback4 cb); 13 | void mr_set_handle_close(mr_callback4 cb); 14 | void mr_set_handle_accept(mr_callback5 cb); 15 | void mr_set_handle_error(mr_callback4 cb); 16 | void mr_set_handle_warning(mr_callback4 cb); 17 | void mr_set_handle_udp(mr_udp_callback cb); 18 | 19 | void mr_socket_run(void); 20 | void mr_socket_update(void); 21 | 22 | void mr_socket_init(void); 23 | void mr_socket_exit(void); 24 | void mr_socket_free(void); 25 | 26 | int mr_socket_send(int fd, void* buffer, int sz); 27 | int mr_socket_send_lowpriority(int fd, void* buffer, int sz); 28 | void mr_socket_nodelay(int fd); 29 | 30 | //tcp part 31 | int mr_socket_listen(uintptr_t uid, const char* host, int port, int backlog); 32 | int mr_socket_connect(uintptr_t uid, const char* host, int port); 33 | int mr_socket_bind(uintptr_t uid, int fd); 34 | void mr_socket_close(uintptr_t uid, int fd); 35 | void mr_socket_shutdown(uintptr_t uid, int fd); 36 | void mr_socket_start(uintptr_t uid, int fd); 37 | 38 | //udp part 39 | int mr_socket_udp(uintptr_t uid, const char* addr, int port); 40 | int mr_socket_udp_connect(int fd, const char* addr, int port); 41 | int mr_socket_udp_send(int fd, const char* address, const void* buffer, int sz); 42 | int mr_socket_udp_address(const char* address, char* udp_addr, int len); 43 | 44 | struct socket_info * mr_socket_info(void); 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /mrsocket/mrsocket.h: -------------------------------------------------------------------------------- 1 | #ifndef mrsocket_h 2 | #define mrsocket_h 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | //#include "mr_time.h" 9 | //#include "mr_buffer.h" 10 | //#include "mr_code.h" 11 | #include "mr_socket.h" 12 | 13 | #ifdef __cplusplus 14 | } 15 | #endif 16 | 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /mrsocket/socket_epoll.h: -------------------------------------------------------------------------------- 1 | #ifndef poll_socket_epoll_h 2 | #define poll_socket_epoll_h 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | static bool 14 | sp_invalid(int efd) { 15 | return efd == -1; 16 | } 17 | 18 | static int 19 | sp_create() { 20 | return epoll_create(1024); 21 | } 22 | 23 | static void 24 | sp_release(int efd) { 25 | close(efd); 26 | } 27 | 28 | static int 29 | sp_add(int efd, int sock, void *ud) { 30 | struct epoll_event ev; 31 | ev.events = EPOLLIN; 32 | ev.data.ptr = ud; 33 | if (epoll_ctl(efd, EPOLL_CTL_ADD, sock, &ev) == -1) { 34 | return 1; 35 | } 36 | return 0; 37 | } 38 | 39 | static void 40 | sp_del(int efd, int sock) { 41 | epoll_ctl(efd, EPOLL_CTL_DEL, sock , NULL); 42 | } 43 | 44 | static void 45 | sp_write(int efd, int sock, void *ud, bool enable) { 46 | struct epoll_event ev; 47 | ev.events = EPOLLIN | (enable ? EPOLLOUT : 0); 48 | ev.data.ptr = ud; 49 | epoll_ctl(efd, EPOLL_CTL_MOD, sock, &ev); 50 | } 51 | 52 | static int 53 | sp_wait(int efd, struct event *e, int max) { 54 | struct epoll_event ev[max]; 55 | int n = epoll_wait(efd , ev, max, -1); 56 | int i; 57 | for (i=0;i 11 | 12 | struct socket_info { 13 | int id; 14 | int type; 15 | uint64_t opaque; 16 | uint64_t read; 17 | uint64_t write; 18 | uint64_t rtime; 19 | uint64_t wtime; 20 | int64_t wbuffer; 21 | char name[128]; 22 | struct socket_info *next; 23 | }; 24 | 25 | struct socket_info * socket_info_create(struct socket_info *last); 26 | void socket_info_release(struct socket_info *); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /mrsocket/socket_kqueue.h: -------------------------------------------------------------------------------- 1 | #ifndef poll_socket_kqueue_h 2 | #define poll_socket_kqueue_h 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | static bool 14 | sp_invalid(int kfd) { 15 | return kfd == -1; 16 | } 17 | 18 | static int 19 | sp_create() { 20 | return kqueue(); 21 | } 22 | 23 | static void 24 | sp_release(int kfd) { 25 | close(kfd); 26 | } 27 | 28 | static void 29 | sp_del(int kfd, int sock) { 30 | struct kevent ke; 31 | EV_SET(&ke, sock, EVFILT_READ, EV_DELETE, 0, 0, NULL); 32 | kevent(kfd, &ke, 1, NULL, 0, NULL); 33 | EV_SET(&ke, sock, EVFILT_WRITE, EV_DELETE, 0, 0, NULL); 34 | kevent(kfd, &ke, 1, NULL, 0, NULL); 35 | } 36 | 37 | static int 38 | sp_add(int kfd, int sock, void *ud) { 39 | struct kevent ke; 40 | EV_SET(&ke, sock, EVFILT_READ, EV_ADD, 0, 0, ud); 41 | if (kevent(kfd, &ke, 1, NULL, 0, NULL) == -1 || ke.flags & EV_ERROR) { 42 | return 1; 43 | } 44 | EV_SET(&ke, sock, EVFILT_WRITE, EV_ADD, 0, 0, ud); 45 | if (kevent(kfd, &ke, 1, NULL, 0, NULL) == -1 || ke.flags & EV_ERROR) { 46 | EV_SET(&ke, sock, EVFILT_READ, EV_DELETE, 0, 0, NULL); 47 | kevent(kfd, &ke, 1, NULL, 0, NULL); 48 | return 1; 49 | } 50 | EV_SET(&ke, sock, EVFILT_WRITE, EV_DISABLE, 0, 0, ud); 51 | if (kevent(kfd, &ke, 1, NULL, 0, NULL) == -1 || ke.flags & EV_ERROR) { 52 | sp_del(kfd, sock); 53 | return 1; 54 | } 55 | return 0; 56 | } 57 | 58 | static void 59 | sp_write(int kfd, int sock, void *ud, bool enable) { 60 | struct kevent ke; 61 | EV_SET(&ke, sock, EVFILT_WRITE, enable ? EV_ENABLE : EV_DISABLE, 0, 0, ud); 62 | if (kevent(kfd, &ke, 1, NULL, 0, NULL) == -1 || ke.flags & EV_ERROR) { 63 | // todo: check error 64 | } 65 | } 66 | 67 | static int 68 | sp_wait(int kfd, struct event *e, int max) { 69 | struct kevent ev[max]; 70 | int n = kevent(kfd, NULL, 0, ev, max, NULL); 71 | 72 | int i; 73 | for (i=0;i 5 | 6 | typedef int poll_fd; 7 | 8 | struct event { 9 | void * s; 10 | bool read; 11 | bool write; 12 | bool error; 13 | bool eof; 14 | }; 15 | 16 | static bool sp_invalid(poll_fd fd); 17 | static poll_fd sp_create(); 18 | static void sp_release(poll_fd fd); 19 | static int sp_add(poll_fd fd, int sock, void *ud); 20 | static void sp_del(poll_fd fd, int sock); 21 | static void sp_write(poll_fd, int sock, void *ud, bool enable); 22 | static int sp_wait(poll_fd, struct event *e, int max); 23 | static void sp_nonblocking(int sock); 24 | 25 | #if defined(__linux__) 26 | #include "socket_epoll.h" 27 | #elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined (__NetBSD__) 28 | #include "socket_kqueue.h" 29 | #else 30 | #include "socket_select.h" 31 | #endif 32 | 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /mrsocket/socket_select.h: -------------------------------------------------------------------------------- 1 | #ifndef poll_socket_epoll_h 2 | #define poll_socket_epoll_h 3 | 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) 13 | 14 | // #include "win/inet.h" 15 | #include 16 | #include 17 | #define O_NONBLOCK 1 18 | #define F_SETFL 0 19 | #define F_GETFL 1 20 | 21 | static inline int fcntl(int fd, int cmd, long arg) { 22 | if (cmd == F_GETFL) 23 | return 0; 24 | 25 | if (cmd == F_SETFL && arg == O_NONBLOCK) { 26 | u_long ulOption = 1; 27 | ioctlsocket(fd, FIONBIO, &ulOption); 28 | } 29 | return 1; 30 | } 31 | 32 | #else 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #endif 43 | 44 | struct fd_ctx 45 | { 46 | int fd; 47 | void *ud; 48 | bool write; 49 | }; 50 | 51 | struct sp_ctx 52 | { 53 | fd_set read_fds; 54 | fd_set write_fds; 55 | fd_set except_fds; 56 | 57 | int used_size; 58 | struct fd_ctx fd_ctxs[FD_SETSIZE]; 59 | }; 60 | 61 | struct sp_ctx* ctx = NULL; 62 | 63 | static bool 64 | sp_invalid(int efd) { 65 | return efd == -1; 66 | } 67 | 68 | static int 69 | sp_create() { 70 | if (ctx != NULL){ 71 | return -1; 72 | } 73 | ctx = (struct sp_ctx*)malloc(sizeof(struct sp_ctx)); 74 | memset(ctx, 0, sizeof(struct sp_ctx)); 75 | int i = 0; 76 | for (; i < FD_SETSIZE; ++i){ 77 | ctx->fd_ctxs[i].fd = -1; 78 | } 79 | return 0; 80 | } 81 | 82 | static void 83 | sp_release(int efd) { 84 | free(ctx); 85 | ctx = NULL; 86 | } 87 | 88 | static int 89 | sp_add(int efd, int sock, void *ud) { 90 | if (ctx->used_size >= FD_SETSIZE){ 91 | fprintf(stderr, "[error]sp_add: select limit FD_SETSIZE:%d/%d \n", ctx->used_size, FD_SETSIZE); 92 | assert(0); 93 | return -1; 94 | } 95 | int i = 0; 96 | for (; i < FD_SETSIZE; ++i){ 97 | if (ctx->fd_ctxs[i].fd < 0){ 98 | ctx->fd_ctxs[i].ud = ud; 99 | ctx->fd_ctxs[i].fd = sock; 100 | ctx->fd_ctxs[i].write = false; 101 | ctx->used_size++; 102 | return 0; 103 | } 104 | } 105 | fprintf(stderr, "[error]sp_add: select limit FD_SETSIZE:%d \n", ctx->used_size); 106 | assert(0); 107 | return -1; 108 | } 109 | 110 | static void 111 | sp_del(int efd, int sock) { 112 | int i = 0; 113 | for (; i < FD_SETSIZE; ++i){ 114 | if (ctx->fd_ctxs[i].fd == sock){ 115 | ctx->fd_ctxs[i].ud = NULL; 116 | ctx->fd_ctxs[i].fd = -1; 117 | ctx->fd_ctxs[i].write = false; 118 | ctx->used_size--; 119 | return; 120 | } 121 | } 122 | fprintf(stderr, "[warn]sp_del no exist sock:%d \n", sock); 123 | } 124 | 125 | static void 126 | sp_write(int efd, int sock, void *ud, bool enable) { 127 | int i = 0; 128 | for (; i < FD_SETSIZE; ++i){ 129 | if (ctx->fd_ctxs[i].fd == sock){ 130 | ctx->fd_ctxs[i].ud = ud; 131 | ctx->fd_ctxs[i].write = enable; 132 | return; 133 | } 134 | } 135 | fprintf(stderr, "[warn]sp_write no exist sock:%d \n", sock); 136 | // assert(false); 137 | } 138 | 139 | static int 140 | sp_wait(int efd, struct event *e, int max) { 141 | FD_ZERO(&ctx->read_fds); 142 | FD_ZERO(&ctx->write_fds); 143 | FD_ZERO(&ctx->except_fds); 144 | 145 | struct fd_ctx* fdctx; 146 | int i = 0; 147 | int idx = 0; 148 | for (; i < FD_SETSIZE; ++i){ 149 | fdctx = &ctx->fd_ctxs[i]; 150 | if (fdctx->fd >= 0){ 151 | FD_SET(fdctx->fd, &ctx->read_fds); 152 | FD_SET(fdctx->fd, &ctx->except_fds); 153 | if (fdctx->write){ 154 | FD_SET(fdctx->fd, &ctx->write_fds); 155 | } 156 | idx++; 157 | if (idx>=ctx->used_size){ 158 | break; 159 | } 160 | } 161 | } 162 | struct timeval tv = {2019030810, 0}; 163 | // printf("[skynet-socket]sp_wait select used_size=%d max=%d\n", ctx->used_size, max); 164 | int ret = select(FD_SETSIZE, &ctx->read_fds, &ctx->write_fds, &ctx->except_fds, (struct timeval*)&tv); 165 | if (ret == 0) { 166 | return 0; 167 | } 168 | if(ret < 0) { 169 | fprintf(stderr, "[error]sp_wait select errno[%d]%s \n", errno, strerror(errno)); 170 | return 0; 171 | } 172 | i = 0; 173 | idx = 0; 174 | bool is_event = false; 175 | struct event* evt; 176 | int sz = 0; 177 | for (; i < FD_SETSIZE; ++i){ 178 | fdctx = &ctx->fd_ctxs[i]; 179 | if (fdctx->fd > 0){ 180 | sz++; 181 | evt = &e[idx]; 182 | if(FD_ISSET(fdctx->fd, &ctx->read_fds)){ 183 | evt->s = fdctx->ud; 184 | evt->read = true; 185 | is_event = true; 186 | } 187 | if(FD_ISSET(fdctx->fd, &ctx->write_fds)){ 188 | evt->s = fdctx->ud; 189 | evt->write = true; 190 | is_event = true; 191 | } 192 | if(FD_ISSET(fdctx->fd, &ctx->except_fds)){ 193 | evt->s = fdctx->ud; 194 | evt->error = true; 195 | evt->read = true; 196 | is_event = true; 197 | } 198 | if(is_event){ 199 | idx++; 200 | is_event = false; 201 | // if(idx >= ctx->used_size) break; 202 | if(idx >= max) break; 203 | } 204 | if (sz >= ctx->used_size){ 205 | break; 206 | } 207 | } 208 | } 209 | // printf("[skynet-socket]sp_wait select event num = %d\n", idx); 210 | return idx; 211 | } 212 | 213 | static void 214 | sp_nonblocking(int fd) { 215 | int flag = fcntl(fd, F_GETFL, 0); 216 | if ( -1 == flag ) { 217 | return; 218 | } 219 | 220 | fcntl(fd, F_SETFL, flag | O_NONBLOCK); 221 | } 222 | 223 | #endif 224 | -------------------------------------------------------------------------------- /mrsocket/socket_server.c: -------------------------------------------------------------------------------- 1 | // #include "skynet.h" 2 | 3 | #include "socket_server.h" 4 | #include "socket_poll.h" 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) 17 | #include "win/winsocket.h" 18 | #include "win/winsocketdef.h" 19 | #include "win/atomic.h" 20 | #include "win/spinlock.h" 21 | 22 | #define ssize_t size_t 23 | #define _CRT_SECURE_NO_WARNINGS 24 | 25 | #else 26 | 27 | #include 28 | #include 29 | #include 30 | #include "spinlock.h" 31 | #include "atomic.h" 32 | 33 | #endif 34 | 35 | #include "mr_config.h" 36 | 37 | 38 | #define MAX_INFO 128 39 | // MAX_SOCKET will be 2^MAX_SOCKET_P 40 | #define MAX_EVENT 64 41 | // #define MIN_READ_BUFFER 64 42 | #define MIN_READ_BUFFER 128 43 | #define SOCKET_TYPE_INVALID 0 44 | #define SOCKET_TYPE_RESERVE 1 45 | #define SOCKET_TYPE_PLISTEN 2 46 | #define SOCKET_TYPE_LISTEN 3 47 | #define SOCKET_TYPE_CONNECTING 4 48 | #define SOCKET_TYPE_CONNECTED 5 49 | #define SOCKET_TYPE_HALFCLOSE 6 50 | #define SOCKET_TYPE_PACCEPT 7 51 | #define SOCKET_TYPE_BIND 8 52 | 53 | #define MAX_SOCKET (1<>MAX_SOCKET_P) & 0xffff) 60 | 61 | #define PROTOCOL_TCP 0 62 | #define PROTOCOL_UDP 1 63 | #define PROTOCOL_UDPv6 2 64 | #define PROTOCOL_UNKNOWN 255 65 | 66 | #define UDP_ADDRESS_SIZE 19 // ipv6 128bit + port 16bit + 1 byte type 67 | 68 | #define MAX_UDP_PACKAGE 65535 69 | 70 | // EAGAIN and EWOULDBLOCK may be not the same value. 71 | #if (EAGAIN != EWOULDBLOCK) 72 | #define AGAIN_WOULDBLOCK EAGAIN : case EWOULDBLOCK 73 | #else 74 | #define AGAIN_WOULDBLOCK EAGAIN 75 | #endif 76 | 77 | #define WARNING_SIZE (1024*1024) 78 | 79 | struct write_buffer { 80 | struct write_buffer * next; 81 | void *buffer; 82 | char *ptr; 83 | int sz; 84 | bool userobject; 85 | uint8_t udp_address[UDP_ADDRESS_SIZE]; 86 | }; 87 | 88 | #define SIZEOF_TCPBUFFER (offsetof(struct write_buffer, udp_address[0])) 89 | #define SIZEOF_UDPBUFFER (sizeof(struct write_buffer)) 90 | 91 | struct wb_list { 92 | struct write_buffer * head; 93 | struct write_buffer * tail; 94 | }; 95 | 96 | struct socket_stat { 97 | uint64_t rtime; 98 | uint64_t wtime; 99 | uint64_t read; 100 | uint64_t write; 101 | }; 102 | 103 | struct socket { 104 | uintptr_t opaque; 105 | struct wb_list high; 106 | struct wb_list low; 107 | int64_t wb_size; 108 | struct socket_stat stat; 109 | volatile uint32_t sending; 110 | int fd; 111 | int id; 112 | uint8_t protocol; 113 | #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) 114 | int type; 115 | int udpconnecting; 116 | #else 117 | uint8_t type; 118 | uint16_t udpconnecting; 119 | #endif 120 | int64_t warn_size; 121 | union { 122 | int size; 123 | uint8_t udp_address[UDP_ADDRESS_SIZE]; 124 | } p; 125 | struct spinlock dw_lock; 126 | int dw_offset; 127 | const void * dw_buffer; 128 | size_t dw_size; 129 | }; 130 | 131 | struct socket_server { 132 | volatile uint64_t time; 133 | int recvctrl_fd; 134 | int sendctrl_fd; 135 | int checkctrl; 136 | poll_fd event_fd; 137 | int alloc_id; 138 | int event_n; 139 | int event_index; 140 | struct socket_object_interface soi; 141 | struct event ev[MAX_EVENT]; 142 | struct socket slot[MAX_SOCKET]; 143 | char buffer[MAX_INFO]; 144 | uint8_t udpbuffer[MAX_UDP_PACKAGE]; 145 | fd_set rfds; 146 | }; 147 | 148 | struct request_open { 149 | int id; 150 | int port; 151 | uintptr_t opaque; 152 | char host[1]; 153 | }; 154 | 155 | struct request_send { 156 | int id; 157 | int sz; 158 | char * buffer; 159 | }; 160 | 161 | struct request_send_udp { 162 | struct request_send send; 163 | uint8_t address[UDP_ADDRESS_SIZE]; 164 | }; 165 | 166 | struct request_setudp { 167 | int id; 168 | uint8_t address[UDP_ADDRESS_SIZE]; 169 | }; 170 | 171 | struct request_close { 172 | int id; 173 | int shutdown; 174 | uintptr_t opaque; 175 | }; 176 | 177 | struct request_listen { 178 | int id; 179 | int fd; 180 | uintptr_t opaque; 181 | char host[1]; 182 | }; 183 | 184 | struct request_bind { 185 | int id; 186 | int fd; 187 | uintptr_t opaque; 188 | }; 189 | 190 | struct request_start { 191 | int id; 192 | uintptr_t opaque; 193 | }; 194 | 195 | struct request_setopt { 196 | int id; 197 | int what; 198 | int value; 199 | }; 200 | 201 | struct request_udp { 202 | int id; 203 | int fd; 204 | int family; 205 | uintptr_t opaque; 206 | }; 207 | 208 | /* 209 | The first byte is TYPE 210 | 211 | S Start socket 212 | B Bind socket 213 | L Listen socket 214 | K Close socket 215 | O Connect to (Open) 216 | X Exit 217 | D Send package (high) 218 | P Send package (low) 219 | A Send UDP package 220 | T Set opt 221 | U Create UDP socket 222 | C set udp address 223 | Q query info 224 | */ 225 | 226 | struct request_package { 227 | uint8_t header[8]; // 6 bytes dummy 228 | union { 229 | char buffer[256]; 230 | struct request_open open; 231 | struct request_send send; 232 | struct request_send_udp send_udp; 233 | struct request_close close; 234 | struct request_listen listen; 235 | struct request_bind bind; 236 | struct request_start start; 237 | struct request_setopt setopt; 238 | struct request_udp udp; 239 | struct request_setudp set_udp; 240 | } u; 241 | uint8_t dummy[256]; 242 | }; 243 | 244 | union sockaddr_all { 245 | struct sockaddr s; 246 | struct sockaddr_in v4; 247 | struct sockaddr_in6 v6; 248 | }; 249 | 250 | struct send_object { 251 | void * buffer; 252 | int sz; 253 | void (*free_func)(void *); 254 | }; 255 | 256 | // #define MALLOC malloc 257 | // #define FREE free 258 | 259 | struct socket_lock { 260 | struct spinlock *lock; 261 | int count; 262 | }; 263 | 264 | static inline void 265 | socket_lock_init(struct socket *s, struct socket_lock *sl) { 266 | sl->lock = &s->dw_lock; 267 | sl->count = 0; 268 | } 269 | 270 | static inline void 271 | socket_lock(struct socket_lock *sl) { 272 | if (sl->count == 0) { 273 | spinlock_lock(sl->lock); 274 | } 275 | ++sl->count; 276 | } 277 | 278 | static inline int 279 | socket_trylock(struct socket_lock *sl) { 280 | if (sl->count == 0) { 281 | if (!spinlock_trylock(sl->lock)) 282 | return 0; // lock failed 283 | } 284 | ++sl->count; 285 | return 1; 286 | } 287 | 288 | static inline void 289 | socket_unlock(struct socket_lock *sl) { 290 | --sl->count; 291 | if (sl->count <= 0) { 292 | assert(sl->count == 0); 293 | spinlock_unlock(sl->lock); 294 | } 295 | } 296 | 297 | static inline bool 298 | send_object_init(struct socket_server *ss, struct send_object *so, void *object, int sz) { 299 | if (sz < 0) { 300 | so->buffer = ss->soi.buffer(object); 301 | so->sz = ss->soi.size(object); 302 | so->free_func = ss->soi.free; 303 | return true; 304 | } else { 305 | so->buffer = object; 306 | so->sz = sz; 307 | so->free_func = FREE; 308 | return false; 309 | } 310 | } 311 | 312 | static inline void 313 | write_buffer_free(struct socket_server *ss, struct write_buffer *wb) { 314 | if (wb->userobject) { 315 | ss->soi.free(wb->buffer); 316 | } else { 317 | FREE(wb->buffer); 318 | } 319 | FREE(wb); 320 | } 321 | 322 | static void 323 | socket_keepalive(int fd) { 324 | int keepalive = 1; 325 | setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepalive , sizeof(keepalive)); 326 | } 327 | 328 | static int 329 | reserve_id(struct socket_server *ss) { 330 | int i; 331 | for (i=0;ialloc_id)); 333 | if (id < 0) { 334 | id = ATOM_AND(&(ss->alloc_id), 0x7fffffff); 335 | } 336 | struct socket *s = &ss->slot[HASH_ID(id)]; 337 | if (s->type == SOCKET_TYPE_INVALID) { 338 | if (ATOM_CAS(&s->type, SOCKET_TYPE_INVALID, SOCKET_TYPE_RESERVE)) { 339 | s->id = id; 340 | s->protocol = PROTOCOL_UNKNOWN; 341 | // socket_server_udp_connect may inc s->udpconncting directly (from other thread, before new_fd), 342 | // so reset it to 0 here rather than in new_fd. 343 | s->udpconnecting = 0; 344 | s->fd = -1; 345 | return id; 346 | } else { 347 | // retry 348 | --i; 349 | } 350 | } 351 | } 352 | return -1; 353 | } 354 | 355 | static inline void 356 | clear_wb_list(struct wb_list *list) { 357 | list->head = NULL; 358 | list->tail = NULL; 359 | } 360 | 361 | struct socket_server * 362 | socket_server_create(uint64_t time) { 363 | int i; 364 | int fd[2]; 365 | poll_fd efd = sp_create(); 366 | if (sp_invalid(efd)) { 367 | fprintf(stderr, "socket-server: create event pool failed.\n"); 368 | return NULL; 369 | } 370 | if (pipe(fd)) { 371 | sp_release(efd); 372 | fprintf(stderr, "socket-server: create socket pair failed.\n"); 373 | return NULL; 374 | } 375 | if (sp_add(efd, fd[0], NULL)) { 376 | // add recvctrl_fd to event poll 377 | fprintf(stderr, "socket-server: can't add server fd to event pool.\n"); 378 | close(fd[0]); 379 | close(fd[1]); 380 | sp_release(efd); 381 | return NULL; 382 | } 383 | 384 | struct socket_server *ss = MALLOC(sizeof(*ss)); 385 | ss->time = time; 386 | ss->event_fd = efd; 387 | ss->recvctrl_fd = fd[0]; 388 | ss->sendctrl_fd = fd[1]; 389 | ss->checkctrl = 1; 390 | for (i=0;islot[i]; 392 | s->type = SOCKET_TYPE_INVALID; 393 | clear_wb_list(&s->high); 394 | clear_wb_list(&s->low); 395 | spinlock_init(&s->dw_lock); 396 | } 397 | ss->alloc_id = 0; 398 | ss->event_n = 0; 399 | ss->event_index = 0; 400 | memset(&ss->soi, 0, sizeof(ss->soi)); 401 | FD_ZERO(&ss->rfds); 402 | #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) 403 | #else 404 | assert(ss->recvctrl_fd < FD_SETSIZE); 405 | #endif 406 | return ss; 407 | } 408 | 409 | void 410 | socket_server_updatetime(struct socket_server *ss, uint64_t time) { 411 | ss->time = time; 412 | } 413 | 414 | static void 415 | free_wb_list(struct socket_server *ss, struct wb_list *list) { 416 | struct write_buffer *wb = list->head; 417 | while (wb) { 418 | struct write_buffer *tmp = wb; 419 | wb = wb->next; 420 | write_buffer_free(ss, tmp); 421 | } 422 | list->head = NULL; 423 | list->tail = NULL; 424 | } 425 | 426 | static void 427 | free_buffer(struct socket_server *ss, const void * buffer, int sz) { 428 | struct send_object so; 429 | send_object_init(ss, &so, (void *)buffer, sz); 430 | so.free_func((void *)buffer); 431 | } 432 | 433 | static void 434 | force_close(struct socket_server *ss, struct socket *s, struct socket_lock *l, struct socket_message *result) { 435 | result->id = s->id; 436 | result->ud = 0; 437 | result->data = NULL; 438 | result->opaque = s->opaque; 439 | if (s->type == SOCKET_TYPE_INVALID) { 440 | return; 441 | } 442 | assert(s->type != SOCKET_TYPE_RESERVE); 443 | free_wb_list(ss,&s->high); 444 | free_wb_list(ss,&s->low); 445 | if (s->type != SOCKET_TYPE_PACCEPT && s->type != SOCKET_TYPE_PLISTEN) { 446 | sp_del(ss->event_fd, s->fd); 447 | } 448 | socket_lock(l); 449 | if (s->type != SOCKET_TYPE_BIND) { 450 | if (close(s->fd) < 0) { 451 | perror("close socket:"); 452 | } 453 | } 454 | s->type = SOCKET_TYPE_INVALID; 455 | if (s->dw_buffer) { 456 | free_buffer(ss, s->dw_buffer, s->dw_size); 457 | s->dw_buffer = NULL; 458 | } 459 | socket_unlock(l); 460 | } 461 | 462 | void 463 | socket_server_release(struct socket_server *ss) { 464 | int i; 465 | struct socket_message dummy; 466 | for (i=0;islot[i]; 468 | struct socket_lock l; 469 | socket_lock_init(s, &l); 470 | if (s->type != SOCKET_TYPE_RESERVE) { 471 | force_close(ss, s, &l, &dummy); 472 | } 473 | spinlock_destroy(&s->dw_lock); 474 | } 475 | close(ss->sendctrl_fd); 476 | close(ss->recvctrl_fd); 477 | sp_release(ss->event_fd); 478 | FREE(ss); 479 | } 480 | 481 | static inline void 482 | check_wb_list(struct wb_list *s) { 483 | assert(s->head == NULL); 484 | assert(s->tail == NULL); 485 | } 486 | 487 | static struct socket * 488 | new_fd(struct socket_server *ss, int id, int fd, int protocol, uintptr_t opaque, bool add) { 489 | struct socket * s = &ss->slot[HASH_ID(id)]; 490 | assert(s->type == SOCKET_TYPE_RESERVE); 491 | 492 | if (add) { 493 | if (sp_add(ss->event_fd, fd, s)) { 494 | s->type = SOCKET_TYPE_INVALID; 495 | return NULL; 496 | } 497 | } 498 | s->id = id; 499 | s->fd = fd; 500 | s->sending = ID_TAG16(id) << 16 | 0; 501 | s->protocol = protocol; 502 | s->p.size = MIN_READ_BUFFER; 503 | s->opaque = opaque; 504 | s->wb_size = 0; 505 | s->warn_size = 0; 506 | check_wb_list(&s->high); 507 | check_wb_list(&s->low); 508 | s->dw_buffer = NULL; 509 | s->dw_size = 0; 510 | memset(&s->stat, 0, sizeof(s->stat)); 511 | return s; 512 | } 513 | 514 | static inline void 515 | stat_read(struct socket_server *ss, struct socket *s, int n) { 516 | s->stat.read += n; 517 | s->stat.rtime = ss->time; 518 | } 519 | 520 | static inline void 521 | stat_write(struct socket_server *ss, struct socket *s, int n) { 522 | s->stat.write += n; 523 | s->stat.wtime = ss->time; 524 | } 525 | 526 | // return -1 when connecting 527 | static int 528 | open_socket(struct socket_server *ss, struct request_open * request, struct socket_message *result) { 529 | int id = request->id; 530 | result->opaque = request->opaque; 531 | result->id = id; 532 | result->ud = 0; 533 | result->data = NULL; 534 | struct socket *ns; 535 | int status; 536 | struct addrinfo ai_hints; 537 | struct addrinfo *ai_list = NULL; 538 | struct addrinfo *ai_ptr = NULL; 539 | char port[16]; 540 | sprintf(port, "%d", request->port); 541 | memset(&ai_hints, 0, sizeof( ai_hints ) ); 542 | ai_hints.ai_family = AF_UNSPEC; 543 | ai_hints.ai_socktype = SOCK_STREAM; 544 | ai_hints.ai_protocol = IPPROTO_TCP; 545 | 546 | status = getaddrinfo( request->host, port, &ai_hints, &ai_list ); 547 | if ( status != 0 ) { 548 | result->data = (void *)gai_strerror(status); 549 | goto _failed; 550 | } 551 | int sock= -1; 552 | for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next ) { 553 | sock = socket( ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol ); 554 | if ( sock < 0 ) { 555 | continue; 556 | } 557 | socket_keepalive(sock); 558 | sp_nonblocking(sock); 559 | status = connect( sock, ai_ptr->ai_addr, ai_ptr->ai_addrlen); 560 | if ( status != 0 && errno != EINPROGRESS) { 561 | close(sock); 562 | sock = -1; 563 | continue; 564 | } 565 | break; 566 | } 567 | 568 | if (sock < 0) { 569 | result->data = strerror(errno); 570 | goto _failed; 571 | } 572 | 573 | ns = new_fd(ss, id, sock, PROTOCOL_TCP, request->opaque, true); 574 | if (ns == NULL) { 575 | close(sock); 576 | result->data = "reach skynet socket number limit"; 577 | goto _failed; 578 | } 579 | 580 | if(status == 0) { 581 | ns->type = SOCKET_TYPE_CONNECTED; 582 | struct sockaddr * addr = ai_ptr->ai_addr; 583 | void * sin_addr = (ai_ptr->ai_family == AF_INET) ? (void*)&((struct sockaddr_in *)addr)->sin_addr : (void*)&((struct sockaddr_in6 *)addr)->sin6_addr; 584 | if (inet_ntop(ai_ptr->ai_family, sin_addr, ss->buffer, sizeof(ss->buffer))) { 585 | result->data = ss->buffer; 586 | } 587 | freeaddrinfo( ai_list ); 588 | return SOCKET_OPEN; 589 | } else { 590 | ns->type = SOCKET_TYPE_CONNECTING; 591 | sp_write(ss->event_fd, ns->fd, ns, true); 592 | } 593 | 594 | freeaddrinfo( ai_list ); 595 | return -1; 596 | _failed: 597 | freeaddrinfo( ai_list ); 598 | ss->slot[HASH_ID(id)].type = SOCKET_TYPE_INVALID; 599 | return SOCKET_ERR; 600 | } 601 | 602 | static int 603 | send_list_tcp(struct socket_server *ss, struct socket *s, struct wb_list *list, struct socket_lock *l, struct socket_message *result) { 604 | while (list->head) { 605 | struct write_buffer * tmp = list->head; 606 | for (;;) { 607 | ssize_t sz = write(s->fd, tmp->ptr, tmp->sz); 608 | if (sz < 0) { 609 | switch(errno) { 610 | case EINTR: 611 | continue; 612 | case AGAIN_WOULDBLOCK: 613 | return -1; 614 | } 615 | force_close(ss,s,l,result); 616 | return SOCKET_CLOSE; 617 | } 618 | stat_write(ss,s,(int)sz); 619 | s->wb_size -= sz; 620 | if (sz != tmp->sz) { 621 | tmp->ptr += sz; 622 | tmp->sz -= sz; 623 | return -1; 624 | } 625 | break; 626 | } 627 | list->head = tmp->next; 628 | write_buffer_free(ss,tmp); 629 | } 630 | list->tail = NULL; 631 | 632 | return -1; 633 | } 634 | 635 | static socklen_t 636 | udp_socket_address(struct socket *s, const uint8_t udp_address[UDP_ADDRESS_SIZE], union sockaddr_all *sa) { 637 | int type = (uint8_t)udp_address[0]; 638 | if (type != s->protocol) 639 | return 0; 640 | uint16_t port = 0; 641 | memcpy(&port, udp_address+1, sizeof(uint16_t)); 642 | switch (s->protocol) { 643 | case PROTOCOL_UDP: 644 | memset(&sa->v4, 0, sizeof(sa->v4)); 645 | sa->s.sa_family = AF_INET; 646 | sa->v4.sin_port = port; 647 | memcpy(&sa->v4.sin_addr, udp_address + 1 + sizeof(uint16_t), sizeof(sa->v4.sin_addr)); // ipv4 address is 32 bits 648 | return sizeof(sa->v4); 649 | case PROTOCOL_UDPv6: 650 | memset(&sa->v6, 0, sizeof(sa->v6)); 651 | sa->s.sa_family = AF_INET6; 652 | sa->v6.sin6_port = port; 653 | memcpy(&sa->v6.sin6_addr, udp_address + 1 + sizeof(uint16_t), sizeof(sa->v6.sin6_addr)); // ipv6 address is 128 bits 654 | return sizeof(sa->v6); 655 | } 656 | return 0; 657 | } 658 | 659 | static void 660 | drop_udp(struct socket_server *ss, struct socket *s, struct wb_list *list, struct write_buffer *tmp) { 661 | s->wb_size -= tmp->sz; 662 | list->head = tmp->next; 663 | if (list->head == NULL) 664 | list->tail = NULL; 665 | write_buffer_free(ss,tmp); 666 | } 667 | 668 | static int 669 | send_list_udp(struct socket_server *ss, struct socket *s, struct wb_list *list, struct socket_message *result) { 670 | while (list->head) { 671 | struct write_buffer * tmp = list->head; 672 | union sockaddr_all sa; 673 | socklen_t sasz = udp_socket_address(s, tmp->udp_address, &sa); 674 | if (sasz == 0) { 675 | fprintf(stderr, "socket-server : udp (%d) type mismatch.\n", s->id); 676 | drop_udp(ss, s, list, tmp); 677 | return -1; 678 | } 679 | int err = sendto(s->fd, tmp->ptr, tmp->sz, 0, &sa.s, sasz); 680 | if (err < 0) { 681 | switch(errno) { 682 | case EINTR: 683 | case AGAIN_WOULDBLOCK: 684 | return -1; 685 | } 686 | fprintf(stderr, "socket-server : udp (%d) sendto error %s.\n",s->id, strerror(errno)); 687 | drop_udp(ss, s, list, tmp); 688 | return -1; 689 | } 690 | stat_write(ss,s,tmp->sz); 691 | s->wb_size -= tmp->sz; 692 | list->head = tmp->next; 693 | write_buffer_free(ss,tmp); 694 | } 695 | list->tail = NULL; 696 | 697 | return -1; 698 | } 699 | 700 | static int 701 | send_list(struct socket_server *ss, struct socket *s, struct wb_list *list, struct socket_lock *l, struct socket_message *result) { 702 | if (s->protocol == PROTOCOL_TCP) { 703 | return send_list_tcp(ss, s, list, l, result); 704 | } else { 705 | return send_list_udp(ss, s, list, result); 706 | } 707 | } 708 | 709 | static inline int 710 | list_uncomplete(struct wb_list *s) { 711 | struct write_buffer *wb = s->head; 712 | if (wb == NULL) 713 | return 0; 714 | 715 | return (void *)wb->ptr != wb->buffer; 716 | } 717 | 718 | static void 719 | raise_uncomplete(struct socket * s) { 720 | struct wb_list *low = &s->low; 721 | struct write_buffer *tmp = low->head; 722 | low->head = tmp->next; 723 | if (low->head == NULL) { 724 | low->tail = NULL; 725 | } 726 | 727 | // move head of low list (tmp) to the empty high list 728 | struct wb_list *high = &s->high; 729 | assert(high->head == NULL); 730 | 731 | tmp->next = NULL; 732 | high->head = high->tail = tmp; 733 | } 734 | 735 | static inline int 736 | send_buffer_empty(struct socket *s) { 737 | return (s->high.head == NULL && s->low.head == NULL); 738 | } 739 | 740 | /* 741 | Each socket has two write buffer list, high priority and low priority. 742 | 743 | 1. send high list as far as possible. 744 | 2. If high list is empty, try to send low list. 745 | 3. If low list head is uncomplete (send a part before), move the head of low list to empty high list (call raise_uncomplete) . 746 | 4. If two lists are both empty, turn off the event. (call check_close) 747 | */ 748 | static int 749 | send_buffer_(struct socket_server *ss, struct socket *s, struct socket_lock *l, struct socket_message *result) { 750 | assert(!list_uncomplete(&s->low)); 751 | // step 1 752 | if (send_list(ss,s,&s->high,l,result) == SOCKET_CLOSE) { 753 | return SOCKET_CLOSE; 754 | } 755 | if (s->high.head == NULL) { 756 | // step 2 757 | if (s->low.head != NULL) { 758 | if (send_list(ss,s,&s->low,l,result) == SOCKET_CLOSE) { 759 | return SOCKET_CLOSE; 760 | } 761 | // step 3 762 | if (list_uncomplete(&s->low)) { 763 | raise_uncomplete(s); 764 | return -1; 765 | } 766 | if (s->low.head) 767 | return -1; 768 | } 769 | // step 4 770 | assert(send_buffer_empty(s) && s->wb_size == 0); 771 | sp_write(ss->event_fd, s->fd, s, false); 772 | 773 | if (s->type == SOCKET_TYPE_HALFCLOSE) { 774 | force_close(ss, s, l, result); 775 | return SOCKET_CLOSE; 776 | } 777 | if(s->warn_size > 0){ 778 | s->warn_size = 0; 779 | result->opaque = s->opaque; 780 | result->id = s->id; 781 | result->ud = 0; 782 | result->data = NULL; 783 | return SOCKET_WARNING; 784 | } 785 | } 786 | 787 | return -1; 788 | } 789 | 790 | static int 791 | send_buffer(struct socket_server *ss, struct socket *s, struct socket_lock *l, struct socket_message *result) { 792 | if (!socket_trylock(l)) 793 | return -1; // blocked by direct write, send later. 794 | if (s->dw_buffer) { 795 | // add direct write buffer before high.head 796 | struct write_buffer * buf = MALLOC(SIZEOF_TCPBUFFER); 797 | struct send_object so; 798 | buf->userobject = send_object_init(ss, &so, (void *)s->dw_buffer, s->dw_size); 799 | buf->ptr = (char*)so.buffer+s->dw_offset; 800 | buf->sz = so.sz - s->dw_offset; 801 | buf->buffer = (void *)s->dw_buffer; 802 | s->wb_size+=buf->sz; 803 | if (s->high.head == NULL) { 804 | s->high.head = s->high.tail = buf; 805 | buf->next = NULL; 806 | } else { 807 | buf->next = s->high.head; 808 | s->high.head = buf; 809 | } 810 | s->dw_buffer = NULL; 811 | } 812 | int r = send_buffer_(ss,s,l,result); 813 | socket_unlock(l); 814 | 815 | return r; 816 | } 817 | 818 | static struct write_buffer * 819 | append_sendbuffer_(struct socket_server *ss, struct wb_list *s, struct request_send * request, int size) { 820 | struct write_buffer * buf = MALLOC(size); 821 | struct send_object so; 822 | buf->userobject = send_object_init(ss, &so, request->buffer, request->sz); 823 | buf->ptr = (char*)so.buffer; 824 | buf->sz = so.sz; 825 | buf->buffer = request->buffer; 826 | buf->next = NULL; 827 | if (s->head == NULL) { 828 | s->head = s->tail = buf; 829 | } else { 830 | assert(s->tail != NULL); 831 | assert(s->tail->next == NULL); 832 | s->tail->next = buf; 833 | s->tail = buf; 834 | } 835 | return buf; 836 | } 837 | 838 | static inline void 839 | append_sendbuffer_udp(struct socket_server *ss, struct socket *s, int priority, struct request_send * request, const uint8_t udp_address[UDP_ADDRESS_SIZE]) { 840 | struct wb_list *wl = (priority == PRIORITY_HIGH) ? &s->high : &s->low; 841 | struct write_buffer *buf = append_sendbuffer_(ss, wl, request, SIZEOF_UDPBUFFER); 842 | memcpy(buf->udp_address, udp_address, UDP_ADDRESS_SIZE); 843 | s->wb_size += buf->sz; 844 | } 845 | 846 | static inline void 847 | append_sendbuffer(struct socket_server *ss, struct socket *s, struct request_send * request) { 848 | struct write_buffer *buf = append_sendbuffer_(ss, &s->high, request, SIZEOF_TCPBUFFER); 849 | s->wb_size += buf->sz; 850 | } 851 | 852 | static inline void 853 | append_sendbuffer_low(struct socket_server *ss,struct socket *s, struct request_send * request) { 854 | struct write_buffer *buf = append_sendbuffer_(ss, &s->low, request, SIZEOF_TCPBUFFER); 855 | s->wb_size += buf->sz; 856 | } 857 | 858 | 859 | /* 860 | When send a package , we can assign the priority : PRIORITY_HIGH or PRIORITY_LOW 861 | 862 | If socket buffer is empty, write to fd directly. 863 | If write a part, append the rest part to high list. (Even priority is PRIORITY_LOW) 864 | Else append package to high (PRIORITY_HIGH) or low (PRIORITY_LOW) list. 865 | */ 866 | static int 867 | send_socket(struct socket_server *ss, struct request_send * request, struct socket_message *result, int priority, const uint8_t *udp_address) { 868 | int id = request->id; 869 | struct socket * s = &ss->slot[HASH_ID(id)]; 870 | struct send_object so; 871 | send_object_init(ss, &so, request->buffer, request->sz); 872 | if (s->type == SOCKET_TYPE_INVALID || s->id != id 873 | || s->type == SOCKET_TYPE_HALFCLOSE 874 | || s->type == SOCKET_TYPE_PACCEPT) { 875 | so.free_func(request->buffer); 876 | return -1; 877 | } 878 | if (s->type == SOCKET_TYPE_PLISTEN || s->type == SOCKET_TYPE_LISTEN) { 879 | fprintf(stderr, "socket-server: write to listen fd %d.\n", id); 880 | so.free_func(request->buffer); 881 | return -1; 882 | } 883 | if (send_buffer_empty(s) && s->type == SOCKET_TYPE_CONNECTED) { 884 | if (s->protocol == PROTOCOL_TCP) { 885 | append_sendbuffer(ss, s, request); // add to high priority list, even priority == PRIORITY_LOW 886 | } else { 887 | // udp 888 | if (udp_address == NULL) { 889 | udp_address = s->p.udp_address; 890 | } 891 | union sockaddr_all sa; 892 | socklen_t sasz = udp_socket_address(s, udp_address, &sa); 893 | if (sasz == 0) { 894 | // udp type mismatch, just drop it. 895 | fprintf(stderr, "socket-server: udp socket (%d) type mistach.\n", id); 896 | so.free_func(request->buffer); 897 | return -1; 898 | } 899 | int n = sendto(s->fd, so.buffer, so.sz, 0, &sa.s, sasz); 900 | if (n != so.sz) { 901 | append_sendbuffer_udp(ss,s,priority,request,udp_address); 902 | } else { 903 | stat_write(ss,s,n); 904 | so.free_func(request->buffer); 905 | return -1; 906 | } 907 | } 908 | sp_write(ss->event_fd, s->fd, s, true); 909 | } else { 910 | if (s->protocol == PROTOCOL_TCP) { 911 | if (priority == PRIORITY_LOW) { 912 | append_sendbuffer_low(ss, s, request); 913 | } else { 914 | append_sendbuffer(ss, s, request); 915 | } 916 | } else { 917 | if (udp_address == NULL) { 918 | udp_address = s->p.udp_address; 919 | } 920 | append_sendbuffer_udp(ss,s,priority,request,udp_address); 921 | } 922 | } 923 | if (s->wb_size >= WARNING_SIZE && s->wb_size >= s->warn_size) { 924 | s->warn_size = s->warn_size == 0 ? WARNING_SIZE *2 : s->warn_size*2; 925 | result->opaque = s->opaque; 926 | result->id = s->id; 927 | result->ud = s->wb_size%1024 == 0 ? s->wb_size/1024 : s->wb_size/1024 + 1; 928 | result->data = NULL; 929 | return SOCKET_WARNING; 930 | } 931 | return -1; 932 | } 933 | 934 | static int 935 | listen_socket(struct socket_server *ss, struct request_listen * request, struct socket_message *result) { 936 | int id = request->id; 937 | int listen_fd = request->fd; 938 | struct socket *s = new_fd(ss, id, listen_fd, PROTOCOL_TCP, request->opaque, false); 939 | if (s == NULL) { 940 | goto _failed; 941 | } 942 | s->type = SOCKET_TYPE_PLISTEN; 943 | return -1; 944 | _failed: 945 | close(listen_fd); 946 | result->opaque = request->opaque; 947 | result->id = id; 948 | result->ud = 0; 949 | result->data = "reach skynet socket number limit"; 950 | ss->slot[HASH_ID(id)].type = SOCKET_TYPE_INVALID; 951 | 952 | return SOCKET_ERR; 953 | } 954 | 955 | static inline int 956 | nomore_sending_data(struct socket *s) { 957 | return send_buffer_empty(s) && s->dw_buffer == NULL && (s->sending & 0xffff) == 0; 958 | } 959 | 960 | static int 961 | close_socket(struct socket_server *ss, struct request_close *request, struct socket_message *result) { 962 | int id = request->id; 963 | struct socket * s = &ss->slot[HASH_ID(id)]; 964 | if (s->type == SOCKET_TYPE_INVALID || s->id != id) { 965 | result->id = id; 966 | result->opaque = request->opaque; 967 | result->ud = 0; 968 | result->data = NULL; 969 | return SOCKET_CLOSE; 970 | } 971 | struct socket_lock l; 972 | socket_lock_init(s, &l); 973 | if (!nomore_sending_data(s)) { 974 | int type = send_buffer(ss,s,&l,result); 975 | // type : -1 or SOCKET_WARNING or SOCKET_CLOSE, SOCKET_WARNING means nomore_sending_data 976 | if (type != -1 && type != SOCKET_WARNING) 977 | return type; 978 | } 979 | if (request->shutdown || nomore_sending_data(s)) { 980 | force_close(ss,s,&l,result); 981 | result->id = id; 982 | result->opaque = request->opaque; 983 | return SOCKET_CLOSE; 984 | } 985 | s->type = SOCKET_TYPE_HALFCLOSE; 986 | 987 | return -1; 988 | } 989 | 990 | static int 991 | bind_socket(struct socket_server *ss, struct request_bind *request, struct socket_message *result) { 992 | int id = request->id; 993 | result->id = id; 994 | result->opaque = request->opaque; 995 | result->ud = 0; 996 | struct socket *s = new_fd(ss, id, request->fd, PROTOCOL_TCP, request->opaque, true); 997 | if (s == NULL) { 998 | result->data = "reach skynet socket number limit"; 999 | return SOCKET_ERR; 1000 | } 1001 | sp_nonblocking(request->fd); 1002 | s->type = SOCKET_TYPE_BIND; 1003 | result->data = "binding"; 1004 | return SOCKET_OPEN; 1005 | } 1006 | 1007 | static int 1008 | start_socket(struct socket_server *ss, struct request_start *request, struct socket_message *result) { 1009 | int id = request->id; 1010 | result->id = id; 1011 | result->opaque = request->opaque; 1012 | result->ud = 0; 1013 | result->data = NULL; 1014 | struct socket *s = &ss->slot[HASH_ID(id)]; 1015 | if (s->type == SOCKET_TYPE_INVALID || s->id !=id) { 1016 | result->data = "invalid socket"; 1017 | return SOCKET_ERR; 1018 | } 1019 | struct socket_lock l; 1020 | socket_lock_init(s, &l); 1021 | if (s->type == SOCKET_TYPE_PACCEPT || s->type == SOCKET_TYPE_PLISTEN) { 1022 | if (sp_add(ss->event_fd, s->fd, s)) { 1023 | force_close(ss, s, &l, result); 1024 | result->data = strerror(errno); 1025 | return SOCKET_ERR; 1026 | } 1027 | s->type = (s->type == SOCKET_TYPE_PACCEPT) ? SOCKET_TYPE_CONNECTED : SOCKET_TYPE_LISTEN; 1028 | s->opaque = request->opaque; 1029 | result->data = "start"; 1030 | return SOCKET_OPEN; 1031 | } else if (s->type == SOCKET_TYPE_CONNECTED) { 1032 | // todo: maybe we should send a message SOCKET_TRANSFER to s->opaque 1033 | s->opaque = request->opaque; 1034 | result->data = "transfer"; 1035 | return SOCKET_OPEN; 1036 | } 1037 | // if s->type == SOCKET_TYPE_HALFCLOSE , SOCKET_CLOSE message will send later 1038 | return -1; 1039 | } 1040 | 1041 | static void 1042 | setopt_socket(struct socket_server *ss, struct request_setopt *request) { 1043 | int id = request->id; 1044 | struct socket *s = &ss->slot[HASH_ID(id)]; 1045 | if (s->type == SOCKET_TYPE_INVALID || s->id !=id) { 1046 | return; 1047 | } 1048 | int v = request->value; 1049 | setsockopt(s->fd, IPPROTO_TCP, request->what, &v, sizeof(v)); 1050 | } 1051 | 1052 | static void 1053 | block_readpipe(int pipefd, void *buffer, int sz) { 1054 | for (;;) { 1055 | int n = read(pipefd, buffer, sz); 1056 | if (n<0) { 1057 | if (errno == EINTR) 1058 | continue; 1059 | fprintf(stderr, "socket-server : read pipe error %s.\n",strerror(errno)); 1060 | return; 1061 | } 1062 | // must atomic read from a pipe 1063 | assert(n == sz); 1064 | return; 1065 | } 1066 | } 1067 | 1068 | static int 1069 | has_cmd(struct socket_server *ss) { 1070 | struct timeval tv = {0,0}; 1071 | int retval; 1072 | 1073 | FD_SET(ss->recvctrl_fd, &ss->rfds); 1074 | 1075 | retval = select(ss->recvctrl_fd+1, &ss->rfds, NULL, NULL, &tv); 1076 | if (retval == 1) { 1077 | return 1; 1078 | } 1079 | return 0; 1080 | } 1081 | 1082 | static void 1083 | add_udp_socket(struct socket_server *ss, struct request_udp *udp) { 1084 | int id = udp->id; 1085 | int protocol; 1086 | if (udp->family == AF_INET6) { 1087 | protocol = PROTOCOL_UDPv6; 1088 | } else { 1089 | protocol = PROTOCOL_UDP; 1090 | } 1091 | struct socket *ns = new_fd(ss, id, udp->fd, protocol, udp->opaque, true); 1092 | if (ns == NULL) { 1093 | close(udp->fd); 1094 | ss->slot[HASH_ID(id)].type = SOCKET_TYPE_INVALID; 1095 | return; 1096 | } 1097 | ns->type = SOCKET_TYPE_CONNECTED; 1098 | memset(ns->p.udp_address, 0, sizeof(ns->p.udp_address)); 1099 | } 1100 | 1101 | static int 1102 | set_udp_address(struct socket_server *ss, struct request_setudp *request, struct socket_message *result) { 1103 | int id = request->id; 1104 | struct socket *s = &ss->slot[HASH_ID(id)]; 1105 | if (s->type == SOCKET_TYPE_INVALID || s->id !=id) { 1106 | return -1; 1107 | } 1108 | int type = request->address[0]; 1109 | if (type != s->protocol) { 1110 | // protocol mismatch 1111 | result->opaque = s->opaque; 1112 | result->id = s->id; 1113 | result->ud = 0; 1114 | result->data = "protocol mismatch"; 1115 | 1116 | return SOCKET_ERR; 1117 | } 1118 | if (type == PROTOCOL_UDP) { 1119 | memcpy(s->p.udp_address, request->address, 1+2+4); // 1 type, 2 port, 4 ipv4 1120 | } else { 1121 | memcpy(s->p.udp_address, request->address, 1+2+16); // 1 type, 2 port, 16 ipv6 1122 | } 1123 | ATOM_DEC(&s->udpconnecting); 1124 | return -1; 1125 | } 1126 | 1127 | static inline void 1128 | inc_sending_ref(struct socket *s, int id) { 1129 | if (s->protocol != PROTOCOL_TCP) 1130 | return; 1131 | for (;;) { 1132 | uint32_t sending = s->sending; 1133 | if ((sending >> 16) == ID_TAG16(id)) { 1134 | if ((sending & 0xffff) == 0xffff) { 1135 | // s->sending may overflow (rarely), so busy waiting here for socket thread dec it. see issue #794 1136 | continue; 1137 | } 1138 | // inc sending only matching the same socket id 1139 | if (ATOM_CAS(&s->sending, sending, sending + 1)) 1140 | return; 1141 | // atom inc failed, retry 1142 | } else { 1143 | // socket id changed, just return 1144 | return; 1145 | } 1146 | } 1147 | } 1148 | 1149 | static inline void 1150 | dec_sending_ref(struct socket_server *ss, int id) { 1151 | struct socket * s = &ss->slot[HASH_ID(id)]; 1152 | // Notice: udp may inc sending while type == SOCKET_TYPE_RESERVE 1153 | if (s->id == id && s->protocol == PROTOCOL_TCP) { 1154 | assert((s->sending & 0xffff) != 0); 1155 | ATOM_DEC(&s->sending); 1156 | } 1157 | } 1158 | 1159 | // return type 1160 | static int 1161 | ctrl_cmd(struct socket_server *ss, struct socket_message *result) { 1162 | int fd = ss->recvctrl_fd; 1163 | // the length of message is one byte, so 256+8 buffer size is enough. 1164 | uint8_t buffer[256]; 1165 | uint8_t header[2]; 1166 | block_readpipe(fd, header, sizeof(header)); 1167 | int type = header[0]; 1168 | int len = header[1]; 1169 | block_readpipe(fd, buffer, len); 1170 | // ctrl command only exist in local fd, so don't worry about endian. 1171 | // printf("[skynet-socket]ctrl_cmd type=%c\n", type); 1172 | switch (type) { 1173 | case 'S': 1174 | return start_socket(ss,(struct request_start *)buffer, result); 1175 | case 'B': 1176 | return bind_socket(ss,(struct request_bind *)buffer, result); 1177 | case 'L': 1178 | return listen_socket(ss,(struct request_listen *)buffer, result); 1179 | case 'K': 1180 | return close_socket(ss,(struct request_close *)buffer, result); 1181 | case 'O': 1182 | return open_socket(ss, (struct request_open *)buffer, result); 1183 | case 'X': 1184 | result->opaque = 0; 1185 | result->id = 0; 1186 | result->ud = 0; 1187 | result->data = NULL; 1188 | return SOCKET_EXIT; 1189 | case 'D': 1190 | case 'P': { 1191 | int priority = (type == 'D') ? PRIORITY_HIGH : PRIORITY_LOW; 1192 | struct request_send * request = (struct request_send *) buffer; 1193 | int ret = send_socket(ss, request, result, priority, NULL); 1194 | dec_sending_ref(ss, request->id); 1195 | return ret; 1196 | } 1197 | case 'A': { 1198 | struct request_send_udp * rsu = (struct request_send_udp *)buffer; 1199 | return send_socket(ss, &rsu->send, result, PRIORITY_HIGH, rsu->address); 1200 | } 1201 | case 'C': 1202 | return set_udp_address(ss, (struct request_setudp *)buffer, result); 1203 | case 'T': 1204 | setopt_socket(ss, (struct request_setopt *)buffer); 1205 | return -1; 1206 | case 'U': 1207 | add_udp_socket(ss, (struct request_udp *)buffer); 1208 | return -1; 1209 | default: 1210 | fprintf(stderr, "socket-server: Unknown ctrl %c.\n",type); 1211 | return -1; 1212 | }; 1213 | 1214 | return -1; 1215 | } 1216 | 1217 | // return -1 (ignore) when error 1218 | static int 1219 | forward_message_tcp(struct socket_server *ss, struct socket *s, struct socket_lock *l, struct socket_message * result) { 1220 | int sz = s->p.size; 1221 | char * buffer = MALLOC(sz); 1222 | int n = (int)read(s->fd, buffer, sz); 1223 | if (n<0) { 1224 | FREE(buffer); 1225 | switch(errno) { 1226 | case EINTR: 1227 | break; 1228 | case AGAIN_WOULDBLOCK: 1229 | fprintf(stderr, "socket-server: EAGAIN capture.\n"); 1230 | break; 1231 | default: 1232 | // close when error 1233 | force_close(ss, s, l, result); 1234 | result->data = strerror(errno); 1235 | return SOCKET_ERR; 1236 | } 1237 | return -1; 1238 | } 1239 | if (n==0) { 1240 | FREE(buffer); 1241 | force_close(ss, s, l, result); 1242 | return SOCKET_CLOSE; 1243 | } 1244 | 1245 | if (s->type == SOCKET_TYPE_HALFCLOSE) { 1246 | // discard recv data 1247 | FREE(buffer); 1248 | return -1; 1249 | } 1250 | 1251 | stat_read(ss,s,n); 1252 | 1253 | if (n == sz) { 1254 | s->p.size *= 2; 1255 | } else if (sz > MIN_READ_BUFFER && n*2 < sz) { 1256 | s->p.size /= 2; 1257 | } 1258 | 1259 | result->opaque = s->opaque; 1260 | result->id = s->id; 1261 | result->ud = n; 1262 | result->data = buffer; 1263 | return SOCKET_DATA; 1264 | } 1265 | 1266 | static int 1267 | gen_udp_address(int protocol, union sockaddr_all *sa, uint8_t * udp_address) { 1268 | int addrsz = 1; 1269 | udp_address[0] = (uint8_t)protocol; 1270 | if (protocol == PROTOCOL_UDP) { 1271 | memcpy(udp_address+addrsz, &sa->v4.sin_port, sizeof(sa->v4.sin_port)); 1272 | addrsz += sizeof(sa->v4.sin_port); 1273 | memcpy(udp_address+addrsz, &sa->v4.sin_addr, sizeof(sa->v4.sin_addr)); 1274 | addrsz += sizeof(sa->v4.sin_addr); 1275 | } else { 1276 | memcpy(udp_address+addrsz, &sa->v6.sin6_port, sizeof(sa->v6.sin6_port)); 1277 | addrsz += sizeof(sa->v6.sin6_port); 1278 | memcpy(udp_address+addrsz, &sa->v6.sin6_addr, sizeof(sa->v6.sin6_addr)); 1279 | addrsz += sizeof(sa->v6.sin6_addr); 1280 | } 1281 | return addrsz; 1282 | } 1283 | 1284 | static int 1285 | forward_message_udp(struct socket_server *ss, struct socket *s, struct socket_lock *l, struct socket_message * result) { 1286 | union sockaddr_all sa; 1287 | socklen_t slen = sizeof(sa); 1288 | int n = recvfrom(s->fd, ss->udpbuffer,MAX_UDP_PACKAGE,0,&sa.s,&slen); 1289 | if (n<0) { 1290 | switch(errno) { 1291 | case EINTR: 1292 | case AGAIN_WOULDBLOCK: 1293 | break; 1294 | default: 1295 | // close when error 1296 | force_close(ss, s, l, result); 1297 | result->data = strerror(errno); 1298 | return SOCKET_ERR; 1299 | } 1300 | return -1; 1301 | } 1302 | stat_read(ss,s,n); 1303 | 1304 | uint8_t * data; 1305 | if (slen == sizeof(sa.v4)) { 1306 | if (s->protocol != PROTOCOL_UDP) 1307 | return -1; 1308 | data = MALLOC(n + 1 + 2 + 4); 1309 | gen_udp_address(PROTOCOL_UDP, &sa, data + n); 1310 | } else { 1311 | if (s->protocol != PROTOCOL_UDPv6) 1312 | return -1; 1313 | data = MALLOC(n + 1 + 2 + 16); 1314 | gen_udp_address(PROTOCOL_UDPv6, &sa, data + n); 1315 | } 1316 | memcpy(data, ss->udpbuffer, n); 1317 | 1318 | result->opaque = s->opaque; 1319 | result->id = s->id; 1320 | result->ud = n; 1321 | result->data = (char *)data; 1322 | 1323 | return SOCKET_UDP; 1324 | } 1325 | 1326 | static int 1327 | report_connect(struct socket_server *ss, struct socket *s, struct socket_lock *l, struct socket_message *result) { 1328 | int error; 1329 | socklen_t len = sizeof(error); 1330 | int code = getsockopt(s->fd, SOL_SOCKET, SO_ERROR, &error, &len); 1331 | if (code < 0 || error) { 1332 | force_close(ss,s,l, result); 1333 | if (code >= 0) 1334 | result->data = strerror(error); 1335 | else 1336 | result->data = strerror(errno); 1337 | return SOCKET_ERR; 1338 | } else { 1339 | s->type = SOCKET_TYPE_CONNECTED; 1340 | result->opaque = s->opaque; 1341 | result->id = s->id; 1342 | result->ud = 0; 1343 | if (nomore_sending_data(s)) { 1344 | sp_write(ss->event_fd, s->fd, s, false); 1345 | } 1346 | union sockaddr_all u; 1347 | socklen_t slen = sizeof(u); 1348 | if (getpeername(s->fd, &u.s, &slen) == 0) { 1349 | void * sin_addr = (u.s.sa_family == AF_INET) ? (void*)&u.v4.sin_addr : (void *)&u.v6.sin6_addr; 1350 | if (inet_ntop(u.s.sa_family, sin_addr, ss->buffer, sizeof(ss->buffer))) { 1351 | result->data = ss->buffer; 1352 | return SOCKET_OPEN; 1353 | } 1354 | } 1355 | result->data = NULL; 1356 | return SOCKET_OPEN; 1357 | } 1358 | } 1359 | 1360 | static int 1361 | getname(union sockaddr_all *u, char *buffer, size_t sz) { 1362 | char tmp[INET6_ADDRSTRLEN]; 1363 | void * sin_addr = (u->s.sa_family == AF_INET) ? (void*)&u->v4.sin_addr : (void *)&u->v6.sin6_addr; 1364 | int sin_port = ntohs((u->s.sa_family == AF_INET) ? u->v4.sin_port : u->v6.sin6_port); 1365 | if (inet_ntop(u->s.sa_family, sin_addr, tmp, sizeof(tmp))) { 1366 | snprintf(buffer, sz, "%s:%d", tmp, sin_port); 1367 | return 1; 1368 | } else { 1369 | buffer[0] = '\0'; 1370 | return 0; 1371 | } 1372 | } 1373 | 1374 | // return 0 when failed, or -1 when file limit 1375 | static int 1376 | report_accept(struct socket_server *ss, struct socket *s, struct socket_message *result) { 1377 | union sockaddr_all u; 1378 | socklen_t len = sizeof(u); 1379 | int client_fd = accept(s->fd, &u.s, &len); 1380 | if (client_fd < 0) { 1381 | if (errno == EMFILE || errno == ENFILE) { 1382 | result->opaque = s->opaque; 1383 | result->id = s->id; 1384 | result->ud = 0; 1385 | result->data = strerror(errno); 1386 | return -1; 1387 | } else { 1388 | return 0; 1389 | } 1390 | } 1391 | int id = reserve_id(ss); 1392 | if (id < 0) { 1393 | close(client_fd); 1394 | return 0; 1395 | } 1396 | socket_keepalive(client_fd); 1397 | sp_nonblocking(client_fd); 1398 | struct socket *ns = new_fd(ss, id, client_fd, PROTOCOL_TCP, s->opaque, false); 1399 | if (ns == NULL) { 1400 | close(client_fd); 1401 | return 0; 1402 | } 1403 | // accept new one connection 1404 | stat_read(ss,s,1); 1405 | 1406 | ns->type = SOCKET_TYPE_PACCEPT; 1407 | result->opaque = s->opaque; 1408 | result->id = s->id; 1409 | result->ud = id; 1410 | result->data = NULL; 1411 | 1412 | if (getname(&u, ss->buffer, sizeof(ss->buffer))) { 1413 | result->data = ss->buffer; 1414 | } 1415 | 1416 | return 1; 1417 | } 1418 | 1419 | static inline void 1420 | clear_closed_event(struct socket_server *ss, struct socket_message * result, int type) { 1421 | if (type == SOCKET_CLOSE || type == SOCKET_ERR) { 1422 | int id = result->id; 1423 | int i; 1424 | for (i=ss->event_index; ievent_n; i++) { 1425 | struct event *e = &ss->ev[i]; 1426 | struct socket *s = e->s; 1427 | if (s) { 1428 | if (s->type == SOCKET_TYPE_INVALID && s->id == id) { 1429 | e->s = NULL; 1430 | break; 1431 | } 1432 | } 1433 | } 1434 | } 1435 | } 1436 | 1437 | // return type 1438 | int 1439 | socket_server_poll(struct socket_server *ss, struct socket_message * result, int * more) { 1440 | for (;;) { 1441 | if (ss->checkctrl) { 1442 | if (has_cmd(ss)) { 1443 | // printf("[skynet-socket]socket_server_poll has_cmd\n"); 1444 | int type = ctrl_cmd(ss, result); 1445 | if (type != -1) { 1446 | clear_closed_event(ss, result, type); 1447 | return type; 1448 | } else 1449 | continue; 1450 | } else { 1451 | ss->checkctrl = 0; 1452 | } 1453 | } 1454 | if (ss->event_index == ss->event_n) { 1455 | // printf("[skynet-socket]socket_server_poll sp_wait\n"); 1456 | ss->event_n = sp_wait(ss->event_fd, ss->ev, MAX_EVENT); 1457 | ss->checkctrl = 1; 1458 | if (more) { 1459 | *more = 0; 1460 | } 1461 | ss->event_index = 0; 1462 | if (ss->event_n <= 0) { 1463 | ss->event_n = 0; 1464 | if (errno == EINTR) { 1465 | continue; 1466 | } 1467 | return -1; 1468 | } 1469 | } 1470 | struct event *e = &ss->ev[ss->event_index++]; 1471 | struct socket *s = e->s; 1472 | if (s == NULL) { 1473 | // dispatch pipe message at beginning 1474 | continue; 1475 | } 1476 | struct socket_lock l; 1477 | socket_lock_init(s, &l); 1478 | switch (s->type) { 1479 | case SOCKET_TYPE_CONNECTING: 1480 | return report_connect(ss, s, &l, result); 1481 | case SOCKET_TYPE_LISTEN: { 1482 | int ok = report_accept(ss, s, result); 1483 | if (ok > 0) { 1484 | return SOCKET_ACCEPT; 1485 | } if (ok < 0 ) { 1486 | return SOCKET_ERR; 1487 | } 1488 | // when ok == 0, retry 1489 | break; 1490 | } 1491 | case SOCKET_TYPE_INVALID: 1492 | fprintf(stderr, "socket-server: invalid socket\n"); 1493 | break; 1494 | default: 1495 | if (e->read) { 1496 | int type; 1497 | if (s->protocol == PROTOCOL_TCP) { 1498 | type = forward_message_tcp(ss, s, &l, result); 1499 | } else { 1500 | type = forward_message_udp(ss, s, &l, result); 1501 | if (type == SOCKET_UDP) { 1502 | // try read again 1503 | --ss->event_index; 1504 | return SOCKET_UDP; 1505 | } 1506 | } 1507 | if (e->write && type != SOCKET_CLOSE && type != SOCKET_ERR) { 1508 | // Try to dispatch write message next step if write flag set. 1509 | e->read = false; 1510 | --ss->event_index; 1511 | } 1512 | if (type == -1) 1513 | break; 1514 | return type; 1515 | } 1516 | if (e->write) { 1517 | int type = send_buffer(ss, s, &l, result); 1518 | if (type == -1) 1519 | break; 1520 | return type; 1521 | } 1522 | if (e->error) { 1523 | // close when error 1524 | int error; 1525 | socklen_t len = sizeof(error); 1526 | int code = getsockopt(s->fd, SOL_SOCKET, SO_ERROR, &error, &len); 1527 | const char * err = NULL; 1528 | if (code < 0) { 1529 | err = strerror(errno); 1530 | } else if (error != 0) { 1531 | err = strerror(error); 1532 | } else { 1533 | err = "Unknown error"; 1534 | } 1535 | force_close(ss, s, &l, result); 1536 | result->data = (char *)err; 1537 | return SOCKET_ERR; 1538 | } 1539 | if(e->eof) { 1540 | force_close(ss, s, &l, result); 1541 | return SOCKET_CLOSE; 1542 | } 1543 | break; 1544 | } 1545 | } 1546 | } 1547 | 1548 | static void 1549 | send_request(struct socket_server *ss, struct request_package *request, char type, int len) { 1550 | request->header[6] = (uint8_t)type; 1551 | request->header[7] = (uint8_t)len; 1552 | for (;;) { 1553 | ssize_t n = write(ss->sendctrl_fd, &request->header[6], len+2); 1554 | if (n<0) { 1555 | if (errno != EINTR) { 1556 | fprintf(stderr, "socket-server : send ctrl command error %s.\n", strerror(errno)); 1557 | } 1558 | continue; 1559 | } 1560 | assert(n == len+2); 1561 | return; 1562 | } 1563 | } 1564 | 1565 | static int 1566 | open_request(struct socket_server *ss, struct request_package *req, uintptr_t opaque, const char *addr, int port) { 1567 | int len = strlen(addr); 1568 | if (len + sizeof(req->u.open) >= 256) { 1569 | fprintf(stderr, "socket-server : Invalid addr %s.\n",addr); 1570 | return -1; 1571 | } 1572 | int id = reserve_id(ss); 1573 | if (id < 0) 1574 | return -1; 1575 | req->u.open.opaque = opaque; 1576 | req->u.open.id = id; 1577 | req->u.open.port = port; 1578 | memcpy(req->u.open.host, addr, len); 1579 | req->u.open.host[len] = '\0'; 1580 | 1581 | return len; 1582 | } 1583 | 1584 | int 1585 | socket_server_connect(struct socket_server *ss, uintptr_t opaque, const char * addr, int port) { 1586 | struct request_package request; 1587 | int len = open_request(ss, &request, opaque, addr, port); 1588 | if (len < 0) 1589 | return -1; 1590 | send_request(ss, &request, 'O', sizeof(request.u.open) + len); 1591 | return request.u.open.id; 1592 | } 1593 | 1594 | static inline int 1595 | can_direct_write(struct socket *s, int id) { 1596 | return s->id == id && nomore_sending_data(s) && s->type == SOCKET_TYPE_CONNECTED && s->udpconnecting == 0; 1597 | } 1598 | 1599 | // return -1 when error, 0 when success 1600 | int 1601 | socket_server_send(struct socket_server *ss, int id, const void * buffer, int sz) { 1602 | struct socket * s = &ss->slot[HASH_ID(id)]; 1603 | if (s->id != id || s->type == SOCKET_TYPE_INVALID) { 1604 | free_buffer(ss, buffer, sz); 1605 | return -1; 1606 | } 1607 | 1608 | struct socket_lock l; 1609 | socket_lock_init(s, &l); 1610 | 1611 | if (can_direct_write(s,id) && socket_trylock(&l)) { 1612 | // may be we can send directly, double check 1613 | if (can_direct_write(s,id)) { 1614 | // send directly 1615 | struct send_object so; 1616 | send_object_init(ss, &so, (void *)buffer, sz); 1617 | ssize_t n; 1618 | if (s->protocol == PROTOCOL_TCP) { 1619 | n = write(s->fd, so.buffer, so.sz); 1620 | } else { 1621 | union sockaddr_all sa; 1622 | socklen_t sasz = udp_socket_address(s, s->p.udp_address, &sa); 1623 | if (sasz == 0) { 1624 | fprintf(stderr, "socket-server : set udp (%d) address first.\n", id); 1625 | socket_unlock(&l); 1626 | so.free_func((void *)buffer); 1627 | return -1; 1628 | } 1629 | n = sendto(s->fd, so.buffer, so.sz, 0, &sa.s, sasz); 1630 | } 1631 | if (n<0) { 1632 | // ignore error, let socket thread try again 1633 | n = 0; 1634 | } 1635 | stat_write(ss,s,n); 1636 | if (n == so.sz) { 1637 | // write done 1638 | socket_unlock(&l); 1639 | so.free_func((void *)buffer); 1640 | return 0; 1641 | } 1642 | // write failed, put buffer into s->dw_* , and let socket thread send it. see send_buffer() 1643 | s->dw_buffer = buffer; 1644 | s->dw_size = sz; 1645 | s->dw_offset = n; 1646 | sp_write(ss->event_fd, s->fd, s, true); 1647 | 1648 | socket_unlock(&l); 1649 | return 0; 1650 | } 1651 | socket_unlock(&l); 1652 | } 1653 | inc_sending_ref(s, id); 1654 | 1655 | struct request_package request; 1656 | request.u.send.id = id; 1657 | request.u.send.sz = sz; 1658 | request.u.send.buffer = (char *)buffer; 1659 | 1660 | send_request(ss, &request, 'D', sizeof(request.u.send)); 1661 | return 0; 1662 | } 1663 | 1664 | // return -1 when error, 0 when success 1665 | int 1666 | socket_server_send_lowpriority(struct socket_server *ss, int id, const void * buffer, int sz) { 1667 | struct socket * s = &ss->slot[HASH_ID(id)]; 1668 | if (s->id != id || s->type == SOCKET_TYPE_INVALID) { 1669 | free_buffer(ss, buffer, sz); 1670 | return -1; 1671 | } 1672 | 1673 | inc_sending_ref(s, id); 1674 | 1675 | struct request_package request; 1676 | request.u.send.id = id; 1677 | request.u.send.sz = sz; 1678 | request.u.send.buffer = (char *)buffer; 1679 | 1680 | send_request(ss, &request, 'P', sizeof(request.u.send)); 1681 | return 0; 1682 | } 1683 | 1684 | void 1685 | socket_server_exit(struct socket_server *ss) { 1686 | struct request_package request; 1687 | send_request(ss, &request, 'X', 0); 1688 | } 1689 | 1690 | void 1691 | socket_server_close(struct socket_server *ss, uintptr_t opaque, int id) { 1692 | struct request_package request; 1693 | request.u.close.id = id; 1694 | request.u.close.shutdown = 0; 1695 | request.u.close.opaque = opaque; 1696 | send_request(ss, &request, 'K', sizeof(request.u.close)); 1697 | } 1698 | 1699 | 1700 | void 1701 | socket_server_shutdown(struct socket_server *ss, uintptr_t opaque, int id) { 1702 | struct request_package request; 1703 | request.u.close.id = id; 1704 | request.u.close.shutdown = 1; 1705 | request.u.close.opaque = opaque; 1706 | send_request(ss, &request, 'K', sizeof(request.u.close)); 1707 | } 1708 | 1709 | // return -1 means failed 1710 | // or return AF_INET or AF_INET6 1711 | static int 1712 | do_bind(const char *host, int port, int protocol, int *family) { 1713 | int fd; 1714 | int status; 1715 | int reuse = 1; 1716 | struct addrinfo ai_hints; 1717 | struct addrinfo *ai_list = NULL; 1718 | char portstr[16]; 1719 | if (host == NULL || host[0] == 0) { 1720 | host = "0.0.0.0"; // INADDR_ANY 1721 | } 1722 | sprintf(portstr, "%d", port); 1723 | memset( &ai_hints, 0, sizeof( ai_hints ) ); 1724 | ai_hints.ai_family = AF_UNSPEC; 1725 | if (protocol == IPPROTO_TCP) { 1726 | ai_hints.ai_socktype = SOCK_STREAM; 1727 | } else { 1728 | assert(protocol == IPPROTO_UDP); 1729 | ai_hints.ai_socktype = SOCK_DGRAM; 1730 | } 1731 | ai_hints.ai_protocol = protocol; 1732 | 1733 | status = getaddrinfo( host, portstr, &ai_hints, &ai_list ); 1734 | if ( status != 0 ) { 1735 | return -1; 1736 | } 1737 | *family = ai_list->ai_family; 1738 | fd = socket(*family, ai_list->ai_socktype, 0); 1739 | if (fd < 0) { 1740 | goto _failed_fd; 1741 | } 1742 | if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&reuse, sizeof(int))==-1) { 1743 | goto _failed; 1744 | } 1745 | status = bind(fd, (struct sockaddr *)ai_list->ai_addr, ai_list->ai_addrlen); 1746 | if (status != 0) 1747 | goto _failed; 1748 | 1749 | freeaddrinfo( ai_list ); 1750 | return fd; 1751 | _failed: 1752 | close(fd); 1753 | _failed_fd: 1754 | freeaddrinfo( ai_list ); 1755 | return -1; 1756 | } 1757 | 1758 | static int 1759 | do_listen(const char * host, int port, int backlog) { 1760 | int family = 0; 1761 | int listen_fd = do_bind(host, port, IPPROTO_TCP, &family); 1762 | if (listen_fd < 0) { 1763 | return -1; 1764 | } 1765 | if (listen(listen_fd, backlog) == -1) { 1766 | close(listen_fd); 1767 | return -1; 1768 | } 1769 | return listen_fd; 1770 | } 1771 | 1772 | int 1773 | socket_server_listen(struct socket_server *ss, uintptr_t opaque, const char * addr, int port, int backlog) { 1774 | int fd = do_listen(addr, port, backlog); 1775 | if (fd < 0) { 1776 | return -1; 1777 | } 1778 | struct request_package request; 1779 | int id = reserve_id(ss); 1780 | if (id < 0) { 1781 | close(fd); 1782 | return id; 1783 | } 1784 | request.u.listen.opaque = opaque; 1785 | request.u.listen.id = id; 1786 | request.u.listen.fd = fd; 1787 | send_request(ss, &request, 'L', sizeof(request.u.listen)); 1788 | return id; 1789 | } 1790 | 1791 | int 1792 | socket_server_bind(struct socket_server *ss, uintptr_t opaque, int fd) { 1793 | struct request_package request; 1794 | int id = reserve_id(ss); 1795 | if (id < 0) 1796 | return -1; 1797 | request.u.bind.opaque = opaque; 1798 | request.u.bind.id = id; 1799 | request.u.bind.fd = fd; 1800 | send_request(ss, &request, 'B', sizeof(request.u.bind)); 1801 | return id; 1802 | } 1803 | 1804 | void 1805 | socket_server_start(struct socket_server *ss, uintptr_t opaque, int id) { 1806 | struct request_package request; 1807 | request.u.start.id = id; 1808 | request.u.start.opaque = opaque; 1809 | send_request(ss, &request, 'S', sizeof(request.u.start)); 1810 | } 1811 | 1812 | void 1813 | socket_server_nodelay(struct socket_server *ss, int id) { 1814 | struct request_package request; 1815 | request.u.setopt.id = id; 1816 | request.u.setopt.what = TCP_NODELAY; 1817 | request.u.setopt.value = 1; 1818 | send_request(ss, &request, 'T', sizeof(request.u.setopt)); 1819 | } 1820 | 1821 | void 1822 | socket_server_userobject(struct socket_server *ss, struct socket_object_interface *soi) { 1823 | ss->soi = *soi; 1824 | } 1825 | 1826 | // UDP 1827 | int 1828 | socket_server_udp(struct socket_server *ss, uintptr_t opaque, const char * addr, int port) { 1829 | int fd; 1830 | int family; 1831 | if (port != 0 || addr != NULL) { 1832 | // bind 1833 | fd = do_bind(addr, port, IPPROTO_UDP, &family); 1834 | if (fd < 0) { 1835 | return -1; 1836 | } 1837 | } else { 1838 | family = AF_INET; 1839 | fd = socket(family, SOCK_DGRAM, 0); 1840 | if (fd < 0) { 1841 | return -1; 1842 | } 1843 | } 1844 | sp_nonblocking(fd); 1845 | 1846 | int id = reserve_id(ss); 1847 | if (id < 0) { 1848 | close(fd); 1849 | return -1; 1850 | } 1851 | struct request_package request; 1852 | request.u.udp.id = id; 1853 | request.u.udp.fd = fd; 1854 | request.u.udp.opaque = opaque; 1855 | request.u.udp.family = family; 1856 | 1857 | send_request(ss, &request, 'U', sizeof(request.u.udp)); 1858 | return id; 1859 | } 1860 | 1861 | int 1862 | socket_server_udp_send(struct socket_server *ss, int id, const struct socket_udp_address *addr, const void *buffer, int sz) { 1863 | struct socket * s = &ss->slot[HASH_ID(id)]; 1864 | if (s->id != id || s->type == SOCKET_TYPE_INVALID) { 1865 | free_buffer(ss, buffer, sz); 1866 | return -1; 1867 | } 1868 | 1869 | const uint8_t *udp_address = (const uint8_t *)addr; 1870 | int addrsz; 1871 | switch (udp_address[0]) { 1872 | case PROTOCOL_UDP: 1873 | addrsz = 1+2+4; // 1 type, 2 port, 4 ipv4 1874 | break; 1875 | case PROTOCOL_UDPv6: 1876 | addrsz = 1+2+16; // 1 type, 2 port, 16 ipv6 1877 | break; 1878 | default: 1879 | free_buffer(ss, buffer, sz); 1880 | return -1; 1881 | } 1882 | 1883 | struct socket_lock l; 1884 | socket_lock_init(s, &l); 1885 | 1886 | if (can_direct_write(s,id) && socket_trylock(&l)) { 1887 | // may be we can send directly, double check 1888 | if (can_direct_write(s,id)) { 1889 | // send directly 1890 | struct send_object so; 1891 | send_object_init(ss, &so, (void *)buffer, sz); 1892 | union sockaddr_all sa; 1893 | socklen_t sasz = udp_socket_address(s, udp_address, &sa); 1894 | if (sasz == 0) { 1895 | socket_unlock(&l); 1896 | so.free_func((void *)buffer); 1897 | return -1; 1898 | } 1899 | int n = sendto(s->fd, so.buffer, so.sz, 0, &sa.s, sasz); 1900 | if (n >= 0) { 1901 | // sendto succ 1902 | stat_write(ss,s,n); 1903 | socket_unlock(&l); 1904 | so.free_func((void *)buffer); 1905 | return 0; 1906 | } 1907 | } 1908 | socket_unlock(&l); 1909 | // let socket thread try again, udp doesn't care the order 1910 | } 1911 | 1912 | struct request_package request; 1913 | request.u.send_udp.send.id = id; 1914 | request.u.send_udp.send.sz = sz; 1915 | request.u.send_udp.send.buffer = (char *)buffer; 1916 | 1917 | memcpy(request.u.send_udp.address, udp_address, addrsz); 1918 | 1919 | send_request(ss, &request, 'A', sizeof(request.u.send_udp.send)+addrsz); 1920 | return 0; 1921 | } 1922 | 1923 | int 1924 | socket_server_udp_connect(struct socket_server *ss, int id, const char * addr, int port) { 1925 | struct socket * s = &ss->slot[HASH_ID(id)]; 1926 | if (s->id != id || s->type == SOCKET_TYPE_INVALID) { 1927 | return -1; 1928 | } 1929 | struct socket_lock l; 1930 | socket_lock_init(s, &l); 1931 | socket_lock(&l); 1932 | if (s->id != id || s->type == SOCKET_TYPE_INVALID) { 1933 | socket_unlock(&l); 1934 | return -1; 1935 | } 1936 | ATOM_INC(&s->udpconnecting); 1937 | socket_unlock(&l); 1938 | 1939 | int status; 1940 | struct addrinfo ai_hints; 1941 | struct addrinfo *ai_list = NULL; 1942 | char portstr[16]; 1943 | sprintf(portstr, "%d", port); 1944 | memset( &ai_hints, 0, sizeof( ai_hints ) ); 1945 | ai_hints.ai_family = AF_UNSPEC; 1946 | ai_hints.ai_socktype = SOCK_DGRAM; 1947 | ai_hints.ai_protocol = IPPROTO_UDP; 1948 | 1949 | status = getaddrinfo(addr, portstr, &ai_hints, &ai_list ); 1950 | if ( status != 0 ) { 1951 | return -1; 1952 | } 1953 | struct request_package request; 1954 | request.u.set_udp.id = id; 1955 | int protocol; 1956 | 1957 | if (ai_list->ai_family == AF_INET) { 1958 | protocol = PROTOCOL_UDP; 1959 | } else if (ai_list->ai_family == AF_INET6) { 1960 | protocol = PROTOCOL_UDPv6; 1961 | } else { 1962 | freeaddrinfo( ai_list ); 1963 | return -1; 1964 | } 1965 | 1966 | int addrsz = gen_udp_address(protocol, (union sockaddr_all *)ai_list->ai_addr, request.u.set_udp.address); 1967 | 1968 | freeaddrinfo( ai_list ); 1969 | 1970 | send_request(ss, &request, 'C', sizeof(request.u.set_udp) - sizeof(request.u.set_udp.address) +addrsz); 1971 | 1972 | return 0; 1973 | } 1974 | 1975 | const struct socket_udp_address * 1976 | socket_server_udp_address(struct socket_server *ss, struct socket_message *msg, int *addrsz) { 1977 | uint8_t * address = (uint8_t *)(msg->data + msg->ud); 1978 | int type = address[0]; 1979 | switch(type) { 1980 | case PROTOCOL_UDP: 1981 | *addrsz = 1+2+4; 1982 | break; 1983 | case PROTOCOL_UDPv6: 1984 | *addrsz = 1+2+16; 1985 | break; 1986 | default: 1987 | return NULL; 1988 | } 1989 | return (const struct socket_udp_address *)address; 1990 | } 1991 | 1992 | 1993 | struct socket_info * 1994 | socket_info_create(struct socket_info *last) { 1995 | struct socket_info *si = MALLOC(sizeof(*si)); 1996 | memset(si, 0 , sizeof(*si)); 1997 | si->next = last; 1998 | return si; 1999 | } 2000 | 2001 | void 2002 | socket_info_release(struct socket_info *si) { 2003 | while (si) { 2004 | struct socket_info *temp = si; 2005 | si = si->next; 2006 | FREE(temp); 2007 | } 2008 | } 2009 | 2010 | static int 2011 | query_info(struct socket *s, struct socket_info *si) { 2012 | union sockaddr_all u; 2013 | socklen_t slen = sizeof(u); 2014 | switch (s->type) { 2015 | case SOCKET_TYPE_BIND: 2016 | si->type = SOCKET_INFO_BIND; 2017 | si->name[0] = '\0'; 2018 | break; 2019 | case SOCKET_TYPE_LISTEN: 2020 | si->type = SOCKET_INFO_LISTEN; 2021 | if (getsockname(s->fd, &u.s, &slen) == 0) { 2022 | getname(&u, si->name, sizeof(si->name)); 2023 | } 2024 | break; 2025 | case SOCKET_TYPE_CONNECTED: 2026 | if (s->protocol == PROTOCOL_TCP) { 2027 | si->type = SOCKET_INFO_TCP; 2028 | if (getpeername(s->fd, &u.s, &slen) == 0) { 2029 | getname(&u, si->name, sizeof(si->name)); 2030 | } 2031 | } else { 2032 | si->type = SOCKET_INFO_UDP; 2033 | if (udp_socket_address(s, s->p.udp_address, &u)) { 2034 | getname(&u, si->name, sizeof(si->name)); 2035 | } 2036 | } 2037 | break; 2038 | default: 2039 | return 0; 2040 | } 2041 | si->id = s->id; 2042 | si->opaque = (uint64_t)s->opaque; 2043 | si->read = s->stat.read; 2044 | si->write = s->stat.write; 2045 | si->rtime = s->stat.rtime; 2046 | si->wtime = s->stat.wtime; 2047 | si->wbuffer = s->wb_size; 2048 | 2049 | return 1; 2050 | } 2051 | 2052 | struct socket_info * 2053 | socket_server_info(struct socket_server *ss) { 2054 | int i; 2055 | struct socket_info * si = NULL; 2056 | for (i=0;islot[i]; 2058 | int id = s->id; 2059 | struct socket_info temp; 2060 | if (query_info(s, &temp) && s->id == id) { 2061 | // socket_server_info may call in different thread, so check socket id again 2062 | si = socket_info_create(si); 2063 | temp.next = si->next; 2064 | *si = temp; 2065 | } 2066 | } 2067 | return si; 2068 | } 2069 | -------------------------------------------------------------------------------- /mrsocket/socket_server.h: -------------------------------------------------------------------------------- 1 | #ifndef skynet_socket_server_h 2 | #define skynet_socket_server_h 3 | 4 | #include 5 | #include "socket_info.h" 6 | 7 | #define SOCKET_DATA 0 8 | #define SOCKET_CLOSE 1 9 | #define SOCKET_OPEN 2 10 | #define SOCKET_ACCEPT 3 11 | #define SOCKET_ERR 4 12 | #define SOCKET_EXIT 5 13 | #define SOCKET_UDP 6 14 | #define SOCKET_WARNING 7 15 | 16 | 17 | #define PROTOCOL_UDP 1 18 | #define PROTOCOL_UDPv6 2 19 | 20 | struct socket_server; 21 | 22 | struct socket_message { 23 | int id; 24 | uintptr_t opaque; 25 | int ud; // for accept, ud is new connection id ; for data, ud is size of data 26 | char * data; 27 | }; 28 | 29 | struct socket_server * socket_server_create(uint64_t time); 30 | void socket_server_release(struct socket_server *); 31 | void socket_server_updatetime(struct socket_server *, uint64_t time); 32 | int socket_server_poll(struct socket_server *, struct socket_message *result, int *more); 33 | 34 | void socket_server_exit(struct socket_server *); 35 | void socket_server_close(struct socket_server *, uintptr_t opaque, int id); 36 | void socket_server_shutdown(struct socket_server *, uintptr_t opaque, int id); 37 | void socket_server_start(struct socket_server *, uintptr_t opaque, int id); 38 | 39 | // return -1 when error 40 | int socket_server_send(struct socket_server *, int id, const void * buffer, int sz); 41 | int socket_server_send_lowpriority(struct socket_server *, int id, const void * buffer, int sz); 42 | 43 | // ctrl command below returns id 44 | int socket_server_listen(struct socket_server *, uintptr_t opaque, const char * addr, int port, int backlog); 45 | int socket_server_connect(struct socket_server *, uintptr_t opaque, const char * addr, int port); 46 | int socket_server_bind(struct socket_server *, uintptr_t opaque, int fd); 47 | 48 | // for tcp 49 | void socket_server_nodelay(struct socket_server *, int id); 50 | 51 | struct socket_udp_address; 52 | 53 | // create an udp socket handle, attach opaque with it . udp socket don't need call socket_server_start to recv message 54 | // if port != 0, bind the socket . if addr == NULL, bind ipv4 0.0.0.0 . If you want to use ipv6, addr can be "::" and port 0. 55 | int socket_server_udp(struct socket_server *, uintptr_t opaque, const char * addr, int port); 56 | // set default dest address, return 0 when success 57 | int socket_server_udp_connect(struct socket_server *, int id, const char * addr, int port); 58 | // If the socket_udp_address is NULL, use last call socket_server_udp_connect address instead 59 | // You can also use socket_server_send 60 | int socket_server_udp_send(struct socket_server *, int id, const struct socket_udp_address *, const void *buffer, int sz); 61 | // extract the address of the message, struct socket_message * should be SOCKET_UDP 62 | const struct socket_udp_address * socket_server_udp_address(struct socket_server *, struct socket_message *, int *addrsz); 63 | 64 | struct socket_object_interface { 65 | void * (*buffer)(void *); 66 | int (*size)(void *); 67 | void (*free)(void *); 68 | }; 69 | 70 | // if you send package sz == -1, use soi. 71 | void socket_server_userobject(struct socket_server *, struct socket_object_interface *soi); 72 | 73 | struct socket_info * socket_server_info(struct socket_server *); 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /mrsocket/spinlock.h: -------------------------------------------------------------------------------- 1 | #ifndef SKYNET_SPINLOCK_H 2 | #define SKYNET_SPINLOCK_H 3 | 4 | #define SPIN_INIT(q) spinlock_init(&(q)->lock); 5 | #define SPIN_LOCK(q) spinlock_lock(&(q)->lock); 6 | #define SPIN_UNLOCK(q) spinlock_unlock(&(q)->lock); 7 | #define SPIN_DESTROY(q) spinlock_destroy(&(q)->lock); 8 | 9 | #ifndef USE_PTHREAD_LOCK 10 | 11 | struct spinlock { 12 | int lock; 13 | }; 14 | 15 | static inline void 16 | spinlock_init(struct spinlock *lock) { 17 | lock->lock = 0; 18 | } 19 | 20 | static inline void 21 | spinlock_lock(struct spinlock *lock) { 22 | while (__sync_lock_test_and_set(&lock->lock,1)) {} 23 | } 24 | 25 | static inline int 26 | spinlock_trylock(struct spinlock *lock) { 27 | return __sync_lock_test_and_set(&lock->lock,1) == 0; 28 | } 29 | 30 | static inline void 31 | spinlock_unlock(struct spinlock *lock) { 32 | __sync_lock_release(&lock->lock); 33 | } 34 | 35 | static inline void 36 | spinlock_destroy(struct spinlock *lock) { 37 | (void) lock; 38 | } 39 | 40 | #else 41 | 42 | #include 43 | 44 | // we use mutex instead of spinlock for some reason 45 | // you can also replace to pthread_spinlock 46 | 47 | struct spinlock { 48 | pthread_mutex_t lock; 49 | }; 50 | 51 | static inline void 52 | spinlock_init(struct spinlock *lock) { 53 | pthread_mutex_init(&lock->lock, NULL); 54 | } 55 | 56 | static inline void 57 | spinlock_lock(struct spinlock *lock) { 58 | pthread_mutex_lock(&lock->lock); 59 | } 60 | 61 | static inline int 62 | spinlock_trylock(struct spinlock *lock) { 63 | return pthread_mutex_trylock(&lock->lock) == 0; 64 | } 65 | 66 | static inline void 67 | spinlock_unlock(struct spinlock *lock) { 68 | pthread_mutex_unlock(&lock->lock); 69 | } 70 | 71 | static inline void 72 | spinlock_destroy(struct spinlock *lock) { 73 | pthread_mutex_destroy(&lock->lock); 74 | } 75 | 76 | #endif 77 | 78 | #endif 79 | -------------------------------------------------------------------------------- /mrsocket/win/atomic.h: -------------------------------------------------------------------------------- 1 | #ifndef WIN_ATOMIC_H 2 | #define WIN_ATOMIC_H 3 | 4 | static inline bool __sync_bool_compare_and_swap(int* ptr, int oval, int nval){ 5 | if(oval == InterlockedCompareExchange(ptr, nval, oval)) 6 | return 1; 7 | 8 | return 0; 9 | } 10 | 11 | static inline int __sync_add_and_fetch(int* ptr, int n){ 12 | InterlockedAdd(ptr, n); 13 | return *ptr; 14 | } 15 | 16 | static inline int __sync_sub_and_fetch(int* ptr, int n){ 17 | InterlockedAdd(ptr, -n); 18 | return *ptr; 19 | } 20 | 21 | static inline int __sync_and_and_fetch(int* ptr, int n){ 22 | InterlockedAnd(ptr, n); 23 | return *ptr; 24 | } 25 | 26 | #define ATOM_CAS(ptr, oval, nval) __sync_bool_compare_and_swap(ptr, oval, nval) 27 | #define ATOM_CAS_POINTER(ptr, oval, nval) __sync_bool_compare_and_swap(ptr, oval, nval) 28 | // #define ATOM_FINC(ptr) __sync_fetch_and_add(ptr, 1) 29 | // #define ATOM_FDEC(ptr) __sync_fetch_and_sub(ptr, 1) 30 | 31 | #define ATOM_INC(ptr) __sync_add_and_fetch(ptr, 1) 32 | #define ATOM_DEC(ptr) __sync_sub_and_fetch(ptr, 1) 33 | #define ATOM_ADD(ptr,n) __sync_add_and_fetch(ptr, n) 34 | #define ATOM_SUB(ptr,n) __sync_sub_and_fetch(ptr, n) 35 | 36 | #define ATOM_AND(ptr,n) __sync_and_and_fetch(ptr, n) 37 | 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /mrsocket/win/spinlock.h: -------------------------------------------------------------------------------- 1 | #ifndef WIN_SPINLOCK_H 2 | #define WIN_SPINLOCK_H 3 | 4 | #define SPIN_INIT(q) spinlock_init(&(q)->lock); 5 | #define SPIN_LOCK(q) spinlock_lock(&(q)->lock); 6 | #define SPIN_UNLOCK(q) spinlock_unlock(&(q)->lock); 7 | #define SPIN_DESTROY(q) spinlock_destroy(&(q)->lock); 8 | 9 | #include "winport.h" 10 | #include 11 | 12 | struct spinlock { 13 | CRITICAL_SECTION lock; 14 | }; 15 | 16 | static inline void 17 | spinlock_init(struct spinlock *lock) { 18 | InitializeCriticalSectionAndSpinCount(&lock->lock, 4000); 19 | } 20 | 21 | static inline void 22 | spinlock_lock(struct spinlock *lock) { 23 | EnterCriticalSection(&lock->lock); 24 | } 25 | 26 | static inline int 27 | spinlock_trylock(struct spinlock *lock) { 28 | return TryEnterCriticalSection(&lock->lock); 29 | } 30 | 31 | static inline void 32 | spinlock_unlock(struct spinlock *lock) { 33 | LeaveCriticalSection(&lock->lock); 34 | } 35 | 36 | static inline void 37 | spinlock_destroy(struct spinlock *lock) { 38 | DeleteCriticalSection(&lock->lock); 39 | } 40 | 41 | // struct spinlock { 42 | // pthread_mutex_t lock; 43 | // }; 44 | 45 | // static inline void 46 | // spinlock_init(struct spinlock *lock) { 47 | // pthread_mutex_init(&lock->lock, NULL); 48 | // } 49 | 50 | // static inline void 51 | // spinlock_lock(struct spinlock *lock) { 52 | // pthread_mutex_lock(&lock->lock); 53 | // } 54 | 55 | // static inline int 56 | // spinlock_trylock(struct spinlock *lock) { 57 | // return pthread_mutex_trylock(&lock->lock) == 0; 58 | // } 59 | 60 | // static inline void 61 | // spinlock_unlock(struct spinlock *lock) { 62 | // pthread_mutex_unlock(&lock->lock); 63 | // } 64 | 65 | // static inline void 66 | // spinlock_destroy(struct spinlock *lock) { 67 | // pthread_mutex_destroy(&lock->lock); 68 | // } 69 | 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /mrsocket/win/winconfig.h: -------------------------------------------------------------------------------- 1 | #ifndef WINCONFIG_H_ 2 | #define WINCONFIG_H_ 3 | 4 | /* Define to `__inline__' or `__inline' if that's what the C compiler 5 | calls it, or to nothing if 'inline' is not supported under any name. */ 6 | #ifndef __cplusplus 7 | #define inline __inline 8 | #endif 9 | 10 | #define __attribute__(x) 11 | #define __func__ __FUNCTION__ 12 | 13 | #define ACL ZKACL /* Conflict with windows API */ 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /mrsocket/win/winport.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #ifdef WIN32 20 | #include "winport.h" 21 | #include 22 | #include /* for int64_t */ 23 | #include /* must always be included before ws2tcpip.h */ 24 | #include /* for SOCKET */ 25 | 26 | int pthread_mutex_lock(pthread_mutex_t* _mutex ){ 27 | int rc = WaitForSingleObject( *_mutex, // handle to mutex 28 | INFINITE); // no time-out interval 29 | return ((rc == WAIT_OBJECT_0) ? 0: rc); 30 | } 31 | 32 | int pthread_mutex_unlock( pthread_mutex_t* _mutex ){ 33 | int rc = ReleaseMutex(*_mutex); 34 | return ((rc != 0)? 0: GetLastError()); 35 | } 36 | 37 | int pthread_mutex_init(pthread_mutex_t* _mutex, void* ignoredAttr){ 38 | //use CreateMutex as we are using the HANDLES in pthread_cond 39 | *_mutex = CreateMutex( 40 | NULL, // default security attributes 41 | FALSE, // initially not owned 42 | NULL); // unnamed mutex 43 | return ((*_mutex == NULL) ? GetLastError() : 0); 44 | } 45 | 46 | int pthread_mutex_destroy(pthread_mutex_t* _mutex) 47 | { 48 | int rc = CloseHandle(*_mutex); 49 | return ((rc != 0)? 0: GetLastError()); 50 | } 51 | 52 | int pthread_create(pthread_t *thread, const pthread_attr_t *attr, unsigned (__stdcall* start_routine)(void* a), void *arg) 53 | { 54 | int _intThreadId; 55 | (*thread).thread_handle = (HANDLE)_beginthreadex( NULL, 0, start_routine , arg, 0, (unsigned int*)&_intThreadId ); 56 | (*thread).thread_id = _intThreadId; 57 | return (((*thread).thread_handle == 0 ) ? errno : 0 ); 58 | } 59 | 60 | 61 | int pthread_equal(pthread_t t1, pthread_t t2){ 62 | //Is there a better way to do this? GetThreadId(handle) is only supported Windows 2003 n above. 63 | return ((t1.thread_id == t2.thread_id) ? 1:0); 64 | } 65 | 66 | pthread_t pthread_self(){ 67 | pthread_t thread_self; 68 | thread_self.thread_handle = GetCurrentThread(); 69 | thread_self.thread_id = GetCurrentThreadId(); 70 | return thread_self; 71 | } 72 | 73 | int pthread_join(pthread_t _thread, void** ignore) 74 | { 75 | int rc = WaitForSingleObject( _thread.thread_handle, INFINITE ); 76 | return ((rc == WAIT_OBJECT_0) ? 0: rc); 77 | } 78 | 79 | int pthread_detach(pthread_t _thread) 80 | { 81 | int rc = CloseHandle(_thread.thread_handle) ; 82 | return (rc != 0) ? 0: GetLastError(); 83 | } 84 | 85 | void pthread_mutexattr_init(pthread_mutexattr_t* ignore){} 86 | void pthread_mutexattr_settype(pthread_mutexattr_t* ingore_attr, int ignore){} 87 | void pthread_mutexattr_destroy(pthread_mutexattr_t* ignore_attr){} 88 | 89 | int 90 | pthread_cond_init (pthread_cond_t *cv, 91 | const pthread_condattr_t * ignore) 92 | { 93 | cv->waiters_count_ = 0; 94 | cv->was_broadcast_ = 0; 95 | cv->sema_ = CreateSemaphore (NULL, // no security 96 | 0, // initially 0 97 | 0x7fffffff, // max count 98 | NULL); // unnamed 99 | if (cv->sema_ == NULL ) 100 | return GetLastError(); 101 | InitializeCriticalSection (&cv->waiters_count_lock_); 102 | cv->waiters_done_ = CreateEvent (NULL, // no security 103 | FALSE, // auto-reset 104 | FALSE, // non-signaled initially 105 | NULL); // unnamed 106 | return (cv->waiters_done_ == NULL) ? GetLastError() : 0; 107 | 108 | } 109 | 110 | 111 | int pthread_cond_destroy(pthread_cond_t *cond) 112 | { 113 | CloseHandle( cond->sema_); 114 | DeleteCriticalSection(&cond->waiters_count_lock_); 115 | return (CloseHandle( cond->waiters_done_ ) == 0)? GetLastError(): 0 ; 116 | } 117 | 118 | 119 | int 120 | pthread_cond_signal (pthread_cond_t *cv) 121 | { 122 | int have_waiters; 123 | EnterCriticalSection (& (cv->waiters_count_lock_)); 124 | have_waiters = cv->waiters_count_ > 0; 125 | LeaveCriticalSection (&cv->waiters_count_lock_); 126 | 127 | // If there aren't any waiters, then this is a no-op. 128 | if (have_waiters){ 129 | return (ReleaseSemaphore (cv->sema_, 1, 0) == 0 ) ? GetLastError() : 0 ; 130 | }else 131 | return 0; 132 | } 133 | 134 | 135 | int 136 | pthread_cond_broadcast (pthread_cond_t *cv) 137 | { 138 | // This is needed to ensure that and are 139 | // consistent relative to each other. 140 | int have_waiters = 0; 141 | EnterCriticalSection (&cv->waiters_count_lock_); 142 | 143 | if (cv->waiters_count_ > 0) { 144 | // We are broadcasting, even if there is just one waiter... 145 | // Record that we are broadcasting, which helps optimize 146 | // for the non-broadcast case. 147 | cv->was_broadcast_ = 1; 148 | have_waiters = 1; 149 | } 150 | 151 | if (have_waiters) { 152 | // Wake up all the waiters atomically. 153 | ReleaseSemaphore (cv->sema_, cv->waiters_count_, 0); 154 | 155 | LeaveCriticalSection (&cv->waiters_count_lock_); 156 | 157 | // Wait for all the awakened threads to acquire the counting 158 | // semaphore. 159 | WaitForSingleObject (cv->waiters_done_, INFINITE); 160 | // This assignment is okay, even without the held 161 | // because no other waiter threads can wake up to access it. 162 | cv->was_broadcast_ = 0; 163 | } 164 | else 165 | LeaveCriticalSection (&cv->waiters_count_lock_); 166 | } 167 | 168 | 169 | int 170 | pthread_cond_wait (pthread_cond_t *cv, 171 | pthread_mutex_t *external_mutex) 172 | { 173 | int last_waiter; 174 | // Avoid race conditions. 175 | EnterCriticalSection (&cv->waiters_count_lock_); 176 | cv->waiters_count_++; 177 | LeaveCriticalSection (&cv->waiters_count_lock_); 178 | 179 | // This call atomically releases the mutex and waits on the 180 | // semaphore until or 181 | // are called by another thread. 182 | SignalObjectAndWait (*external_mutex, cv->sema_, INFINITE, FALSE); 183 | 184 | // Reacquire lock to avoid race conditions. 185 | EnterCriticalSection (&cv->waiters_count_lock_); 186 | 187 | // We're no longer waiting... 188 | cv->waiters_count_--; 189 | 190 | // Check to see if we're the last waiter after . 191 | last_waiter = cv->was_broadcast_ && cv->waiters_count_ == 0; 192 | 193 | LeaveCriticalSection (&cv->waiters_count_lock_); 194 | 195 | // If we're the last waiter thread during this particular broadcast 196 | // then let all the other threads proceed. 197 | if (last_waiter) 198 | // This call atomically signals the event and waits until 199 | // it can acquire the . This is required to ensure fairness. 200 | SignalObjectAndWait (cv->waiters_done_, *external_mutex, INFINITE, FALSE); 201 | else 202 | // Always regain the external mutex since that's the guarantee we 203 | // give to our callers. 204 | WaitForSingleObject (*external_mutex, INFINITE); 205 | } 206 | 207 | int pthread_key_create(pthread_key_t *key, void (*destructor)(void *) ) 208 | { 209 | int result = 0; 210 | pthread_key_t* newkey; 211 | 212 | if ((newkey = (pthread_key_t*) calloc (1, sizeof (pthread_key_t))) == NULL) 213 | { 214 | result = ENOMEM; 215 | } 216 | else if ((newkey->key = TlsAlloc ()) == TLS_OUT_OF_INDEXES) 217 | { 218 | result = EAGAIN; 219 | free (newkey); 220 | newkey = NULL; 221 | } 222 | else if (destructor != NULL) 223 | { 224 | //--we have to store the function pointer for destructor, so that we can call it 225 | //--to free up the user allocated storage-- 226 | newkey->destructor = destructor; 227 | } 228 | key = newkey; 229 | return (result); 230 | } 231 | 232 | int pthread_key_delete(pthread_key_t key) 233 | { 234 | int rc = 0; 235 | LPVOID lpvData = TlsGetValue(key.key); 236 | rc = TlsFree (key.key); 237 | rc = (rc != 0 ) ? 0 : GetLastError(); 238 | if (key.destructor != NULL && lpvData != 0){ 239 | key.destructor(lpvData); //we take control of calling destructor, instead of calling it on thread exit. 240 | } 241 | free (&key); 242 | return (rc); 243 | } 244 | 245 | void *pthread_getspecific(pthread_key_t key) 246 | { 247 | LPVOID lpvData = TlsGetValue(key.key); 248 | if ((lpvData == 0) && (GetLastError() != ERROR_SUCCESS)) 249 | return NULL; 250 | else 251 | return lpvData; 252 | } 253 | 254 | int pthread_setspecific(pthread_key_t key, const void *value) 255 | { 256 | int rc = TlsSetValue (key.key, value); 257 | return ((rc != 0 ) ? 0 : GetLastError()); 258 | } 259 | 260 | int gettimeofday(struct timeval *tp, void *tzp) { 261 | int64_t now = 0; 262 | if (tzp != 0) { errno = EINVAL; return -1; } 263 | GetSystemTimeAsFileTime( (LPFILETIME)&now ); 264 | tp->tv_sec = (long)(now / 10000000 - 11644473600LL); 265 | tp->tv_usec = (now / 10) % 1000000; 266 | return 0; 267 | } 268 | 269 | int close(SOCKET fd) { 270 | return closesocket(fd); 271 | } 272 | 273 | int Win32WSAStartup() 274 | { 275 | WORD wVersionRq; 276 | WSADATA wsaData; 277 | int err; 278 | 279 | wVersionRq = MAKEWORD(2,0); 280 | err = WSAStartup(wVersionRq, &wsaData); 281 | if (err != 0) 282 | return 1; 283 | 284 | // confirm the version information 285 | if ((LOBYTE(wsaData.wVersion) != 2) || 286 | (HIBYTE(wsaData.wVersion) != 0)) 287 | { 288 | Win32WSACleanup(); 289 | return 1; 290 | } 291 | return 0; 292 | } 293 | 294 | void Win32WSACleanup() 295 | { 296 | WSACleanup(); 297 | } 298 | 299 | #endif //WIN32 300 | 301 | 302 | 303 | -------------------------------------------------------------------------------- /mrsocket/win/winport.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | /** 20 | * This header file is to port pthread lib , sockets and other utility methods on windows. 21 | * Specifically the threads function, mutexes, keys, and socket initialization. 22 | */ 23 | 24 | #ifndef WINPORT_H_ 25 | #define WINPORT_H_ 26 | 27 | #ifdef WIN32 28 | //#include "winconfig.h" 29 | 30 | #define _WINSOCK_DEPRECATED_NO_WARNINGS 31 | #include /* must always be included before ws2tcpip.h */ 32 | #include /* for struct sock_addr used in zookeeper.h */ 33 | 34 | /* POSIX names are deprecated, use ISO conformant names instead. */ 35 | #define strdup _strdup 36 | #define getcwd _getcwd 37 | #define getpid _getpid 38 | 39 | /* Windows "secure" versions of POSIX reentrant functions */ 40 | #define strtok_r strtok_s 41 | #define localtime_r(a,b) localtime_s(b,a) 42 | 43 | /* After this version of MSVC, snprintf became a defined function, 44 | and so cannot be redefined, nor can #ifndef be used to guard it. */ 45 | #if ((defined(_MSC_VER) && _MSC_VER < 1900) || !defined(_MSC_VER)) 46 | #define snprintf _snprintf 47 | #endif 48 | 49 | 50 | #include 51 | #include 52 | #include /* for int64_t */ 53 | #include 54 | #include 55 | 56 | 57 | typedef int ssize_t; 58 | typedef HANDLE pthread_mutex_t; 59 | 60 | struct pthread_t_ 61 | { 62 | HANDLE thread_handle; 63 | DWORD thread_id; 64 | }; 65 | 66 | typedef struct pthread_t_ pthread_t; 67 | typedef int pthread_mutexattr_t; 68 | typedef int pthread_condattr_t; 69 | typedef int pthread_attr_t; 70 | #define PTHREAD_MUTEX_RECURSIVE 0 71 | 72 | int pthread_mutex_lock(pthread_mutex_t* _mutex ); 73 | int pthread_mutex_unlock( pthread_mutex_t* _mutex ); 74 | int pthread_mutex_init(pthread_mutex_t* _mutex, void* ignoredAttr); 75 | int pthread_mutex_destroy(pthread_mutex_t* _mutex); 76 | int pthread_create(pthread_t *thread, const pthread_attr_t *attr, unsigned (__stdcall* start_routine)(void* a), void *arg); 77 | int pthread_equal(pthread_t t1, pthread_t t2); 78 | pthread_t pthread_self(); 79 | int pthread_join(pthread_t _thread, void** ignore); 80 | int pthread_detach(pthread_t _thread); 81 | 82 | void pthread_mutexattr_init(pthread_mutexattr_t* ignore); 83 | void pthread_mutexattr_settype(pthread_mutexattr_t* ingore_attr, int ignore); 84 | void pthread_mutexattr_destroy(pthread_mutexattr_t* ignore_attr); 85 | 86 | 87 | // http://www.cs.wustl.edu/~schmidt/win32-cv-1.html 88 | 89 | typedef struct 90 | { 91 | int waiters_count_; 92 | // Number of waiting threads. 93 | 94 | CRITICAL_SECTION waiters_count_lock_; 95 | // Serialize access to . 96 | 97 | HANDLE sema_; 98 | // Semaphore used to queue up threads waiting for the condition to 99 | // become signaled. 100 | 101 | HANDLE waiters_done_; 102 | // An auto-reset event used by the broadcast/signal thread to wait 103 | // for all the waiting thread(s) to wake up and be released from the 104 | // semaphore. 105 | 106 | size_t was_broadcast_; 107 | // Keeps track of whether we were broadcasting or signaling. This 108 | // allows us to optimize the code if we're just signaling. 109 | }pthread_cond_t; 110 | 111 | int pthread_cond_init (pthread_cond_t *cv,const pthread_condattr_t * ignore); 112 | int pthread_cond_destroy(pthread_cond_t *cond); 113 | int pthread_cond_signal (pthread_cond_t *cv); 114 | int pthread_cond_broadcast (pthread_cond_t *cv); 115 | int pthread_cond_wait (pthread_cond_t *cv, pthread_mutex_t *external_mutex); 116 | 117 | 118 | struct pthread_key_t_ 119 | { 120 | DWORD key; 121 | void (*destructor) (void *); 122 | }; 123 | 124 | typedef struct pthread_key_t_ pthread_key_t; 125 | int pthread_key_create(pthread_key_t *key, void (*destructor)(void *) ); 126 | int pthread_key_delete(pthread_key_t key); 127 | void *pthread_getspecific(pthread_key_t key); 128 | int pthread_setspecific(pthread_key_t key, const void *value); 129 | 130 | int gettimeofday(struct timeval *tp, void *tzp); 131 | int close(SOCKET fd); 132 | int Win32WSAStartup(); 133 | void Win32WSACleanup(); 134 | #endif //WIN32 135 | 136 | 137 | 138 | #endif //WINPORT_H_ 139 | -------------------------------------------------------------------------------- /mrsocket/win/winsocket.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | Copyright (c) 2015-2017 dpull.com 3 | http://www.dpull.com 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 18 | THE SOFTWARE. 19 | ****************************************************************************/ 20 | 21 | // #include "winsocket.h" 22 | 23 | // #include 24 | // #include 25 | // #include 26 | // #include 27 | // #include 28 | // #include 29 | // #include 30 | // #include 31 | // #include "winport.h" 32 | 33 | // #include 34 | // #include 35 | // #pragma comment(lib, "ws2_32.lib") 36 | 37 | // static int write_extend_socket(int fd, const void* buffer, size_t sz) 38 | // { 39 | // int ret = send_extend_errno(fd, (const char*)buffer, sz, 0); 40 | // if (ret == SOCKET_ERROR && WSAGetLastError() == WSAENOTSOCK) 41 | // return write(fd, buffer, sz); 42 | // return ret; 43 | // } 44 | 45 | // static int read_extend_socket(int fd, void* buffer, size_t sz) 46 | // { 47 | // int ret = recv_extend_errno(fd, (char*)buffer, sz, 0); 48 | // if (ret == SOCKET_ERROR && WSAGetLastError() == WSAENOTSOCK) 49 | // return read(fd, buffer, sz); 50 | // return ret; 51 | // } 52 | 53 | // static int close_extend_socket(int fd) 54 | // { 55 | // int ret = closesocket(fd); 56 | // if (ret == SOCKET_ERROR && WSAGetLastError() == WSAENOTSOCK) 57 | // return close(fd); 58 | // return ret; 59 | // } 60 | 61 | // static int pipe_socket(int fds[2]) 62 | // { 63 | // if (Win32WSAStartup()){ 64 | // printf("Error initializing ws2_32.dll"); 65 | // assert(0); 66 | // return 0; 67 | // } 68 | // struct sockaddr_in name; 69 | // int namelen = sizeof(name); 70 | // SOCKET server = INVALID_SOCKET; 71 | // SOCKET client1 = INVALID_SOCKET; 72 | // SOCKET client2 = INVALID_SOCKET; 73 | 74 | // memset(&name, 0, sizeof(name)); 75 | // name.sin_family = AF_INET; 76 | // name.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 77 | // name.sin_port = 0; 78 | 79 | // server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 80 | // if (server == INVALID_SOCKET) 81 | // goto failed; 82 | 83 | // int yes=1; 84 | // if (setsockopt(server,SOL_SOCKET,SO_REUSEADDR,(char*)&yes,sizeof(yes)) == SOCKET_ERROR) 85 | // goto failed; 86 | 87 | // if (bind(server, (struct sockaddr*)&name, namelen) == SOCKET_ERROR) 88 | // goto failed; 89 | 90 | // if (listen(server, 5) == SOCKET_ERROR) 91 | // goto failed; 92 | 93 | // if(getsockname(server, (struct sockaddr*)&name, &namelen) == SOCKET_ERROR) 94 | // goto failed; 95 | 96 | // client1 = socket(AF_INET, SOCK_STREAM, 0); 97 | // if (client1 == INVALID_SOCKET) 98 | // goto failed; 99 | 100 | // if (connect(client1, (struct sockaddr*)&name, namelen) == SOCKET_ERROR) 101 | // goto failed; 102 | 103 | // client2 = accept(server, (struct sockaddr*)&name, &namelen); 104 | // if (client2 == INVALID_SOCKET) 105 | // goto failed; 106 | 107 | // closesocket(server); 108 | // fds[0] = (uintptr_t)client1; 109 | // fds[1] = (uintptr_t)client2; 110 | // return 0; 111 | 112 | // failed: 113 | // if (server != INVALID_SOCKET) 114 | // closesocket(server); 115 | 116 | // if (client1 != INVALID_SOCKET) 117 | // closesocket(client1); 118 | 119 | // if (client2 != INVALID_SOCKET) 120 | // closesocket(client2); 121 | // return -1; 122 | // } 123 | 124 | // static int connect_extend_errno(SOCKET s, const struct sockaddr* name, int namelen) 125 | // { 126 | // int ret = connect(s, name, namelen); 127 | // if (ret == SOCKET_ERROR) { 128 | // errno = WSAGetLastError(); 129 | // if (errno == WSAEWOULDBLOCK) 130 | // errno = EINPROGRESS; 131 | // } 132 | // return ret; 133 | // } 134 | 135 | // static int send_extend_errno(SOCKET s, const char* buffer, int sz, int flag) 136 | // { 137 | // int ret = send(s, buffer, sz, flag); 138 | // if (ret == SOCKET_ERROR) { 139 | // errno = WSAGetLastError(); 140 | // if (errno == WSAEWOULDBLOCK) 141 | // errno = EAGAIN; 142 | // } 143 | // return ret; 144 | // } 145 | 146 | // static int recv_extend_errno(SOCKET s, char* buffer, int sz, int flag) 147 | // { 148 | // int ret = recv(s, buffer, sz, flag); 149 | // if (ret == SOCKET_ERROR) { 150 | // errno = WSAGetLastError(); 151 | // if (errno == WSAEWOULDBLOCK) 152 | // errno = EAGAIN; 153 | // } 154 | // return ret; 155 | // } 156 | 157 | // static int getsockopt_extend_voidptr(SOCKET s, int level, int optname, void* optval, int* optlen) 158 | // { 159 | // return getsockopt(s, level, optname, (char*)optval, optlen); 160 | // } 161 | 162 | // static int setsockopt_extend_voidptr(SOCKET s, int level, int optname, const void* optval, int optlen) 163 | // { 164 | // return setsockopt(s, level, optname, (char*)optval, optlen); 165 | // } 166 | 167 | 168 | // static int recvfrom_extend_voidptr(SOCKET s, void* buf, int len, int flags, struct sockaddr* from, int* fromlen) 169 | // { 170 | // int ret = recvfrom(s, (char*)buf, len, flags, from, fromlen); 171 | // if (ret == SOCKET_ERROR) { 172 | // errno = WSAGetLastError(); 173 | // if (errno == WSAEWOULDBLOCK) 174 | // errno = EAGAIN; 175 | // if (errno == WSAECONNRESET) 176 | // errno = EAGAIN; 177 | // } 178 | // return ret; 179 | // } -------------------------------------------------------------------------------- /mrsocket/win/winsocket.h: -------------------------------------------------------------------------------- 1 | #ifndef winsocket_h 2 | #define winsocket_h 3 | 4 | #include 5 | #include 6 | 7 | // static int write_extend_socket(int fd, const void *buffer, size_t sz); 8 | // static int read_extend_socket(int fd, void *buffer, size_t sz); 9 | // static int close_extend_socket(int fd); 10 | // static int pipe_socket(int fd[2]); 11 | // static int connect_extend_errno(SOCKET s, const struct sockaddr* name, int namelen); 12 | // static int send_extend_errno(SOCKET s, const char* buffer, int sz, int flag); 13 | // static int recv_extend_errno(SOCKET s, char* buffer, int sz, int flag); 14 | // static int recv_extend_errno(SOCKET s, char* buffer, int sz, int flag); 15 | // static int getsockopt_extend_voidptr(SOCKET s, int level, int optname, void* optval, int* optlen); 16 | // static int setsockopt_extend_voidptr(SOCKET s, int level, int optname, const void* optval, int optlen); 17 | // static int recvfrom_extend_voidptr(SOCKET s, void* buf, int len, int flags, struct sockaddr* from, int* fromlen); 18 | 19 | // #ifndef DONOT_USE_IO_EXTEND 20 | // #define write(fd, ptr, sz) write_extend_socket(fd, ptr, sz) 21 | // #define read(fd, ptr, sz) read_extend_socket(fd, ptr, sz) 22 | // #define close(fd) close_extend_socket(fd) 23 | // #define pipe(fd) pipe_socket(fd) 24 | // #define connect(s, name, namelen) connect_extend_errno(s, name, namelen) 25 | // #define send(s, buffer, sz, flag) send_extend_errno(s, buffer, sz, flag) 26 | // #define recv(s, buffer, sz, flag) recv_extend_errno(s, buffer, sz, flag) 27 | // #define getsockopt(s, level, optname, optval, optlen) getsockopt_extend_voidptr(s, level, optname, optval, optlen) 28 | // #define setsockopt(s, level, optname, optval, optlen) setsockopt_extend_voidptr(s, level, optname, optval, optlen) 29 | // #define recvfrom(s, buf, len, flags, from, fromlen) recvfrom_extend_voidptr(s, buf, len, flags, from, fromlen) 30 | // #endif 31 | 32 | // #undef near 33 | 34 | 35 | static int write_extend_socket(int fd, const void* buffer, size_t sz) 36 | { 37 | int ret = send_extend_errno(fd, (const char*)buffer, sz, 0); 38 | if (ret == SOCKET_ERROR && WSAGetLastError() == WSAENOTSOCK) 39 | return write(fd, buffer, sz); 40 | return ret; 41 | } 42 | 43 | static int read_extend_socket(int fd, void* buffer, size_t sz) 44 | { 45 | int ret = recv_extend_errno(fd, (char*)buffer, sz, 0); 46 | if (ret == SOCKET_ERROR && WSAGetLastError() == WSAENOTSOCK) 47 | return read(fd, buffer, sz); 48 | return ret; 49 | } 50 | 51 | static int close_extend_socket(int fd) 52 | { 53 | int ret = closesocket(fd); 54 | if (ret == SOCKET_ERROR && WSAGetLastError() == WSAENOTSOCK) 55 | return close(fd); 56 | return ret; 57 | } 58 | 59 | static int pipe_socket(int fds[2]) 60 | { 61 | if (Win32WSAStartup()){ 62 | printf("Error initializing ws2_32.dll"); 63 | assert(0); 64 | return 0; 65 | } 66 | struct sockaddr_in name; 67 | int namelen = sizeof(name); 68 | SOCKET server = INVALID_SOCKET; 69 | SOCKET client1 = INVALID_SOCKET; 70 | SOCKET client2 = INVALID_SOCKET; 71 | 72 | memset(&name, 0, sizeof(name)); 73 | name.sin_family = AF_INET; 74 | name.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 75 | name.sin_port = 0; 76 | 77 | server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 78 | if (server == INVALID_SOCKET) 79 | goto failed; 80 | 81 | int yes=1; 82 | if (setsockopt(server,SOL_SOCKET,SO_REUSEADDR,(char*)&yes,sizeof(yes)) == SOCKET_ERROR) 83 | goto failed; 84 | 85 | if (bind(server, (struct sockaddr*)&name, namelen) == SOCKET_ERROR) 86 | goto failed; 87 | 88 | if (listen(server, 5) == SOCKET_ERROR) 89 | goto failed; 90 | 91 | if(getsockname(server, (struct sockaddr*)&name, &namelen) == SOCKET_ERROR) 92 | goto failed; 93 | 94 | client1 = socket(AF_INET, SOCK_STREAM, 0); 95 | if (client1 == INVALID_SOCKET) 96 | goto failed; 97 | 98 | if (connect(client1, (struct sockaddr*)&name, namelen) == SOCKET_ERROR) 99 | goto failed; 100 | 101 | client2 = accept(server, (struct sockaddr*)&name, &namelen); 102 | if (client2 == INVALID_SOCKET) 103 | goto failed; 104 | 105 | closesocket(server); 106 | fds[0] = (uintptr_t)client1; 107 | fds[1] = (uintptr_t)client2; 108 | return 0; 109 | 110 | failed: 111 | if (server != INVALID_SOCKET) 112 | closesocket(server); 113 | 114 | if (client1 != INVALID_SOCKET) 115 | closesocket(client1); 116 | 117 | if (client2 != INVALID_SOCKET) 118 | closesocket(client2); 119 | return -1; 120 | } 121 | 122 | static int connect_extend_errno(SOCKET s, const struct sockaddr* name, int namelen) 123 | { 124 | int ret = connect(s, name, namelen); 125 | if (ret == SOCKET_ERROR) { 126 | errno = WSAGetLastError(); 127 | if (errno == WSAEWOULDBLOCK) 128 | errno = EINPROGRESS; 129 | } 130 | return ret; 131 | } 132 | 133 | static int send_extend_errno(SOCKET s, const char* buffer, int sz, int flag) 134 | { 135 | int ret = send(s, buffer, sz, flag); 136 | if (ret == SOCKET_ERROR) { 137 | errno = WSAGetLastError(); 138 | if (errno == WSAEWOULDBLOCK) 139 | errno = EAGAIN; 140 | } 141 | return ret; 142 | } 143 | 144 | static int recv_extend_errno(SOCKET s, char* buffer, int sz, int flag) 145 | { 146 | int ret = recv(s, buffer, sz, flag); 147 | if (ret == SOCKET_ERROR) { 148 | errno = WSAGetLastError(); 149 | if (errno == WSAEWOULDBLOCK) 150 | errno = EAGAIN; 151 | } 152 | return ret; 153 | } 154 | 155 | static int getsockopt_extend_voidptr(SOCKET s, int level, int optname, void* optval, int* optlen) 156 | { 157 | return getsockopt(s, level, optname, (char*)optval, optlen); 158 | } 159 | 160 | static int setsockopt_extend_voidptr(SOCKET s, int level, int optname, const void* optval, int optlen) 161 | { 162 | return setsockopt(s, level, optname, (char*)optval, optlen); 163 | } 164 | 165 | 166 | static int recvfrom_extend_voidptr(SOCKET s, void* buf, int len, int flags, struct sockaddr* from, int* fromlen) 167 | { 168 | int ret = recvfrom(s, (char*)buf, len, flags, from, fromlen); 169 | if (ret == SOCKET_ERROR) { 170 | errno = WSAGetLastError(); 171 | if (errno == WSAEWOULDBLOCK) 172 | errno = EAGAIN; 173 | if (errno == WSAECONNRESET) 174 | errno = EAGAIN; 175 | } 176 | return ret; 177 | } 178 | 179 | 180 | #endif -------------------------------------------------------------------------------- /mrsocket/win/winsocketdef.h: -------------------------------------------------------------------------------- 1 | #ifndef winsocketdef_h 2 | #define winsocketdef_h 3 | 4 | #include "win/winsocket.h" 5 | 6 | #ifndef DONOT_USE_IO_EXTEND 7 | #define write(fd, ptr, sz) write_extend_socket(fd, ptr, sz) 8 | #define read(fd, ptr, sz) read_extend_socket(fd, ptr, sz) 9 | #define close(fd) close_extend_socket(fd) 10 | #define pipe(fd) pipe_socket(fd) 11 | #define connect(s, name, namelen) connect_extend_errno(s, name, namelen) 12 | #define send(s, buffer, sz, flag) send_extend_errno(s, buffer, sz, flag) 13 | #define recv(s, buffer, sz, flag) recv_extend_errno(s, buffer, sz, flag) 14 | #define getsockopt(s, level, optname, optval, optlen) getsockopt_extend_voidptr(s, level, optname, optval, optlen) 15 | #define setsockopt(s, level, optname, optval, optlen) setsockopt_extend_voidptr(s, level, optname, optval, optlen) 16 | #define recvfrom(s, buf, len, flags, from, fromlen) recvfrom_extend_voidptr(s, buf, len, flags, from, fromlen) 17 | #endif 18 | 19 | #undef near 20 | 21 | 22 | #endif -------------------------------------------------------------------------------- /mrtool/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skynetlua/mushroom/c1a10c03bcba1c5a529c5d36acd831982ccc5a90/mrtool/.DS_Store -------------------------------------------------------------------------------- /mrtool/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set(LIB_HEADER 3 | mr_time.h 4 | mr_buffer.h 5 | mr_code.h 6 | ) 7 | 8 | set(LIB_SRC 9 | mr_buffer.c 10 | ) 11 | 12 | list(APPEND LIB_SRC ${LIB_HEADER}) 13 | add_library(mrtool STATIC ${LIB_SRC}) 14 | -------------------------------------------------------------------------------- /mrtool/mr_buffer.c: -------------------------------------------------------------------------------- 1 | 2 | #include "mr_buffer.h" 3 | #include 4 | #include 5 | #include "mr_config.h" 6 | 7 | #define MIN_PACK 256 8 | 9 | 10 | struct mr_buffer_node { 11 | char* msg; 12 | size_t sz; 13 | struct mr_buffer_node *next; 14 | }; 15 | 16 | 17 | struct mr_buffer* mr_buffer_create(int head_len){ 18 | struct mr_buffer* buffer = (struct mr_buffer*)MALLOC(sizeof(struct mr_buffer)); 19 | memset(buffer, 0, sizeof(struct mr_buffer)); 20 | 21 | // buffer->read_len = 0; 22 | buffer->read_cap = MIN_PACK; 23 | buffer->read_data = MALLOC(buffer->read_cap); 24 | 25 | // buffer->write_len = 0; 26 | buffer->write_cap = MIN_PACK; 27 | buffer->write_data = MALLOC(buffer->write_cap); 28 | 29 | if (head_len < 1) 30 | buffer->head_len = 2; 31 | else if (head_len > 4) 32 | buffer->head_len = 4; 33 | else 34 | buffer->head_len = head_len; 35 | 36 | return buffer; 37 | } 38 | 39 | void mr_buffer_free(struct mr_buffer* buffer){ 40 | if (!buffer) return; 41 | 42 | struct mr_buffer_node* bnode; 43 | while(buffer->read_head != NULL){ 44 | bnode = buffer->read_head; 45 | buffer->read_head = bnode->next; 46 | 47 | FREE(bnode->msg); 48 | FREE(bnode); 49 | } 50 | FREE(buffer->read_data); 51 | FREE(buffer->write_data); 52 | FREE(buffer); 53 | } 54 | 55 | int mr_buffer_read_push(struct mr_buffer* buffer, char* msg, size_t len){ 56 | if (msg == NULL || len <= 0){ 57 | return -1; 58 | } 59 | struct mr_buffer_node* bnode = (struct mr_buffer_node*)MALLOC(sizeof(struct mr_buffer_node)); 60 | bnode->msg = (char*)MALLOC(len); 61 | memcpy(bnode->msg, msg, len); 62 | bnode->sz = len; 63 | bnode->next = NULL; 64 | 65 | if (buffer->read_head == NULL) { 66 | assert(buffer->read_tail == NULL); 67 | buffer->read_head = buffer->read_tail = bnode; 68 | } else { 69 | buffer->read_tail->next = bnode; 70 | buffer->read_tail = bnode; 71 | } 72 | buffer->read_size += len; 73 | return (int)buffer->read_size; 74 | } 75 | 76 | static inline void mr_buffer_pop_buffer_node(struct mr_buffer* buffer){ 77 | struct mr_buffer_node* bnode = buffer->read_head; 78 | buffer->read_size -= bnode->sz - buffer->read_offset; 79 | buffer->read_offset = 0; 80 | buffer->read_head = bnode->next; 81 | if (buffer->read_head == NULL) { 82 | buffer->read_tail = NULL; 83 | } 84 | FREE(bnode->msg); 85 | FREE(bnode); 86 | } 87 | 88 | int mr_buffer_read_header(struct mr_buffer* buffer, size_t len) { 89 | if (len > 4 || len < 1) return -2; 90 | if (len > buffer->read_size) return -1; 91 | int sz = 0; 92 | struct mr_buffer_node * bnode = buffer->read_head; 93 | const uint8_t* ptr = (const uint8_t*)bnode->msg + buffer->read_offset; 94 | size_t i = 0; 95 | for (; i < len; i++) { 96 | sz <<= 8; 97 | sz |= *ptr; 98 | buffer->read_offset++; 99 | if (bnode->sz - buffer->read_offset == 0){ 100 | mr_buffer_pop_buffer_node(buffer); 101 | if(i < len){ 102 | break; 103 | } 104 | bnode = buffer->read_head; 105 | assert(bnode); 106 | ptr = (const uint8_t*)bnode->msg + buffer->read_offset; 107 | }else{ 108 | ptr++; 109 | } 110 | } 111 | buffer->read_size -= len; 112 | return sz; 113 | } 114 | 115 | int mr_buffer_read(struct mr_buffer* buffer, char* data, int len) { 116 | if (data == NULL) return -2; 117 | if(len > buffer->read_size) return -1; 118 | 119 | struct mr_buffer_node* bnode = buffer->read_head; 120 | size_t size; 121 | size_t rd_len = len; 122 | do{ 123 | size = bnode->sz - buffer->read_offset; 124 | if (rd_len >= size){ 125 | memcpy(data, bnode->msg + buffer->read_offset, size); 126 | mr_buffer_pop_buffer_node(buffer); 127 | bnode = buffer->read_head; 128 | rd_len -= size; 129 | data += size; 130 | }else{ 131 | memcpy(data, bnode->msg + buffer->read_offset, rd_len); 132 | buffer->read_offset += rd_len; 133 | buffer->read_size -= rd_len; 134 | rd_len = 0; 135 | } 136 | }while(rd_len > 0); 137 | return len; 138 | } 139 | 140 | static inline void mr_buffer_adjust_pack(struct mr_buffer* buffer, int len, int type) 141 | { 142 | if (type == 0){ 143 | if (len >= buffer->read_cap) { 144 | while(len >= buffer->read_cap) 145 | buffer->read_cap *= 2; 146 | 147 | FREE(buffer->read_data); 148 | buffer->read_data = MALLOC(buffer->read_cap); 149 | } 150 | else if (buffer->read_cap > MIN_PACK && buffer->read_cap > len*2) { 151 | buffer->read_cap /= 2; 152 | FREE(buffer->read_data); 153 | buffer->read_data = MALLOC(buffer->read_cap); 154 | } 155 | }else{ 156 | if (len >= buffer->write_cap) { 157 | while(len >= buffer->write_cap) 158 | buffer->write_cap *= 2; 159 | 160 | FREE(buffer->write_data); 161 | buffer->write_data = MALLOC(buffer->write_cap); 162 | } 163 | else if (buffer->write_cap > MIN_PACK && buffer->write_cap > len*2) { 164 | buffer->write_cap /= 2; 165 | FREE(buffer->write_data); 166 | buffer->write_data = MALLOC(buffer->write_cap); 167 | } 168 | } 169 | } 170 | 171 | int mr_buffer_read_pack(struct mr_buffer* buffer) { 172 | int rlen = buffer->pack_len; 173 | if (rlen <= 0){ 174 | rlen = mr_buffer_read_header(buffer, buffer->head_len); 175 | if (rlen <= 0){ 176 | return -1; 177 | } 178 | buffer->pack_len = rlen; 179 | } 180 | if(rlen > buffer->read_size) return -1; 181 | buffer->pack_len = 0; 182 | 183 | buffer->read_len = rlen; 184 | mr_buffer_adjust_pack(buffer, rlen, 0); 185 | mr_buffer_read(buffer, buffer->read_data, rlen); 186 | return rlen; 187 | } 188 | 189 | //write//////////////// 190 | int mr_buffer_write_push(struct mr_buffer* buffer, char* msg, size_t len){ 191 | if (msg == NULL || len <= 0){ 192 | return -1; 193 | } 194 | struct mr_buffer_node* bnode = (struct mr_buffer_node*)MALLOC(sizeof(struct mr_buffer_node)); 195 | bnode->msg = (char*)MALLOC(len); 196 | memcpy(bnode->msg, msg, len); 197 | bnode->sz = len; 198 | bnode->next = NULL; 199 | 200 | if (buffer->write_head == NULL) { 201 | assert(buffer->write_tail == NULL); 202 | buffer->write_head = buffer->write_tail = bnode; 203 | } else { 204 | buffer->write_tail->next = bnode; 205 | buffer->write_tail = bnode; 206 | } 207 | buffer->write_size += len; 208 | return (int)buffer->write_size; 209 | } 210 | 211 | int mr_buffer_write_pack(struct mr_buffer* buffer){ 212 | int max_len = 0; 213 | int head_len = buffer->head_len; 214 | switch(head_len){ 215 | case 1: 216 | max_len = 0xff; 217 | break; 218 | case 2: 219 | max_len = 0xffff; 220 | break; 221 | case 4: 222 | max_len = 0xffffffff; 223 | break; 224 | default: 225 | return -1; 226 | break; 227 | } 228 | 229 | size_t len = buffer->write_size; 230 | if (len > max_len){ 231 | assert(0); 232 | return -1; 233 | } 234 | int wlen = head_len+(int)len; 235 | buffer->write_len = wlen; 236 | mr_buffer_adjust_pack(buffer, wlen, 1); 237 | 238 | char* data = buffer->write_data+head_len; 239 | 240 | struct mr_buffer_node* bnode; 241 | while(buffer->write_head != NULL){ 242 | bnode = buffer->write_head; 243 | buffer->write_head = bnode->next; 244 | 245 | memcpy(data, bnode->msg, bnode->sz); 246 | data += bnode->sz; 247 | 248 | FREE(bnode->msg); 249 | FREE(bnode); 250 | } 251 | buffer->write_tail = NULL; 252 | buffer->write_size = 0; 253 | 254 | char* pdata = buffer->write_data; 255 | int i = head_len-1; 256 | for (; i >= 0; i--) { 257 | *(pdata+i) = len & 0xff; 258 | len >>= 8; 259 | } 260 | return buffer->write_len; 261 | } 262 | 263 | // int mr_buffer_write_pack(struct mr_buffer* buffer, char* data, size_t len) { 264 | // int max_len = 0; 265 | // int head_len = buffer->head_len; 266 | // switch(head_len){ 267 | // case 1: 268 | // max_len = 0xff; 269 | // break; 270 | // case 2: 271 | // max_len = 0xffff; 272 | // break; 273 | // case 4: 274 | // max_len = 0xffffffff; 275 | // break; 276 | // default: 277 | // return -1; 278 | // break; 279 | // } 280 | // if (len > max_len){ 281 | // assert(0); 282 | // return -1; 283 | // } 284 | 285 | // int wlen = head_len+(int)len; 286 | // buffer->write_len = wlen; 287 | // assert(data != buffer->write_data); 288 | // mr_buffer_adjust_pack(buffer, wlen, 1); 289 | // memcpy(buffer->write_data+head_len, data, len); 290 | 291 | // char* pdata = buffer->write_data; 292 | // int i = head_len-1; 293 | // for (; i >= 0; i--) { 294 | // *(pdata+i) = len & 0xff; 295 | // len >>= 8; 296 | // } 297 | // return buffer->write_len; 298 | // } 299 | -------------------------------------------------------------------------------- /mrtool/mr_buffer.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __mr_buffer_h__ 3 | #define __mr_buffer_h__ 4 | 5 | #include 6 | #include 7 | 8 | struct mr_buffer { 9 | int head_len; 10 | 11 | int pack_len; 12 | 13 | size_t read_size; 14 | size_t read_offset; 15 | struct mr_buffer_node *read_head; 16 | struct mr_buffer_node *read_tail; 17 | 18 | int read_len; 19 | int read_cap; 20 | char* read_data; 21 | 22 | size_t write_size; 23 | // size_t write_offset; 24 | struct mr_buffer_node *write_head; 25 | struct mr_buffer_node *write_tail; 26 | 27 | int write_len; 28 | int write_cap; 29 | char* write_data; 30 | }; 31 | 32 | 33 | #define mr_buffer_size(buffer) (buffer)->size 34 | 35 | // static inline size_t mr_buffer_size(struct mr_buffer* buffer){ 36 | // return buffer->size; 37 | // } 38 | 39 | struct mr_buffer* mr_buffer_create(int head_len); 40 | void mr_buffer_free(struct mr_buffer* buffer); 41 | int mr_buffer_read_push(struct mr_buffer* buffer, char* msg, size_t len); 42 | int mr_buffer_read_header(struct mr_buffer* buffer, size_t len); 43 | int mr_buffer_read(struct mr_buffer* buffer, char* data, int len); 44 | int mr_buffer_read_pack(struct mr_buffer* buffer); 45 | 46 | 47 | int mr_buffer_write_push(struct mr_buffer* buffer, char* msg, size_t len); 48 | int mr_buffer_write_pack(struct mr_buffer* buffer); 49 | 50 | // int mr_buffer_write_pack(struct mr_buffer* buffer, char* data, size_t len); 51 | 52 | 53 | #endif -------------------------------------------------------------------------------- /mrtool/mr_code.h: -------------------------------------------------------------------------------- 1 | #ifndef mr_code_h 2 | #define mr_code_h 3 | 4 | #include 5 | 6 | #ifndef DATA_BIG_ENDIAN 7 | #ifdef _BIG_ENDIAN_ 8 | #if _BIG_ENDIAN_ 9 | #define DATA_BIG_ENDIAN 1 10 | #endif 11 | #endif 12 | #ifndef DATA_BIG_ENDIAN 13 | #if defined(__hppa__) || \ 14 | defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \ 15 | (defined(__MIPS__) && defined(__MIPSEB__)) || \ 16 | defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) || \ 17 | defined(__sparc__) || defined(__powerpc__) || \ 18 | defined(__mc68000__) || defined(__s390x__) || defined(__s390__) 19 | #define DATA_BIG_ENDIAN 1 20 | #endif 21 | #endif 22 | #ifndef DATA_BIG_ENDIAN 23 | #define DATA_BIG_ENDIAN 0 24 | #endif 25 | #endif 26 | 27 | 28 | static inline char *mr_encode8u(char *p, unsigned char c){ 29 | *(unsigned char*)p++ = c; 30 | return p; 31 | } 32 | 33 | static inline const char *mr_decode8u(const char *p, unsigned char *c){ 34 | *c = *(unsigned char*)p++; 35 | return p; 36 | } 37 | 38 | static inline char *mr_encode16u(char *p, unsigned short w){ 39 | #if DATA_BIG_ENDIAN 40 | *(unsigned char*)(p + 0) = (w & 255); 41 | *(unsigned char*)(p + 1) = (w >> 8); 42 | #else 43 | *(unsigned short*)(p) = w; 44 | #endif 45 | p += 2; 46 | return p; 47 | } 48 | 49 | static inline const char *mr_decode16u(const char *p, unsigned short *w) 50 | { 51 | #if DATA_BIG_ENDIAN 52 | *w = *(const unsigned char*)(p + 1); 53 | *w = *(const unsigned char*)(p + 0) + (*w << 8); 54 | #else 55 | *w = *(const unsigned short*)p; 56 | #endif 57 | p += 2; 58 | return p; 59 | } 60 | 61 | static inline char *mr_encode32u(char *p, uint32_t l) 62 | { 63 | #if DATA_BIG_ENDIAN 64 | *(unsigned char*)(p + 0) = (unsigned char)((l >> 0) & 0xff); 65 | *(unsigned char*)(p + 1) = (unsigned char)((l >> 8) & 0xff); 66 | *(unsigned char*)(p + 2) = (unsigned char)((l >> 16) & 0xff); 67 | *(unsigned char*)(p + 3) = (unsigned char)((l >> 24) & 0xff); 68 | #else 69 | *(uint32_t*)p = l; 70 | #endif 71 | p += 4; 72 | return p; 73 | } 74 | 75 | static inline const char *mr_decode32u(const char *p, uint32_t *l) 76 | { 77 | #if DATA_BIG_ENDIAN 78 | *l = *(const unsigned char*)(p + 3); 79 | *l = *(const unsigned char*)(p + 2) + (*l << 8); 80 | *l = *(const unsigned char*)(p + 1) + (*l << 8); 81 | *l = *(const unsigned char*)(p + 0) + (*l << 8); 82 | #else 83 | *l = *(const uint32_t*)p; 84 | #endif 85 | p += 4; 86 | return p; 87 | } 88 | 89 | static inline char *mr_encode64u(char *p, uint64_t l) 90 | { 91 | #if DATA_BIG_ENDIAN 92 | *(unsigned char*)(p + 0) = (unsigned char)((l >> 0) & 0xff); 93 | *(unsigned char*)(p + 1) = (unsigned char)((l >> 8) & 0xff); 94 | *(unsigned char*)(p + 2) = (unsigned char)((l >> 16) & 0xff); 95 | *(unsigned char*)(p + 3) = (unsigned char)((l >> 24) & 0xff); 96 | *(unsigned char*)(p + 0) = (unsigned char)((l >> 32) & 0xff); 97 | *(unsigned char*)(p + 1) = (unsigned char)((l >> 40) & 0xff); 98 | *(unsigned char*)(p + 2) = (unsigned char)((l >> 48) & 0xff); 99 | *(unsigned char*)(p + 3) = (unsigned char)((l >> 56) & 0xff); 100 | #else 101 | *(uint64_t*)p = l; 102 | #endif 103 | p += 8; 104 | return p; 105 | } 106 | 107 | static inline const char *mr_decode64u(const char *p, uint64_t *l) 108 | { 109 | #if DATA_BIG_ENDIAN 110 | *l = *(const unsigned char*)(p + 7); 111 | *l = *(const unsigned char*)(p + 6) + (*l << 8); 112 | *l = *(const unsigned char*)(p + 5) + (*l << 8); 113 | *l = *(const unsigned char*)(p + 4) + (*l << 8); 114 | *l = *(const unsigned char*)(p + 3) + (*l << 8); 115 | *l = *(const unsigned char*)(p + 2) + (*l << 8); 116 | *l = *(const unsigned char*)(p + 1) + (*l << 8); 117 | *l = *(const unsigned char*)(p + 0) + (*l << 8); 118 | #else 119 | *l = *(const uint64_t*)p; 120 | #endif 121 | p += 8; 122 | return p; 123 | } 124 | 125 | 126 | #endif 127 | 128 | -------------------------------------------------------------------------------- /mrtool/mr_time.h: -------------------------------------------------------------------------------- 1 | #ifndef __mr_time_h__ 2 | #define __mr_time_h__ 3 | 4 | #include 5 | 6 | #include 7 | #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) 8 | #include 9 | #else 10 | #include 11 | #include 12 | #endif 13 | 14 | static inline void mr_timeofday(long *sec, long *usec){ 15 | #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) 16 | static long mode = 0, addsec = 0; 17 | BOOL retval; 18 | static int64_t freq = 1; 19 | int64_t qpc; 20 | if (mode == 0) { 21 | retval = QueryPerformanceFrequency((LARGE_INTEGER*)&freq); 22 | freq = (freq == 0)? 1 : freq; 23 | retval = QueryPerformanceCounter((LARGE_INTEGER*)&qpc); 24 | addsec = (long)time(NULL); 25 | addsec = addsec - (long)((qpc / freq) & 0x7fffffff); 26 | mode = 1; 27 | } 28 | retval = QueryPerformanceCounter((LARGE_INTEGER*)&qpc); 29 | retval = retval * 2; 30 | if (sec) *sec = (long)(qpc / freq) + addsec; 31 | if (usec) *usec = (long)((qpc % freq) * 1000000 / freq); 32 | #else 33 | struct timeval time; 34 | gettimeofday(&time, NULL); 35 | if (sec) *sec = time.tv_sec; 36 | if (usec) *usec = time.tv_usec; 37 | #endif 38 | } 39 | 40 | static inline int64_t mr_clock64(void){ 41 | long s, u; 42 | mr_timeofday(&s, &u); 43 | int64_t value = ((int64_t)s) * 1000 + (u / 1000); 44 | return value; 45 | } 46 | 47 | static inline uint32_t mr_clock(void){ 48 | return (uint32_t)(mr_clock64() & 0xfffffffful); 49 | } 50 | 51 | static inline int64_t mr_time(void){ 52 | long s, u; 53 | mr_timeofday(&s, &u); 54 | int64_t value = ((int64_t)s) * 1000 + (u / 1000); 55 | return value; 56 | } 57 | 58 | static inline void mr_sleep(unsigned long millisecond){ 59 | #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) 60 | Sleep(millisecond); 61 | #else 62 | // struct timespec ts; 63 | // ts.tv_sec = (time_t)(millisecond / 1000); 64 | // ts.tv_nsec = (long)((millisecond % 1000) * 1000000); 65 | // nanosleep(&ts, NULL); 66 | usleep((millisecond << 10) - (millisecond << 4) - (millisecond << 3)); 67 | #endif 68 | } 69 | 70 | #endif 71 | 72 | 73 | -------------------------------------------------------------------------------- /mrtool/mrtool.h: -------------------------------------------------------------------------------- 1 | #ifndef __mr_tool_h__ 2 | #define __mr_tool_h__ 3 | 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | #include "mr_time.h" 10 | #include "mr_buffer.h" 11 | #include "mr_code.h" 12 | 13 | #ifdef __cplusplus 14 | } 15 | #endif 16 | 17 | 18 | #endif //__mr_tool_h__ 19 | 20 | 21 | --------------------------------------------------------------------------------