├── .gitattributes ├── LICENSE.md ├── README.md ├── common.cpp ├── common.h ├── fd_manager.cpp ├── fd_manager.h ├── libev ├── CVS │ ├── Entries │ ├── Repository │ └── Root ├── Changes ├── LICENSE ├── Makefile.am ├── README ├── README.embed ├── Symbols.ev ├── Symbols.event ├── autogen.sh ├── configure.ac ├── ev++.h ├── ev.3 ├── ev.c ├── ev.h ├── ev.pod ├── ev_epoll.c ├── ev_kqueue.c ├── ev_poll.c ├── ev_port.c ├── ev_select.c ├── ev_vars.h ├── ev_win32.c ├── ev_wrap.h ├── event.c ├── event.h ├── event_compat.h ├── import_libevent ├── libev.m4 ├── update_ev_c ├── update_ev_wrap └── update_symbols ├── log.cpp ├── log.h ├── main.cpp ├── makefile ├── my_ev.cpp ├── my_ev.h └── my_ev_common.h /.gitattributes: -------------------------------------------------------------------------------- 1 | libev/* linguist-vendored 2 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Yu Wang (wangyucn at gmail.com) 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 | # tinyPortMapper (or tinyPortForwarder) 2 | A Lightweight High-Performance Port Mapping/Forwarding Utility using epoll, Supports both TCP and UDP 3 | 4 | # Supported Platforms 5 | Linux host (including desktop Linux,Android phone/tablet, OpenWRT router, or Raspberry PI). Binaries of `amd64` `x86` `mips_be` `mips_le` `arm` are provided. 6 | 7 | # Getting Started 8 | 9 | ### Installing 10 | 11 | Download binary release from https://github.com/wangyu-/tinyPortMapper/releases 12 | 13 | ### Running 14 | Assume you want to map/forward local port 1234 to 10.222.2.1:443 15 | ``` 16 | # for both TCP and UDP 17 | ./tinymapper_amd64 -l0.0.0.0:1234 -r10.222.2.1:443 -t -u 18 | 19 | # for TCP only 20 | ./tinymapper_amd64 -l0.0.0.0:1234 -r10.222.2.1:443 -t 21 | 22 | # for UDP only 23 | ./tinymapper_amd64 -l0.0.0.0:1234 -r10.222.2.1:443 -u 24 | 25 | # for ipv6, both TCP and UDP 26 | # ipv6 address must be surrounded with `[]`, ipv4 address must NOT be surrounded with `[]` 27 | ./tinymapper_amd64 -l[::]:1234 -r[2001:19f0:7001:1111:00:ff:11:22]:443 -t -u 28 | ``` 29 | 30 | ##### NOTE 31 | ``` 32 | # local port and remote port can be the same 33 | ./tinymapper_amd64 -l0.0.0.0:443 -r10.222.2.1:443 -u 34 | 35 | # you can also use 6-to-4 or 4-to-6 forward 36 | ./tinymapper_amd64 -l0.0.0.0:1234 -r[2001:19f0:7001:1111:00:ff:11:22]:443 -t -u 37 | ./tinymapper_amd64 -l[::]:1234 -r44.55.66.77:443 -t -u 38 | 39 | # you can also use ipv4-mapped ipv6 address 40 | # this is especially useful if you want to play with ipv6 and you dont have a real ipv6 address 41 | ./tinymapper_amd64 -l[::]:4433 -r[::ffff:10.222.2.1]:443 -t -u 42 | ./tinymapper_amd64 -l[::ffff:0.0.0.0]:4433 -r[::ffff:10.222.2.1]:443 -t -u 43 | ``` 44 | # Options 45 | ``` 46 | tinyPortMapper 47 | git version:25ea4ec047 build date:Nov 4 2017 22:55:23 48 | repository: https://github.com/wangyu-/tinyPortMapper 49 | 50 | usage: 51 | ./this_program -l : -r : [options] 52 | 53 | main options: 54 | -t enable TCP forwarding/mapping 55 | -u enable UDP forwarding/mapping 56 | 57 | other options: 58 | --sock-buf buf size for socket, >=10 and <=10240, unit: kbyte, default: 1024 59 | --log-level 0: never 1: fatal 2: error 3: warn 60 | 4: info (default) 5: debug 6: trace 61 | --log-position enable file name, function name, line number in log 62 | --disable-color disable log color 63 | -h,--help print this help message 64 | ``` 65 | 66 | # Peformance Test 67 | ``` 68 | root@debian9:~# iperf3 -c 127.0.0.1 -p5202 69 | Connecting to host 127.0.0.1, port 5202 70 | [ 4] local 127.0.0.1 port 37604 connected to 127.0.0.1 port 5202 71 | [ ID] Interval Transfer Bandwidth Retr Cwnd 72 | [ 4] 0.00-1.00 sec 696 MBytes 5.84 Gbits/sec 0 639 KBytes 73 | [ 4] 1.00-2.00 sec 854 MBytes 7.17 Gbits/sec 0 639 KBytes 74 | [ 4] 2.00-3.00 sec 727 MBytes 6.10 Gbits/sec 0 639 KBytes 75 | [ 4] 3.00-4.00 sec 670 MBytes 5.62 Gbits/sec 0 639 KBytes 76 | [ 4] 4.00-5.00 sec 644 MBytes 5.40 Gbits/sec 0 639 KBytes 77 | [ 4] 5.00-6.00 sec 957 MBytes 8.03 Gbits/sec 0 639 KBytes 78 | [ 4] 6.00-7.00 sec 738 MBytes 6.19 Gbits/sec 0 639 KBytes 79 | [ 4] 7.00-8.00 sec 714 MBytes 5.99 Gbits/sec 0 639 KBytes 80 | [ 4] 8.00-9.00 sec 817 MBytes 6.85 Gbits/sec 0 639 KBytes 81 | [ 4] 9.00-10.00 sec 619 MBytes 5.19 Gbits/sec 0 639 KBytes 82 | - - - - - - - - - - - - - - - - - - - - - - - - - 83 | [ ID] Interval Transfer Bandwidth Retr 84 | [ 4] 0.00-10.00 sec 7.26 GBytes 6.24 Gbits/sec 0 sender 85 | [ 4] 0.00-10.00 sec 7.26 GBytes 6.24 Gbits/sec receiver 86 | 87 | ``` 88 | 89 | #### Details and more test results at: 90 | 91 | https://github.com/wangyu-/tinyPortMapper/wiki/Performance-Test 92 | -------------------------------------------------------------------------------- /common.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * comm.cpp 3 | * 4 | * Created on: Jul 29, 2017 5 | * Author: wangyu 6 | */ 7 | 8 | #include "common.h" 9 | #include "log.h" 10 | 11 | 12 | 13 | int about_to_exit=0; 14 | 15 | 16 | int socket_buf_size=1024*1024; 17 | 18 | #if defined(__MINGW32__) 19 | int inet_pton(int af, const char *src, void *dst) 20 | { 21 | struct sockaddr_storage ss; 22 | int size = sizeof(ss); 23 | char src_copy[INET6_ADDRSTRLEN+1]; 24 | 25 | ZeroMemory(&ss, sizeof(ss)); 26 | /* stupid non-const API */ 27 | strncpy (src_copy, src, INET6_ADDRSTRLEN+1); 28 | src_copy[INET6_ADDRSTRLEN] = 0; 29 | 30 | if (WSAStringToAddress(src_copy, af, NULL, (struct sockaddr *)&ss, &size) == 0) { 31 | switch(af) { 32 | case AF_INET: 33 | *(struct in_addr *)dst = ((struct sockaddr_in *)&ss)->sin_addr; 34 | return 1; 35 | case AF_INET6: 36 | *(struct in6_addr *)dst = ((struct sockaddr_in6 *)&ss)->sin6_addr; 37 | return 1; 38 | } 39 | } 40 | return 0; 41 | } 42 | 43 | const char *inet_ntop(int af, const void *src, char *dst, socklen_t size) 44 | { 45 | struct sockaddr_storage ss; 46 | unsigned long s = size; 47 | 48 | ZeroMemory(&ss, sizeof(ss)); 49 | ss.ss_family = af; 50 | 51 | switch(af) { 52 | case AF_INET: 53 | ((struct sockaddr_in *)&ss)->sin_addr = *(struct in_addr *)src; 54 | break; 55 | case AF_INET6: 56 | ((struct sockaddr_in6 *)&ss)->sin6_addr = *(struct in6_addr *)src; 57 | break; 58 | default: 59 | return NULL; 60 | } 61 | /* cannot direclty use &size because of strict aliasing rules */ 62 | return (WSAAddressToString((struct sockaddr *)&ss, sizeof(ss), NULL, dst, &s) == 0)? 63 | dst : NULL; 64 | } 65 | char *get_sock_error() 66 | { 67 | static char buf[1000]; 68 | int e=WSAGetLastError(); 69 | wchar_t *s = NULL; 70 | FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 71 | NULL, e, 72 | MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 73 | (LPWSTR)&s, 0, NULL); 74 | sprintf(buf, "%d:%S", e,s); 75 | int len=strlen(buf); 76 | if(len>0&&buf[len-1]=='\n') buf[len-1]=0; 77 | LocalFree(s); 78 | return buf; 79 | } 80 | int get_sock_errno() 81 | { 82 | return WSAGetLastError(); 83 | } 84 | #else 85 | char *get_sock_error() 86 | { 87 | static char buf[1000]; 88 | sprintf(buf, "%d:%s", errno,strerror(errno)); 89 | return buf; 90 | } 91 | int get_sock_errno() 92 | { 93 | return errno; 94 | } 95 | #endif 96 | 97 | int init_ws() 98 | { 99 | #if defined(__MINGW32__) 100 | WORD wVersionRequested; 101 | WSADATA wsaData; 102 | int err; 103 | 104 | /* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */ 105 | wVersionRequested = MAKEWORD(2, 2); 106 | 107 | err = WSAStartup(wVersionRequested, &wsaData); 108 | if (err != 0) { 109 | /* Tell the user that we could not find a usable */ 110 | /* Winsock DLL. */ 111 | printf("WSAStartup failed with error: %d\n", err); 112 | exit(-1); 113 | } 114 | 115 | /* Confirm that the WinSock DLL supports 2.2.*/ 116 | /* Note that if the DLL supports versions greater */ 117 | /* than 2.2 in addition to 2.2, it will still return */ 118 | /* 2.2 in wVersion since that is the version we */ 119 | /* requested. */ 120 | 121 | if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) { 122 | /* Tell the user that we could not find a usable */ 123 | /* WinSock DLL. */ 124 | printf("Could not find a usable version of Winsock.dll\n"); 125 | WSACleanup(); 126 | exit(-1); 127 | } 128 | else 129 | { 130 | printf("The Winsock 2.2 dll was found okay"); 131 | } 132 | 133 | int tmp[]={0,100,200,300,500,800,1000,2000,3000,4000,-1}; 134 | int succ=0; 135 | for(int i=1;tmp[i]!=-1;i++) 136 | { 137 | if(_setmaxstdio(100)==-1) break; 138 | else succ=i; 139 | } 140 | printf(", _setmaxstdio() was set to %d\n",tmp[succ]); 141 | #endif 142 | return 0; 143 | } 144 | 145 | 146 | /* 147 | struct random_fd_t 148 | { 149 | int random_number_fd; 150 | random_fd_t() 151 | { 152 | random_number_fd=open("/dev/urandom",O_RDONLY); 153 | 154 | if(random_number_fd==-1) 155 | { 156 | mylog(log_fatal,"error open /dev/urandom\n"); 157 | myexit(-1); 158 | } 159 | setnonblocking(random_number_fd); 160 | } 161 | int get_fd() 162 | { 163 | return random_number_fd; 164 | } 165 | }random_fd;*/ 166 | 167 | /* 168 | u64_t get_current_time()//ms 169 | { 170 | //timespec tmp_time; 171 | //clock_gettime(CLOCK_MONOTONIC, &tmp_time); 172 | //return ((u64_t)tmp_time.tv_sec)*1000llu+((u64_t)tmp_time.tv_nsec)/(1000*1000llu); 173 | return (u64_t)(ev_time()*1000); 174 | } 175 | 176 | u64_t get_current_time_us() 177 | { 178 | //timespec tmp_time; 179 | //clock_gettime(CLOCK_MONOTONIC, &tmp_time); 180 | //return (uint64_t(tmp_time.tv_sec))*1000llu*1000llu+ (uint64_t(tmp_time.tv_nsec))/1000llu; 181 | return (u64_t)(ev_time()*1000*1000); 182 | } 183 | */ 184 | 185 | u64_t get_current_time_us() 186 | { 187 | static u64_t value_fix=0; 188 | static u64_t largest_value=0; 189 | 190 | u64_t raw_value=(u64_t)(ev_time()*1000*1000); 191 | 192 | u64_t fixed_value=raw_value+value_fix; 193 | 194 | if(fixed_value< largest_value) 195 | { 196 | value_fix+= largest_value- fixed_value; 197 | } 198 | else 199 | { 200 | largest_value=fixed_value; 201 | } 202 | 203 | //printf("<%lld,%lld,%lld>\n",raw_value,value_fix,raw_value + value_fix); 204 | return raw_value + value_fix; //new fixed value 205 | } 206 | 207 | u64_t get_current_time() 208 | { 209 | return get_current_time_us()/1000lu; 210 | } 211 | 212 | 213 | u64_t pack_u64(u32_t a,u32_t b) 214 | { 215 | u64_t ret=a; 216 | ret<<=32u; 217 | ret+=b; 218 | return ret; 219 | } 220 | u32_t get_u64_h(u64_t a) 221 | { 222 | return a>>32u; 223 | } 224 | u32_t get_u64_l(u64_t a) 225 | { 226 | return (a<<32u)>>32u; 227 | } 228 | 229 | void write_u16(char * p,u16_t w) 230 | { 231 | *(unsigned char*)(p + 1) = (w & 0xff); 232 | *(unsigned char*)(p + 0) = (w >> 8); 233 | } 234 | u16_t read_u16(char * p) 235 | { 236 | u16_t res; 237 | res = *(const unsigned char*)(p + 0); 238 | res = *(const unsigned char*)(p + 1) + (res << 8); 239 | return res; 240 | } 241 | 242 | void write_u32(char * p,u32_t l) 243 | { 244 | *(unsigned char*)(p + 3) = (unsigned char)((l >> 0) & 0xff); 245 | *(unsigned char*)(p + 2) = (unsigned char)((l >> 8) & 0xff); 246 | *(unsigned char*)(p + 1) = (unsigned char)((l >> 16) & 0xff); 247 | *(unsigned char*)(p + 0) = (unsigned char)((l >> 24) & 0xff); 248 | } 249 | u32_t read_u32(char * p) 250 | { 251 | u32_t res; 252 | res = *(const unsigned char*)(p + 0); 253 | res = *(const unsigned char*)(p + 1) + (res << 8); 254 | res = *(const unsigned char*)(p + 2) + (res << 8); 255 | res = *(const unsigned char*)(p + 3) + (res << 8); 256 | return res; 257 | } 258 | 259 | void write_u64(char * s,u64_t a) 260 | { 261 | assert(0==1); 262 | } 263 | u64_t read_u64(char * s) 264 | { 265 | assert(0==1); 266 | return 0; 267 | } 268 | 269 | 270 | char * my_ntoa(u32_t ip) 271 | { 272 | in_addr a; 273 | a.s_addr=ip; 274 | return inet_ntoa(a); 275 | } 276 | /* 277 | u64_t get_true_random_number_64() 278 | { 279 | u64_t ret; 280 | int size=read(random_fd.get_fd(),&ret,sizeof(ret)); 281 | if(size!=sizeof(ret)) 282 | { 283 | mylog(log_fatal,"get random number failed %d\n",size); 284 | 285 | myexit(-1); 286 | } 287 | 288 | return ret; 289 | } 290 | u32_t get_true_random_number() 291 | { 292 | u32_t ret; 293 | int size=read(random_fd.get_fd(),&ret,sizeof(ret)); 294 | if(size!=sizeof(ret)) 295 | { 296 | mylog(log_fatal,"get random number failed %d\n",size); 297 | myexit(-1); 298 | } 299 | return ret; 300 | }*/ 301 | 302 | /* 303 | u32_t get_true_random_number_nz() //nz for non-zero 304 | { 305 | u32_t ret=0; 306 | while(ret==0) 307 | { 308 | ret=get_true_random_number(); 309 | } 310 | return ret; 311 | }*/ 312 | /* 313 | u64_t ntoh64(u64_t a) 314 | { 315 | if(__BYTE_ORDER == __LITTLE_ENDIAN) 316 | { 317 | return __bswap_64( a); 318 | } 319 | else return a; 320 | 321 | } 322 | u64_t hton64(u64_t a) 323 | { 324 | if(__BYTE_ORDER == __LITTLE_ENDIAN) 325 | { 326 | return __bswap_64( a); 327 | } 328 | else return a; 329 | 330 | }*/ 331 | 332 | void setnonblocking(int sock) { 333 | #if !defined(__MINGW32__) 334 | int opts; 335 | opts = fcntl(sock, F_GETFL); 336 | 337 | if (opts < 0) { 338 | mylog(log_fatal,"fcntl(sock,GETFL)\n"); 339 | //perror("fcntl(sock,GETFL)"); 340 | myexit(1); 341 | } 342 | opts = opts | O_NONBLOCK; 343 | if (fcntl(sock, F_SETFL, opts) < 0) { 344 | mylog(log_fatal,"fcntl(sock,SETFL,opts)\n"); 345 | //perror("fcntl(sock,SETFL,opts)"); 346 | myexit(1); 347 | } 348 | #else 349 | int iResult; 350 | u_long iMode = 1; 351 | iResult = ioctlsocket(sock, FIONBIO, &iMode); 352 | if (iResult != NO_ERROR) 353 | printf("ioctlsocket failed with error: %d\n", iResult); 354 | 355 | #endif 356 | } 357 | 358 | int set_buf_size(int fd,int socket_buf_size) 359 | { 360 | if(setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &socket_buf_size, sizeof(socket_buf_size))<0) 361 | { 362 | mylog(log_fatal,"SO_SNDBUF fail socket_buf_size=%d errno=%s\n",socket_buf_size,get_sock_error()); 363 | myexit(1); 364 | } 365 | if(setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &socket_buf_size, sizeof(socket_buf_size))<0) 366 | { 367 | mylog(log_fatal,"SO_RCVBUF fail socket_buf_size=%d errno=%s\n",socket_buf_size,get_sock_error()); 368 | myexit(1); 369 | } 370 | return 0; 371 | } 372 | 373 | void myexit(int a) 374 | { 375 | if(enable_log_color) 376 | printf("%s\n",RESET); 377 | // clear_iptables_rule(); 378 | exit(a); 379 | } 380 | /* 381 | void signal_handler(int sig) 382 | { 383 | about_to_exit=1; 384 | // myexit(0); 385 | }*/ 386 | 387 | /* 388 | void get_true_random_chars(char * s,int len) 389 | { 390 | int size=read(random_fd.get_fd(),s,len); 391 | if(size!=len) 392 | { 393 | printf("get random number failed\n"); 394 | exit(-1); 395 | } 396 | }*/ 397 | 398 | /* 399 | int random_between(u32_t a,u32_t b) 400 | { 401 | if(a>b) 402 | { 403 | mylog(log_fatal,"min >max?? %d %d\n",a ,b); 404 | myexit(1); 405 | } 406 | if(a==b)return a; 407 | else return a+get_true_random_number()%(b+1-a); 408 | }*/ 409 | 410 | 411 | int round_up_div(int a,int b) 412 | { 413 | return (a+b-1)/b; 414 | } 415 | /* 416 | int create_fifo(char * file) 417 | { 418 | if(mkfifo (file, 0666)!=0) 419 | { 420 | if(errno==EEXIST) 421 | { 422 | mylog(log_warn,"warning fifo file %s exist\n",file); 423 | } 424 | else 425 | { 426 | mylog(log_fatal,"create fifo file %s failed\n",file); 427 | myexit(-1); 428 | } 429 | } 430 | int fifo_fd=open (file, O_RDWR); 431 | if(fifo_fd<0) 432 | { 433 | mylog(log_fatal,"create fifo file %s failed\n",file); 434 | myexit(-1); 435 | } 436 | struct stat st; 437 | if (fstat(fifo_fd, &st)!=0) 438 | { 439 | mylog(log_fatal,"fstat failed for fifo file %s\n",file); 440 | myexit(-1); 441 | } 442 | 443 | if(!S_ISFIFO(st.st_mode)) 444 | { 445 | mylog(log_fatal,"%s is not a fifo\n",file); 446 | myexit(-1); 447 | } 448 | 449 | setnonblocking(fifo_fd); 450 | return fifo_fd; 451 | }*/ 452 | 453 | 454 | int new_listen_socket(int &fd,u32_t ip,int port) 455 | { 456 | fd =socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 457 | 458 | int yes = 1; 459 | //setsockopt(udp_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)); 460 | 461 | struct sockaddr_in local_me={0}; 462 | 463 | socklen_t slen = sizeof(sockaddr_in); 464 | //memset(&local_me, 0, sizeof(local_me)); 465 | local_me.sin_family = AF_INET; 466 | local_me.sin_port = htons(port); 467 | local_me.sin_addr.s_addr = ip; 468 | 469 | if (::bind(fd, (struct sockaddr*) &local_me, slen) == -1) { 470 | mylog(log_fatal,"socket bind error\n"); 471 | //perror("socket bind error"); 472 | myexit(1); 473 | } 474 | setnonblocking(fd); 475 | set_buf_size(fd,socket_buf_size); 476 | 477 | mylog(log_debug,"local_listen_fd=%d\n,",fd); 478 | 479 | return 0; 480 | } 481 | /* 482 | int set_timer(int epollfd,int &timer_fd) 483 | { 484 | int ret; 485 | epoll_event ev; 486 | 487 | itimerspec its; 488 | memset(&its,0,sizeof(its)); 489 | 490 | if((timer_fd=timerfd_create(CLOCK_MONOTONIC,TFD_NONBLOCK)) < 0) 491 | { 492 | mylog(log_fatal,"timer_fd create error\n"); 493 | myexit(1); 494 | } 495 | its.it_interval.tv_sec=(timer_interval/1000); 496 | its.it_interval.tv_nsec=(timer_interval%1000)*1000ll*1000ll; 497 | its.it_value.tv_nsec=1; //imidiately 498 | timerfd_settime(timer_fd,0,&its,0); 499 | setnonblocking(timer_fd); 500 | 501 | 502 | ev.events = EPOLLIN; 503 | ev.data.u64 = timer_fd; 504 | 505 | ret=epoll_ctl(epollfd, EPOLL_CTL_ADD, timer_fd, &ev); 506 | if (ret < 0) { 507 | mylog(log_fatal,"epoll_ctl return %d\n", ret); 508 | myexit(-1); 509 | } 510 | return 0; 511 | }*/ 512 | 513 | int address_t::from_str(char *str) 514 | { 515 | clear(); 516 | 517 | char ip_addr_str[100];u32_t port; 518 | mylog(log_info,"parsing address: %s\n",str); 519 | int is_ipv6=0; 520 | if(sscanf(str, "[%[^]]]:%u", ip_addr_str,&port)==2) 521 | { 522 | mylog(log_info,"its an ipv6 adress\n"); 523 | inner.ipv6.sin6_family=AF_INET6; 524 | is_ipv6=1; 525 | } 526 | else if(sscanf(str, "%[^:]:%u", ip_addr_str,&port)==2) 527 | { 528 | mylog(log_info,"its an ipv4 adress\n"); 529 | inner.ipv4.sin_family=AF_INET; 530 | } 531 | else 532 | { 533 | mylog(log_error,"failed to parse\n"); 534 | myexit(-1); 535 | } 536 | 537 | mylog(log_info,"ip_address is {%s}, port is {%u}\n",ip_addr_str,port); 538 | 539 | if(port>65535) 540 | { 541 | mylog(log_error,"invalid port: %d\n",port); 542 | myexit(-1); 543 | } 544 | 545 | int ret=-100; 546 | if(is_ipv6) 547 | { 548 | ret=inet_pton(AF_INET6, ip_addr_str,&(inner.ipv6.sin6_addr)); 549 | inner.ipv6.sin6_port=htons(port); 550 | if(ret==0) // 0 if address type doesnt match 551 | { 552 | mylog(log_error,"ip_addr %s is not an ipv6 address, %d\n",ip_addr_str,ret); 553 | myexit(-1); 554 | } 555 | else if(ret==1) // inet_pton returns 1 on success 556 | { 557 | //okay 558 | } 559 | else 560 | { 561 | mylog(log_error,"ip_addr %s is invalid, %d\n",ip_addr_str,ret); 562 | myexit(-1); 563 | } 564 | } 565 | else 566 | { 567 | ret=inet_pton(AF_INET, ip_addr_str,&(inner.ipv4.sin_addr)); 568 | inner.ipv4.sin_port=htons(port); 569 | 570 | if(ret==0) 571 | { 572 | mylog(log_error,"ip_addr %s is not an ipv4 address, %d\n",ip_addr_str,ret); 573 | myexit(-1); 574 | } 575 | else if(ret==1) 576 | { 577 | //okay 578 | } 579 | else 580 | { 581 | mylog(log_error,"ip_addr %s is invalid, %d\n",ip_addr_str,ret); 582 | myexit(-1); 583 | } 584 | } 585 | 586 | return 0; 587 | } 588 | 589 | char * address_t::get_str() 590 | { 591 | static char res[max_addr_len]; 592 | to_str(res); 593 | return res; 594 | } 595 | void address_t::to_str(char * s) 596 | { 597 | //static char res[max_addr_len]; 598 | char ip_addr[max_addr_len]; 599 | u32_t port; 600 | const char * ret=0; 601 | if(get_type()==AF_INET6) 602 | { 603 | ret=inet_ntop(AF_INET6, &inner.ipv6.sin6_addr, ip_addr,max_addr_len); 604 | port=inner.ipv6.sin6_port; 605 | } 606 | else if(get_type()==AF_INET) 607 | { 608 | ret=inet_ntop(AF_INET, &inner.ipv4.sin_addr, ip_addr,max_addr_len); 609 | port=inner.ipv4.sin_port; 610 | } 611 | else 612 | { 613 | assert(0==1); 614 | } 615 | 616 | if(ret==0) //NULL on failure 617 | { 618 | mylog(log_error,"inet_ntop failed\n"); 619 | myexit(-1); 620 | } 621 | 622 | port=ntohs(port); 623 | 624 | ip_addr[max_addr_len-1]=0; 625 | if(get_type()==AF_INET6) 626 | { 627 | sprintf(s,"[%s]:%u",ip_addr,(u32_t)port); 628 | }else 629 | { 630 | sprintf(s,"%s:%u",ip_addr,(u32_t)port); 631 | } 632 | 633 | //return res; 634 | } 635 | 636 | int address_t::from_sockaddr(sockaddr * addr,socklen_t slen) 637 | { 638 | memset(&inner,0,sizeof(inner)); 639 | if(addr->sa_family==AF_INET6) 640 | { 641 | assert(slen==sizeof(sockaddr_in6)); 642 | inner.ipv6= *( (sockaddr_in6*) addr ); 643 | 644 | } 645 | else if(addr->sa_family==AF_INET) 646 | { 647 | assert(slen==sizeof(sockaddr_in)); 648 | inner.ipv4= *( (sockaddr_in*) addr ); 649 | } 650 | else 651 | { 652 | assert(0==1); 653 | } 654 | return 0; 655 | } 656 | 657 | int address_t::new_connected_udp_fd() 658 | { 659 | 660 | int new_udp_fd; 661 | new_udp_fd = socket(get_type(), SOCK_DGRAM, IPPROTO_UDP); 662 | if (new_udp_fd < 0) { 663 | mylog(log_warn, "create udp_fd error\n"); 664 | return -1; 665 | } 666 | setnonblocking(new_udp_fd); 667 | set_buf_size(new_udp_fd,socket_buf_size); 668 | 669 | mylog(log_debug, "created new udp_fd %d\n", new_udp_fd); 670 | int ret = connect(new_udp_fd, (struct sockaddr *) &inner, get_len()); 671 | if (ret != 0) { 672 | mylog(log_warn, "udp fd connect fail %d %s\n",ret,get_sock_error() ); 673 | sock_close(new_udp_fd); 674 | return -1; 675 | } 676 | 677 | return new_udp_fd; 678 | } 679 | 680 | u32_t djb2(unsigned char *str, int len) { 681 | u32_t hash = 5381; 682 | int c; 683 | for (int i=0; i 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | #include 22 | //#include 23 | //#include 24 | //#include //for socket ofcourse 25 | //#include 26 | //#include 27 | #include //for exit(0); 28 | #include //For errno - the error number 29 | //#include //Provides declarations for tcp header 30 | //#include 31 | //#include //Provides declarations for ip header 32 | //#include 33 | //#include 34 | #include 35 | //#include 36 | //#include 37 | //#include 38 | #include 39 | #include 40 | //#include 41 | //#include 42 | //#include 43 | //#include 44 | //#include 45 | #include 46 | #include 47 | 48 | #if !defined(NO_LIBEV_EMBED) 49 | #include 50 | #else 51 | #include "ev.h" 52 | #endif 53 | 54 | #if defined(__MINGW32__) 55 | #include 56 | #include 57 | typedef unsigned char u_int8_t; 58 | typedef unsigned short u_int16_t; 59 | typedef unsigned int u_int32_t; 60 | typedef int socklen_t; 61 | #else 62 | #include //for socket ofcourse 63 | #include 64 | #include 65 | #include 66 | #include 67 | #endif 68 | 69 | 70 | //#include 71 | //#include 72 | 73 | #include 74 | #include 75 | #include 76 | #include 77 | #include 78 | #include 79 | #include 80 | //#include 81 | using namespace std; 82 | 83 | #if defined(__MINGW32__) 84 | int inet_pton(int af, const char *src, void *dst); 85 | const char *inet_ntop(int af, const void *src, char *dst, socklen_t size); 86 | #define setsockopt(a,b,c,d,e) setsockopt(a,b,c,(const char *)(d),e) 87 | #endif 88 | 89 | char *get_sock_error(); 90 | int get_sock_errno(); 91 | 92 | 93 | typedef unsigned long long u64_t; //this works on most platform,avoid using the PRId64 94 | typedef long long i64_t; 95 | 96 | typedef unsigned int u32_t; 97 | typedef int i32_t; 98 | 99 | typedef unsigned short u16_t; 100 | typedef short i16_t; 101 | 102 | typedef u64_t my_time_t; 103 | 104 | //const int max_data_len=2200; 105 | //const int buf_len=max_data_len+200; 106 | 107 | const int max_addr_len=100; 108 | 109 | const int max_data_len_udp=65536; 110 | const int max_data_len_tcp=4096*4; 111 | 112 | const u32_t conn_timeout_udp=180000; 113 | const u32_t conn_timeout_tcp=360000; 114 | 115 | const int max_conn_num=20000; 116 | 117 | const int conn_clear_ratio=30; 118 | const int conn_clear_min=1; 119 | 120 | const u32_t conn_clear_interval=1000; 121 | 122 | const u32_t timer_interval=400;//this should be smaller than heartbeat_interval and retry interval; 123 | 124 | extern int about_to_exit; 125 | 126 | extern int socket_buf_size; 127 | 128 | typedef u64_t fd64_t; 129 | 130 | 131 | 132 | #if defined(__MINGW32__) 133 | typedef SOCKET my_fd_t; 134 | inline int sock_close(my_fd_t fd) 135 | { 136 | return closesocket(fd); 137 | } 138 | #else 139 | typedef int my_fd_t; 140 | inline int sock_close(my_fd_t fd) 141 | { 142 | return close(fd); 143 | } 144 | 145 | #endif 146 | 147 | struct not_copy_able_t 148 | { 149 | not_copy_able_t() 150 | { 151 | 152 | } 153 | not_copy_able_t(const not_copy_able_t &other) 154 | { 155 | assert(0==1); 156 | } 157 | const not_copy_able_t & operator=(const not_copy_able_t &other) 158 | { 159 | assert(0==1); 160 | return other; 161 | } 162 | }; 163 | 164 | struct tcp_info_t:not_copy_able_t 165 | { 166 | fd64_t fd64; 167 | ev_io ev; 168 | //epoll_event ev; 169 | //char * data; 170 | char data[max_data_len_tcp+200];//use a larger buffer than udp 171 | char * begin; 172 | int data_len; 173 | tcp_info_t() 174 | { 175 | //data=(char*)malloc(max_data_len_tcp+200); 176 | 177 | begin=data; 178 | data_len=0; 179 | 180 | } 181 | ~tcp_info_t() 182 | { 183 | //if(data) 184 | //free(data); 185 | } 186 | /* 187 | void free_memory() 188 | { 189 | free(data); 190 | data=0; 191 | begin=0; 192 | }*/ 193 | }; 194 | 195 | int init_ws(); 196 | 197 | u32_t djb2(unsigned char *str,int len); 198 | u32_t sdbm(unsigned char *str,int len); 199 | 200 | 201 | struct address_t //TODO scope id 202 | { 203 | struct hash_function 204 | { 205 | u32_t operator()(const address_t &key) const 206 | { 207 | return sdbm((unsigned char*)&key.inner,sizeof(key.inner)); 208 | } 209 | }; 210 | 211 | union storage_t //sockaddr_storage is too huge, we dont use it. 212 | { 213 | sockaddr_in ipv4; 214 | sockaddr_in6 ipv6; 215 | }; 216 | storage_t inner; 217 | 218 | address_t() 219 | { 220 | clear(); 221 | } 222 | void clear() 223 | { 224 | memset(&inner,0,sizeof(inner)); 225 | } 226 | int from_str(char * str); 227 | 228 | int from_sockaddr(sockaddr *,socklen_t); 229 | 230 | char* get_str(); 231 | void to_str(char *); 232 | 233 | inline u32_t get_type() 234 | { 235 | return ((sockaddr*)&inner)->sa_family; 236 | } 237 | 238 | inline u32_t get_len() 239 | { 240 | u32_t type=get_type(); 241 | switch(type) 242 | { 243 | case AF_INET: 244 | return sizeof(sockaddr_in); 245 | case AF_INET6: 246 | return sizeof(sockaddr_in6); 247 | default: 248 | assert(0==1); 249 | } 250 | return -1; 251 | } 252 | 253 | bool operator == (const address_t &b) const 254 | { 255 | //return this->data==b.data; 256 | return memcmp(&this->inner,&b.inner,sizeof(this->inner))==0; 257 | } 258 | 259 | int new_connected_udp_fd(); 260 | }; 261 | 262 | 263 | struct udp_pair_t:not_copy_able_t 264 | { 265 | address_t adress; 266 | fd64_t fd64; 267 | ev_io ev; 268 | int local_listen_fd; 269 | //u64_t last_active_time; 270 | char addr_s[max_addr_len]; 271 | list::iterator it; 272 | udp_pair_t() 273 | { 274 | addr_s[0]=0; 275 | } 276 | //int not_used=0; 277 | }; 278 | 279 | struct tcp_pair_t:not_copy_able_t 280 | { 281 | tcp_info_t local; 282 | tcp_info_t remote; 283 | //u64_t last_active_time; 284 | list::iterator it; 285 | char addr_s[max_addr_len]; 286 | //int not_used=0; 287 | tcp_pair_t() 288 | { 289 | addr_s[0]=0; 290 | } 291 | }; 292 | 293 | struct fd_info_t:not_copy_able_t 294 | { 295 | int is_tcp=0; 296 | tcp_pair_t *tcp_pair_p=0; 297 | udp_pair_t *udp_pair_p=0; 298 | }; 299 | 300 | 301 | u64_t get_current_time(); 302 | u64_t get_current_time_us(); 303 | u64_t pack_u64(u32_t a,u32_t b); 304 | u32_t get_u64_h(u64_t a); 305 | u32_t get_u64_l(u64_t a); 306 | 307 | void write_u16(char *,u16_t a); 308 | u16_t read_u16(char *); 309 | 310 | void write_u32(char *,u32_t a); 311 | u32_t read_u32(char *); 312 | 313 | void write_u64(char *,u64_t a); 314 | u64_t read_uu64(char *); 315 | 316 | char * my_ntoa(u32_t ip); 317 | 318 | void myexit(int a); 319 | void init_random_number_fd(); 320 | u64_t get_fake_random_number_64(); 321 | u32_t get_fake_random_number(); 322 | u32_t get_fake_random_number_nz(); 323 | u64_t ntoh64(u64_t a); 324 | u64_t hton64(u64_t a); 325 | bool larger_than_u16(uint16_t a,uint16_t b); 326 | bool larger_than_u32(u32_t a,u32_t b); 327 | void setnonblocking(int sock); 328 | 329 | int set_buf_size(int fd,int socket_buf_size); 330 | 331 | void signal_handler(int sig); 332 | 333 | void get_fake_random_chars(char * s,int len); 334 | int random_between(u32_t a,u32_t b); 335 | 336 | 337 | int round_up_div(int a,int b); 338 | 339 | int set_timer(int epollfd,int &timer_fd); 340 | 341 | //#endif /* COMMON_H_ */ 342 | -------------------------------------------------------------------------------- /fd_manager.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * fd_manager.cpp 3 | * 4 | * Created on: Sep 25, 2017 5 | * Author: root 6 | */ 7 | 8 | 9 | #include "fd_manager.h" 10 | fd_manager_t fd_manager; 11 | 12 | int fd_manager_t::fd_exist(int fd) 13 | { 14 | return fd_to_fd64_mp.find(fd)!=fd_to_fd64_mp.end(); 15 | } 16 | int fd_manager_t::exist(fd64_t fd64) 17 | { 18 | return fd64_to_fd_mp.find(fd64)!=fd64_to_fd_mp.end(); 19 | } 20 | int fd_manager_t::to_fd(fd64_t fd64) 21 | { 22 | assert(exist(fd64)); 23 | return fd64_to_fd_mp[fd64]; 24 | } 25 | 26 | void fd_manager_t::fd64_close(fd64_t fd64) 27 | { 28 | assert(exist(fd64)); 29 | int fd=fd64_to_fd_mp[fd64]; 30 | fd64_to_fd_mp.erase(fd64); 31 | fd_to_fd64_mp.erase(fd); 32 | if(exist_info(fd64)) 33 | { 34 | fd_info_mp.erase(fd64); 35 | } 36 | sock_close(fd); 37 | // assert(close(fd)==0); 38 | } 39 | void fd_manager_t::reserve(int n) 40 | { 41 | fd_to_fd64_mp.reserve(n); 42 | fd64_to_fd_mp.reserve(n); 43 | fd_info_mp.reserve(n); 44 | } 45 | u64_t fd_manager_t::create(int fd) 46 | { 47 | assert(!fd_exist(fd)); 48 | fd64_t fd64=counter++; 49 | fd_to_fd64_mp[fd]=fd64; 50 | fd64_to_fd_mp[fd64]=fd; 51 | return fd64; 52 | } 53 | fd_manager_t::fd_manager_t() 54 | { 55 | counter=u32_t(-1); 56 | counter+=100; 57 | reserve(10007); 58 | } 59 | fd_info_t & fd_manager_t::get_info(fd64_t fd64) 60 | { 61 | assert(exist(fd64)); 62 | return fd_info_mp[fd64]; 63 | } 64 | int fd_manager_t::exist_info(fd64_t fd64) 65 | { 66 | return fd_info_mp.find(fd64)!=fd_info_mp.end(); 67 | } 68 | -------------------------------------------------------------------------------- /fd_manager.h: -------------------------------------------------------------------------------- 1 | /* 2 | * fd_manager.h 3 | * 4 | * Created on: Sep 25, 2017 5 | * Author: root 6 | */ 7 | 8 | #pragma once 9 | 10 | //#ifndef FD_MANAGER_H_ 11 | //#define FD_MANAGER_H_ 12 | 13 | #include "common.h" 14 | //#include "packet.h" 15 | 16 | 17 | struct fd_manager_t //conver fd to a uniq 64bit number,avoid fd value conflict caused by close and re-create 18 | //this class is not strictly necessary,it just makes epoll fd handling easier 19 | { 20 | fd_info_t & get_info(fd64_t fd64); 21 | int exist_info(fd64_t); 22 | int exist(fd64_t fd64); 23 | int to_fd(fd64_t); 24 | void fd64_close(fd64_t fd64); 25 | void reserve(int n); 26 | u64_t create(int fd); 27 | fd_manager_t(); 28 | private: 29 | u64_t counter; 30 | unordered_map fd_to_fd64_mp; //TODO combine those maps 31 | unordered_map fd64_to_fd_mp; 32 | unordered_map fd_info_mp; 33 | int fd_exist(int fd); 34 | //void remove_fd(int fd); 35 | //fd64_t fd_to_fd64(int fd); 36 | }; 37 | 38 | extern fd_manager_t fd_manager; 39 | 40 | //#endif /* FD_MANAGER_H_ */ 41 | -------------------------------------------------------------------------------- /libev/CVS/Entries: -------------------------------------------------------------------------------- 1 | /Changes/1.315/Wed Jun 21 14:42:30 2017// 2 | /LICENSE/1.11/Thu Jan 16 11:51:05 2014// 3 | /Makefile.am/1.9/Wed Dec 21 18:16:08 2011// 4 | /README/1.21/Fri Mar 30 17:43:55 2012// 5 | /README.embed/1.29/Sat Nov 24 10:10:26 2007// 6 | /Symbols.ev/1.14/Tue Jan 11 13:45:28 2011// 7 | /Symbols.event/1.4/Tue May 8 15:52:13 2012// 8 | /autogen.sh/1.3/Mon May 30 15:28:54 2011// 9 | /configure.ac/1.42/Wed Dec 28 04:22:06 2016// 10 | /ev++.h/1.63/Fri Dec 1 06:37:30 2017// 11 | /ev.3/1.107/Wed Jun 21 14:42:30 2017// 12 | /ev.c/1.481/Thu Jun 1 20:25:50 2017// 13 | /ev.h/1.187/Wed Dec 28 04:22:06 2016// 14 | /ev.pod/1.441/Thu Jul 13 10:46:52 2017// 15 | /ev_epoll.c/1.72/Wed Jun 21 14:42:30 2017// 16 | /ev_kqueue.c/1.56/Thu Feb 18 04:48:05 2016// 17 | /ev_poll.c/1.40/Thu Feb 18 04:48:05 2016// 18 | /ev_port.c/1.29/Thu Feb 18 04:48:05 2016// 19 | /ev_select.c/1.56/Thu Feb 18 04:48:05 2016// 20 | /ev_vars.h/1.58/Tue Sep 9 21:51:35 2014// 21 | /ev_win32.c/1.18/Thu Nov 12 07:02:37 2015// 22 | /ev_wrap.h/1.38/Tue Nov 6 20:56:50 2012// 23 | /event.c/1.52/Mon Apr 2 23:14:41 2012// 24 | /event.h/1.26/Mon Apr 2 23:15:27 2012// 25 | /event_compat.h/1.8/Wed Feb 16 08:02:51 2011// 26 | /import_libevent/1.29/Tue Apr 15 04:34:07 2008// 27 | /libev.m4/1.16/Mon Oct 28 12:36:44 2013// 28 | /update_ev_c/1.2/Wed Jan 18 12:13:14 2012// 29 | /update_ev_wrap/1.6/Sun May 6 13:09:29 2012// 30 | /update_symbols/1.1/Wed Dec 19 01:59:29 2007// 31 | D 32 | -------------------------------------------------------------------------------- /libev/CVS/Repository: -------------------------------------------------------------------------------- 1 | libev 2 | -------------------------------------------------------------------------------- /libev/CVS/Root: -------------------------------------------------------------------------------- 1 | :pserver:anonymous@cvs.schmorp.de/schmorpforge 2 | -------------------------------------------------------------------------------- /libev/Changes: -------------------------------------------------------------------------------- 1 | Revision history for libev, a high-performance and full-featured event loop. 2 | 3 | - ANDROID => __ANDROID__ (reported by enh@google.com). 4 | - disable epoll_create1 on android because it has broken header files 5 | and google is unwilling to fix them (reported by enh@google.com). 6 | 7 | 4.24 Wed Dec 28 05:19:55 CET 2016 8 | - bump version to 4.24, as the release tarball inexplicably 9 | didn't have the right version in ev.h, even though the cvs-tagged 10 | version did have the right one (reported by Ales Teska). 11 | 12 | 4.23 Wed Nov 16 18:23:41 CET 2016 13 | - move some declarations at the beginning to help certain retarded 14 | microsoft compilers, even though their documentation claims 15 | otherwise (reported by Ruslan Osmanov). 16 | 17 | 4.22 Sun Dec 20 22:11:50 CET 2015 18 | - when epoll detects unremovable fds in the fd set, rebuild 19 | only the epoll descriptor, not the signal pipe, to avoid 20 | SIGPIPE in ev_async_send. This doesn't solve it on fork, 21 | so document what needs to be done in ev_loop_fork 22 | (analyzed by Benjamin Mahler). 23 | - remove superfluous sys/timeb.h include on win32 24 | (analyzed by Jason Madden). 25 | - updated libecb. 26 | 27 | 4.20 Sat Jun 20 13:01:43 CEST 2015 28 | - prefer noexcept over throw () with C++ 11. 29 | - update ecb.h due to incompatibilities with c11. 30 | - fix a potential aliasing issue when reading and writing 31 | watcher callbacks. 32 | 33 | 4.19 Thu Sep 25 08:18:25 CEST 2014 34 | - ev.h wasn't valid C++ anymore, which tripped compilers other than 35 | clang, msvc or gcc (analyzed by Raphael 'kena' Poss). Unfortunately, 36 | C++ doesn't support typedefs for function pointers fully, so the affected 37 | declarations have to spell out the types each time. 38 | - when not using autoconf, tighten the check for clock_gettime and related 39 | functionality. 40 | 41 | 4.18 Fri Sep 5 17:55:26 CEST 2014 42 | - events on files were not always generated properly with the 43 | epoll backend (testcase by Assaf Inbal). 44 | - mark event pipe fd as cloexec after a fork (analyzed by Sami Farin). 45 | - (ecb) support m68k, m88k and sh (patch by Miod Vallat). 46 | - use a reasonable fallback for EV_NSIG instead of erroring out 47 | when we can't detect the signal set size. 48 | - in the absence of autoconf, do not use the clock syscall 49 | on glibc >= 2.17 (avoids the syscall AND -lrt on systems 50 | doing clock_gettime in userspace). 51 | - ensure extern "C" function pointers are used for externally-visible 52 | loop callbacks (not watcher callbacks yet). 53 | - (ecb) work around memory barriers and volatile apparently both being 54 | broken in visual studio 2008 and later (analysed and patch by Nicolas Noble). 55 | 56 | 4.15 Fri Mar 1 12:04:50 CET 2013 57 | - destroying a non-default loop would stop the global waitpid 58 | watcher (Denis Bilenko). 59 | - queueing pending watchers of higher priority from a watcher now invokes 60 | them in a timely fashion (reported by Denis Bilenko). 61 | - add throw() to all libev functions that cannot throw exceptions, for 62 | further code size decrease when compiling for C++. 63 | - add throw () to callbacks that must not throw exceptions (allocator, 64 | syserr, loop acquire/release, periodic reschedule cbs). 65 | - fix event_base_loop return code, add event_get_callback, event_base_new, 66 | event_base_get_method calls to improve libevent 1.x emulation and add 67 | some libevent 2.x functionality (based on a patch by Jeff Davey). 68 | - add more memory fences to fix a bug reported by Jeff Davey. Better 69 | be overfenced than underprotected. 70 | - ev_run now returns a boolean status (true meaning watchers are 71 | still active). 72 | - ev_once: undef EV_ERROR in ev_kqueue.c, to avoid clashing with 73 | libev's EV_ERROR (reported by 191919). 74 | - (ecb) add memory fence support for xlC (Darin McBride). 75 | - (ecb) add memory fence support for gcc-mips (Anton Kirilov). 76 | - (ecb) add memory fence support for gcc-alpha (Christian Weisgerber). 77 | - work around some kernels losing file descriptors by leaking 78 | the kqueue descriptor in the child. 79 | - work around linux inotify not reporting IN_ATTRIB changes for directories 80 | in many cases. 81 | - include sys/syscall.h instead of plain syscall.h. 82 | - check for io watcher loops in ev_verify, check for the most 83 | common reported usage bug in ev_io_start. 84 | - choose socket vs. WSASocket at compiletime using EV_USE_WSASOCKET. 85 | - always use WSASend/WSARecv directly on windows, hoping that this 86 | works in all cases (unlike read/write/send/recv...). 87 | - try to detect signals around a fork faster (test program by 88 | Denis Bilenko). 89 | - work around recent glibc versions that leak memory in realloc. 90 | - rename ev::embed::set to ev::embed::set_embed to avoid clashing 91 | the watcher base set (loop) method. 92 | - rewrite the async/signal pipe logic to always keep a valid fd, which 93 | simplifies (and hopefully correctifies :) the race checking 94 | on fork, at the cost of one extra fd. 95 | - add fat, msdos, jffs2, ramfs, ntfs and btrfs to the list of 96 | inotify-supporting filesystems. 97 | - move orig_CFLAGS assignment to after AC_INIT, as newer autoconf 98 | versions ignore it before 99 | (https://bugzilla.redhat.com/show_bug.cgi?id=908096). 100 | - add some untested android support. 101 | - enum expressions must be of type int (reported by Juan Pablo L). 102 | 103 | 4.11 Sat Feb 4 19:52:39 CET 2012 104 | - INCOMPATIBLE CHANGE: ev_timer_again now clears the pending status, as 105 | was documented already, but not implemented in the repeating case. 106 | - new compiletime symbols: EV_NO_SMP and EV_NO_THREADS. 107 | - fix a race where the workaround against the epoll fork bugs 108 | caused signals to not be handled anymore. 109 | - correct backend_fudge for most backends, and implement a windows 110 | specific workaround to avoid looping because we call both 111 | select and Sleep, both with different time resolutions. 112 | - document range and guarantees of ev_sleep. 113 | - document reasonable ranges for periodics interval and offset. 114 | - rename backend_fudge to backend_mintime to avoid future confusion :) 115 | - change the default periodic reschedule function to hopefully be more 116 | exact and correct even in corner cases or in the far future. 117 | - do not rely on -lm anymore: use it when available but use our 118 | own floor () if it is missing. This should make it easier to embed, 119 | as no external libraries are required. 120 | - strategically import macros from libecb and mark rarely-used functions 121 | as cache-cold (saving almost 2k code size on typical amd64 setups). 122 | - add Symbols.ev and Symbols.event files, that were missing. 123 | - fix backend_mintime value for epoll (was 1/1024, is 1/1000 now). 124 | - fix #3 "be smart about timeouts" to not "deadlock" when 125 | timeout == now, also improve the section overall. 126 | - avoid "AVOIDING FINISHING BEFORE RETURNING" idiom. 127 | - support new EV_API_STATIC mode to make all libev symbols 128 | static. 129 | - supply default CFLAGS of -g -O3 with gcc when original CFLAGS 130 | were empty. 131 | 132 | 4.04 Wed Feb 16 09:01:51 CET 2011 133 | - fix two problems in the native win32 backend, where reuse of fd's 134 | with different underlying handles caused handles not to be removed 135 | or added to the select set (analyzed and tested by Bert Belder). 136 | - do no rely on ceil() in ev_e?poll.c. 137 | - backport libev to HP-UX versions before 11 v3. 138 | - configure did not detect nanosleep and clock_gettime properly when 139 | they are available in the libc (as opposed to -lrt). 140 | 141 | 4.03 Tue Jan 11 14:37:25 CET 2011 142 | - officially support polling files with all backends. 143 | - support files, /dev/zero etc. the same way as select in the epoll 144 | backend, by generating events on our own. 145 | - ports backend: work around solaris bug 6874410 and many related ones 146 | (EINTR, maybe more), with no performance loss (note that the solaris 147 | bug report is actually wrong, reality is far more bizarre and broken 148 | than that). 149 | - define EV_READ/EV_WRITE as macros in event.h, as some programs use 150 | #ifdef to test for them. 151 | - new (experimental) function: ev_feed_signal. 152 | - new (to become default) EVFLAG_NOSIGMASK flag. 153 | - new EVBACKEND_MASK symbol. 154 | - updated COMMON IDIOMS SECTION. 155 | 156 | 4.01 Fri Nov 5 21:51:29 CET 2010 157 | - automake fucked it up, apparently, --add-missing -f is not quite enough 158 | to make it update its files, so 4.00 didn't install ev++.h and 159 | event.h on make install. grrr. 160 | - ev_loop(count|depth) didn't return anything (Robin Haberkorn). 161 | - change EV_UNDEF to 0xffffffff to silence some overzealous compilers. 162 | - use "(libev) " prefix for all libev error messages now. 163 | 164 | 4.00 Mon Oct 25 12:32:12 CEST 2010 165 | - "PORTING FROM LIBEV 3.X TO 4.X" (in ev.pod) is recommended reading. 166 | - ev_embed_stop did not correctly stop the watcher (very good 167 | testcase by Vladimir Timofeev). 168 | - ev_run will now always update the current loop time - it erroneously 169 | didn't when idle watchers were active, causing timers not to fire. 170 | - fix a bug where a timeout of zero caused the timer not to fire 171 | in the libevent emulation (testcase by Péter Szabó). 172 | - applied win32 fixes by Michael Lenaghan (also James Mansion). 173 | - replace EV_MINIMAL by EV_FEATURES. 174 | - prefer EPOLL_CTL_ADD over EPOLL_CTL_MOD in some more cases, as it 175 | seems the former is *much* faster than the latter. 176 | - linux kernel version detection (for inotify bug workarounds) 177 | did not work properly. 178 | - reduce the number of spurious wake-ups with the ports backend. 179 | - remove dependency on sys/queue.h on freebsd (patch by Vanilla Hsu). 180 | - do async init within ev_async_start, not ev_async_set, which avoids 181 | an API quirk where the set function must be called in the C++ API 182 | even when there is nothing to set. 183 | - add (undocumented) EV_ENABLE when adding events with kqueue, 184 | this might help with OS X, which seems to need it despite documenting 185 | not to need it (helpfully pointed out by Tilghman Lesher). 186 | - do not use poll by default on freebsd, it's broken (what isn't 187 | on freebsd...). 188 | - allow to embed epoll on kernels >= 2.6.32. 189 | - configure now prepends -O3, not appends it, so one can still 190 | override it. 191 | - ev.pod: greatly expanded the portability section, added a porting 192 | section, a description of watcher states and made lots of minor fixes. 193 | - disable poll backend on AIX, the poll header spams the namespace 194 | and it's not worth working around dead platforms (reported 195 | and analyzed by Aivars Kalvans). 196 | - improve header file compatibility of the standalone eventfd code 197 | in an obscure case. 198 | - implement EV_AVOID_STDIO option. 199 | - do not use sscanf to parse linux version number (smaller, faster, 200 | no sscanf dependency). 201 | - new EV_CHILD_ENABLE and EV_SIGNAL_ENABLE configurable settings. 202 | - update libev.m4 HAVE_CLOCK_SYSCALL test for newer glibcs. 203 | - add section on accept() problems to the manpage. 204 | - rename EV_TIMEOUT to EV_TIMER. 205 | - rename ev_loop_count/depth/verify/loop/unloop. 206 | - remove ev_default_destroy and ev_default_fork. 207 | - switch to two-digit minor version. 208 | - work around an apparent gentoo compiler bug. 209 | - define _DARWIN_UNLIMITED_SELECT. just so. 210 | - use enum instead of #define for most constants. 211 | - improve compatibility to older C++ compilers. 212 | - (experimental) ev_run/ev_default_loop/ev_break/ev_loop_new have now 213 | default arguments when compiled as C++. 214 | - enable automake dependency tracking. 215 | - ev_loop_new no longer leaks memory when loop creation failed. 216 | - new ev_cleanup watcher type. 217 | 218 | 3.9 Thu Dec 31 07:59:59 CET 2009 219 | - signalfd is no longer used by default and has to be requested 220 | explicitly - this means that easy to catch bugs become hard to 221 | catch race conditions, but the users have spoken. 222 | - point out the unspecified signal mask in the documentation, and 223 | that this is a race condition regardless of EV_SIGNALFD. 224 | - backport inotify code to C89. 225 | - inotify file descriptors could leak into child processes. 226 | - ev_stat watchers could keep an erroneous extra ref on the loop, 227 | preventing exit when unregistering all watchers (testcases 228 | provided by ry@tinyclouds.org). 229 | - implement EV_WIN32_HANDLE_TO_FD and EV_WIN32_CLOSE_FD configuration 230 | symbols to make it easier for apps to do their own fd management. 231 | - support EV_IDLE_ENABLE being disabled in ev++.h 232 | (patch by Didier Spezia). 233 | - take advantage of inotify_init1, if available, to set cloexec/nonblock 234 | on fd creation, to avoid races. 235 | - the signal handling pipe wasn't always initialised under windows 236 | (analysed by lekma). 237 | - changed minimum glibc requirement from glibc 2.9 to 2.7, for 238 | signalfd. 239 | - add missing string.h include (Denis F. Latypoff). 240 | - only replace ev_stat.prev when we detect an actual difference, 241 | so prev is (almost) always different to attr. this might 242 | have caused the problems with 04_stat.t. 243 | - add ev::timer->remaining () method to C++ API. 244 | 245 | 3.8 Sun Aug 9 14:30:45 CEST 2009 246 | - incompatible change: do not necessarily reset signal handler 247 | to SIG_DFL when a sighandler is stopped. 248 | - ev_default_destroy did not properly free or zero some members, 249 | potentially causing crashes and memory corruption on repeated 250 | ev_default_destroy/ev_default_loop calls. 251 | - take advantage of signalfd on GNU/Linux systems. 252 | - document that the signal mask might be in an unspecified 253 | state when using libev's signal handling. 254 | - take advantage of some GNU/Linux calls to set cloexec/nonblock 255 | on fd creation, to avoid race conditions. 256 | 257 | 3.7 Fri Jul 17 16:36:32 CEST 2009 258 | - ev_unloop and ev_loop wrongly used a global variable to exit loops, 259 | instead of using a per-loop variable (bug caught by accident...). 260 | - the ev_set_io_collect_interval interpretation has changed. 261 | - add new functionality: ev_set_userdata, ev_userdata, 262 | ev_set_invoke_pending_cb, ev_set_loop_release_cb, 263 | ev_invoke_pending, ev_pending_count, together with a long example 264 | about thread locking. 265 | - add ev_timer_remaining (as requested by Denis F. Latypoff). 266 | - add ev_loop_depth. 267 | - calling ev_unloop in fork/prepare watchers will no longer poll 268 | for new events. 269 | - Denis F. Latypoff corrected many typos in example code snippets. 270 | - honor autoconf detection of EV_USE_CLOCK_SYSCALL, also double- 271 | check that the syscall number is available before trying to 272 | use it (reported by ry@tinyclouds). 273 | - use GetSystemTimeAsFileTime instead of _timeb on windows, for 274 | slightly higher accuracy. 275 | - properly declare ev_loop_verify and ev_now_update even when 276 | !EV_MULTIPLICITY. 277 | - do not compile in any priority code when EV_MAXPRI == EV_MINPRI. 278 | - support EV_MINIMAL==2 for a reduced API. 279 | - actually 0-initialise struct sigaction when installing signals. 280 | - add section on hibernate and stopped processes to ev_timer docs. 281 | 282 | 3.6 Tue Apr 28 02:49:30 CEST 2009 283 | - multiple timers becoming ready within an event loop iteration 284 | will be invoked in the "correct" order now. 285 | - do not leave the event loop early just because we have no active 286 | watchers, fixing a problem when embedding a kqueue loop 287 | that has active kernel events but no registered watchers 288 | (reported by blacksand blacksand). 289 | - correctly zero the idx values for arrays, so destroying and 290 | reinitialising the default loop actually works (patch by 291 | Malek Hadj-Ali). 292 | - implement ev_suspend and ev_resume. 293 | - new EV_CUSTOM revents flag for use by applications. 294 | - add documentation section about priorities. 295 | - add a glossary to the documentation. 296 | - extend the ev_fork description slightly. 297 | - optimize a jump out of call_pending. 298 | 299 | 3.53 Sun Feb 15 02:38:20 CET 2009 300 | - fix a bug in event pipe creation on win32 that would cause a 301 | failed assertion on event loop creation (patch by Malek Hadj-Ali). 302 | - probe for CLOCK_REALTIME support at runtime as well and fall 303 | back to gettimeofday if there is an error, to support older 304 | operating systems with newer header files/libraries. 305 | - prefer gettimeofday over clock_gettime with USE_CLOCK_SYSCALL 306 | (default most everywhere), otherwise not. 307 | 308 | 3.52 Wed Jan 7 21:43:02 CET 2009 309 | - fix compilation of select backend in fd_set mode when NFDBITS is 310 | missing (to get it to compile on QNX, reported by Rodrigo Campos). 311 | - better select-nfds handling when select backend is in fd_set mode. 312 | - diagnose fd_set overruns when select backend is in fd_set mode. 313 | - due to a thinko, instead of disabling everything but 314 | select on the borked OS X platform, everything but select was 315 | allowed (reported by Emanuele Giaquinta). 316 | - actually verify that local and remote port are matching in 317 | libev's socketpair emulation, which makes denial-of-service 318 | attacks harder (but not impossible - it's windows). Make sure 319 | it even works under vista, which thinks that getpeer/sockname 320 | should return fantasy port numbers. 321 | - include "libev" in all assertion messages for potentially 322 | clearer diagnostics. 323 | - event_get_version (libevent compatibility) returned 324 | a useless string instead of the expected version string 325 | (patch by W.C.A. Wijngaards). 326 | 327 | 3.51 Wed Dec 24 23:00:11 CET 2008 328 | - fix a bug where an inotify watcher was added twice, causing 329 | freezes on hash collisions (reported and analysed by Graham Leggett). 330 | - new config symbol, EV_USE_CLOCK_SYSCALL, to make libev use 331 | a direct syscall - slower, but no dependency on librt et al. 332 | - assume negative return values != -1 signals success of port_getn 333 | (http://cvs.epicsol.org/cgi/viewcvs.cgi/epic5/source/newio.c?rev=1.52) 334 | (no known failure reports, but it doesn't hurt). 335 | - fork detection in ev_embed now stops and restarts the watcher 336 | automatically. 337 | - EXPERIMENTAL: default the method to operator () in ev++.h, 338 | to make it nicer to use functors (requested by Benedek László). 339 | - fixed const object callbacks in ev++.h. 340 | - replaced loop_ref argument of watcher.set (loop) by a direct 341 | ev_loop * in ev++.h, to avoid clashes with functor patch. 342 | - do not try to watch the empty string via inotify. 343 | - inotify watchers could be leaked under certain circumstances. 344 | - OS X 10.5 is actually even more broken than earlier versions, 345 | so fall back to select on that piece of garbage. 346 | - fixed some weirdness in the ev_embed documentation. 347 | 348 | 3.49 Wed Nov 19 11:26:53 CET 2008 349 | - ev_stat watchers will now use inotify as a mere hint on 350 | kernels <2.6.25, or if the filesystem is not in the 351 | "known to be good" list. 352 | - better mingw32 compatibility (it's not as borked as native win32) 353 | (analysed by Roger Pack). 354 | - include stdio.h in the example program, as too many people are 355 | confused by the weird C language otherwise. I guess the next thing 356 | I get told is that the "..." ellipses in the examples don't compile 357 | with their C compiler. 358 | 359 | 3.48 Thu Oct 30 09:02:37 CET 2008 360 | - further optimise away the EPOLL_CTL_ADD/MOD combo in the epoll 361 | backend by assuming the kernel event mask hasn't changed if 362 | ADD fails with EEXIST. 363 | - work around spurious event notification bugs in epoll by using 364 | a 32-bit generation counter. recreate kernel state if we receive 365 | spurious notifications or unwanted events. this is very costly, 366 | but I didn't come up with this horrible design. 367 | - use memset to initialise most arrays now and do away with the 368 | init functions. 369 | - expand time-out strategies into a "Be smart about timeouts" section. 370 | - drop the "struct" from all ev_watcher declarations in the 371 | documentation and did other clarifications (yeah, it was a mistake 372 | to have a struct AND a function called ev_loop). 373 | - fix a bug where ev_default would not initialise the default 374 | loop again after it was destroyed with ev_default_destroy. 375 | - rename syserr to ev_syserr to avoid name clashes when embedding, 376 | do similar changes for event.c. 377 | 378 | 3.45 Tue Oct 21 21:59:26 CEST 2008 379 | - disable inotify usage on linux <2.6.25, as it is broken 380 | (reported by Yoann Vandoorselaere). 381 | - ev_stat erroneously would try to add inotify watchers 382 | even when inotify wasn't available (this should only 383 | have a performance impact). 384 | - ev_once now passes both timeout and io to the callback if both 385 | occur concurrently, instead of giving timeouts precedence. 386 | - disable EV_USE_INOTIFY when sys/inotify.h is too old. 387 | 388 | 3.44 Mon Sep 29 05:18:39 CEST 2008 389 | - embed watchers now automatically invoke ev_loop_fork on the 390 | embedded loop when the parent loop forks. 391 | - new function: ev_now_update (loop). 392 | - verify_watcher was not marked static. 393 | - improve the "associating..." manpage section. 394 | - documentation tweaks here and there. 395 | 396 | 3.43 Sun Jul 6 05:34:41 CEST 2008 397 | - include more include files on windows to get struct _stati64 398 | (reported by Chris Hulbert, but doesn't quite fix his issue). 399 | - add missing #include in ev.c on windows (reported by 400 | Matt Tolton). 401 | 402 | 3.42 Tue Jun 17 12:12:07 CEST 2008 403 | - work around yet another windows bug: FD_SET actually adds fd's 404 | multiple times to the fd_*SET*, despite official MSN docs claiming 405 | otherwise. Reported and well-analysed by Matt Tolton. 406 | - define NFDBITS to 0 when EV_SELECT_IS_WINSOCKET to make it compile 407 | (reported any analysed by Chris Hulbert). 408 | - fix a bug in ev_ebadf (this function is only used to catch 409 | programming errors in the libev user). reported by Matt Tolton. 410 | - fix a bug in fd_intern on win32 (could lead to compile errors 411 | under some circumstances, but would work correctly if it compiles). 412 | reported by Matt Tolton. 413 | - (try to) work around missing lstat on windows. 414 | - pass in the write fd set as except fd set under windows. windows 415 | is so uncontrollably lame that it requires this. this means that 416 | switching off oobinline is not supported (but tcp/ip doesn't 417 | have oob, so that would be stupid anyways. 418 | - use posix module symbol to auto-detect monotonic clock presence 419 | and some other default values. 420 | 421 | 3.41 Fri May 23 18:42:54 CEST 2008 422 | - work around an obscure bug in winsocket select: if you 423 | provide only empty fd sets then select returns WSAEINVAL. how sucky. 424 | - improve timer scheduling stability and reduce use of time_epsilon. 425 | - use 1-based 2-heap for EV_MINIMAL, simplifies code, reduces 426 | codesize and makes for better cache-efficiency. 427 | - use 3-based 4-heap for !EV_MINIMAL. this makes better use 428 | of cpu cache lines and gives better growth behaviour than 429 | 2-based heaps. 430 | - cache timestamp within heap for !EV_MINIMAL, to avoid random 431 | memory accesses. 432 | - document/add EV_USE_4HEAP and EV_HEAP_CACHE_AT. 433 | - fix a potential aliasing issue in ev_timer_again. 434 | - add/document ev_periodic_at, retract direct access to ->at. 435 | - improve ev_stat docs. 436 | - add portability requirements section. 437 | - fix manpage headers etc. 438 | - normalise WSA error codes to lower range on windows. 439 | - add consistency check code that can be called automatically 440 | or on demand to check for internal structures (ev_loop_verify). 441 | 442 | 3.31 Wed Apr 16 20:45:04 CEST 2008 443 | - added last minute fix for ev_poll.c by Brandon Black. 444 | 445 | 3.3 Wed Apr 16 19:04:10 CEST 2008 446 | - event_base_loopexit should return 0 on success 447 | (W.C.A. Wijngaards). 448 | - added linux eventfd support. 449 | - try to autodetect epoll and inotify support 450 | by libc header version if not using autoconf. 451 | - new symbols: EV_DEFAULT_UC and EV_DEFAULT_UC_. 452 | - declare functions defined in ev.h as inline if 453 | C99 or gcc are available. 454 | - enable inlining with gcc versions 2 and 3. 455 | - work around broken poll implementations potentially 456 | not clearing revents field in ev_poll (Brandon Black) 457 | (no such systems are known at this time). 458 | - work around a bug in realloc on openbsd and darwin, 459 | also makes the erroneous valgrind complaints 460 | go away (noted by various people). 461 | - fix ev_async_pending, add c++ wrapper for ev_async 462 | (based on patch sent by Johannes Deisenhofer). 463 | - add sensible set method to ev::embed. 464 | - made integer constants type int in ev.h. 465 | 466 | 3.2 Wed Apr 2 17:11:19 CEST 2008 467 | - fix a 64 bit overflow issue in the select backend, 468 | by using fd_mask instead of int for the mask. 469 | - rename internal sighandler to avoid clash with very old perls. 470 | - entering ev_loop will not clear the ONESHOT or NONBLOCKING 471 | flags of any outer loops anymore. 472 | - add ev_async_pending. 473 | 474 | 3.1 Thu Mar 13 13:45:22 CET 2008 475 | - implement ev_async watchers. 476 | - only initialise signal pipe on demand. 477 | - make use of sig_atomic_t configurable. 478 | - improved documentation. 479 | 480 | 3.0 Mon Jan 28 13:14:47 CET 2008 481 | - API/ABI bump to version 3.0. 482 | - ev++.h includes "ev.h" by default now, not . 483 | - slightly improved documentation. 484 | - speed up signal detection after a fork. 485 | - only optionally return trace status changed in ev_child 486 | watchers. 487 | - experimental (and undocumented) loop wrappers for ev++.h. 488 | 489 | 2.01 Tue Dec 25 08:04:41 CET 2007 490 | - separate Changes file. 491 | - fix ev_path_set => ev_stat_set typo. 492 | - remove event_compat.h from the libev tarball. 493 | - change how include files are found. 494 | - doc updates. 495 | - update licenses, explicitly allow for GPL relicensing. 496 | 497 | 2.0 Sat Dec 22 17:47:03 CET 2007 498 | - new ev_sleep, ev_set_(io|timeout)_collect_interval. 499 | - removed epoll from embeddable fd set. 500 | - fix embed watchers. 501 | - renamed ev_embed.loop to other. 502 | - added exported Symbol tables. 503 | - undefine member wrapper macros at the end of ev.c. 504 | - respect EV_H in ev++.h. 505 | 506 | 1.86 Tue Dec 18 02:36:57 CET 2007 507 | - fix memleak on loop destroy (not relevant for perl). 508 | 509 | 1.85 Fri Dec 14 20:32:40 CET 2007 510 | - fix some aliasing issues w.r.t. timers and periodics 511 | (not relevant for perl). 512 | 513 | (for historic versions refer to EV/Changes, found in the Perl interface) 514 | 515 | 0.1 Wed Oct 31 21:31:48 CET 2007 516 | - original version; hacked together in <24h. 517 | 518 | -------------------------------------------------------------------------------- /libev/LICENSE: -------------------------------------------------------------------------------- 1 | All files in libev are 2 | Copyright (c)2007,2008,2009,2010,2011,2012,2013 Marc Alexander Lehmann. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above 12 | copyright notice, this list of conditions and the following 13 | disclaimer in the documentation and/or other materials provided 14 | with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | 28 | Alternatively, the contents of this package may be used under the terms 29 | of the GNU General Public License ("GPL") version 2 or any later version, 30 | in which case the provisions of the GPL are applicable instead of the 31 | above. If you wish to allow the use of your version of this package only 32 | under the terms of the GPL and not to allow others to use your version of 33 | this file under the BSD license, indicate your decision by deleting the 34 | provisions above and replace them with the notice and other provisions 35 | required by the GPL in this and the other files of this package. If you do 36 | not delete the provisions above, a recipient may use your version of this 37 | file under either the BSD or the GPL. 38 | -------------------------------------------------------------------------------- /libev/Makefile.am: -------------------------------------------------------------------------------- 1 | AUTOMAKE_OPTIONS = foreign 2 | 3 | VERSION_INFO = 4:0:0 4 | 5 | EXTRA_DIST = LICENSE Changes libev.m4 autogen.sh \ 6 | ev_vars.h ev_wrap.h \ 7 | ev_epoll.c ev_select.c ev_poll.c ev_kqueue.c ev_port.c ev_win32.c \ 8 | ev.3 ev.pod Symbols.ev Symbols.event 9 | 10 | man_MANS = ev.3 11 | 12 | include_HEADERS = ev.h ev++.h event.h 13 | 14 | lib_LTLIBRARIES = libev.la 15 | 16 | libev_la_SOURCES = ev.c event.c 17 | libev_la_LDFLAGS = -version-info $(VERSION_INFO) 18 | 19 | ev.3: ev.pod 20 | pod2man -n LIBEV -r "libev-$(VERSION)" -c "libev - high performance full featured event loop" -s3 <$< >$@ 21 | -------------------------------------------------------------------------------- /libev/README: -------------------------------------------------------------------------------- 1 | libev is a high-performance event loop/event model with lots of features. 2 | (see benchmark at http://libev.schmorp.de/bench.html) 3 | 4 | 5 | ABOUT 6 | 7 | Homepage: http://software.schmorp.de/pkg/libev 8 | Mailinglist: libev@lists.schmorp.de 9 | http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev 10 | Library Documentation: http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod 11 | 12 | Libev is modelled (very losely) after libevent and the Event perl 13 | module, but is faster, scales better and is more correct, and also more 14 | featureful. And also smaller. Yay. 15 | 16 | Some of the specialties of libev not commonly found elsewhere are: 17 | 18 | - extensive and detailed, readable documentation (not doxygen garbage). 19 | - fully supports fork, can detect fork in various ways and automatically 20 | re-arms kernel mechanisms that do not support fork. 21 | - highly optimised select, poll, epoll, kqueue and event ports backends. 22 | - filesystem object (path) watching (with optional linux inotify support). 23 | - wallclock-based times (using absolute time, cron-like). 24 | - relative timers/timeouts (handle time jumps). 25 | - fast intra-thread communication between multiple 26 | event loops (with optional fast linux eventfd backend). 27 | - extremely easy to embed (fully documented, no dependencies, 28 | autoconf supported but optional). 29 | - very small codebase, no bloated library, simple code. 30 | - fully extensible by being able to plug into the event loop, 31 | integrate other event loops, integrate other event loop users. 32 | - very little memory use (small watchers, small event loop data). 33 | - optional C++ interface allowing method and function callbacks 34 | at no extra memory or runtime overhead. 35 | - optional Perl interface with similar characteristics (capable 36 | of running Glib/Gtk2 on libev). 37 | - support for other languages (multiple C++ interfaces, D, Ruby, 38 | Python) available from third-parties. 39 | 40 | Examples of programs that embed libev: the EV perl module, node.js, 41 | auditd, rxvt-unicode, gvpe (GNU Virtual Private Ethernet), the 42 | Deliantra MMORPG server (http://www.deliantra.net/), Rubinius (a 43 | next-generation Ruby VM), the Ebb web server, the Rev event toolkit. 44 | 45 | 46 | CONTRIBUTORS 47 | 48 | libev was written and designed by Marc Lehmann and Emanuele Giaquinta. 49 | 50 | The following people sent in patches or made other noteworthy 51 | contributions to the design (for minor patches, see the Changes 52 | file. If I forgot to include you, please shout at me, it was an 53 | accident): 54 | 55 | W.C.A. Wijngaards 56 | Christopher Layne 57 | Chris Brody 58 | 59 | -------------------------------------------------------------------------------- /libev/README.embed: -------------------------------------------------------------------------------- 1 | This file is now included in the main libev documentation, see 2 | 3 | http://cvs.schmorp.de/libev/ev.html 4 | -------------------------------------------------------------------------------- /libev/Symbols.ev: -------------------------------------------------------------------------------- 1 | ev_async_send 2 | ev_async_start 3 | ev_async_stop 4 | ev_backend 5 | ev_break 6 | ev_check_start 7 | ev_check_stop 8 | ev_child_start 9 | ev_child_stop 10 | ev_cleanup_start 11 | ev_cleanup_stop 12 | ev_clear_pending 13 | ev_default_loop 14 | ev_default_loop_ptr 15 | ev_depth 16 | ev_embed_start 17 | ev_embed_stop 18 | ev_embed_sweep 19 | ev_embeddable_backends 20 | ev_feed_event 21 | ev_feed_fd_event 22 | ev_feed_signal 23 | ev_feed_signal_event 24 | ev_fork_start 25 | ev_fork_stop 26 | ev_idle_start 27 | ev_idle_stop 28 | ev_invoke 29 | ev_invoke_pending 30 | ev_io_start 31 | ev_io_stop 32 | ev_iteration 33 | ev_loop_destroy 34 | ev_loop_fork 35 | ev_loop_new 36 | ev_now 37 | ev_now_update 38 | ev_once 39 | ev_pending_count 40 | ev_periodic_again 41 | ev_periodic_start 42 | ev_periodic_stop 43 | ev_prepare_start 44 | ev_prepare_stop 45 | ev_recommended_backends 46 | ev_ref 47 | ev_resume 48 | ev_run 49 | ev_set_allocator 50 | ev_set_invoke_pending_cb 51 | ev_set_io_collect_interval 52 | ev_set_loop_release_cb 53 | ev_set_syserr_cb 54 | ev_set_timeout_collect_interval 55 | ev_set_userdata 56 | ev_signal_start 57 | ev_signal_stop 58 | ev_sleep 59 | ev_stat_start 60 | ev_stat_stat 61 | ev_stat_stop 62 | ev_supported_backends 63 | ev_suspend 64 | ev_time 65 | ev_timer_again 66 | ev_timer_remaining 67 | ev_timer_start 68 | ev_timer_stop 69 | ev_unref 70 | ev_userdata 71 | ev_verify 72 | ev_version_major 73 | ev_version_minor 74 | -------------------------------------------------------------------------------- /libev/Symbols.event: -------------------------------------------------------------------------------- 1 | event_active 2 | event_add 3 | event_base_dispatch 4 | event_base_free 5 | event_base_get_method 6 | event_base_loop 7 | event_base_loopexit 8 | event_base_new 9 | event_base_once 10 | event_base_priority_init 11 | event_base_set 12 | event_del 13 | event_dispatch 14 | event_get_callback 15 | event_get_method 16 | event_get_version 17 | event_init 18 | event_loop 19 | event_loopexit 20 | event_once 21 | event_pending 22 | event_priority_init 23 | event_priority_set 24 | event_set 25 | -------------------------------------------------------------------------------- /libev/autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | autoreconf --install --symlink --force 4 | -------------------------------------------------------------------------------- /libev/configure.ac: -------------------------------------------------------------------------------- 1 | AC_INIT 2 | 3 | orig_CFLAGS="$CFLAGS" 4 | 5 | AC_CONFIG_SRCDIR([ev_epoll.c]) 6 | 7 | dnl also update ev.h! 8 | AM_INIT_AUTOMAKE(libev,4.24) 9 | AC_CONFIG_HEADERS([config.h]) 10 | AM_MAINTAINER_MODE 11 | 12 | AC_PROG_CC 13 | 14 | dnl Supply default CFLAGS, if not specified 15 | if test -z "$orig_CFLAGS"; then 16 | if test x$GCC = xyes; then 17 | CFLAGS="-g -O3" 18 | fi 19 | fi 20 | 21 | AC_PROG_INSTALL 22 | AC_PROG_LIBTOOL 23 | 24 | m4_include([libev.m4]) 25 | 26 | AC_CONFIG_FILES([Makefile]) 27 | AC_OUTPUT 28 | -------------------------------------------------------------------------------- /libev/ev++.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libev simple C++ wrapper classes 3 | * 4 | * Copyright (c) 2007,2008,2010 Marc Alexander Lehmann 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without modifica- 8 | * tion, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- 19 | * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 20 | * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- 21 | * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- 25 | * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 26 | * OF THE POSSIBILITY OF SUCH DAMAGE. 27 | * 28 | * Alternatively, the contents of this file may be used under the terms of 29 | * the GNU General Public License ("GPL") version 2 or any later version, 30 | * in which case the provisions of the GPL are applicable instead of 31 | * the above. If you wish to allow the use of your version of this file 32 | * only under the terms of the GPL and not to allow others to use your 33 | * version of this file under the BSD license, indicate your decision 34 | * by deleting the provisions above and replace them with the notice 35 | * and other provisions required by the GPL. If you do not delete the 36 | * provisions above, a recipient may use your version of this file under 37 | * either the BSD or the GPL. 38 | */ 39 | 40 | #ifndef EVPP_H__ 41 | #define EVPP_H__ 42 | 43 | #ifdef EV_H 44 | # include EV_H 45 | #else 46 | # include "ev.h" 47 | #endif 48 | 49 | #ifndef EV_USE_STDEXCEPT 50 | # define EV_USE_STDEXCEPT 1 51 | #endif 52 | 53 | #if EV_USE_STDEXCEPT 54 | # include 55 | #endif 56 | 57 | namespace ev { 58 | 59 | typedef ev_tstamp tstamp; 60 | 61 | enum { 62 | UNDEF = EV_UNDEF, 63 | NONE = EV_NONE, 64 | READ = EV_READ, 65 | WRITE = EV_WRITE, 66 | #if EV_COMPAT3 67 | TIMEOUT = EV_TIMEOUT, 68 | #endif 69 | TIMER = EV_TIMER, 70 | PERIODIC = EV_PERIODIC, 71 | SIGNAL = EV_SIGNAL, 72 | CHILD = EV_CHILD, 73 | STAT = EV_STAT, 74 | IDLE = EV_IDLE, 75 | CHECK = EV_CHECK, 76 | PREPARE = EV_PREPARE, 77 | FORK = EV_FORK, 78 | ASYNC = EV_ASYNC, 79 | EMBED = EV_EMBED, 80 | # undef ERROR // some systems stupidly #define ERROR 81 | ERROR = EV_ERROR 82 | }; 83 | 84 | enum 85 | { 86 | AUTO = EVFLAG_AUTO, 87 | NOENV = EVFLAG_NOENV, 88 | FORKCHECK = EVFLAG_FORKCHECK, 89 | 90 | SELECT = EVBACKEND_SELECT, 91 | POLL = EVBACKEND_POLL, 92 | EPOLL = EVBACKEND_EPOLL, 93 | KQUEUE = EVBACKEND_KQUEUE, 94 | DEVPOLL = EVBACKEND_DEVPOLL, 95 | PORT = EVBACKEND_PORT 96 | }; 97 | 98 | enum 99 | { 100 | #if EV_COMPAT3 101 | NONBLOCK = EVLOOP_NONBLOCK, 102 | ONESHOT = EVLOOP_ONESHOT, 103 | #endif 104 | NOWAIT = EVRUN_NOWAIT, 105 | ONCE = EVRUN_ONCE 106 | }; 107 | 108 | enum how_t 109 | { 110 | ONE = EVBREAK_ONE, 111 | ALL = EVBREAK_ALL 112 | }; 113 | 114 | struct bad_loop 115 | #if EV_USE_STDEXCEPT 116 | : std::runtime_error 117 | #endif 118 | { 119 | #if EV_USE_STDEXCEPT 120 | bad_loop () 121 | : std::runtime_error ("libev event loop cannot be initialized, bad value of LIBEV_FLAGS?") 122 | { 123 | } 124 | #endif 125 | }; 126 | 127 | #ifdef EV_AX 128 | # undef EV_AX 129 | #endif 130 | 131 | #ifdef EV_AX_ 132 | # undef EV_AX_ 133 | #endif 134 | 135 | #if EV_MULTIPLICITY 136 | # define EV_AX raw_loop 137 | # define EV_AX_ raw_loop, 138 | #else 139 | # define EV_AX 140 | # define EV_AX_ 141 | #endif 142 | 143 | struct loop_ref 144 | { 145 | loop_ref (EV_P) throw () 146 | #if EV_MULTIPLICITY 147 | : EV_AX (EV_A) 148 | #endif 149 | { 150 | } 151 | 152 | bool operator == (const loop_ref &other) const throw () 153 | { 154 | #if EV_MULTIPLICITY 155 | return EV_AX == other.EV_AX; 156 | #else 157 | return true; 158 | #endif 159 | } 160 | 161 | bool operator != (const loop_ref &other) const throw () 162 | { 163 | #if EV_MULTIPLICITY 164 | return ! (*this == other); 165 | #else 166 | return false; 167 | #endif 168 | } 169 | 170 | #if EV_MULTIPLICITY 171 | bool operator == (const EV_P) const throw () 172 | { 173 | return this->EV_AX == EV_A; 174 | } 175 | 176 | bool operator != (const EV_P) const throw () 177 | { 178 | return ! (*this == EV_A); 179 | } 180 | 181 | operator struct ev_loop * () const throw () 182 | { 183 | return EV_AX; 184 | } 185 | 186 | operator const struct ev_loop * () const throw () 187 | { 188 | return EV_AX; 189 | } 190 | 191 | bool is_default () const throw () 192 | { 193 | return EV_AX == ev_default_loop (0); 194 | } 195 | #endif 196 | 197 | #if EV_COMPAT3 198 | void loop (int flags = 0) 199 | { 200 | ev_run (EV_AX_ flags); 201 | } 202 | 203 | void unloop (how_t how = ONE) throw () 204 | { 205 | ev_break (EV_AX_ how); 206 | } 207 | #endif 208 | 209 | void run (int flags = 0) 210 | { 211 | ev_run (EV_AX_ flags); 212 | } 213 | 214 | void break_loop (how_t how = ONE) throw () 215 | { 216 | ev_break (EV_AX_ how); 217 | } 218 | 219 | void post_fork () throw () 220 | { 221 | ev_loop_fork (EV_AX); 222 | } 223 | 224 | unsigned int backend () const throw () 225 | { 226 | return ev_backend (EV_AX); 227 | } 228 | 229 | tstamp now () const throw () 230 | { 231 | return ev_now (EV_AX); 232 | } 233 | 234 | void ref () throw () 235 | { 236 | ev_ref (EV_AX); 237 | } 238 | 239 | void unref () throw () 240 | { 241 | ev_unref (EV_AX); 242 | } 243 | 244 | #if EV_FEATURE_API 245 | unsigned int iteration () const throw () 246 | { 247 | return ev_iteration (EV_AX); 248 | } 249 | 250 | unsigned int depth () const throw () 251 | { 252 | return ev_depth (EV_AX); 253 | } 254 | 255 | void set_io_collect_interval (tstamp interval) throw () 256 | { 257 | ev_set_io_collect_interval (EV_AX_ interval); 258 | } 259 | 260 | void set_timeout_collect_interval (tstamp interval) throw () 261 | { 262 | ev_set_timeout_collect_interval (EV_AX_ interval); 263 | } 264 | #endif 265 | 266 | // function callback 267 | void once (int fd, int events, tstamp timeout, void (*cb)(int, void *), void *arg = 0) throw () 268 | { 269 | ev_once (EV_AX_ fd, events, timeout, cb, arg); 270 | } 271 | 272 | // method callback 273 | template 274 | void once (int fd, int events, tstamp timeout, K *object) throw () 275 | { 276 | once (fd, events, timeout, method_thunk, object); 277 | } 278 | 279 | // default method == operator () 280 | template 281 | void once (int fd, int events, tstamp timeout, K *object) throw () 282 | { 283 | once (fd, events, timeout, method_thunk, object); 284 | } 285 | 286 | template 287 | static void method_thunk (int revents, void *arg) 288 | { 289 | (static_cast(arg)->*method) 290 | (revents); 291 | } 292 | 293 | // no-argument method callback 294 | template 295 | void once (int fd, int events, tstamp timeout, K *object) throw () 296 | { 297 | once (fd, events, timeout, method_noargs_thunk, object); 298 | } 299 | 300 | template 301 | static void method_noargs_thunk (int revents, void *arg) 302 | { 303 | (static_cast(arg)->*method) 304 | (); 305 | } 306 | 307 | // simpler function callback 308 | template 309 | void once (int fd, int events, tstamp timeout) throw () 310 | { 311 | once (fd, events, timeout, simpler_func_thunk); 312 | } 313 | 314 | template 315 | static void simpler_func_thunk (int revents, void *arg) 316 | { 317 | (*cb) 318 | (revents); 319 | } 320 | 321 | // simplest function callback 322 | template 323 | void once (int fd, int events, tstamp timeout) throw () 324 | { 325 | once (fd, events, timeout, simplest_func_thunk); 326 | } 327 | 328 | template 329 | static void simplest_func_thunk (int revents, void *arg) 330 | { 331 | (*cb) 332 | (); 333 | } 334 | 335 | void feed_fd_event (int fd, int revents) throw () 336 | { 337 | ev_feed_fd_event (EV_AX_ fd, revents); 338 | } 339 | 340 | void feed_signal_event (int signum) throw () 341 | { 342 | ev_feed_signal_event (EV_AX_ signum); 343 | } 344 | 345 | #if EV_MULTIPLICITY 346 | struct ev_loop* EV_AX; 347 | #endif 348 | 349 | }; 350 | 351 | #if EV_MULTIPLICITY 352 | struct dynamic_loop : loop_ref 353 | { 354 | 355 | dynamic_loop (unsigned int flags = AUTO) throw (bad_loop) 356 | : loop_ref (ev_loop_new (flags)) 357 | { 358 | if (!EV_AX) 359 | throw bad_loop (); 360 | } 361 | 362 | ~dynamic_loop () throw () 363 | { 364 | ev_loop_destroy (EV_AX); 365 | EV_AX = 0; 366 | } 367 | 368 | private: 369 | 370 | dynamic_loop (const dynamic_loop &); 371 | 372 | dynamic_loop & operator= (const dynamic_loop &); 373 | 374 | }; 375 | #endif 376 | 377 | struct default_loop : loop_ref 378 | { 379 | default_loop (unsigned int flags = AUTO) throw (bad_loop) 380 | #if EV_MULTIPLICITY 381 | : loop_ref (ev_default_loop (flags)) 382 | #endif 383 | { 384 | if ( 385 | #if EV_MULTIPLICITY 386 | !EV_AX 387 | #else 388 | !ev_default_loop (flags) 389 | #endif 390 | ) 391 | throw bad_loop (); 392 | } 393 | 394 | private: 395 | default_loop (const default_loop &); 396 | default_loop &operator = (const default_loop &); 397 | }; 398 | 399 | inline loop_ref get_default_loop () throw () 400 | { 401 | #if EV_MULTIPLICITY 402 | return ev_default_loop (0); 403 | #else 404 | return loop_ref (); 405 | #endif 406 | } 407 | 408 | #undef EV_AX 409 | #undef EV_AX_ 410 | 411 | #undef EV_PX 412 | #undef EV_PX_ 413 | #if EV_MULTIPLICITY 414 | # define EV_PX loop_ref EV_A 415 | # define EV_PX_ loop_ref EV_A_ 416 | #else 417 | # define EV_PX 418 | # define EV_PX_ 419 | #endif 420 | 421 | template 422 | struct base : ev_watcher 423 | { 424 | #if EV_MULTIPLICITY 425 | EV_PX; 426 | 427 | // loop set 428 | void set (EV_P) throw () 429 | { 430 | this->EV_A = EV_A; 431 | } 432 | #endif 433 | 434 | base (EV_PX) throw () 435 | #if EV_MULTIPLICITY 436 | : EV_A (EV_A) 437 | #endif 438 | { 439 | ev_init (this, 0); 440 | } 441 | 442 | void set_ (const void *data, void (*cb)(EV_P_ ev_watcher *w, int revents)) throw () 443 | { 444 | this->data = (void *)data; 445 | ev_set_cb (static_cast(this), cb); 446 | } 447 | 448 | // function callback 449 | template 450 | void set (void *data = 0) throw () 451 | { 452 | set_ (data, function_thunk); 453 | } 454 | 455 | template 456 | static void function_thunk (EV_P_ ev_watcher *w, int revents) 457 | { 458 | function 459 | (*static_cast(w), revents); 460 | } 461 | 462 | // method callback 463 | template 464 | void set (K *object) throw () 465 | { 466 | set_ (object, method_thunk); 467 | } 468 | 469 | // default method == operator () 470 | template 471 | void set (K *object) throw () 472 | { 473 | set_ (object, method_thunk); 474 | } 475 | 476 | template 477 | static void method_thunk (EV_P_ ev_watcher *w, int revents) 478 | { 479 | (static_cast(w->data)->*method) 480 | (*static_cast(w), revents); 481 | } 482 | 483 | // no-argument callback 484 | template 485 | void set (K *object) throw () 486 | { 487 | set_ (object, method_noargs_thunk); 488 | } 489 | 490 | template 491 | static void method_noargs_thunk (EV_P_ ev_watcher *w, int revents) 492 | { 493 | (static_cast(w->data)->*method) 494 | (); 495 | } 496 | 497 | void operator ()(int events = EV_UNDEF) 498 | { 499 | return 500 | ev_cb (static_cast(this)) 501 | (static_cast(this), events); 502 | } 503 | 504 | bool is_active () const throw () 505 | { 506 | return ev_is_active (static_cast(this)); 507 | } 508 | 509 | bool is_pending () const throw () 510 | { 511 | return ev_is_pending (static_cast(this)); 512 | } 513 | 514 | void feed_event (int revents) throw () 515 | { 516 | ev_feed_event (EV_A_ static_cast(this), revents); 517 | } 518 | }; 519 | 520 | inline tstamp now (EV_P) throw () 521 | { 522 | return ev_now (EV_A); 523 | } 524 | 525 | inline void delay (tstamp interval) throw () 526 | { 527 | ev_sleep (interval); 528 | } 529 | 530 | inline int version_major () throw () 531 | { 532 | return ev_version_major (); 533 | } 534 | 535 | inline int version_minor () throw () 536 | { 537 | return ev_version_minor (); 538 | } 539 | 540 | inline unsigned int supported_backends () throw () 541 | { 542 | return ev_supported_backends (); 543 | } 544 | 545 | inline unsigned int recommended_backends () throw () 546 | { 547 | return ev_recommended_backends (); 548 | } 549 | 550 | inline unsigned int embeddable_backends () throw () 551 | { 552 | return ev_embeddable_backends (); 553 | } 554 | 555 | inline void set_allocator (void *(*cb)(void *ptr, long size) throw ()) throw () 556 | { 557 | ev_set_allocator (cb); 558 | } 559 | 560 | inline void set_syserr_cb (void (*cb)(const char *msg) throw ()) throw () 561 | { 562 | ev_set_syserr_cb (cb); 563 | } 564 | 565 | #if EV_MULTIPLICITY 566 | #define EV_CONSTRUCT(cppstem,cstem) \ 567 | (EV_PX = get_default_loop ()) throw () \ 568 | : base (EV_A) \ 569 | { \ 570 | } 571 | #else 572 | #define EV_CONSTRUCT(cppstem,cstem) \ 573 | () throw () \ 574 | { \ 575 | } 576 | #endif 577 | 578 | /* using a template here would require quite a few more lines, 579 | * so a macro solution was chosen */ 580 | #define EV_BEGIN_WATCHER(cppstem,cstem) \ 581 | \ 582 | struct cppstem : base \ 583 | { \ 584 | void start () throw () \ 585 | { \ 586 | ev_ ## cstem ## _start (EV_A_ static_cast(this)); \ 587 | } \ 588 | \ 589 | void stop () throw () \ 590 | { \ 591 | ev_ ## cstem ## _stop (EV_A_ static_cast(this)); \ 592 | } \ 593 | \ 594 | cppstem EV_CONSTRUCT(cppstem,cstem) \ 595 | \ 596 | ~cppstem () throw () \ 597 | { \ 598 | stop (); \ 599 | } \ 600 | \ 601 | using base::set; \ 602 | \ 603 | private: \ 604 | \ 605 | cppstem (const cppstem &o); \ 606 | \ 607 | cppstem &operator =(const cppstem &o); \ 608 | \ 609 | public: 610 | 611 | #define EV_END_WATCHER(cppstem,cstem) \ 612 | }; 613 | 614 | EV_BEGIN_WATCHER (io, io) 615 | void set (int fd, int events) throw () 616 | { 617 | int active = is_active (); 618 | if (active) stop (); 619 | ev_io_set (static_cast(this), fd, events); 620 | if (active) start (); 621 | } 622 | 623 | void set (int events) throw () 624 | { 625 | int active = is_active (); 626 | if (active) stop (); 627 | ev_io_set (static_cast(this), fd, events); 628 | if (active) start (); 629 | } 630 | 631 | void start (int fd, int events) throw () 632 | { 633 | set (fd, events); 634 | start (); 635 | } 636 | EV_END_WATCHER (io, io) 637 | 638 | EV_BEGIN_WATCHER (timer, timer) 639 | void set (ev_tstamp after, ev_tstamp repeat = 0.) throw () 640 | { 641 | int active = is_active (); 642 | if (active) stop (); 643 | ev_timer_set (static_cast(this), after, repeat); 644 | if (active) start (); 645 | } 646 | 647 | void start (ev_tstamp after, ev_tstamp repeat = 0.) throw () 648 | { 649 | set (after, repeat); 650 | start (); 651 | } 652 | 653 | void again () throw () 654 | { 655 | ev_timer_again (EV_A_ static_cast(this)); 656 | } 657 | 658 | ev_tstamp remaining () 659 | { 660 | return ev_timer_remaining (EV_A_ static_cast(this)); 661 | } 662 | EV_END_WATCHER (timer, timer) 663 | 664 | #if EV_PERIODIC_ENABLE 665 | EV_BEGIN_WATCHER (periodic, periodic) 666 | void set (ev_tstamp at, ev_tstamp interval = 0.) throw () 667 | { 668 | int active = is_active (); 669 | if (active) stop (); 670 | ev_periodic_set (static_cast(this), at, interval, 0); 671 | if (active) start (); 672 | } 673 | 674 | void start (ev_tstamp at, ev_tstamp interval = 0.) throw () 675 | { 676 | set (at, interval); 677 | start (); 678 | } 679 | 680 | void again () throw () 681 | { 682 | ev_periodic_again (EV_A_ static_cast(this)); 683 | } 684 | EV_END_WATCHER (periodic, periodic) 685 | #endif 686 | 687 | #if EV_SIGNAL_ENABLE 688 | EV_BEGIN_WATCHER (sig, signal) 689 | void set (int signum) throw () 690 | { 691 | int active = is_active (); 692 | if (active) stop (); 693 | ev_signal_set (static_cast(this), signum); 694 | if (active) start (); 695 | } 696 | 697 | void start (int signum) throw () 698 | { 699 | set (signum); 700 | start (); 701 | } 702 | EV_END_WATCHER (sig, signal) 703 | #endif 704 | 705 | #if EV_CHILD_ENABLE 706 | EV_BEGIN_WATCHER (child, child) 707 | void set (int pid, int trace = 0) throw () 708 | { 709 | int active = is_active (); 710 | if (active) stop (); 711 | ev_child_set (static_cast(this), pid, trace); 712 | if (active) start (); 713 | } 714 | 715 | void start (int pid, int trace = 0) throw () 716 | { 717 | set (pid, trace); 718 | start (); 719 | } 720 | EV_END_WATCHER (child, child) 721 | #endif 722 | 723 | #if EV_STAT_ENABLE 724 | EV_BEGIN_WATCHER (stat, stat) 725 | void set (const char *path, ev_tstamp interval = 0.) throw () 726 | { 727 | int active = is_active (); 728 | if (active) stop (); 729 | ev_stat_set (static_cast(this), path, interval); 730 | if (active) start (); 731 | } 732 | 733 | void start (const char *path, ev_tstamp interval = 0.) throw () 734 | { 735 | stop (); 736 | set (path, interval); 737 | start (); 738 | } 739 | 740 | void update () throw () 741 | { 742 | ev_stat_stat (EV_A_ static_cast(this)); 743 | } 744 | EV_END_WATCHER (stat, stat) 745 | #endif 746 | 747 | #if EV_IDLE_ENABLE 748 | EV_BEGIN_WATCHER (idle, idle) 749 | void set () throw () { } 750 | EV_END_WATCHER (idle, idle) 751 | #endif 752 | 753 | #if EV_PREPARE_ENABLE 754 | EV_BEGIN_WATCHER (prepare, prepare) 755 | void set () throw () { } 756 | EV_END_WATCHER (prepare, prepare) 757 | #endif 758 | 759 | #if EV_CHECK_ENABLE 760 | EV_BEGIN_WATCHER (check, check) 761 | void set () throw () { } 762 | EV_END_WATCHER (check, check) 763 | #endif 764 | 765 | #if EV_EMBED_ENABLE 766 | EV_BEGIN_WATCHER (embed, embed) 767 | void set_embed (struct ev_loop *embedded_loop) throw () 768 | { 769 | int active = is_active (); 770 | if (active) stop (); 771 | ev_embed_set (static_cast(this), embedded_loop); 772 | if (active) start (); 773 | } 774 | 775 | void start (struct ev_loop *embedded_loop) throw () 776 | { 777 | set (embedded_loop); 778 | start (); 779 | } 780 | 781 | void sweep () 782 | { 783 | ev_embed_sweep (EV_A_ static_cast(this)); 784 | } 785 | EV_END_WATCHER (embed, embed) 786 | #endif 787 | 788 | #if EV_FORK_ENABLE 789 | EV_BEGIN_WATCHER (fork, fork) 790 | void set () throw () { } 791 | EV_END_WATCHER (fork, fork) 792 | #endif 793 | 794 | #if EV_ASYNC_ENABLE 795 | EV_BEGIN_WATCHER (async, async) 796 | void send () throw () 797 | { 798 | ev_async_send (EV_A_ static_cast(this)); 799 | } 800 | 801 | bool async_pending () throw () 802 | { 803 | return ev_async_pending (static_cast(this)); 804 | } 805 | EV_END_WATCHER (async, async) 806 | #endif 807 | 808 | #undef EV_PX 809 | #undef EV_PX_ 810 | #undef EV_CONSTRUCT 811 | #undef EV_BEGIN_WATCHER 812 | #undef EV_END_WATCHER 813 | } 814 | 815 | #endif 816 | 817 | -------------------------------------------------------------------------------- /libev/ev_epoll.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libev epoll fd activity backend 3 | * 4 | * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without modifica- 8 | * tion, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- 19 | * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 20 | * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- 21 | * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- 25 | * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 26 | * OF THE POSSIBILITY OF SUCH DAMAGE. 27 | * 28 | * Alternatively, the contents of this file may be used under the terms of 29 | * the GNU General Public License ("GPL") version 2 or any later version, 30 | * in which case the provisions of the GPL are applicable instead of 31 | * the above. If you wish to allow the use of your version of this file 32 | * only under the terms of the GPL and not to allow others to use your 33 | * version of this file under the BSD license, indicate your decision 34 | * by deleting the provisions above and replace them with the notice 35 | * and other provisions required by the GPL. If you do not delete the 36 | * provisions above, a recipient may use your version of this file under 37 | * either the BSD or the GPL. 38 | */ 39 | 40 | /* 41 | * general notes about epoll: 42 | * 43 | * a) epoll silently removes fds from the fd set. as nothing tells us 44 | * that an fd has been removed otherwise, we have to continually 45 | * "rearm" fds that we suspect *might* have changed (same 46 | * problem with kqueue, but much less costly there). 47 | * b) the fact that ADD != MOD creates a lot of extra syscalls due to a) 48 | * and seems not to have any advantage. 49 | * c) the inability to handle fork or file descriptors (think dup) 50 | * limits the applicability over poll, so this is not a generic 51 | * poll replacement. 52 | * d) epoll doesn't work the same as select with many file descriptors 53 | * (such as files). while not critical, no other advanced interface 54 | * seems to share this (rather non-unixy) limitation. 55 | * e) epoll claims to be embeddable, but in practise you never get 56 | * a ready event for the epoll fd (broken: <=2.6.26, working: >=2.6.32). 57 | * f) epoll_ctl returning EPERM means the fd is always ready. 58 | * 59 | * lots of "weird code" and complication handling in this file is due 60 | * to these design problems with epoll, as we try very hard to avoid 61 | * epoll_ctl syscalls for common usage patterns and handle the breakage 62 | * ensuing from receiving events for closed and otherwise long gone 63 | * file descriptors. 64 | */ 65 | 66 | #include 67 | 68 | #define EV_EMASK_EPERM 0x80 69 | 70 | static void 71 | epoll_modify (EV_P_ int fd, int oev, int nev) 72 | { 73 | struct epoll_event ev; 74 | unsigned char oldmask; 75 | 76 | /* 77 | * we handle EPOLL_CTL_DEL by ignoring it here 78 | * on the assumption that the fd is gone anyways 79 | * if that is wrong, we have to handle the spurious 80 | * event in epoll_poll. 81 | * if the fd is added again, we try to ADD it, and, if that 82 | * fails, we assume it still has the same eventmask. 83 | */ 84 | if (!nev) 85 | return; 86 | 87 | oldmask = anfds [fd].emask; 88 | anfds [fd].emask = nev; 89 | 90 | /* store the generation counter in the upper 32 bits, the fd in the lower 32 bits */ 91 | ev.data.u64 = (uint64_t)(uint32_t)fd 92 | | ((uint64_t)(uint32_t)++anfds [fd].egen << 32); 93 | ev.events = (nev & EV_READ ? EPOLLIN : 0) 94 | | (nev & EV_WRITE ? EPOLLOUT : 0); 95 | 96 | if (expect_true (!epoll_ctl (backend_fd, oev && oldmask != nev ? EPOLL_CTL_MOD : EPOLL_CTL_ADD, fd, &ev))) 97 | return; 98 | 99 | if (expect_true (errno == ENOENT)) 100 | { 101 | /* if ENOENT then the fd went away, so try to do the right thing */ 102 | if (!nev) 103 | goto dec_egen; 104 | 105 | if (!epoll_ctl (backend_fd, EPOLL_CTL_ADD, fd, &ev)) 106 | return; 107 | } 108 | else if (expect_true (errno == EEXIST)) 109 | { 110 | /* EEXIST means we ignored a previous DEL, but the fd is still active */ 111 | /* if the kernel mask is the same as the new mask, we assume it hasn't changed */ 112 | if (oldmask == nev) 113 | goto dec_egen; 114 | 115 | if (!epoll_ctl (backend_fd, EPOLL_CTL_MOD, fd, &ev)) 116 | return; 117 | } 118 | else if (expect_true (errno == EPERM)) 119 | { 120 | /* EPERM means the fd is always ready, but epoll is too snobbish */ 121 | /* to handle it, unlike select or poll. */ 122 | anfds [fd].emask = EV_EMASK_EPERM; 123 | 124 | /* add fd to epoll_eperms, if not already inside */ 125 | if (!(oldmask & EV_EMASK_EPERM)) 126 | { 127 | array_needsize (int, epoll_eperms, epoll_epermmax, epoll_epermcnt + 1, EMPTY2); 128 | epoll_eperms [epoll_epermcnt++] = fd; 129 | } 130 | 131 | return; 132 | } 133 | 134 | fd_kill (EV_A_ fd); 135 | 136 | dec_egen: 137 | /* we didn't successfully call epoll_ctl, so decrement the generation counter again */ 138 | --anfds [fd].egen; 139 | } 140 | 141 | static void 142 | epoll_poll (EV_P_ ev_tstamp timeout) 143 | { 144 | int i; 145 | int eventcnt; 146 | 147 | if (expect_false (epoll_epermcnt)) 148 | timeout = 0.; 149 | 150 | /* epoll wait times cannot be larger than (LONG_MAX - 999UL) / HZ msecs, which is below */ 151 | /* the default libev max wait time, however. */ 152 | EV_RELEASE_CB; 153 | eventcnt = epoll_wait (backend_fd, epoll_events, epoll_eventmax, timeout * 1e3); 154 | EV_ACQUIRE_CB; 155 | 156 | if (expect_false (eventcnt < 0)) 157 | { 158 | if (errno != EINTR) 159 | ev_syserr ("(libev) epoll_wait"); 160 | 161 | return; 162 | } 163 | 164 | for (i = 0; i < eventcnt; ++i) 165 | { 166 | struct epoll_event *ev = epoll_events + i; 167 | 168 | int fd = (uint32_t)ev->data.u64; /* mask out the lower 32 bits */ 169 | int want = anfds [fd].events; 170 | int got = (ev->events & (EPOLLOUT | EPOLLERR | EPOLLHUP) ? EV_WRITE : 0) 171 | | (ev->events & (EPOLLIN | EPOLLERR | EPOLLHUP) ? EV_READ : 0); 172 | 173 | /* 174 | * check for spurious notification. 175 | * this only finds spurious notifications on egen updates 176 | * other spurious notifications will be found by epoll_ctl, below 177 | * we assume that fd is always in range, as we never shrink the anfds array 178 | */ 179 | if (expect_false ((uint32_t)anfds [fd].egen != (uint32_t)(ev->data.u64 >> 32))) 180 | { 181 | /* recreate kernel state */ 182 | postfork |= 2; 183 | continue; 184 | } 185 | 186 | if (expect_false (got & ~want)) 187 | { 188 | anfds [fd].emask = want; 189 | 190 | /* 191 | * we received an event but are not interested in it, try mod or del 192 | * this often happens because we optimistically do not unregister fds 193 | * when we are no longer interested in them, but also when we get spurious 194 | * notifications for fds from another process. this is partially handled 195 | * above with the gencounter check (== our fd is not the event fd), and 196 | * partially here, when epoll_ctl returns an error (== a child has the fd 197 | * but we closed it). 198 | */ 199 | ev->events = (want & EV_READ ? EPOLLIN : 0) 200 | | (want & EV_WRITE ? EPOLLOUT : 0); 201 | 202 | /* pre-2.6.9 kernels require a non-null pointer with EPOLL_CTL_DEL, */ 203 | /* which is fortunately easy to do for us. */ 204 | if (epoll_ctl (backend_fd, want ? EPOLL_CTL_MOD : EPOLL_CTL_DEL, fd, ev)) 205 | { 206 | postfork |= 2; /* an error occurred, recreate kernel state */ 207 | continue; 208 | } 209 | } 210 | 211 | fd_event (EV_A_ fd, got); 212 | } 213 | 214 | /* if the receive array was full, increase its size */ 215 | if (expect_false (eventcnt == epoll_eventmax)) 216 | { 217 | ev_free (epoll_events); 218 | epoll_eventmax = array_nextsize (sizeof (struct epoll_event), epoll_eventmax, epoll_eventmax + 1); 219 | epoll_events = (struct epoll_event *)ev_malloc (sizeof (struct epoll_event) * epoll_eventmax); 220 | } 221 | 222 | /* now synthesize events for all fds where epoll fails, while select works... */ 223 | for (i = epoll_epermcnt; i--; ) 224 | { 225 | int fd = epoll_eperms [i]; 226 | unsigned char events = anfds [fd].events & (EV_READ | EV_WRITE); 227 | 228 | if (anfds [fd].emask & EV_EMASK_EPERM && events) 229 | fd_event (EV_A_ fd, events); 230 | else 231 | { 232 | epoll_eperms [i] = epoll_eperms [--epoll_epermcnt]; 233 | anfds [fd].emask = 0; 234 | } 235 | } 236 | } 237 | 238 | inline_size 239 | int 240 | epoll_init (EV_P_ int flags) 241 | { 242 | #if defined EPOLL_CLOEXEC && !defined __ANDROID__ 243 | backend_fd = epoll_create1 (EPOLL_CLOEXEC); 244 | 245 | if (backend_fd < 0 && (errno == EINVAL || errno == ENOSYS)) 246 | #endif 247 | backend_fd = epoll_create (256); 248 | 249 | if (backend_fd < 0) 250 | return 0; 251 | 252 | fcntl (backend_fd, F_SETFD, FD_CLOEXEC); 253 | 254 | backend_mintime = 1e-3; /* epoll does sometimes return early, this is just to avoid the worst */ 255 | backend_modify = epoll_modify; 256 | backend_poll = epoll_poll; 257 | 258 | epoll_eventmax = 64; /* initial number of events receivable per poll */ 259 | epoll_events = (struct epoll_event *)ev_malloc (sizeof (struct epoll_event) * epoll_eventmax); 260 | 261 | return EVBACKEND_EPOLL; 262 | } 263 | 264 | inline_size 265 | void 266 | epoll_destroy (EV_P) 267 | { 268 | ev_free (epoll_events); 269 | array_free (epoll_eperm, EMPTY); 270 | } 271 | 272 | inline_size 273 | void 274 | epoll_fork (EV_P) 275 | { 276 | close (backend_fd); 277 | 278 | while ((backend_fd = epoll_create (256)) < 0) 279 | ev_syserr ("(libev) epoll_create"); 280 | 281 | fcntl (backend_fd, F_SETFD, FD_CLOEXEC); 282 | 283 | fd_rearm_all (EV_A); 284 | } 285 | 286 | -------------------------------------------------------------------------------- /libev/ev_kqueue.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libev kqueue backend 3 | * 4 | * Copyright (c) 2007,2008,2009,2010,2011,2012,2013 Marc Alexander Lehmann 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without modifica- 8 | * tion, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- 19 | * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 20 | * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- 21 | * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- 25 | * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 26 | * OF THE POSSIBILITY OF SUCH DAMAGE. 27 | * 28 | * Alternatively, the contents of this file may be used under the terms of 29 | * the GNU General Public License ("GPL") version 2 or any later version, 30 | * in which case the provisions of the GPL are applicable instead of 31 | * the above. If you wish to allow the use of your version of this file 32 | * only under the terms of the GPL and not to allow others to use your 33 | * version of this file under the BSD license, indicate your decision 34 | * by deleting the provisions above and replace them with the notice 35 | * and other provisions required by the GPL. If you do not delete the 36 | * provisions above, a recipient may use your version of this file under 37 | * either the BSD or the GPL. 38 | */ 39 | 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | 46 | inline_speed 47 | void 48 | kqueue_change (EV_P_ int fd, int filter, int flags, int fflags) 49 | { 50 | ++kqueue_changecnt; 51 | array_needsize (struct kevent, kqueue_changes, kqueue_changemax, kqueue_changecnt, EMPTY2); 52 | 53 | EV_SET (&kqueue_changes [kqueue_changecnt - 1], fd, filter, flags, fflags, 0, 0); 54 | } 55 | 56 | /* OS X at least needs this */ 57 | #ifndef EV_ENABLE 58 | # define EV_ENABLE 0 59 | #endif 60 | #ifndef NOTE_EOF 61 | # define NOTE_EOF 0 62 | #endif 63 | 64 | static void 65 | kqueue_modify (EV_P_ int fd, int oev, int nev) 66 | { 67 | if (oev != nev) 68 | { 69 | if (oev & EV_READ) 70 | kqueue_change (EV_A_ fd, EVFILT_READ , EV_DELETE, 0); 71 | 72 | if (oev & EV_WRITE) 73 | kqueue_change (EV_A_ fd, EVFILT_WRITE, EV_DELETE, 0); 74 | } 75 | 76 | /* to detect close/reopen reliably, we have to re-add */ 77 | /* event requests even when oev == nev */ 78 | 79 | if (nev & EV_READ) 80 | kqueue_change (EV_A_ fd, EVFILT_READ , EV_ADD | EV_ENABLE, NOTE_EOF); 81 | 82 | if (nev & EV_WRITE) 83 | kqueue_change (EV_A_ fd, EVFILT_WRITE, EV_ADD | EV_ENABLE, NOTE_EOF); 84 | } 85 | 86 | static void 87 | kqueue_poll (EV_P_ ev_tstamp timeout) 88 | { 89 | int res, i; 90 | struct timespec ts; 91 | 92 | /* need to resize so there is enough space for errors */ 93 | if (kqueue_changecnt > kqueue_eventmax) 94 | { 95 | ev_free (kqueue_events); 96 | kqueue_eventmax = array_nextsize (sizeof (struct kevent), kqueue_eventmax, kqueue_changecnt); 97 | kqueue_events = (struct kevent *)ev_malloc (sizeof (struct kevent) * kqueue_eventmax); 98 | } 99 | 100 | EV_RELEASE_CB; 101 | EV_TS_SET (ts, timeout); 102 | res = kevent (backend_fd, kqueue_changes, kqueue_changecnt, kqueue_events, kqueue_eventmax, &ts); 103 | EV_ACQUIRE_CB; 104 | kqueue_changecnt = 0; 105 | 106 | if (expect_false (res < 0)) 107 | { 108 | if (errno != EINTR) 109 | ev_syserr ("(libev) kevent"); 110 | 111 | return; 112 | } 113 | 114 | for (i = 0; i < res; ++i) 115 | { 116 | int fd = kqueue_events [i].ident; 117 | 118 | if (expect_false (kqueue_events [i].flags & EV_ERROR)) 119 | { 120 | int err = kqueue_events [i].data; 121 | 122 | /* we are only interested in errors for fds that we are interested in :) */ 123 | if (anfds [fd].events) 124 | { 125 | if (err == ENOENT) /* resubmit changes on ENOENT */ 126 | kqueue_modify (EV_A_ fd, 0, anfds [fd].events); 127 | else if (err == EBADF) /* on EBADF, we re-check the fd */ 128 | { 129 | if (fd_valid (fd)) 130 | kqueue_modify (EV_A_ fd, 0, anfds [fd].events); 131 | else 132 | fd_kill (EV_A_ fd); 133 | } 134 | else /* on all other errors, we error out on the fd */ 135 | fd_kill (EV_A_ fd); 136 | } 137 | } 138 | else 139 | fd_event ( 140 | EV_A_ 141 | fd, 142 | kqueue_events [i].filter == EVFILT_READ ? EV_READ 143 | : kqueue_events [i].filter == EVFILT_WRITE ? EV_WRITE 144 | : 0 145 | ); 146 | } 147 | 148 | if (expect_false (res == kqueue_eventmax)) 149 | { 150 | ev_free (kqueue_events); 151 | kqueue_eventmax = array_nextsize (sizeof (struct kevent), kqueue_eventmax, kqueue_eventmax + 1); 152 | kqueue_events = (struct kevent *)ev_malloc (sizeof (struct kevent) * kqueue_eventmax); 153 | } 154 | } 155 | 156 | inline_size 157 | int 158 | kqueue_init (EV_P_ int flags) 159 | { 160 | /* initialize the kernel queue */ 161 | kqueue_fd_pid = getpid (); 162 | if ((backend_fd = kqueue ()) < 0) 163 | return 0; 164 | 165 | fcntl (backend_fd, F_SETFD, FD_CLOEXEC); /* not sure if necessary, hopefully doesn't hurt */ 166 | 167 | backend_mintime = 1e-9; /* apparently, they did the right thing in freebsd */ 168 | backend_modify = kqueue_modify; 169 | backend_poll = kqueue_poll; 170 | 171 | kqueue_eventmax = 64; /* initial number of events receivable per poll */ 172 | kqueue_events = (struct kevent *)ev_malloc (sizeof (struct kevent) * kqueue_eventmax); 173 | 174 | kqueue_changes = 0; 175 | kqueue_changemax = 0; 176 | kqueue_changecnt = 0; 177 | 178 | return EVBACKEND_KQUEUE; 179 | } 180 | 181 | inline_size 182 | void 183 | kqueue_destroy (EV_P) 184 | { 185 | ev_free (kqueue_events); 186 | ev_free (kqueue_changes); 187 | } 188 | 189 | inline_size 190 | void 191 | kqueue_fork (EV_P) 192 | { 193 | /* some BSD kernels don't just destroy the kqueue itself, 194 | * but also close the fd, which isn't documented, and 195 | * impossible to support properly. 196 | * we remember the pid of the kqueue call and only close 197 | * the fd if the pid is still the same. 198 | * this leaks fds on sane kernels, but BSD interfaces are 199 | * notoriously buggy and rarely get fixed. 200 | */ 201 | pid_t newpid = getpid (); 202 | 203 | if (newpid == kqueue_fd_pid) 204 | close (backend_fd); 205 | 206 | kqueue_fd_pid = newpid; 207 | while ((backend_fd = kqueue ()) < 0) 208 | ev_syserr ("(libev) kqueue"); 209 | 210 | fcntl (backend_fd, F_SETFD, FD_CLOEXEC); 211 | 212 | /* re-register interest in fds */ 213 | fd_rearm_all (EV_A); 214 | } 215 | 216 | /* sys/event.h defines EV_ERROR */ 217 | #undef EV_ERROR 218 | 219 | -------------------------------------------------------------------------------- /libev/ev_poll.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libev poll fd activity backend 3 | * 4 | * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without modifica- 8 | * tion, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- 19 | * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 20 | * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- 21 | * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- 25 | * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 26 | * OF THE POSSIBILITY OF SUCH DAMAGE. 27 | * 28 | * Alternatively, the contents of this file may be used under the terms of 29 | * the GNU General Public License ("GPL") version 2 or any later version, 30 | * in which case the provisions of the GPL are applicable instead of 31 | * the above. If you wish to allow the use of your version of this file 32 | * only under the terms of the GPL and not to allow others to use your 33 | * version of this file under the BSD license, indicate your decision 34 | * by deleting the provisions above and replace them with the notice 35 | * and other provisions required by the GPL. If you do not delete the 36 | * provisions above, a recipient may use your version of this file under 37 | * either the BSD or the GPL. 38 | */ 39 | 40 | #include 41 | 42 | inline_size 43 | void 44 | pollidx_init (int *base, int count) 45 | { 46 | /* consider using memset (.., -1, ...), which is practically guaranteed 47 | * to work on all systems implementing poll */ 48 | while (count--) 49 | *base++ = -1; 50 | } 51 | 52 | static void 53 | poll_modify (EV_P_ int fd, int oev, int nev) 54 | { 55 | int idx; 56 | 57 | if (oev == nev) 58 | return; 59 | 60 | array_needsize (int, pollidxs, pollidxmax, fd + 1, pollidx_init); 61 | 62 | idx = pollidxs [fd]; 63 | 64 | if (idx < 0) /* need to allocate a new pollfd */ 65 | { 66 | pollidxs [fd] = idx = pollcnt++; 67 | array_needsize (struct pollfd, polls, pollmax, pollcnt, EMPTY2); 68 | polls [idx].fd = fd; 69 | } 70 | 71 | assert (polls [idx].fd == fd); 72 | 73 | if (nev) 74 | polls [idx].events = 75 | (nev & EV_READ ? POLLIN : 0) 76 | | (nev & EV_WRITE ? POLLOUT : 0); 77 | else /* remove pollfd */ 78 | { 79 | pollidxs [fd] = -1; 80 | 81 | if (expect_true (idx < --pollcnt)) 82 | { 83 | polls [idx] = polls [pollcnt]; 84 | pollidxs [polls [idx].fd] = idx; 85 | } 86 | } 87 | } 88 | 89 | static void 90 | poll_poll (EV_P_ ev_tstamp timeout) 91 | { 92 | struct pollfd *p; 93 | int res; 94 | 95 | EV_RELEASE_CB; 96 | res = poll (polls, pollcnt, timeout * 1e3); 97 | EV_ACQUIRE_CB; 98 | 99 | if (expect_false (res < 0)) 100 | { 101 | if (errno == EBADF) 102 | fd_ebadf (EV_A); 103 | else if (errno == ENOMEM && !syserr_cb) 104 | fd_enomem (EV_A); 105 | else if (errno != EINTR) 106 | ev_syserr ("(libev) poll"); 107 | } 108 | else 109 | for (p = polls; res; ++p) 110 | { 111 | assert (("libev: poll() returned illegal result, broken BSD kernel?", p < polls + pollcnt)); 112 | 113 | if (expect_false (p->revents)) /* this expect is debatable */ 114 | { 115 | --res; 116 | 117 | if (expect_false (p->revents & POLLNVAL)) 118 | fd_kill (EV_A_ p->fd); 119 | else 120 | fd_event ( 121 | EV_A_ 122 | p->fd, 123 | (p->revents & (POLLOUT | POLLERR | POLLHUP) ? EV_WRITE : 0) 124 | | (p->revents & (POLLIN | POLLERR | POLLHUP) ? EV_READ : 0) 125 | ); 126 | } 127 | } 128 | } 129 | 130 | inline_size 131 | int 132 | poll_init (EV_P_ int flags) 133 | { 134 | backend_mintime = 1e-3; 135 | backend_modify = poll_modify; 136 | backend_poll = poll_poll; 137 | 138 | pollidxs = 0; pollidxmax = 0; 139 | polls = 0; pollmax = 0; pollcnt = 0; 140 | 141 | return EVBACKEND_POLL; 142 | } 143 | 144 | inline_size 145 | void 146 | poll_destroy (EV_P) 147 | { 148 | ev_free (pollidxs); 149 | ev_free (polls); 150 | } 151 | 152 | -------------------------------------------------------------------------------- /libev/ev_port.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libev solaris event port backend 3 | * 4 | * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without modifica- 8 | * tion, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- 19 | * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 20 | * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- 21 | * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- 25 | * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 26 | * OF THE POSSIBILITY OF SUCH DAMAGE. 27 | * 28 | * Alternatively, the contents of this file may be used under the terms of 29 | * the GNU General Public License ("GPL") version 2 or any later version, 30 | * in which case the provisions of the GPL are applicable instead of 31 | * the above. If you wish to allow the use of your version of this file 32 | * only under the terms of the GPL and not to allow others to use your 33 | * version of this file under the BSD license, indicate your decision 34 | * by deleting the provisions above and replace them with the notice 35 | * and other provisions required by the GPL. If you do not delete the 36 | * provisions above, a recipient may use your version of this file under 37 | * either the BSD or the GPL. 38 | */ 39 | 40 | /* useful reading: 41 | * 42 | * http://bugs.opensolaris.org/view_bug.do?bug_id=6268715 (random results) 43 | * http://bugs.opensolaris.org/view_bug.do?bug_id=6455223 (just totally broken) 44 | * http://bugs.opensolaris.org/view_bug.do?bug_id=6873782 (manpage ETIME) 45 | * http://bugs.opensolaris.org/view_bug.do?bug_id=6874410 (implementation ETIME) 46 | * http://www.mail-archive.com/networking-discuss@opensolaris.org/msg11898.html ETIME vs. nget 47 | * http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/lib/libc/port/gen/event_port.c (libc) 48 | * http://cvs.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/uts/common/fs/portfs/port.c#1325 (kernel) 49 | */ 50 | 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | 58 | inline_speed 59 | void 60 | port_associate_and_check (EV_P_ int fd, int ev) 61 | { 62 | if (0 > 63 | port_associate ( 64 | backend_fd, PORT_SOURCE_FD, fd, 65 | (ev & EV_READ ? POLLIN : 0) 66 | | (ev & EV_WRITE ? POLLOUT : 0), 67 | 0 68 | ) 69 | ) 70 | { 71 | if (errno == EBADFD) 72 | fd_kill (EV_A_ fd); 73 | else 74 | ev_syserr ("(libev) port_associate"); 75 | } 76 | } 77 | 78 | static void 79 | port_modify (EV_P_ int fd, int oev, int nev) 80 | { 81 | /* we need to reassociate no matter what, as closes are 82 | * once more silently being discarded. 83 | */ 84 | if (!nev) 85 | { 86 | if (oev) 87 | port_dissociate (backend_fd, PORT_SOURCE_FD, fd); 88 | } 89 | else 90 | port_associate_and_check (EV_A_ fd, nev); 91 | } 92 | 93 | static void 94 | port_poll (EV_P_ ev_tstamp timeout) 95 | { 96 | int res, i; 97 | struct timespec ts; 98 | uint_t nget = 1; 99 | 100 | /* we initialise this to something we will skip in the loop, as */ 101 | /* port_getn can return with nget unchanged, but no indication */ 102 | /* whether it was the original value or has been updated :/ */ 103 | port_events [0].portev_source = 0; 104 | 105 | EV_RELEASE_CB; 106 | EV_TS_SET (ts, timeout); 107 | res = port_getn (backend_fd, port_events, port_eventmax, &nget, &ts); 108 | EV_ACQUIRE_CB; 109 | 110 | /* port_getn may or may not set nget on error */ 111 | /* so we rely on port_events [0].portev_source not being updated */ 112 | if (res == -1 && errno != ETIME && errno != EINTR) 113 | ev_syserr ("(libev) port_getn (see http://bugs.opensolaris.org/view_bug.do?bug_id=6268715, try LIBEV_FLAGS=3 env variable)"); 114 | 115 | for (i = 0; i < nget; ++i) 116 | { 117 | if (port_events [i].portev_source == PORT_SOURCE_FD) 118 | { 119 | int fd = port_events [i].portev_object; 120 | 121 | fd_event ( 122 | EV_A_ 123 | fd, 124 | (port_events [i].portev_events & (POLLOUT | POLLERR | POLLHUP) ? EV_WRITE : 0) 125 | | (port_events [i].portev_events & (POLLIN | POLLERR | POLLHUP) ? EV_READ : 0) 126 | ); 127 | 128 | fd_change (EV_A_ fd, EV__IOFDSET); 129 | } 130 | } 131 | 132 | if (expect_false (nget == port_eventmax)) 133 | { 134 | ev_free (port_events); 135 | port_eventmax = array_nextsize (sizeof (port_event_t), port_eventmax, port_eventmax + 1); 136 | port_events = (port_event_t *)ev_malloc (sizeof (port_event_t) * port_eventmax); 137 | } 138 | } 139 | 140 | inline_size 141 | int 142 | port_init (EV_P_ int flags) 143 | { 144 | /* Initialize the kernel queue */ 145 | if ((backend_fd = port_create ()) < 0) 146 | return 0; 147 | 148 | assert (("libev: PORT_SOURCE_FD must not be zero", PORT_SOURCE_FD)); 149 | 150 | fcntl (backend_fd, F_SETFD, FD_CLOEXEC); /* not sure if necessary, hopefully doesn't hurt */ 151 | 152 | /* if my reading of the opensolaris kernel sources are correct, then 153 | * opensolaris does something very stupid: it checks if the time has already 154 | * elapsed and doesn't round up if that is the case,m otherwise it DOES round 155 | * up. Since we can't know what the case is, we need to guess by using a 156 | * "large enough" timeout. Normally, 1e-9 would be correct. 157 | */ 158 | backend_mintime = 1e-3; /* needed to compensate for port_getn returning early */ 159 | backend_modify = port_modify; 160 | backend_poll = port_poll; 161 | 162 | port_eventmax = 64; /* initial number of events receivable per poll */ 163 | port_events = (port_event_t *)ev_malloc (sizeof (port_event_t) * port_eventmax); 164 | 165 | return EVBACKEND_PORT; 166 | } 167 | 168 | inline_size 169 | void 170 | port_destroy (EV_P) 171 | { 172 | ev_free (port_events); 173 | } 174 | 175 | inline_size 176 | void 177 | port_fork (EV_P) 178 | { 179 | close (backend_fd); 180 | 181 | while ((backend_fd = port_create ()) < 0) 182 | ev_syserr ("(libev) port"); 183 | 184 | fcntl (backend_fd, F_SETFD, FD_CLOEXEC); 185 | 186 | /* re-register interest in fds */ 187 | fd_rearm_all (EV_A); 188 | } 189 | 190 | -------------------------------------------------------------------------------- /libev/ev_select.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libev select fd activity backend 3 | * 4 | * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without modifica- 8 | * tion, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- 19 | * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 20 | * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- 21 | * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- 25 | * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 26 | * OF THE POSSIBILITY OF SUCH DAMAGE. 27 | * 28 | * Alternatively, the contents of this file may be used under the terms of 29 | * the GNU General Public License ("GPL") version 2 or any later version, 30 | * in which case the provisions of the GPL are applicable instead of 31 | * the above. If you wish to allow the use of your version of this file 32 | * only under the terms of the GPL and not to allow others to use your 33 | * version of this file under the BSD license, indicate your decision 34 | * by deleting the provisions above and replace them with the notice 35 | * and other provisions required by the GPL. If you do not delete the 36 | * provisions above, a recipient may use your version of this file under 37 | * either the BSD or the GPL. 38 | */ 39 | 40 | #ifndef _WIN32 41 | /* for unix systems */ 42 | # include 43 | # ifndef __hpux 44 | /* for REAL unix systems */ 45 | # include 46 | # endif 47 | #endif 48 | 49 | #ifndef EV_SELECT_USE_FD_SET 50 | # ifdef NFDBITS 51 | # define EV_SELECT_USE_FD_SET 0 52 | # else 53 | # define EV_SELECT_USE_FD_SET 1 54 | # endif 55 | #endif 56 | 57 | #if EV_SELECT_IS_WINSOCKET 58 | # undef EV_SELECT_USE_FD_SET 59 | # define EV_SELECT_USE_FD_SET 1 60 | # undef NFDBITS 61 | # define NFDBITS 0 62 | #endif 63 | 64 | #if !EV_SELECT_USE_FD_SET 65 | # define NFDBYTES (NFDBITS / 8) 66 | #endif 67 | 68 | #include 69 | 70 | static void 71 | select_modify (EV_P_ int fd, int oev, int nev) 72 | { 73 | if (oev == nev) 74 | return; 75 | 76 | { 77 | #if EV_SELECT_USE_FD_SET 78 | 79 | #if EV_SELECT_IS_WINSOCKET 80 | SOCKET handle = anfds [fd].handle; 81 | #else 82 | int handle = fd; 83 | #endif 84 | 85 | assert (("libev: fd >= FD_SETSIZE passed to fd_set-based select backend", fd < FD_SETSIZE)); 86 | 87 | /* FD_SET is broken on windows (it adds the fd to a set twice or more, 88 | * which eventually leads to overflows). Need to call it only on changes. 89 | */ 90 | #if EV_SELECT_IS_WINSOCKET 91 | if ((oev ^ nev) & EV_READ) 92 | #endif 93 | if (nev & EV_READ) 94 | FD_SET (handle, (fd_set *)vec_ri); 95 | else 96 | FD_CLR (handle, (fd_set *)vec_ri); 97 | 98 | #if EV_SELECT_IS_WINSOCKET 99 | if ((oev ^ nev) & EV_WRITE) 100 | #endif 101 | if (nev & EV_WRITE) 102 | FD_SET (handle, (fd_set *)vec_wi); 103 | else 104 | FD_CLR (handle, (fd_set *)vec_wi); 105 | 106 | #else 107 | 108 | int word = fd / NFDBITS; 109 | fd_mask mask = 1UL << (fd % NFDBITS); 110 | 111 | if (expect_false (vec_max <= word)) 112 | { 113 | int new_max = word + 1; 114 | 115 | vec_ri = ev_realloc (vec_ri, new_max * NFDBYTES); 116 | vec_ro = ev_realloc (vec_ro, new_max * NFDBYTES); /* could free/malloc */ 117 | vec_wi = ev_realloc (vec_wi, new_max * NFDBYTES); 118 | vec_wo = ev_realloc (vec_wo, new_max * NFDBYTES); /* could free/malloc */ 119 | #ifdef _WIN32 120 | vec_eo = ev_realloc (vec_eo, new_max * NFDBYTES); /* could free/malloc */ 121 | #endif 122 | 123 | for (; vec_max < new_max; ++vec_max) 124 | ((fd_mask *)vec_ri) [vec_max] = 125 | ((fd_mask *)vec_wi) [vec_max] = 0; 126 | } 127 | 128 | ((fd_mask *)vec_ri) [word] |= mask; 129 | if (!(nev & EV_READ)) 130 | ((fd_mask *)vec_ri) [word] &= ~mask; 131 | 132 | ((fd_mask *)vec_wi) [word] |= mask; 133 | if (!(nev & EV_WRITE)) 134 | ((fd_mask *)vec_wi) [word] &= ~mask; 135 | #endif 136 | } 137 | } 138 | 139 | static void 140 | select_poll (EV_P_ ev_tstamp timeout) 141 | { 142 | struct timeval tv; 143 | int res; 144 | int fd_setsize; 145 | 146 | EV_RELEASE_CB; 147 | EV_TV_SET (tv, timeout); 148 | 149 | #if EV_SELECT_USE_FD_SET 150 | fd_setsize = sizeof (fd_set); 151 | #else 152 | fd_setsize = vec_max * NFDBYTES; 153 | #endif 154 | 155 | memcpy (vec_ro, vec_ri, fd_setsize); 156 | memcpy (vec_wo, vec_wi, fd_setsize); 157 | 158 | #ifdef _WIN32 159 | /* pass in the write set as except set. 160 | * the idea behind this is to work around a windows bug that causes 161 | * errors to be reported as an exception and not by setting 162 | * the writable bit. this is so uncontrollably lame. 163 | */ 164 | memcpy (vec_eo, vec_wi, fd_setsize); 165 | res = select (vec_max * NFDBITS, (fd_set *)vec_ro, (fd_set *)vec_wo, (fd_set *)vec_eo, &tv); 166 | #elif EV_SELECT_USE_FD_SET 167 | fd_setsize = anfdmax < FD_SETSIZE ? anfdmax : FD_SETSIZE; 168 | res = select (fd_setsize, (fd_set *)vec_ro, (fd_set *)vec_wo, 0, &tv); 169 | #else 170 | res = select (vec_max * NFDBITS, (fd_set *)vec_ro, (fd_set *)vec_wo, 0, &tv); 171 | #endif 172 | EV_ACQUIRE_CB; 173 | 174 | if (expect_false (res < 0)) 175 | { 176 | #if EV_SELECT_IS_WINSOCKET 177 | errno = WSAGetLastError (); 178 | #endif 179 | #ifdef WSABASEERR 180 | /* on windows, select returns incompatible error codes, fix this */ 181 | if (errno >= WSABASEERR && errno < WSABASEERR + 1000) 182 | if (errno == WSAENOTSOCK) 183 | errno = EBADF; 184 | else 185 | errno -= WSABASEERR; 186 | #endif 187 | 188 | #ifdef _WIN32 189 | /* select on windows erroneously returns EINVAL when no fd sets have been 190 | * provided (this is documented). what microsoft doesn't tell you that this bug 191 | * exists even when the fd sets _are_ provided, so we have to check for this bug 192 | * here and emulate by sleeping manually. 193 | * we also get EINVAL when the timeout is invalid, but we ignore this case here 194 | * and assume that EINVAL always means: you have to wait manually. 195 | */ 196 | if (errno == EINVAL) 197 | { 198 | if (timeout) 199 | { 200 | unsigned long ms = timeout * 1e3; 201 | Sleep (ms ? ms : 1); 202 | } 203 | 204 | return; 205 | } 206 | #endif 207 | 208 | if (errno == EBADF) 209 | fd_ebadf (EV_A); 210 | else if (errno == ENOMEM && !syserr_cb) 211 | fd_enomem (EV_A); 212 | else if (errno != EINTR) 213 | ev_syserr ("(libev) select"); 214 | 215 | return; 216 | } 217 | 218 | #if EV_SELECT_USE_FD_SET 219 | 220 | { 221 | int fd; 222 | 223 | for (fd = 0; fd < anfdmax; ++fd) 224 | if (anfds [fd].events) 225 | { 226 | int events = 0; 227 | #if EV_SELECT_IS_WINSOCKET 228 | SOCKET handle = anfds [fd].handle; 229 | #else 230 | int handle = fd; 231 | #endif 232 | 233 | if (FD_ISSET (handle, (fd_set *)vec_ro)) events |= EV_READ; 234 | if (FD_ISSET (handle, (fd_set *)vec_wo)) events |= EV_WRITE; 235 | #ifdef _WIN32 236 | if (FD_ISSET (handle, (fd_set *)vec_eo)) events |= EV_WRITE; 237 | #endif 238 | 239 | if (expect_true (events)) 240 | fd_event (EV_A_ fd, events); 241 | } 242 | } 243 | 244 | #else 245 | 246 | { 247 | int word, bit; 248 | for (word = vec_max; word--; ) 249 | { 250 | fd_mask word_r = ((fd_mask *)vec_ro) [word]; 251 | fd_mask word_w = ((fd_mask *)vec_wo) [word]; 252 | #ifdef _WIN32 253 | word_w |= ((fd_mask *)vec_eo) [word]; 254 | #endif 255 | 256 | if (word_r || word_w) 257 | for (bit = NFDBITS; bit--; ) 258 | { 259 | fd_mask mask = 1UL << bit; 260 | int events = 0; 261 | 262 | events |= word_r & mask ? EV_READ : 0; 263 | events |= word_w & mask ? EV_WRITE : 0; 264 | 265 | if (expect_true (events)) 266 | fd_event (EV_A_ word * NFDBITS + bit, events); 267 | } 268 | } 269 | } 270 | 271 | #endif 272 | } 273 | 274 | inline_size 275 | int 276 | select_init (EV_P_ int flags) 277 | { 278 | backend_mintime = 1e-6; 279 | backend_modify = select_modify; 280 | backend_poll = select_poll; 281 | 282 | #if EV_SELECT_USE_FD_SET 283 | vec_ri = ev_malloc (sizeof (fd_set)); FD_ZERO ((fd_set *)vec_ri); 284 | vec_ro = ev_malloc (sizeof (fd_set)); 285 | vec_wi = ev_malloc (sizeof (fd_set)); FD_ZERO ((fd_set *)vec_wi); 286 | vec_wo = ev_malloc (sizeof (fd_set)); 287 | #ifdef _WIN32 288 | vec_eo = ev_malloc (sizeof (fd_set)); 289 | #endif 290 | #else 291 | vec_max = 0; 292 | vec_ri = 0; 293 | vec_ro = 0; 294 | vec_wi = 0; 295 | vec_wo = 0; 296 | #ifdef _WIN32 297 | vec_eo = 0; 298 | #endif 299 | #endif 300 | 301 | return EVBACKEND_SELECT; 302 | } 303 | 304 | inline_size 305 | void 306 | select_destroy (EV_P) 307 | { 308 | ev_free (vec_ri); 309 | ev_free (vec_ro); 310 | ev_free (vec_wi); 311 | ev_free (vec_wo); 312 | #ifdef _WIN32 313 | ev_free (vec_eo); 314 | #endif 315 | } 316 | 317 | -------------------------------------------------------------------------------- /libev/ev_vars.h: -------------------------------------------------------------------------------- 1 | /* 2 | * loop member variable declarations 3 | * 4 | * Copyright (c) 2007,2008,2009,2010,2011,2012,2013 Marc Alexander Lehmann 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without modifica- 8 | * tion, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- 19 | * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 20 | * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- 21 | * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- 25 | * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 26 | * OF THE POSSIBILITY OF SUCH DAMAGE. 27 | * 28 | * Alternatively, the contents of this file may be used under the terms of 29 | * the GNU General Public License ("GPL") version 2 or any later version, 30 | * in which case the provisions of the GPL are applicable instead of 31 | * the above. If you wish to allow the use of your version of this file 32 | * only under the terms of the GPL and not to allow others to use your 33 | * version of this file under the BSD license, indicate your decision 34 | * by deleting the provisions above and replace them with the notice 35 | * and other provisions required by the GPL. If you do not delete the 36 | * provisions above, a recipient may use your version of this file under 37 | * either the BSD or the GPL. 38 | */ 39 | 40 | #define VARx(type,name) VAR(name, type name) 41 | 42 | VARx(ev_tstamp, now_floor) /* last time we refreshed rt_time */ 43 | VARx(ev_tstamp, mn_now) /* monotonic clock "now" */ 44 | VARx(ev_tstamp, rtmn_diff) /* difference realtime - monotonic time */ 45 | 46 | /* for reverse feeding of events */ 47 | VARx(W *, rfeeds) 48 | VARx(int, rfeedmax) 49 | VARx(int, rfeedcnt) 50 | 51 | VAR (pendings, ANPENDING *pendings [NUMPRI]) 52 | VAR (pendingmax, int pendingmax [NUMPRI]) 53 | VAR (pendingcnt, int pendingcnt [NUMPRI]) 54 | VARx(int, pendingpri) /* highest priority currently pending */ 55 | VARx(ev_prepare, pending_w) /* dummy pending watcher */ 56 | 57 | VARx(ev_tstamp, io_blocktime) 58 | VARx(ev_tstamp, timeout_blocktime) 59 | 60 | VARx(int, backend) 61 | VARx(int, activecnt) /* total number of active events ("refcount") */ 62 | VARx(EV_ATOMIC_T, loop_done) /* signal by ev_break */ 63 | 64 | VARx(int, backend_fd) 65 | VARx(ev_tstamp, backend_mintime) /* assumed typical timer resolution */ 66 | VAR (backend_modify, void (*backend_modify)(EV_P_ int fd, int oev, int nev)) 67 | VAR (backend_poll , void (*backend_poll)(EV_P_ ev_tstamp timeout)) 68 | 69 | VARx(ANFD *, anfds) 70 | VARx(int, anfdmax) 71 | 72 | VAR (evpipe, int evpipe [2]) 73 | VARx(ev_io, pipe_w) 74 | VARx(EV_ATOMIC_T, pipe_write_wanted) 75 | VARx(EV_ATOMIC_T, pipe_write_skipped) 76 | 77 | #if !defined(_WIN32) || EV_GENWRAP 78 | VARx(pid_t, curpid) 79 | #endif 80 | 81 | VARx(char, postfork) /* true if we need to recreate kernel state after fork */ 82 | 83 | #if EV_USE_SELECT || EV_GENWRAP 84 | VARx(void *, vec_ri) 85 | VARx(void *, vec_ro) 86 | VARx(void *, vec_wi) 87 | VARx(void *, vec_wo) 88 | #if defined(_WIN32) || EV_GENWRAP 89 | VARx(void *, vec_eo) 90 | #endif 91 | VARx(int, vec_max) 92 | #endif 93 | 94 | #if EV_USE_POLL || EV_GENWRAP 95 | VARx(struct pollfd *, polls) 96 | VARx(int, pollmax) 97 | VARx(int, pollcnt) 98 | VARx(int *, pollidxs) /* maps fds into structure indices */ 99 | VARx(int, pollidxmax) 100 | #endif 101 | 102 | #if EV_USE_EPOLL || EV_GENWRAP 103 | VARx(struct epoll_event *, epoll_events) 104 | VARx(int, epoll_eventmax) 105 | VARx(int *, epoll_eperms) 106 | VARx(int, epoll_epermcnt) 107 | VARx(int, epoll_epermmax) 108 | #endif 109 | 110 | #if EV_USE_KQUEUE || EV_GENWRAP 111 | VARx(pid_t, kqueue_fd_pid) 112 | VARx(struct kevent *, kqueue_changes) 113 | VARx(int, kqueue_changemax) 114 | VARx(int, kqueue_changecnt) 115 | VARx(struct kevent *, kqueue_events) 116 | VARx(int, kqueue_eventmax) 117 | #endif 118 | 119 | #if EV_USE_PORT || EV_GENWRAP 120 | VARx(struct port_event *, port_events) 121 | VARx(int, port_eventmax) 122 | #endif 123 | 124 | #if EV_USE_IOCP || EV_GENWRAP 125 | VARx(HANDLE, iocp) 126 | #endif 127 | 128 | VARx(int *, fdchanges) 129 | VARx(int, fdchangemax) 130 | VARx(int, fdchangecnt) 131 | 132 | VARx(ANHE *, timers) 133 | VARx(int, timermax) 134 | VARx(int, timercnt) 135 | 136 | #if EV_PERIODIC_ENABLE || EV_GENWRAP 137 | VARx(ANHE *, periodics) 138 | VARx(int, periodicmax) 139 | VARx(int, periodiccnt) 140 | #endif 141 | 142 | #if EV_IDLE_ENABLE || EV_GENWRAP 143 | VAR (idles, ev_idle **idles [NUMPRI]) 144 | VAR (idlemax, int idlemax [NUMPRI]) 145 | VAR (idlecnt, int idlecnt [NUMPRI]) 146 | #endif 147 | VARx(int, idleall) /* total number */ 148 | 149 | VARx(struct ev_prepare **, prepares) 150 | VARx(int, preparemax) 151 | VARx(int, preparecnt) 152 | 153 | VARx(struct ev_check **, checks) 154 | VARx(int, checkmax) 155 | VARx(int, checkcnt) 156 | 157 | #if EV_FORK_ENABLE || EV_GENWRAP 158 | VARx(struct ev_fork **, forks) 159 | VARx(int, forkmax) 160 | VARx(int, forkcnt) 161 | #endif 162 | 163 | #if EV_CLEANUP_ENABLE || EV_GENWRAP 164 | VARx(struct ev_cleanup **, cleanups) 165 | VARx(int, cleanupmax) 166 | VARx(int, cleanupcnt) 167 | #endif 168 | 169 | #if EV_ASYNC_ENABLE || EV_GENWRAP 170 | VARx(EV_ATOMIC_T, async_pending) 171 | VARx(struct ev_async **, asyncs) 172 | VARx(int, asyncmax) 173 | VARx(int, asynccnt) 174 | #endif 175 | 176 | #if EV_USE_INOTIFY || EV_GENWRAP 177 | VARx(int, fs_fd) 178 | VARx(ev_io, fs_w) 179 | VARx(char, fs_2625) /* whether we are running in linux 2.6.25 or newer */ 180 | VAR (fs_hash, ANFS fs_hash [EV_INOTIFY_HASHSIZE]) 181 | #endif 182 | 183 | VARx(EV_ATOMIC_T, sig_pending) 184 | #if EV_USE_SIGNALFD || EV_GENWRAP 185 | VARx(int, sigfd) 186 | VARx(ev_io, sigfd_w) 187 | VARx(sigset_t, sigfd_set) 188 | #endif 189 | 190 | VARx(unsigned int, origflags) /* original loop flags */ 191 | 192 | #if EV_FEATURE_API || EV_GENWRAP 193 | VARx(unsigned int, loop_count) /* total number of loop iterations/blocks */ 194 | VARx(unsigned int, loop_depth) /* #ev_run enters - #ev_run leaves */ 195 | 196 | VARx(void *, userdata) 197 | /* C++ doesn't support the ev_loop_callback typedef here. stinks. */ 198 | VAR (release_cb, void (*release_cb)(EV_P) EV_THROW) 199 | VAR (acquire_cb, void (*acquire_cb)(EV_P) EV_THROW) 200 | VAR (invoke_cb , ev_loop_callback invoke_cb) 201 | #endif 202 | 203 | #undef VARx 204 | 205 | -------------------------------------------------------------------------------- /libev/ev_win32.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libev win32 compatibility cruft (_not_ a backend) 3 | * 4 | * Copyright (c) 2007,2008,2009 Marc Alexander Lehmann 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without modifica- 8 | * tion, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- 19 | * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 20 | * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- 21 | * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- 25 | * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 26 | * OF THE POSSIBILITY OF SUCH DAMAGE. 27 | * 28 | * Alternatively, the contents of this file may be used under the terms of 29 | * the GNU General Public License ("GPL") version 2 or any later version, 30 | * in which case the provisions of the GPL are applicable instead of 31 | * the above. If you wish to allow the use of your version of this file 32 | * only under the terms of the GPL and not to allow others to use your 33 | * version of this file under the BSD license, indicate your decision 34 | * by deleting the provisions above and replace them with the notice 35 | * and other provisions required by the GPL. If you do not delete the 36 | * provisions above, a recipient may use your version of this file under 37 | * either the BSD or the GPL. 38 | */ 39 | 40 | #ifdef _WIN32 41 | 42 | /* note: the comment below could not be substantiated, but what would I care */ 43 | /* MSDN says this is required to handle SIGFPE */ 44 | /* my wild guess would be that using something floating-pointy is required */ 45 | /* for the crt to do something about it */ 46 | volatile double SIGFPE_REQ = 0.0f; 47 | 48 | static SOCKET 49 | ev_tcp_socket (void) 50 | { 51 | #if EV_USE_WSASOCKET 52 | return WSASocket (AF_INET, SOCK_STREAM, 0, 0, 0, 0); 53 | #else 54 | return socket (AF_INET, SOCK_STREAM, 0); 55 | #endif 56 | } 57 | 58 | /* oh, the humanity! */ 59 | static int 60 | ev_pipe (int filedes [2]) 61 | { 62 | struct sockaddr_in addr = { 0 }; 63 | int addr_size = sizeof (addr); 64 | struct sockaddr_in adr2; 65 | int adr2_size = sizeof (adr2); 66 | SOCKET listener; 67 | SOCKET sock [2] = { -1, -1 }; 68 | 69 | if ((listener = ev_tcp_socket ()) == INVALID_SOCKET) 70 | return -1; 71 | 72 | addr.sin_family = AF_INET; 73 | addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); 74 | addr.sin_port = 0; 75 | 76 | if (bind (listener, (struct sockaddr *)&addr, addr_size)) 77 | goto fail; 78 | 79 | if (getsockname (listener, (struct sockaddr *)&addr, &addr_size)) 80 | goto fail; 81 | 82 | if (listen (listener, 1)) 83 | goto fail; 84 | 85 | if ((sock [0] = ev_tcp_socket ()) == INVALID_SOCKET) 86 | goto fail; 87 | 88 | if (connect (sock [0], (struct sockaddr *)&addr, addr_size)) 89 | goto fail; 90 | 91 | /* TODO: returns INVALID_SOCKET on winsock accept, not < 0. fix it */ 92 | /* when convenient, probably by just removing error checking altogether? */ 93 | if ((sock [1] = accept (listener, 0, 0)) < 0) 94 | goto fail; 95 | 96 | /* windows vista returns fantasy port numbers for sockets: 97 | * example for two interconnected tcp sockets: 98 | * 99 | * (Socket::unpack_sockaddr_in getsockname $sock0)[0] == 53364 100 | * (Socket::unpack_sockaddr_in getpeername $sock0)[0] == 53363 101 | * (Socket::unpack_sockaddr_in getsockname $sock1)[0] == 53363 102 | * (Socket::unpack_sockaddr_in getpeername $sock1)[0] == 53365 103 | * 104 | * wow! tridirectional sockets! 105 | * 106 | * this way of checking ports seems to work: 107 | */ 108 | if (getpeername (sock [0], (struct sockaddr *)&addr, &addr_size)) 109 | goto fail; 110 | 111 | if (getsockname (sock [1], (struct sockaddr *)&adr2, &adr2_size)) 112 | goto fail; 113 | 114 | errno = WSAEINVAL; 115 | if (addr_size != adr2_size 116 | || addr.sin_addr.s_addr != adr2.sin_addr.s_addr /* just to be sure, I mean, it's windows */ 117 | || addr.sin_port != adr2.sin_port) 118 | goto fail; 119 | 120 | closesocket (listener); 121 | 122 | #if EV_SELECT_IS_WINSOCKET 123 | filedes [0] = EV_WIN32_HANDLE_TO_FD (sock [0]); 124 | filedes [1] = EV_WIN32_HANDLE_TO_FD (sock [1]); 125 | #else 126 | /* when select isn't winsocket, we also expect socket, connect, accept etc. 127 | * to work on fds */ 128 | filedes [0] = sock [0]; 129 | filedes [1] = sock [1]; 130 | #endif 131 | 132 | return 0; 133 | 134 | fail: 135 | closesocket (listener); 136 | 137 | if (sock [0] != INVALID_SOCKET) closesocket (sock [0]); 138 | if (sock [1] != INVALID_SOCKET) closesocket (sock [1]); 139 | 140 | return -1; 141 | } 142 | 143 | #undef pipe 144 | #define pipe(filedes) ev_pipe (filedes) 145 | 146 | #define EV_HAVE_EV_TIME 1 147 | ev_tstamp 148 | ev_time (void) 149 | { 150 | FILETIME ft; 151 | ULARGE_INTEGER ui; 152 | 153 | GetSystemTimeAsFileTime (&ft); 154 | ui.u.LowPart = ft.dwLowDateTime; 155 | ui.u.HighPart = ft.dwHighDateTime; 156 | 157 | /* msvc cannot convert ulonglong to double... yes, it is that sucky */ 158 | return (LONGLONG)(ui.QuadPart - 116444736000000000) * 1e-7; 159 | } 160 | 161 | #endif 162 | 163 | -------------------------------------------------------------------------------- /libev/ev_wrap.h: -------------------------------------------------------------------------------- 1 | /* DO NOT EDIT, automatically generated by update_ev_wrap */ 2 | #ifndef EV_WRAP_H 3 | #define EV_WRAP_H 4 | #define acquire_cb ((loop)->acquire_cb) 5 | #define activecnt ((loop)->activecnt) 6 | #define anfdmax ((loop)->anfdmax) 7 | #define anfds ((loop)->anfds) 8 | #define async_pending ((loop)->async_pending) 9 | #define asynccnt ((loop)->asynccnt) 10 | #define asyncmax ((loop)->asyncmax) 11 | #define asyncs ((loop)->asyncs) 12 | #define backend ((loop)->backend) 13 | #define backend_fd ((loop)->backend_fd) 14 | #define backend_mintime ((loop)->backend_mintime) 15 | #define backend_modify ((loop)->backend_modify) 16 | #define backend_poll ((loop)->backend_poll) 17 | #define checkcnt ((loop)->checkcnt) 18 | #define checkmax ((loop)->checkmax) 19 | #define checks ((loop)->checks) 20 | #define cleanupcnt ((loop)->cleanupcnt) 21 | #define cleanupmax ((loop)->cleanupmax) 22 | #define cleanups ((loop)->cleanups) 23 | #define curpid ((loop)->curpid) 24 | #define epoll_epermcnt ((loop)->epoll_epermcnt) 25 | #define epoll_epermmax ((loop)->epoll_epermmax) 26 | #define epoll_eperms ((loop)->epoll_eperms) 27 | #define epoll_eventmax ((loop)->epoll_eventmax) 28 | #define epoll_events ((loop)->epoll_events) 29 | #define evpipe ((loop)->evpipe) 30 | #define fdchangecnt ((loop)->fdchangecnt) 31 | #define fdchangemax ((loop)->fdchangemax) 32 | #define fdchanges ((loop)->fdchanges) 33 | #define forkcnt ((loop)->forkcnt) 34 | #define forkmax ((loop)->forkmax) 35 | #define forks ((loop)->forks) 36 | #define fs_2625 ((loop)->fs_2625) 37 | #define fs_fd ((loop)->fs_fd) 38 | #define fs_hash ((loop)->fs_hash) 39 | #define fs_w ((loop)->fs_w) 40 | #define idleall ((loop)->idleall) 41 | #define idlecnt ((loop)->idlecnt) 42 | #define idlemax ((loop)->idlemax) 43 | #define idles ((loop)->idles) 44 | #define invoke_cb ((loop)->invoke_cb) 45 | #define io_blocktime ((loop)->io_blocktime) 46 | #define iocp ((loop)->iocp) 47 | #define kqueue_changecnt ((loop)->kqueue_changecnt) 48 | #define kqueue_changemax ((loop)->kqueue_changemax) 49 | #define kqueue_changes ((loop)->kqueue_changes) 50 | #define kqueue_eventmax ((loop)->kqueue_eventmax) 51 | #define kqueue_events ((loop)->kqueue_events) 52 | #define kqueue_fd_pid ((loop)->kqueue_fd_pid) 53 | #define loop_count ((loop)->loop_count) 54 | #define loop_depth ((loop)->loop_depth) 55 | #define loop_done ((loop)->loop_done) 56 | #define mn_now ((loop)->mn_now) 57 | #define now_floor ((loop)->now_floor) 58 | #define origflags ((loop)->origflags) 59 | #define pending_w ((loop)->pending_w) 60 | #define pendingcnt ((loop)->pendingcnt) 61 | #define pendingmax ((loop)->pendingmax) 62 | #define pendingpri ((loop)->pendingpri) 63 | #define pendings ((loop)->pendings) 64 | #define periodiccnt ((loop)->periodiccnt) 65 | #define periodicmax ((loop)->periodicmax) 66 | #define periodics ((loop)->periodics) 67 | #define pipe_w ((loop)->pipe_w) 68 | #define pipe_write_skipped ((loop)->pipe_write_skipped) 69 | #define pipe_write_wanted ((loop)->pipe_write_wanted) 70 | #define pollcnt ((loop)->pollcnt) 71 | #define pollidxmax ((loop)->pollidxmax) 72 | #define pollidxs ((loop)->pollidxs) 73 | #define pollmax ((loop)->pollmax) 74 | #define polls ((loop)->polls) 75 | #define port_eventmax ((loop)->port_eventmax) 76 | #define port_events ((loop)->port_events) 77 | #define postfork ((loop)->postfork) 78 | #define preparecnt ((loop)->preparecnt) 79 | #define preparemax ((loop)->preparemax) 80 | #define prepares ((loop)->prepares) 81 | #define release_cb ((loop)->release_cb) 82 | #define rfeedcnt ((loop)->rfeedcnt) 83 | #define rfeedmax ((loop)->rfeedmax) 84 | #define rfeeds ((loop)->rfeeds) 85 | #define rtmn_diff ((loop)->rtmn_diff) 86 | #define sig_pending ((loop)->sig_pending) 87 | #define sigfd ((loop)->sigfd) 88 | #define sigfd_set ((loop)->sigfd_set) 89 | #define sigfd_w ((loop)->sigfd_w) 90 | #define timeout_blocktime ((loop)->timeout_blocktime) 91 | #define timercnt ((loop)->timercnt) 92 | #define timermax ((loop)->timermax) 93 | #define timers ((loop)->timers) 94 | #define userdata ((loop)->userdata) 95 | #define vec_eo ((loop)->vec_eo) 96 | #define vec_max ((loop)->vec_max) 97 | #define vec_ri ((loop)->vec_ri) 98 | #define vec_ro ((loop)->vec_ro) 99 | #define vec_wi ((loop)->vec_wi) 100 | #define vec_wo ((loop)->vec_wo) 101 | #else 102 | #undef EV_WRAP_H 103 | #undef acquire_cb 104 | #undef activecnt 105 | #undef anfdmax 106 | #undef anfds 107 | #undef async_pending 108 | #undef asynccnt 109 | #undef asyncmax 110 | #undef asyncs 111 | #undef backend 112 | #undef backend_fd 113 | #undef backend_mintime 114 | #undef backend_modify 115 | #undef backend_poll 116 | #undef checkcnt 117 | #undef checkmax 118 | #undef checks 119 | #undef cleanupcnt 120 | #undef cleanupmax 121 | #undef cleanups 122 | #undef curpid 123 | #undef epoll_epermcnt 124 | #undef epoll_epermmax 125 | #undef epoll_eperms 126 | #undef epoll_eventmax 127 | #undef epoll_events 128 | #undef evpipe 129 | #undef fdchangecnt 130 | #undef fdchangemax 131 | #undef fdchanges 132 | #undef forkcnt 133 | #undef forkmax 134 | #undef forks 135 | #undef fs_2625 136 | #undef fs_fd 137 | #undef fs_hash 138 | #undef fs_w 139 | #undef idleall 140 | #undef idlecnt 141 | #undef idlemax 142 | #undef idles 143 | #undef invoke_cb 144 | #undef io_blocktime 145 | #undef iocp 146 | #undef kqueue_changecnt 147 | #undef kqueue_changemax 148 | #undef kqueue_changes 149 | #undef kqueue_eventmax 150 | #undef kqueue_events 151 | #undef kqueue_fd_pid 152 | #undef loop_count 153 | #undef loop_depth 154 | #undef loop_done 155 | #undef mn_now 156 | #undef now_floor 157 | #undef origflags 158 | #undef pending_w 159 | #undef pendingcnt 160 | #undef pendingmax 161 | #undef pendingpri 162 | #undef pendings 163 | #undef periodiccnt 164 | #undef periodicmax 165 | #undef periodics 166 | #undef pipe_w 167 | #undef pipe_write_skipped 168 | #undef pipe_write_wanted 169 | #undef pollcnt 170 | #undef pollidxmax 171 | #undef pollidxs 172 | #undef pollmax 173 | #undef polls 174 | #undef port_eventmax 175 | #undef port_events 176 | #undef postfork 177 | #undef preparecnt 178 | #undef preparemax 179 | #undef prepares 180 | #undef release_cb 181 | #undef rfeedcnt 182 | #undef rfeedmax 183 | #undef rfeeds 184 | #undef rtmn_diff 185 | #undef sig_pending 186 | #undef sigfd 187 | #undef sigfd_set 188 | #undef sigfd_w 189 | #undef timeout_blocktime 190 | #undef timercnt 191 | #undef timermax 192 | #undef timers 193 | #undef userdata 194 | #undef vec_eo 195 | #undef vec_max 196 | #undef vec_ri 197 | #undef vec_ro 198 | #undef vec_wi 199 | #undef vec_wo 200 | #endif 201 | -------------------------------------------------------------------------------- /libev/event.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libevent compatibility layer 3 | * 4 | * Copyright (c) 2007,2008,2009,2010,2012 Marc Alexander Lehmann 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without modifica- 8 | * tion, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- 19 | * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 20 | * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- 21 | * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- 25 | * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 26 | * OF THE POSSIBILITY OF SUCH DAMAGE. 27 | * 28 | * Alternatively, the contents of this file may be used under the terms of 29 | * the GNU General Public License ("GPL") version 2 or any later version, 30 | * in which case the provisions of the GPL are applicable instead of 31 | * the above. If you wish to allow the use of your version of this file 32 | * only under the terms of the GPL and not to allow others to use your 33 | * version of this file under the BSD license, indicate your decision 34 | * by deleting the provisions above and replace them with the notice 35 | * and other provisions required by the GPL. If you do not delete the 36 | * provisions above, a recipient may use your version of this file under 37 | * either the BSD or the GPL. 38 | */ 39 | 40 | #include 41 | #include 42 | #include 43 | 44 | #ifdef EV_EVENT_H 45 | # include EV_EVENT_H 46 | #else 47 | # include "event.h" 48 | #endif 49 | 50 | #if EV_MULTIPLICITY 51 | # define dLOOPev struct ev_loop *loop = (struct ev_loop *)ev->ev_base 52 | # define dLOOPbase struct ev_loop *loop = (struct ev_loop *)base 53 | #else 54 | # define dLOOPev 55 | # define dLOOPbase 56 | #endif 57 | 58 | /* never accessed, will always be cast from/to ev_loop */ 59 | struct event_base 60 | { 61 | int dummy; 62 | }; 63 | 64 | static struct event_base *ev_x_cur; 65 | 66 | static ev_tstamp 67 | ev_tv_get (struct timeval *tv) 68 | { 69 | if (tv) 70 | { 71 | ev_tstamp after = tv->tv_sec + tv->tv_usec * 1e-6; 72 | return after ? after : 1e-6; 73 | } 74 | else 75 | return -1.; 76 | } 77 | 78 | #define EVENT_STRINGIFY(s) # s 79 | #define EVENT_VERSION(a,b) EVENT_STRINGIFY (a) "." EVENT_STRINGIFY (b) 80 | 81 | const char * 82 | event_get_version (void) 83 | { 84 | /* returns ABI, not API or library, version */ 85 | return EVENT_VERSION (EV_VERSION_MAJOR, EV_VERSION_MINOR); 86 | } 87 | 88 | const char * 89 | event_get_method (void) 90 | { 91 | return "libev"; 92 | } 93 | 94 | void *event_init (void) 95 | { 96 | #if EV_MULTIPLICITY 97 | if (ev_x_cur) 98 | ev_x_cur = (struct event_base *)ev_loop_new (EVFLAG_AUTO); 99 | else 100 | ev_x_cur = (struct event_base *)ev_default_loop (EVFLAG_AUTO); 101 | #else 102 | assert (("libev: multiple event bases not supported when not compiled with EV_MULTIPLICITY", !ev_x_cur)); 103 | 104 | ev_x_cur = (struct event_base *)(long)ev_default_loop (EVFLAG_AUTO); 105 | #endif 106 | 107 | return ev_x_cur; 108 | } 109 | 110 | const char * 111 | event_base_get_method (const struct event_base *base) 112 | { 113 | return "libev"; 114 | } 115 | 116 | struct event_base * 117 | event_base_new (void) 118 | { 119 | #if EV_MULTIPLICITY 120 | return (struct event_base *)ev_loop_new (EVFLAG_AUTO); 121 | #else 122 | assert (("libev: multiple event bases not supported when not compiled with EV_MULTIPLICITY")); 123 | return NULL; 124 | #endif 125 | } 126 | 127 | void event_base_free (struct event_base *base) 128 | { 129 | dLOOPbase; 130 | 131 | #if EV_MULTIPLICITY 132 | if (!ev_is_default_loop (loop)) 133 | ev_loop_destroy (loop); 134 | #endif 135 | } 136 | 137 | int event_dispatch (void) 138 | { 139 | return event_base_dispatch (ev_x_cur); 140 | } 141 | 142 | #ifdef EV_STANDALONE 143 | void event_set_log_callback (event_log_cb cb) 144 | { 145 | /* nop */ 146 | } 147 | #endif 148 | 149 | int event_loop (int flags) 150 | { 151 | return event_base_loop (ev_x_cur, flags); 152 | } 153 | 154 | int event_loopexit (struct timeval *tv) 155 | { 156 | return event_base_loopexit (ev_x_cur, tv); 157 | } 158 | 159 | event_callback_fn event_get_callback 160 | (const struct event *ev) 161 | { 162 | return ev->ev_callback; 163 | } 164 | 165 | static void 166 | ev_x_cb (struct event *ev, int revents) 167 | { 168 | revents &= EV_READ | EV_WRITE | EV_TIMER | EV_SIGNAL; 169 | 170 | ev->ev_res = revents; 171 | ev->ev_callback (ev->ev_fd, (short)revents, ev->ev_arg); 172 | } 173 | 174 | static void 175 | ev_x_cb_sig (EV_P_ struct ev_signal *w, int revents) 176 | { 177 | struct event *ev = (struct event *)(((char *)w) - offsetof (struct event, iosig.sig)); 178 | 179 | if (revents & EV_ERROR) 180 | event_del (ev); 181 | 182 | ev_x_cb (ev, revents); 183 | } 184 | 185 | static void 186 | ev_x_cb_io (EV_P_ struct ev_io *w, int revents) 187 | { 188 | struct event *ev = (struct event *)(((char *)w) - offsetof (struct event, iosig.io)); 189 | 190 | if ((revents & EV_ERROR) || !(ev->ev_events & EV_PERSIST)) 191 | event_del (ev); 192 | 193 | ev_x_cb (ev, revents); 194 | } 195 | 196 | static void 197 | ev_x_cb_to (EV_P_ struct ev_timer *w, int revents) 198 | { 199 | struct event *ev = (struct event *)(((char *)w) - offsetof (struct event, to)); 200 | 201 | event_del (ev); 202 | 203 | ev_x_cb (ev, revents); 204 | } 205 | 206 | void event_set (struct event *ev, int fd, short events, void (*cb)(int, short, void *), void *arg) 207 | { 208 | if (events & EV_SIGNAL) 209 | ev_init (&ev->iosig.sig, ev_x_cb_sig); 210 | else 211 | ev_init (&ev->iosig.io, ev_x_cb_io); 212 | 213 | ev_init (&ev->to, ev_x_cb_to); 214 | 215 | ev->ev_base = ev_x_cur; /* not threadsafe, but it's how libevent works */ 216 | ev->ev_fd = fd; 217 | ev->ev_events = events; 218 | ev->ev_pri = 0; 219 | ev->ev_callback = cb; 220 | ev->ev_arg = arg; 221 | ev->ev_res = 0; 222 | ev->ev_flags = EVLIST_INIT; 223 | } 224 | 225 | int event_once (int fd, short events, void (*cb)(int, short, void *), void *arg, struct timeval *tv) 226 | { 227 | return event_base_once (ev_x_cur, fd, events, cb, arg, tv); 228 | } 229 | 230 | int event_add (struct event *ev, struct timeval *tv) 231 | { 232 | dLOOPev; 233 | 234 | if (ev->ev_events & EV_SIGNAL) 235 | { 236 | if (!ev_is_active (&ev->iosig.sig)) 237 | { 238 | ev_signal_set (&ev->iosig.sig, ev->ev_fd); 239 | ev_signal_start (EV_A_ &ev->iosig.sig); 240 | 241 | ev->ev_flags |= EVLIST_SIGNAL; 242 | } 243 | } 244 | else if (ev->ev_events & (EV_READ | EV_WRITE)) 245 | { 246 | if (!ev_is_active (&ev->iosig.io)) 247 | { 248 | ev_io_set (&ev->iosig.io, ev->ev_fd, ev->ev_events & (EV_READ | EV_WRITE)); 249 | ev_io_start (EV_A_ &ev->iosig.io); 250 | 251 | ev->ev_flags |= EVLIST_INSERTED; 252 | } 253 | } 254 | 255 | if (tv) 256 | { 257 | ev->to.repeat = ev_tv_get (tv); 258 | ev_timer_again (EV_A_ &ev->to); 259 | ev->ev_flags |= EVLIST_TIMEOUT; 260 | } 261 | else 262 | { 263 | ev_timer_stop (EV_A_ &ev->to); 264 | ev->ev_flags &= ~EVLIST_TIMEOUT; 265 | } 266 | 267 | ev->ev_flags |= EVLIST_ACTIVE; 268 | 269 | return 0; 270 | } 271 | 272 | int event_del (struct event *ev) 273 | { 274 | dLOOPev; 275 | 276 | if (ev->ev_events & EV_SIGNAL) 277 | ev_signal_stop (EV_A_ &ev->iosig.sig); 278 | else if (ev->ev_events & (EV_READ | EV_WRITE)) 279 | ev_io_stop (EV_A_ &ev->iosig.io); 280 | 281 | if (ev_is_active (&ev->to)) 282 | ev_timer_stop (EV_A_ &ev->to); 283 | 284 | ev->ev_flags = EVLIST_INIT; 285 | 286 | return 0; 287 | } 288 | 289 | void event_active (struct event *ev, int res, short ncalls) 290 | { 291 | dLOOPev; 292 | 293 | if (res & EV_TIMEOUT) 294 | ev_feed_event (EV_A_ &ev->to, res & EV_TIMEOUT); 295 | 296 | if (res & EV_SIGNAL) 297 | ev_feed_event (EV_A_ &ev->iosig.sig, res & EV_SIGNAL); 298 | 299 | if (res & (EV_READ | EV_WRITE)) 300 | ev_feed_event (EV_A_ &ev->iosig.io, res & (EV_READ | EV_WRITE)); 301 | } 302 | 303 | int event_pending (struct event *ev, short events, struct timeval *tv) 304 | { 305 | short revents = 0; 306 | dLOOPev; 307 | 308 | if (ev->ev_events & EV_SIGNAL) 309 | { 310 | /* sig */ 311 | if (ev_is_active (&ev->iosig.sig) || ev_is_pending (&ev->iosig.sig)) 312 | revents |= EV_SIGNAL; 313 | } 314 | else if (ev->ev_events & (EV_READ | EV_WRITE)) 315 | { 316 | /* io */ 317 | if (ev_is_active (&ev->iosig.io) || ev_is_pending (&ev->iosig.io)) 318 | revents |= ev->ev_events & (EV_READ | EV_WRITE); 319 | } 320 | 321 | if (ev->ev_events & EV_TIMEOUT || ev_is_active (&ev->to) || ev_is_pending (&ev->to)) 322 | { 323 | revents |= EV_TIMEOUT; 324 | 325 | if (tv) 326 | { 327 | ev_tstamp at = ev_now (EV_A); 328 | 329 | tv->tv_sec = (long)at; 330 | tv->tv_usec = (long)((at - (ev_tstamp)tv->tv_sec) * 1e6); 331 | } 332 | } 333 | 334 | return events & revents; 335 | } 336 | 337 | int event_priority_init (int npri) 338 | { 339 | return event_base_priority_init (ev_x_cur, npri); 340 | } 341 | 342 | int event_priority_set (struct event *ev, int pri) 343 | { 344 | ev->ev_pri = pri; 345 | 346 | return 0; 347 | } 348 | 349 | int event_base_set (struct event_base *base, struct event *ev) 350 | { 351 | ev->ev_base = base; 352 | 353 | return 0; 354 | } 355 | 356 | int event_base_loop (struct event_base *base, int flags) 357 | { 358 | dLOOPbase; 359 | 360 | return !ev_run (EV_A_ flags); 361 | } 362 | 363 | int event_base_dispatch (struct event_base *base) 364 | { 365 | return event_base_loop (base, 0); 366 | } 367 | 368 | static void 369 | ev_x_loopexit_cb (int revents, void *base) 370 | { 371 | dLOOPbase; 372 | 373 | ev_break (EV_A_ EVBREAK_ONE); 374 | } 375 | 376 | int event_base_loopexit (struct event_base *base, struct timeval *tv) 377 | { 378 | ev_tstamp after = ev_tv_get (tv); 379 | dLOOPbase; 380 | 381 | ev_once (EV_A_ -1, 0, after >= 0. ? after : 0., ev_x_loopexit_cb, (void *)base); 382 | 383 | return 0; 384 | } 385 | 386 | struct ev_x_once 387 | { 388 | int fd; 389 | void (*cb)(int, short, void *); 390 | void *arg; 391 | }; 392 | 393 | static void 394 | ev_x_once_cb (int revents, void *arg) 395 | { 396 | struct ev_x_once *once = (struct ev_x_once *)arg; 397 | 398 | once->cb (once->fd, (short)revents, once->arg); 399 | free (once); 400 | } 401 | 402 | int event_base_once (struct event_base *base, int fd, short events, void (*cb)(int, short, void *), void *arg, struct timeval *tv) 403 | { 404 | struct ev_x_once *once = (struct ev_x_once *)malloc (sizeof (struct ev_x_once)); 405 | dLOOPbase; 406 | 407 | if (!once) 408 | return -1; 409 | 410 | once->fd = fd; 411 | once->cb = cb; 412 | once->arg = arg; 413 | 414 | ev_once (EV_A_ fd, events & (EV_READ | EV_WRITE), ev_tv_get (tv), ev_x_once_cb, (void *)once); 415 | 416 | return 0; 417 | } 418 | 419 | int event_base_priority_init (struct event_base *base, int npri) 420 | { 421 | /*dLOOPbase;*/ 422 | 423 | return 0; 424 | } 425 | 426 | -------------------------------------------------------------------------------- /libev/event.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libevent compatibility header, only core events supported 3 | * 4 | * Copyright (c) 2007,2008,2010,2012 Marc Alexander Lehmann 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without modifica- 8 | * tion, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- 19 | * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 20 | * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- 21 | * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- 25 | * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 26 | * OF THE POSSIBILITY OF SUCH DAMAGE. 27 | * 28 | * Alternatively, the contents of this file may be used under the terms of 29 | * the GNU General Public License ("GPL") version 2 or any later version, 30 | * in which case the provisions of the GPL are applicable instead of 31 | * the above. If you wish to allow the use of your version of this file 32 | * only under the terms of the GPL and not to allow others to use your 33 | * version of this file under the BSD license, indicate your decision 34 | * by deleting the provisions above and replace them with the notice 35 | * and other provisions required by the GPL. If you do not delete the 36 | * provisions above, a recipient may use your version of this file under 37 | * either the BSD or the GPL. 38 | */ 39 | 40 | #ifndef EVENT_H_ 41 | #define EVENT_H_ 42 | 43 | #ifdef EV_H 44 | # include EV_H 45 | #else 46 | # include "ev.h" 47 | #endif 48 | 49 | #ifndef EVLOOP_NONBLOCK 50 | # define EVLOOP_NONBLOCK EVRUN_NOWAIT 51 | #endif 52 | #ifndef EVLOOP_ONESHOT 53 | # define EVLOOP_ONESHOT EVRUN_ONCE 54 | #endif 55 | #ifndef EV_TIMEOUT 56 | # define EV_TIMEOUT EV_TIMER 57 | #endif 58 | 59 | #ifdef __cplusplus 60 | extern "C" { 61 | #endif 62 | 63 | /* we need sys/time.h for struct timeval only */ 64 | #if !defined (WIN32) || defined (__MINGW32__) 65 | # include /* mingw seems to need this, for whatever reason */ 66 | # include 67 | #endif 68 | 69 | struct event_base; 70 | 71 | #define EVLIST_TIMEOUT 0x01 72 | #define EVLIST_INSERTED 0x02 73 | #define EVLIST_SIGNAL 0x04 74 | #define EVLIST_ACTIVE 0x08 75 | #define EVLIST_INTERNAL 0x10 76 | #define EVLIST_INIT 0x80 77 | 78 | typedef void (*event_callback_fn)(int, short, void *); 79 | 80 | struct event 81 | { 82 | /* libev watchers we map onto */ 83 | union { 84 | struct ev_io io; 85 | struct ev_signal sig; 86 | } iosig; 87 | struct ev_timer to; 88 | 89 | /* compatibility slots */ 90 | struct event_base *ev_base; 91 | event_callback_fn ev_callback; 92 | void *ev_arg; 93 | int ev_fd; 94 | int ev_pri; 95 | int ev_res; 96 | int ev_flags; 97 | short ev_events; 98 | }; 99 | 100 | event_callback_fn event_get_callback (const struct event *ev); 101 | 102 | #define EV_READ EV_READ 103 | #define EV_WRITE EV_WRITE 104 | #define EV_PERSIST 0x10 105 | #define EV_ET 0x20 /* nop */ 106 | 107 | #define EVENT_SIGNAL(ev) ((int) (ev)->ev_fd) 108 | #define EVENT_FD(ev) ((int) (ev)->ev_fd) 109 | 110 | #define event_initialized(ev) ((ev)->ev_flags & EVLIST_INIT) 111 | 112 | #define evtimer_add(ev,tv) event_add (ev, tv) 113 | #define evtimer_set(ev,cb,data) event_set (ev, -1, 0, cb, data) 114 | #define evtimer_del(ev) event_del (ev) 115 | #define evtimer_pending(ev,tv) event_pending (ev, EV_TIMEOUT, tv) 116 | #define evtimer_initialized(ev) event_initialized (ev) 117 | 118 | #define timeout_add(ev,tv) evtimer_add (ev, tv) 119 | #define timeout_set(ev,cb,data) evtimer_set (ev, cb, data) 120 | #define timeout_del(ev) evtimer_del (ev) 121 | #define timeout_pending(ev,tv) evtimer_pending (ev, tv) 122 | #define timeout_initialized(ev) evtimer_initialized (ev) 123 | 124 | #define signal_add(ev,tv) event_add (ev, tv) 125 | #define signal_set(ev,sig,cb,data) event_set (ev, sig, EV_SIGNAL | EV_PERSIST, cb, data) 126 | #define signal_del(ev) event_del (ev) 127 | #define signal_pending(ev,tv) event_pending (ev, EV_SIGNAL, tv) 128 | #define signal_initialized(ev) event_initialized (ev) 129 | 130 | const char *event_get_version (void); 131 | const char *event_get_method (void); 132 | 133 | void *event_init (void); 134 | void event_base_free (struct event_base *base); 135 | 136 | #define EVLOOP_ONCE EVLOOP_ONESHOT 137 | int event_loop (int); 138 | int event_loopexit (struct timeval *tv); 139 | int event_dispatch (void); 140 | 141 | #define _EVENT_LOG_DEBUG 0 142 | #define _EVENT_LOG_MSG 1 143 | #define _EVENT_LOG_WARN 2 144 | #define _EVENT_LOG_ERR 3 145 | typedef void (*event_log_cb)(int severity, const char *msg); 146 | void event_set_log_callback(event_log_cb cb); 147 | 148 | void event_set (struct event *ev, int fd, short events, void (*cb)(int, short, void *), void *arg); 149 | int event_once (int fd, short events, void (*cb)(int, short, void *), void *arg, struct timeval *tv); 150 | 151 | int event_add (struct event *ev, struct timeval *tv); 152 | int event_del (struct event *ev); 153 | void event_active (struct event *ev, int res, short ncalls); /* ncalls is being ignored */ 154 | 155 | int event_pending (struct event *ev, short, struct timeval *tv); 156 | 157 | int event_priority_init (int npri); 158 | int event_priority_set (struct event *ev, int pri); 159 | 160 | struct event_base *event_base_new (void); 161 | const char *event_base_get_method (const struct event_base *); 162 | int event_base_set (struct event_base *base, struct event *ev); 163 | int event_base_loop (struct event_base *base, int); 164 | int event_base_loopexit (struct event_base *base, struct timeval *tv); 165 | int event_base_dispatch (struct event_base *base); 166 | int event_base_once (struct event_base *base, int fd, short events, void (*cb)(int, short, void *), void *arg, struct timeval *tv); 167 | int event_base_priority_init (struct event_base *base, int fd); 168 | 169 | /* next line is different in the libevent+libev version */ 170 | /*libevent-include*/ 171 | 172 | #ifdef __cplusplus 173 | } 174 | #endif 175 | 176 | #endif 177 | 178 | -------------------------------------------------------------------------------- /libev/event_compat.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2004 Niels Provos 3 | * Copyright (c) 2008 Marc Alexander Lehmann 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 3. The name of the author may not be used to endorse or promote products 15 | * derived from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | #ifdef __cplusplus 29 | extern "C" { 30 | #endif 31 | 32 | #ifdef _WIN32 33 | # define WIN32_LEAN_AND_MEAN 34 | # include 35 | # undef WIN32_LEAN_AND_MEAN 36 | typedef unsigned char u_char; 37 | typedef unsigned short u_short; 38 | #else 39 | # include 40 | # include 41 | # include 42 | #endif 43 | 44 | #include 45 | 46 | /* Fix so that ppl dont have to run with */ 47 | #ifndef TAILQ_ENTRY 48 | #define _EVENT_DEFINED_TQENTRY 49 | #define TAILQ_ENTRY(type) \ 50 | struct { \ 51 | struct type *tqe_next; /* next element */ \ 52 | struct type **tqe_prev; /* address of previous next element */ \ 53 | } 54 | #endif /* !TAILQ_ENTRY */ 55 | #ifndef RB_ENTRY 56 | #define _EVENT_DEFINED_RBENTRY 57 | #define RB_ENTRY(type) \ 58 | struct { \ 59 | struct type *rbe_left; /* left element */ \ 60 | struct type *rbe_right; /* right element */ \ 61 | struct type *rbe_parent; /* parent element */ \ 62 | int rbe_color; /* node color */ \ 63 | } 64 | #endif /* !RB_ENTRY */ 65 | 66 | /* 67 | * Key-Value pairs. Can be used for HTTP headers but also for 68 | * query argument parsing. 69 | */ 70 | struct evkeyval { 71 | TAILQ_ENTRY(evkeyval) next; 72 | 73 | char *key; 74 | char *value; 75 | }; 76 | 77 | #ifdef _EVENT_DEFINED_TQENTRY 78 | #undef TAILQ_ENTRY 79 | struct event_list; 80 | struct evkeyvalq; 81 | #undef _EVENT_DEFINED_TQENTRY 82 | #else 83 | TAILQ_HEAD (event_list, event); 84 | TAILQ_HEAD (evkeyvalq, evkeyval); 85 | #endif /* _EVENT_DEFINED_TQENTRY */ 86 | #ifdef _EVENT_DEFINED_RBENTRY 87 | #undef RB_ENTRY 88 | #undef _EVENT_DEFINED_RBENTRY 89 | #endif /* _EVENT_DEFINED_RBENTRY */ 90 | 91 | struct eventop { 92 | char *name; 93 | void *(*init)(struct event_base *); 94 | int (*add)(void *, struct event *); 95 | int (*del)(void *, struct event *); 96 | int (*recalc)(struct event_base *, void *, int); 97 | int (*dispatch)(struct event_base *, void *, struct timeval *); 98 | void (*dealloc)(struct event_base *, void *); 99 | }; 100 | 101 | /* These functions deal with buffering input and output */ 102 | 103 | struct evbuffer { 104 | u_char *buffer; 105 | u_char *orig_buffer; 106 | 107 | size_t misalign; 108 | size_t totallen; 109 | size_t off; 110 | 111 | void (*cb)(struct evbuffer *, size_t, size_t, void *); 112 | void *cbarg; 113 | }; 114 | 115 | /* Just for error reporting - use other constants otherwise */ 116 | #define EVBUFFER_READ 0x01 117 | #define EVBUFFER_WRITE 0x02 118 | #define EVBUFFER_EOF 0x10 119 | #define EVBUFFER_ERROR 0x20 120 | #define EVBUFFER_TIMEOUT 0x40 121 | 122 | struct bufferevent; 123 | typedef void (*evbuffercb)(struct bufferevent *, void *); 124 | typedef void (*everrorcb)(struct bufferevent *, short what, void *); 125 | 126 | struct event_watermark { 127 | size_t low; 128 | size_t high; 129 | }; 130 | 131 | struct bufferevent { 132 | struct event ev_read; 133 | struct event ev_write; 134 | 135 | struct evbuffer *input; 136 | struct evbuffer *output; 137 | 138 | struct event_watermark wm_read; 139 | struct event_watermark wm_write; 140 | 141 | evbuffercb readcb; 142 | evbuffercb writecb; 143 | everrorcb errorcb; 144 | void *cbarg; 145 | 146 | int timeout_read; /* in seconds */ 147 | int timeout_write; /* in seconds */ 148 | 149 | short enabled; /* events that are currently enabled */ 150 | }; 151 | 152 | struct bufferevent *bufferevent_new(int fd, 153 | evbuffercb readcb, evbuffercb writecb, everrorcb errorcb, void *cbarg); 154 | int bufferevent_base_set(struct event_base *base, struct bufferevent *bufev); 155 | int bufferevent_priority_set(struct bufferevent *bufev, int pri); 156 | void bufferevent_free(struct bufferevent *bufev); 157 | int bufferevent_write(struct bufferevent *bufev, const void *data, size_t size); 158 | int bufferevent_write_buffer(struct bufferevent *bufev, struct evbuffer *buf); 159 | size_t bufferevent_read(struct bufferevent *bufev, void *data, size_t size); 160 | int bufferevent_enable(struct bufferevent *bufev, short event); 161 | int bufferevent_disable(struct bufferevent *bufev, short event); 162 | void bufferevent_settimeout(struct bufferevent *bufev, 163 | int timeout_read, int timeout_write); 164 | 165 | #define EVBUFFER_LENGTH(x) (x)->off 166 | #define EVBUFFER_DATA(x) (x)->buffer 167 | #define EVBUFFER_INPUT(x) (x)->input 168 | #define EVBUFFER_OUTPUT(x) (x)->output 169 | 170 | struct evbuffer *evbuffer_new(void); 171 | void evbuffer_free(struct evbuffer *); 172 | int evbuffer_expand(struct evbuffer *, size_t); 173 | int evbuffer_add(struct evbuffer *, const void *, size_t); 174 | int evbuffer_remove(struct evbuffer *, void *, size_t); 175 | char *evbuffer_readline(struct evbuffer *); 176 | int evbuffer_add_buffer(struct evbuffer *, struct evbuffer *); 177 | int evbuffer_add_printf(struct evbuffer *, const char *fmt, ...); 178 | int evbuffer_add_vprintf(struct evbuffer *, const char *fmt, va_list ap); 179 | void evbuffer_drain(struct evbuffer *, size_t); 180 | int evbuffer_write(struct evbuffer *, int); 181 | int evbuffer_read(struct evbuffer *, int, int); 182 | u_char *evbuffer_find(struct evbuffer *, const u_char *, size_t); 183 | void evbuffer_setcb(struct evbuffer *, void (*)(struct evbuffer *, size_t, size_t, void *), void *); 184 | 185 | /* 186 | * Marshaling tagged data - We assume that all tags are inserted in their 187 | * numeric order - so that unknown tags will always be higher than the 188 | * known ones - and we can just ignore the end of an event buffer. 189 | */ 190 | 191 | void evtag_init(void); 192 | 193 | void evtag_marshal(struct evbuffer *evbuf, uint32_t tag, const void *data, 194 | uint32_t len); 195 | 196 | void encode_int(struct evbuffer *evbuf, uint32_t number); 197 | 198 | void evtag_marshal_int(struct evbuffer *evbuf, uint32_t tag, uint32_t integer); 199 | 200 | void evtag_marshal_string(struct evbuffer *buf, uint32_t tag, 201 | const char *string); 202 | 203 | void evtag_marshal_timeval(struct evbuffer *evbuf, uint32_t tag, 204 | struct timeval *tv); 205 | 206 | int evtag_unmarshal(struct evbuffer *src, uint32_t *ptag, struct evbuffer *dst); 207 | int evtag_peek(struct evbuffer *evbuf, uint32_t *ptag); 208 | int evtag_peek_length(struct evbuffer *evbuf, uint32_t *plength); 209 | int evtag_payload_length(struct evbuffer *evbuf, uint32_t *plength); 210 | int evtag_consume(struct evbuffer *evbuf); 211 | 212 | int evtag_unmarshal_int(struct evbuffer *evbuf, uint32_t need_tag, 213 | uint32_t *pinteger); 214 | 215 | int evtag_unmarshal_fixed(struct evbuffer *src, uint32_t need_tag, void *data, 216 | size_t len); 217 | 218 | int evtag_unmarshal_string(struct evbuffer *evbuf, uint32_t need_tag, 219 | char **pstring); 220 | 221 | int evtag_unmarshal_timeval(struct evbuffer *evbuf, uint32_t need_tag, 222 | struct timeval *ptv); 223 | 224 | #ifdef __cplusplus 225 | } 226 | #endif 227 | -------------------------------------------------------------------------------- /libev/import_libevent: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | LE=../libevent-1.4.3-stable 4 | 5 | if ! [ -e evbuffer.c ]; then 6 | echo do not run this programm unless you know what you are doing 7 | exit 1 8 | fi 9 | 10 | # this program combines libev and libevent into a single package 11 | 12 | cvs update -AdP libev 13 | rsync -avP libev/. . --exclude CVS 14 | 15 | rm -f configure.ac 16 | 17 | cp $LE/evdns.h . 18 | 19 | perl -i -pe 's%^/.libevent-include./%#include "event_compat.h"%' event.h 20 | 21 | perl -ne ' 22 | s/\s+char buf\[64\];/\tchar buf[96];/; 23 | if (/#include "event.h"/) { 24 | print "#ifndef EV_STANDALONE\n$_#endif\n"; 25 | next; 26 | } 27 | if (/#include "misc.h"/) { 28 | print "#ifndef EV_STANDALONE\n$_#endif\n"; 29 | next; 30 | } 31 | if (/#include "(unistd.h|sys\/time.h)"/) { 32 | print "#ifndef WIN32\n$_#endif\n"; 33 | next; 34 | } 35 | next if /#include "log.h"/; 36 | 37 | print; 38 | ' <$LE/evdns.c >evdns.c 39 | 40 | cp $LE/autogen.sh . 41 | cp $LE/epoll_sub.c . 42 | cp $LE/evbuffer.c . 43 | cp $LE/buffer.c . 44 | cp $LE/evhttp.h . 45 | cp $LE/evutil.h . 46 | cp $LE/evutil.c . 47 | cp $LE/event-config.h . 48 | cp $LE/event-internal.h . 49 | cp $LE/evrpc.h . 50 | cp $LE/evrpc.c . 51 | cp $LE/evrpc-internal.h . 52 | cp $LE/http.c . 53 | cp $LE/event_tagging.c . 54 | cp $LE/http-internal.h . 55 | cp $LE/strlcpy-internal.h . 56 | cp $LE/log.c . 57 | cp $LE/log.h . 58 | cp $LE/strlcpy.c . 59 | rsync -a $LE/WIN32* $LE/sample $LE/test $LE/compat . --del 60 | #rename 's/libevent/libev/' WIN32-Prj/lib* 61 | cp $LE/aclocal.m4 . 62 | #cp $LE/acconfig.h . 63 | cp $LE/config.h.in . 64 | cp $LE/event_rpcgen.py . 65 | cp $LE/*.3 . 66 | 67 | #perl -i -pe 's/libevent/libev/g' sample/Makefile.am 68 | #perl -i -pe 's/libevent/libev/g' test/Makefile.am 69 | 70 | perl -i -pe 's/#include $/#include "event.h"/' test/*.c 71 | 72 | perl -i -ne ' 73 | next if /"event-internal.h"/; 74 | s/base\d?->sig.ev_signal_added/0/; 75 | s/base\d?->sig.ev_signal_pair\[0\]/-1/; 76 | s/base->sig.evsignal_caught/0/; 77 | next if /^\ttest_signal_(dealloc|pipeloss|switchbase|assert|restore)\(\)/; 78 | next if /^\ttest_simplesignal\(\)/; # non-default-loop 79 | next if /^\ttest_immediatesignal\(\)/; # non-default-loop 80 | next if /test_priorities\(\d\)/; 81 | print; 82 | ' test/regress.c 83 | 84 | perl -ne ' 85 | s/\bmin_heap.h\b//g; 86 | s/\bsignal.c\b//g; 87 | s/\bevport.c\b//g; 88 | s/\bkqueue.c\b//g; 89 | s/\bdevpoll.c\b//g; 90 | s/\brtsig.c\b//g; 91 | s/\bselect.c\b//g; 92 | s/\bpoll.c\b//g; 93 | s/\bepoll.c\b//g; 94 | s/\bepoll_sub.c\b//g; 95 | s/\bevent-internal.h\b//g; 96 | s/\bevsignal.h\b//g; 97 | s/^(man_MANS\s*=)/$1 ev.3 /; 98 | s/^(EXTRA_DIST\s*=)/$1 libev.m4 ev.h ev_vars.h ev_wrap.h event_compat.h ev++.h ev_epoll.c ev_select.c ev_poll.c ev_kqueue.c ev_port.c ev_win32.c ev.3 ev.pod /; 99 | s/^(include_HEADERS\s*=)/$1 ev.h event_compat.h ev++.h /; 100 | s/^(CORE_SRC\s*=)/$1 ev.c /; 101 | s/^(SYS_LIBS\s*=)/$1 -lm /; 102 | #s/libevent/libev/g; 103 | print; 104 | ' <$LE/Makefile.am >Makefile.am 105 | 106 | perl -ne ' 107 | #s/-Wall/-Wall -Wno-comment -Wunused-function -Wno-unused-value/; 108 | s/-Wall//g; 109 | #s/libevent/libev/g; 110 | #VERSION 111 | s/AM_INIT_AUTOMAKE\s*\(.*,(.*)\)/AM_INIT_AUTOMAKE(libevent-$1+libev,3.1)/; 112 | s/AC_LIBOBJ\(select\)/: ;/g; 113 | s/AC_LIBOBJ\(poll\)/: ;/g; 114 | s/AC_LIBOBJ\(kqueue\)/: ;/g; 115 | s/AC_LIBOBJ\(epoll\)/: ;/g; 116 | s/AC_LIBOBJ\(devpoll\)/: ;/g; 117 | s/AC_LIBOBJ\(evport\)/: ;/g; 118 | s/AC_LIBOBJ\(signal\)/: ;/g; 119 | s/AC_LIBOBJ\(rtsig\)/: ;/g; 120 | print "m4_include([libev.m4])\n" if /^AC_OUTPUT/; 121 | print; 122 | ' <$LE/configure.in >configure.in 123 | 124 | aclocal-1.7 125 | automake-1.7 --add-missing 126 | autoconf 127 | autoheader 128 | libtoolize 129 | CC="ccache gcc" ./configure --prefix=/opt/libev --disable-shared "$@" 130 | 131 | 132 | -------------------------------------------------------------------------------- /libev/libev.m4: -------------------------------------------------------------------------------- 1 | dnl this file is part of libev, do not make local modifications 2 | dnl http://software.schmorp.de/pkg/libev 3 | 4 | dnl libev support 5 | AC_CHECK_HEADERS(sys/inotify.h sys/epoll.h sys/event.h port.h poll.h sys/select.h sys/eventfd.h sys/signalfd.h) 6 | 7 | AC_CHECK_FUNCS(inotify_init epoll_ctl kqueue port_create poll select eventfd signalfd) 8 | 9 | AC_CHECK_FUNCS(clock_gettime, [], [ 10 | dnl on linux, try syscall wrapper first 11 | if test $(uname) = Linux; then 12 | AC_MSG_CHECKING(for clock_gettime syscall) 13 | AC_LINK_IFELSE([AC_LANG_PROGRAM( 14 | [#include 15 | #include 16 | #include ], 17 | [struct timespec ts; int status = syscall (SYS_clock_gettime, CLOCK_REALTIME, &ts)])], 18 | [ac_have_clock_syscall=1 19 | AC_DEFINE(HAVE_CLOCK_SYSCALL, 1, Define to 1 to use the syscall interface for clock_gettime) 20 | AC_MSG_RESULT(yes)], 21 | [AC_MSG_RESULT(no)]) 22 | fi 23 | if test -z "$LIBEV_M4_AVOID_LIBRT" && test -z "$ac_have_clock_syscall"; then 24 | AC_CHECK_LIB(rt, clock_gettime) 25 | unset ac_cv_func_clock_gettime 26 | AC_CHECK_FUNCS(clock_gettime) 27 | fi 28 | ]) 29 | 30 | AC_CHECK_FUNCS(nanosleep, [], [ 31 | if test -z "$LIBEV_M4_AVOID_LIBRT"; then 32 | AC_CHECK_LIB(rt, nanosleep) 33 | unset ac_cv_func_nanosleep 34 | AC_CHECK_FUNCS(nanosleep) 35 | fi 36 | ]) 37 | 38 | if test -z "$LIBEV_M4_AVOID_LIBM"; then 39 | LIBM=m 40 | fi 41 | AC_SEARCH_LIBS(floor, $LIBM, [AC_DEFINE(HAVE_FLOOR, 1, Define to 1 if the floor function is available)]) 42 | 43 | -------------------------------------------------------------------------------- /libev/update_ev_c: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | ( 4 | sed -ne '1,\%/\* ECB.H BEGIN \*/%p' ev.c 5 | cat ~/src/libecb/ecb.h 6 | sed -ne '\%/\* ECB.H END \*/%,$p' ev.c 7 | ) >ev.c~ && mv ev.c~ ev.c 8 | 9 | -------------------------------------------------------------------------------- /libev/update_ev_wrap: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ( 4 | echo '#define VAR(name,decl) name' 5 | echo '#define EV_GENWRAP 1' 6 | cat ev_vars.h 7 | ) | cc -E -o - - | perl -ne ' 8 | while (<>) { 9 | push @syms, $1 if /(^\w+)/; 10 | } 11 | print "/* DO NOT EDIT, automatically generated by update_ev_wrap */\n", 12 | "#ifndef EV_WRAP_H\n", 13 | "#define EV_WRAP_H\n", 14 | (map "#define $_ ((loop)->$_)\n", sort @syms), 15 | "#else\n", 16 | "#undef EV_WRAP_H\n", 17 | (map "#undef $_\n", sort @syms), 18 | "#endif\n"; 19 | ' >ev_wrap.h 20 | -------------------------------------------------------------------------------- /libev/update_symbols: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | make ev.o event.o || exit 4 | 5 | nm ev.o | perl -ne 'print "$1\n" if /\S+ [A-Z] (\S+)/' > Symbols.ev 6 | nm event.o | perl -ne 'print "$1\n" if /\S+ [A-Z] (\S+)/' > Symbols.event 7 | 8 | -------------------------------------------------------------------------------- /log.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int log_level=log_info; 5 | 6 | int enable_log_position=0; 7 | int enable_log_color=1; 8 | 9 | 10 | void log0(const char * file,const char * function,int line,int level,const char* str, ...) { 11 | 12 | if(level>log_level) return ; 13 | if(level>log_trace||level<0) return ; 14 | 15 | 16 | time_t timer; 17 | char buffer[100]; 18 | struct tm* tm_info; 19 | 20 | time(&timer); 21 | tm_info = localtime(&timer); 22 | 23 | if(enable_log_color) 24 | printf("%s",log_color[level]); 25 | 26 | strftime(buffer, 100, "%Y-%m-%d %H:%M:%S", tm_info); 27 | printf("[%s][%s]",buffer,log_text[level]); 28 | 29 | if(enable_log_position)printf("[%s,func:%s,line:%d]",file,function,line); 30 | 31 | va_list vlist; 32 | va_start(vlist, str); 33 | vfprintf(stdout, str, vlist); 34 | va_end(vlist); 35 | if(enable_log_color) 36 | printf("%s",RESET); 37 | 38 | //printf("\n"); 39 | //if(enable_log_color) 40 | //printf(log_color[level]); 41 | fflush(stdout); 42 | 43 | if(log_level==log_fatal) 44 | { 45 | about_to_exit=1; 46 | } 47 | } 48 | 49 | void log_bare(int level,const char* str, ...) 50 | { 51 | if(level>log_level) return ; 52 | if(level>log_trace||level<0) return ; 53 | if(enable_log_color) 54 | printf("%s",log_color[level]); 55 | va_list vlist; 56 | va_start(vlist, str); 57 | vfprintf(stdout, str, vlist); 58 | va_end(vlist); 59 | if(enable_log_color) 60 | printf("%s",RESET); 61 | fflush(stdout); 62 | 63 | } 64 | -------------------------------------------------------------------------------- /log.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | //#ifndef _LOG_MYLOG_H_ 4 | //#define _LOG_MYLOG_H_ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | //#include 14 | 15 | //#include 16 | #include 17 | 18 | #include 19 | //#include 20 | 21 | //#include 22 | 23 | using namespace std; 24 | 25 | 26 | #define RED "\x1B[31m" 27 | #define GRN "\x1B[32m" 28 | #define YEL "\x1B[33m" 29 | #define BLU "\x1B[34m" 30 | #define MAG "\x1B[35m" 31 | #define CYN "\x1B[36m" 32 | #define WHT "\x1B[37m" 33 | #define RESET "\x1B[0m" 34 | 35 | 36 | const int log_never=0; 37 | const int log_fatal=1; 38 | const int log_error=2; 39 | const int log_warn=3; 40 | const int log_info=4; 41 | const int log_debug=5; 42 | const int log_trace=6; 43 | const int log_end=7; 44 | 45 | const char log_text[][20]={"NEVER","FATAL","ERROR","WARN","INFO","DEBUG","TRACE",""}; 46 | const char log_color[][20]={RED,RED,RED,YEL,GRN,MAG,""}; 47 | 48 | extern int log_level; 49 | extern int enable_log_position; 50 | extern int enable_log_color; 51 | 52 | 53 | #ifdef MY_DEBUG 54 | #define mylog(__first_argu__dummy_abcde__,...) printf(__VA_ARGS__) 55 | 56 | #else 57 | #define mylog(...) log0(__FILE__,__FUNCTION__,__LINE__,__VA_ARGS__) 58 | #endif 59 | 60 | 61 | //#define mylog(__first_argu__dummy_abcde__,...) {;} 62 | 63 | void log0(const char * file,const char * function,int line,int level,const char* str, ...); 64 | 65 | void log_bare(int level,const char* str, ...); 66 | 67 | 68 | //#endif 69 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | cc_cross=/home/wangyu/Desktop/arm-2014.05/bin/arm-none-linux-gnueabi-g++ 2 | cc_local=g++ 3 | cc_mips24kc_be=/toolchains/lede-sdk-17.01.2-ar71xx-generic_gcc-5.4.0_musl-1.1.16.Linux-x86_64/staging_dir/toolchain-mips_24kc_gcc-5.4.0_musl-1.1.16/bin/mips-openwrt-linux-musl-g++ 4 | cc_mips24kc_le=/toolchains/lede-sdk-17.01.2-ramips-mt7621_gcc-5.4.0_musl-1.1.16.Linux-x86_64/staging_dir/toolchain-mipsel_24kc_gcc-5.4.0_musl-1.1.16/bin/mipsel-openwrt-linux-musl-g++ 5 | cc_arm= /toolchains/lede-sdk-17.01.2-bcm53xx_gcc-5.4.0_musl-1.1.16_eabi.Linux-x86_64/staging_dir/toolchain-arm_cortex-a9_gcc-5.4.0_musl-1.1.16_eabi/bin/arm-openwrt-linux-c++ 6 | cc_mingw_cross=i686-w64-mingw32-g++-posix 7 | cc_mac_cross=o64-clang++ -stdlib=libc++ 8 | cc_x86=/toolchains/lede-sdk-17.01.2-x86-generic_gcc-5.4.0_musl-1.1.16.Linux-x86_64/staging_dir/toolchain-i386_pentium4_gcc-5.4.0_musl-1.1.16/bin/i486-openwrt-linux-c++ 9 | cc_amd64=/toolchains/lede-sdk-17.01.2-x86-64_gcc-5.4.0_musl-1.1.16.Linux-x86_64/staging_dir/toolchain-x86_64_gcc-5.4.0_musl-1.1.16/bin/x86_64-openwrt-linux-c++ 10 | #cc_bcm2708=/home/wangyu/raspberry/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-g++ 11 | 12 | 13 | SOURCES0=main.cpp log.cpp common.cpp fd_manager.cpp 14 | SOURCES=${SOURCES0} my_ev.cpp -isystem libev 15 | NAME=tinymapper 16 | 17 | 18 | FLAGS= -std=c++11 -Wall -Wextra -Wno-unused-variable -Wno-unused-parameter -Wno-missing-field-initializers ${OPT} 19 | TARGETS=amd64 arm mips24kc_be x86 mips24kc_le 20 | 21 | TAR=${NAME}_binaries.tar.gz `echo ${TARGETS}|sed -r 's/([^ ]+)/${NAME}_\1/g'` version.txt 22 | 23 | export STAGING_DIR=/tmp/ #just for supress warning of staging_dir not define 24 | 25 | # targets for nativei (non-cross) compile 26 | all:git_version 27 | rm -f ${NAME} 28 | ${cc_local} -o ${NAME} -I. ${SOURCES} ${FLAGS} -lrt -ggdb -static -O2 29 | 30 | freebsd:git_version 31 | rm -f ${NAME} 32 | ${cc_local} -o ${NAME} -I. ${SOURCES} ${FLAGS} -lrt -ggdb -static -O2 33 | 34 | mingw:git_version 35 | rm -f ${NAME} 36 | ${cc_local} -o ${NAME} -I. ${SOURCES} ${FLAGS} -ggdb -static -O2 -lws2_32 37 | 38 | mingw_wepoll:git_version #to compile you need a pacthed version of libev with wepoll backend 39 | rm -f ${NAME} 40 | ${cc_local} -o ${NAME} -I. ${SOURCES0} ${FLAGS} -ggdb -static -O2 -DNO_LIBEV_EMBED -D_WIN32 -lev -lws2_32 41 | 42 | mac:git_version 43 | rm -f ${NAME} 44 | ${cc_local} -o ${NAME} -I. ${SOURCES} ${FLAGS} -ggdb -O2 45 | 46 | cygwin:git_version 47 | rm -f ${NAME} 48 | ${cc_local} -o ${NAME} -I. ${SOURCES} ${FLAGS} -lrt -ggdb -static -O2 -D_GNU_SOURCE 49 | 50 | #targes for general cross compile 51 | 52 | cross:git_version 53 | ${cc_cross} -o ${NAME}_cross -I. ${SOURCES} ${FLAGS} -lrt -O2 54 | 55 | cross2:git_version 56 | ${cc_cross} -o ${NAME}_cross -I. ${SOURCES} ${FLAGS} -lrt -static -lgcc_eh -O2 57 | 58 | cross3:git_version 59 | ${cc_cross} -o ${NAME}_cross -I. ${SOURCES} ${FLAGS} -lrt -static -O2 60 | 61 | #targets only for debug purpose 62 | fast: git_version 63 | rm -f ${NAME} 64 | ${cc_local} -o ${NAME} -I. ${SOURCES} ${FLAGS} -lrt -ggdb 65 | debug: git_version 66 | rm -f ${NAME} 67 | ${cc_local} -o ${NAME} -I. ${SOURCES} ${FLAGS} -lrt -Wformat-nonliteral -D MY_DEBUG -ggdb 68 | debug2: git_version 69 | rm -f ${NAME} 70 | ${cc_local} -o ${NAME} -I. ${SOURCES} ${FLAGS} -lrt -Wformat-nonliteral -ggdb 71 | 72 | #targets only for 'make release' 73 | 74 | mips24kc_be: git_version 75 | ${cc_mips24kc_be} -o ${NAME}_$@ -I. ${SOURCES} ${FLAGS} -lrt -lgcc_eh -static -O2 76 | 77 | mips24kc_le: git_version 78 | ${cc_mips24kc_le} -o ${NAME}_$@ -I. ${SOURCES} ${FLAGS} -lrt -lgcc_eh -static -O2 79 | 80 | amd64:git_version 81 | ${cc_amd64} -o ${NAME}_$@ -I. ${SOURCES} ${FLAGS} -lrt -static -O2 -lgcc_eh -ggdb 82 | 83 | x86:git_version #to build this you need 'g++-multilib' installed 84 | ${cc_x86} -o ${NAME}_$@ -I. ${SOURCES} ${FLAGS} -lrt -static -O2 -lgcc_eh -ggdb 85 | arm:git_version 86 | ${cc_arm} -o ${NAME}_$@ -I. ${SOURCES} ${FLAGS} -lrt -static -O2 -lgcc_eh 87 | 88 | 89 | release: ${TARGETS} 90 | cp git_version.h version.txt 91 | tar -zcvf ${TAR} 92 | 93 | #targets for cross compile windows targets on linux 94 | 95 | mingw_cross:git_version #to build this and the below one you need 'mingw-w64' installed (the cross compile version on linux) 96 | ${cc_mingw_cross} -o ${NAME}.exe -I. ${SOURCES} ${FLAGS} -ggdb -static -O2 -lws2_32 97 | 98 | mingw_cross_wepoll:git_version #to compile you need a pacthed version of libev with wepoll backend installed 99 | ${cc_mingw_cross} -o ${NAME}_wepoll.exe -I. ${SOURCES0} ${FLAGS} -ggdb -static -O2 -DNO_LIBEV_EMBED -D_WIN32 -lev -lws2_32 100 | 101 | #targets for cross compile macos targets on linux 102 | 103 | mac_cross:git_version #need to install 'osxcross' first. 104 | ${cc_mac_cross} -o ${NAME}_mac -I. ${SOURCES} ${FLAGS} -ggdb -O2 105 | 106 | #release2 includes all binary in 'release' plus win and mac cross compile targets 107 | 108 | release2: ${TARGETS} mingw_cross mingw_cross_wepoll mac_cross 109 | cp git_version.h version.txt 110 | tar -zcvf ${TAR} ${NAME}.exe ${NAME}_wepoll.exe ${NAME}_mac 111 | 112 | clean: 113 | rm -f ${TAR} 114 | rm -f ${NAME} ${NAME}_cross ${NAME}.exe ${NAME}_wepoll.exe ${NAME}_mac 115 | rm -f git_version.h 116 | 117 | git_version: 118 | echo "const char *gitversion = \"$(shell git rev-parse HEAD)\";" > git_version.h 119 | -------------------------------------------------------------------------------- /my_ev.cpp: -------------------------------------------------------------------------------- 1 | #pragma GCC diagnostic push 2 | 3 | #pragma GCC diagnostic ignored "-Wextra" 4 | #pragma GCC diagnostic ignored "-Wsign-compare" 5 | #pragma GCC diagnostic ignored "-Wcomment" 6 | #pragma GCC diagnostic ignored "-Wparentheses" 7 | #pragma GCC diagnostic ignored "-Wstrict-aliasing" 8 | #pragma GCC diagnostic ignored "-Wunused-value" 9 | 10 | #pragma GCC diagnostic ignored "-Wall" 11 | #pragma GCC diagnostic ignored "-W" 12 | 13 | #include "my_ev_common.h" 14 | #include "ev.c" 15 | 16 | #pragma GCC diagnostic pop 17 | -------------------------------------------------------------------------------- /my_ev.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "my_ev_common.h" 4 | #include "ev.h" 5 | 6 | //#if defined(__MINGW32__) 7 | //#define my_ev_io_set(ev,fd_,events_) ev_io_set(ev,_open_osfhandle(fd_,0),events_) 8 | //#define my_ev_io_init(ev,cb,fd,events) ev_io_init(ev,cb,_open_osfhandle(fd,0),events) 9 | //#else 10 | //#define my_ev_io_set(ev,fd_,events_) ev_io_set(ev,fd_,events_) 11 | //#define my_ev_io_init(ev,cb,fd,events) ev_io_init(ev,cb,fd,events) 12 | //#endif 13 | -------------------------------------------------------------------------------- /my_ev_common.h: -------------------------------------------------------------------------------- 1 | 2 | #define EV_STANDALONE 1 3 | #define EV_COMMON void *data; unsigned long long u64; 4 | #define EV_COMPAT3 0 5 | 6 | #if defined(__MINGW32__) 7 | # define EV_FD_TO_WIN32_HANDLE(fd) (fd) 8 | # define EV_WIN32_HANDLE_TO_FD(handle) (handle) 9 | # define EV_WIN32_CLOSE_FD(fd) closesocket (fd) 10 | # define FD_SETSIZE 8192 11 | 12 | #endif 13 | //#define EV_VERIFY 2 14 | --------------------------------------------------------------------------------