├── .gitignore ├── README.md ├── evhttp.h ├── http-internal.h ├── test ├── regress_dns.c ├── regress_http.c ├── regress.rpc ├── test-init.c ├── Makefile.am ├── Makefile.nmake ├── test.sh ├── test-time.c ├── test-eof.c ├── test-weof.c ├── regress.h ├── bench.c └── regress.gen.h ├── sample ├── Makefile.am ├── signal-test.c ├── time-test.c └── event-test.c ├── strlcpy-internal.h ├── m4 ├── ltversion.m4 ├── ltsugar.m4 ├── lt~obsolete.m4 └── ltoptions.m4 ├── epoll_sub.c ├── log.h ├── evsignal.h ├── strlcpy.c ├── evrpc-internal.h ├── event-internal.h ├── log.c ├── compat └── sys │ └── _libevent_time.h ├── min_heap.h ├── evutil.h ├── WIN32-Code ├── config.h └── event-config.h ├── config.h ├── evutil.c ├── epoll.c ├── poll.c ├── select.c ├── event_tagging.c ├── signal.c ├── devpoll.c └── evbuffer.c /.gitignore: -------------------------------------------------------------------------------- 1 | /WIN32-Prj 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # libevent commented 2 | 3 | libevent-1.4.15源码阅读注释版 4 | -------------------------------------------------------------------------------- /evhttp.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saosir/libevent-comment/HEAD/evhttp.h -------------------------------------------------------------------------------- /http-internal.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saosir/libevent-comment/HEAD/http-internal.h -------------------------------------------------------------------------------- /test/regress_dns.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saosir/libevent-comment/HEAD/test/regress_dns.c -------------------------------------------------------------------------------- /test/regress_http.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saosir/libevent-comment/HEAD/test/regress_http.c -------------------------------------------------------------------------------- /sample/Makefile.am: -------------------------------------------------------------------------------- 1 | AUTOMAKE_OPTIONS = foreign no-dependencies 2 | 3 | LDADD = ../libevent.la 4 | AM_CFLAGS = -I$(top_srcdir) -I$(top_srcdir)/compat 5 | 6 | noinst_PROGRAMS = event-test time-test signal-test 7 | 8 | event_test_sources = event-test.c 9 | time_test_sources = time-test.c 10 | signal_test_sources = signal-test.c 11 | 12 | verify: 13 | 14 | DISTCLEANFILES = *~ 15 | -------------------------------------------------------------------------------- /test/regress.rpc: -------------------------------------------------------------------------------- 1 | /* tests data packing and unpacking */ 2 | 3 | struct msg { 4 | string from_name = 1; 5 | string to_name = 2; 6 | optional struct[kill] attack = 3; 7 | array struct[run] run = 4; 8 | } 9 | 10 | struct kill { 11 | string weapon = 0x10121; 12 | string action = 2; 13 | optional int how_often = 3; 14 | } 15 | 16 | struct run { 17 | string how = 1; 18 | optional bytes some_bytes = 2; 19 | bytes fixed_bytes[24] = 3; 20 | } 21 | -------------------------------------------------------------------------------- /strlcpy-internal.h: -------------------------------------------------------------------------------- 1 | #ifndef _STRLCPY_INTERNAL_H_ 2 | #define _STRLCPY_INTERNAL_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #ifdef HAVE_CONFIG_H 9 | #include "config.h" 10 | #endif /* HAVE_CONFIG_H */ 11 | 12 | #ifndef HAVE_STRLCPY 13 | #include 14 | size_t _event_strlcpy(char* dst, const char* src, size_t siz); 15 | #define strlcpy _event_strlcpy 16 | #endif 17 | 18 | #ifdef __cplusplus 19 | } 20 | #endif 21 | 22 | #endif 23 | 24 | -------------------------------------------------------------------------------- /m4/ltversion.m4: -------------------------------------------------------------------------------- 1 | # ltversion.m4 -- version numbers -*- Autoconf -*- 2 | # 3 | # Copyright (C) 2004 Free Software Foundation, Inc. 4 | # Written by Scott James Remnant, 2004 5 | # 6 | # This file is free software; the Free Software Foundation gives 7 | # unlimited permission to copy and/or distribute it, with or without 8 | # modifications, as long as this notice is preserved. 9 | 10 | # @configure_input@ 11 | 12 | # serial 3337 ltversion.m4 13 | # This file is part of GNU Libtool 14 | 15 | m4_define([LT_PACKAGE_VERSION], [2.4.2]) 16 | m4_define([LT_PACKAGE_REVISION], [1.3337]) 17 | 18 | AC_DEFUN([LTVERSION_VERSION], 19 | [macro_version='2.4.2' 20 | macro_revision='1.3337' 21 | _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) 22 | _LT_DECL(, macro_revision, 0) 23 | ]) 24 | -------------------------------------------------------------------------------- /test/test-init.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Compile with: 3 | * cc -I/usr/local/include -o time-test time-test.c -L/usr/local/lib -levent 4 | */ 5 | #ifdef HAVE_CONFIG_H 6 | #include "config.h" 7 | #endif 8 | 9 | #ifdef WIN32 10 | #include 11 | #endif 12 | 13 | #include 14 | #include 15 | #ifdef HAVE_SYS_TIME_H 16 | #include 17 | #endif 18 | #ifdef HAVE_SYS_SOCKET_H 19 | #include 20 | #endif 21 | #include 22 | #include 23 | #include 24 | #include 25 | #ifdef HAVE_UNISTD_H 26 | #include 27 | #endif 28 | #include 29 | 30 | #include 31 | 32 | int 33 | main(int argc, char **argv) 34 | { 35 | /* Initalize the event library */ 36 | event_init(); 37 | 38 | return (0); 39 | } 40 | 41 | -------------------------------------------------------------------------------- /test/Makefile.am: -------------------------------------------------------------------------------- 1 | AUTOMAKE_OPTIONS = foreign no-dependencies 2 | 3 | AM_CFLAGS = -I$(top_srcdir) -I$(top_srcdir)/compat 4 | 5 | EXTRA_DIST = regress.rpc regress.gen.h regress.gen.c 6 | 7 | noinst_PROGRAMS = test-init test-eof test-weof test-time regress bench 8 | 9 | BUILT_SOURCES = regress.gen.c regress.gen.h 10 | test_init_SOURCES = test-init.c 11 | test_init_LDADD = ../libevent_core.la 12 | test_eof_SOURCES = test-eof.c 13 | test_eof_LDADD = ../libevent_core.la 14 | test_weof_SOURCES = test-weof.c 15 | test_weof_LDADD = ../libevent_core.la 16 | test_time_SOURCES = test-time.c 17 | test_time_LDADD = ../libevent_core.la 18 | regress_SOURCES = regress.c regress.h regress_http.c regress_dns.c \ 19 | regress_rpc.c \ 20 | regress.gen.c regress.gen.h 21 | regress_LDADD = ../libevent.la 22 | bench_SOURCES = bench.c 23 | bench_LDADD = ../libevent.la 24 | 25 | regress.gen.c regress.gen.h: regress.rpc $(top_srcdir)/event_rpcgen.py 26 | $(top_srcdir)/event_rpcgen.py $(srcdir)/regress.rpc || echo "No Python installed" 27 | 28 | DISTCLEANFILES = *~ 29 | 30 | test: test-init test-eof test-weof test-time regress 31 | 32 | verify: test 33 | @$(srcdir)/test.sh 34 | 35 | bench test-init test-eof test-weof test-time: ../libevent.la 36 | -------------------------------------------------------------------------------- /sample/signal-test.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Compile with: 3 | * cc -I/usr/local/include -o signal-test \ 4 | * signal-test.c -L/usr/local/lib -levent 5 | */ 6 | 7 | #include 8 | 9 | #ifdef HAVE_CONFIG_H 10 | #include "config.h" 11 | #endif 12 | 13 | #include 14 | #ifndef WIN32 15 | #include 16 | #include 17 | #include 18 | #else 19 | #include 20 | #endif 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | 30 | int called = 0; 31 | 32 | static void 33 | signal_cb(int fd, short event, void *arg) 34 | { 35 | struct event *signal = arg; 36 | 37 | printf("%s: got signal %d\n", __func__, EVENT_SIGNAL(signal)); 38 | 39 | if (called >= 2) 40 | event_del(signal); 41 | 42 | called++; 43 | } 44 | 45 | int 46 | main (int argc, char **argv) 47 | { 48 | struct event signal_int; 49 | 50 | /* Initalize the event library */ 51 | struct event_base* base = event_base_new(); 52 | 53 | /* Initalize one event */ 54 | event_set(&signal_int, SIGINT, EV_SIGNAL|EV_PERSIST, signal_cb, 55 | &signal_int); 56 | event_base_set(base, &signal_int); 57 | 58 | event_add(&signal_int, NULL); 59 | 60 | event_base_dispatch(base); 61 | event_base_free(base); 62 | 63 | return (0); 64 | } 65 | 66 | -------------------------------------------------------------------------------- /sample/time-test.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Compile with: 3 | * cc -I/usr/local/include -o time-test time-test.c -L/usr/local/lib -levent 4 | */ 5 | 6 | #include 7 | 8 | #ifdef HAVE_CONFIG_H 9 | #include "config.h" 10 | #endif 11 | 12 | #include 13 | #ifndef WIN32 14 | #include 15 | #include 16 | #endif 17 | #include 18 | #ifdef HAVE_SYS_TIME_H 19 | #include 20 | #endif 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include 28 | #include 29 | 30 | int lasttime; 31 | 32 | static void 33 | timeout_cb(int fd, short event, void *arg) 34 | { 35 | struct timeval tv; 36 | struct event *timeout = arg; 37 | int newtime = time(NULL); 38 | 39 | printf("%s: called at %d: %d\n", __func__, newtime, 40 | newtime - lasttime); 41 | lasttime = newtime; 42 | 43 | evutil_timerclear(&tv); 44 | tv.tv_sec = 2; 45 | event_add(timeout, &tv); 46 | } 47 | 48 | int 49 | main (int argc, char **argv) 50 | { 51 | struct event timeout; 52 | struct timeval tv; 53 | 54 | /* Initalize the event library */ 55 | event_init(); 56 | 57 | /* Initalize one event */ 58 | evtimer_set(&timeout, timeout_cb, &timeout); 59 | 60 | evutil_timerclear(&tv); 61 | tv.tv_sec = 2; 62 | event_add(&timeout, &tv); 63 | 64 | lasttime = time(NULL); 65 | 66 | event_dispatch(); 67 | 68 | return (0); 69 | } 70 | 71 | -------------------------------------------------------------------------------- /test/Makefile.nmake: -------------------------------------------------------------------------------- 1 | 2 | CFLAGS=/I.. /I../include /I../WIN32-Code /I../compat /DWIN32 /DHAVE_CONFIG_H 3 | 4 | CFLAGS=$(CFLAGS) /Ox /W3 /wd4996 /nologo 5 | 6 | REGRESS_OBJS=regress.obj regress_http.obj regress_dns.obj \ 7 | regress_rpc.obj regress.gen.obj \ 8 | 9 | OTHER_OBJS=test-init.obj test-eof.obj test-weof.obj test-time.obj \ 10 | bench.obj bench_cascade.obj bench_http.obj bench_httpclient.obj 11 | 12 | PROGRAMS=regress.exe \ 13 | test-init.exe test-eof.exe test-weof.exe test-time.exe 14 | 15 | # Disabled for now: 16 | # bench.exe bench_cascade.exe bench_http.exe bench_httpclient.exe 17 | 18 | 19 | LIBS=..\libevent.lib ws2_32.lib advapi32.lib 20 | 21 | all: $(PROGRAMS) 22 | 23 | regress.exe: $(REGRESS_OBJS) 24 | $(CC) $(CFLAGS) $(LIBS) $(REGRESS_OBJS) 25 | 26 | test-init.exe: test-init.obj 27 | $(CC) $(CFLAGS) $(LIBS) test-init.obj 28 | test-eof.exe: test-eof.obj 29 | $(CC) $(CFLAGS) $(LIBS) test-eof.obj 30 | test-weof.exe: test-weof.obj 31 | $(CC) $(CFLAGS) $(LIBS) test-weof.obj 32 | test-time.exe: test-time.obj 33 | $(CC) $(CFLAGS) $(LIBS) test-time.obj 34 | 35 | bench.exe: bench.obj 36 | $(CC) $(CFLAGS) $(LIBS) bench.obj 37 | bench_cascade.exe: bench_cascade.obj 38 | $(CC) $(CFLAGS) $(LIBS) bench_cascade.obj 39 | bench_http.exe: bench_http.obj 40 | $(CC) $(CFLAGS) $(LIBS) bench_http.obj 41 | bench_httpclient.exe: bench_httpclient.obj 42 | $(CC) $(CFLAGS) $(LIBS) bench_httpclient.obj 43 | 44 | clean: 45 | -del $(REGRESS_OBJS) 46 | -del $(OTHER_OBJS) 47 | -del regress.exe 48 | -------------------------------------------------------------------------------- /test/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | setup () { 4 | EVENT_NOKQUEUE=yes; export EVENT_NOKQUEUE 5 | EVENT_NODEVPOLL=yes; export EVENT_NODEVPOLL 6 | EVENT_NOPOLL=yes; export EVENT_NOPOLL 7 | EVENT_NOSELECT=yes; export EVENT_NOSELECT 8 | EVENT_NOEPOLL=yes; export EVENT_NOEPOLL 9 | EVENT_NOEVPORT=yes; export EVENT_NOEVPORT 10 | } 11 | 12 | test () { 13 | if ./test-init 2>/dev/null ; 14 | then 15 | true 16 | else 17 | echo Skipping test 18 | return 19 | fi 20 | 21 | echo -n " test-eof: " 22 | if ./test-eof >/dev/null ; 23 | then 24 | echo OKAY ; 25 | else 26 | echo FAILED ; 27 | fi 28 | echo -n " test-weof: " 29 | if ./test-weof >/dev/null ; 30 | then 31 | echo OKAY ; 32 | else 33 | echo FAILED ; 34 | fi 35 | echo -n " test-time: " 36 | if ./test-time >/dev/null ; 37 | then 38 | echo OKAY ; 39 | else 40 | echo FAILED ; 41 | fi 42 | echo -n " regress: " 43 | if ./regress >/dev/null ; 44 | then 45 | echo OKAY ; 46 | else 47 | echo FAILED ; 48 | fi 49 | } 50 | 51 | echo "Running tests:" 52 | 53 | # Need to do this by hand? 54 | setup 55 | unset EVENT_NOKQUEUE 56 | export EVENT_NOKQUEUE 57 | echo "KQUEUE" 58 | test 59 | 60 | setup 61 | unset EVENT_NODEVPOLL 62 | export EVENT_NODEVPOLL 63 | echo "DEVPOLL" 64 | test 65 | 66 | setup 67 | unset EVENT_NOPOLL 68 | export EVENT_NOPOLL 69 | echo "POLL" 70 | test 71 | 72 | setup 73 | unset EVENT_NOSELECT 74 | export EVENT_NOSELECT 75 | echo "SELECT" 76 | test 77 | 78 | setup 79 | unset EVENT_NOEPOLL 80 | export EVENT_NOEPOLL 81 | echo "EPOLL" 82 | test 83 | 84 | setup 85 | unset EVENT_NOEVPORT 86 | export EVENT_NOEVPORT 87 | echo "EVPORT" 88 | test 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /test/test-time.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Compile with: 3 | * cc -I/usr/local/include -o time-test time-test.c -L/usr/local/lib -levent 4 | */ 5 | #ifdef HAVE_CONFIG_H 6 | #include "config.h" 7 | #endif 8 | 9 | #ifdef WIN32 10 | #include 11 | #endif 12 | 13 | #include 14 | #include 15 | #ifdef HAVE_SYS_TIME_H 16 | #include 17 | #endif 18 | #include 19 | #include 20 | #include 21 | #include 22 | #ifdef HAVE_UNISTD_H 23 | #include 24 | #endif 25 | #include 26 | 27 | #include 28 | 29 | int called = 0; 30 | 31 | #define NEVENT 20000 32 | 33 | struct event *ev[NEVENT]; 34 | 35 | static int 36 | rand_int(int n) 37 | { 38 | #ifdef WIN32 39 | return (int)(rand() * n); 40 | #else 41 | return (int)(random() % n); 42 | #endif 43 | } 44 | 45 | static void 46 | time_cb(int fd, short event, void *arg) 47 | { 48 | struct timeval tv; 49 | int i, j; 50 | 51 | called++; 52 | 53 | if (called < 10*NEVENT) { 54 | for (i = 0; i < 10; i++) { 55 | j = rand_int(NEVENT); 56 | tv.tv_sec = 0; 57 | tv.tv_usec = rand_int(50000); 58 | if (tv.tv_usec % 2) 59 | evtimer_add(ev[j], &tv); 60 | else 61 | evtimer_del(ev[j]); 62 | } 63 | } 64 | } 65 | 66 | int 67 | main (int argc, char **argv) 68 | { 69 | struct timeval tv; 70 | int i; 71 | 72 | /* Initalize the event library */ 73 | event_init(); 74 | 75 | for (i = 0; i < NEVENT; i++) { 76 | ev[i] = malloc(sizeof(struct event)); 77 | 78 | /* Initalize one event */ 79 | evtimer_set(ev[i], time_cb, ev[i]); 80 | tv.tv_sec = 0; 81 | tv.tv_usec = rand_int(50000); 82 | evtimer_add(ev[i], &tv); 83 | } 84 | 85 | event_dispatch(); 86 | 87 | return (called < NEVENT); 88 | } 89 | 90 | -------------------------------------------------------------------------------- /test/test-eof.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Compile with: 3 | * cc -I/usr/local/include -o time-test time-test.c -L/usr/local/lib -levent 4 | */ 5 | #ifdef HAVE_CONFIG_H 6 | #include "config.h" 7 | #endif 8 | 9 | 10 | #ifdef WIN32 11 | #include 12 | #endif 13 | #include 14 | #include 15 | #ifdef HAVE_SYS_TIME_H 16 | #include 17 | #endif 18 | #ifdef HAVE_SYS_SOCKET_H 19 | #include 20 | #endif 21 | #include 22 | #include 23 | #include 24 | #include 25 | #ifdef HAVE_UNISTD_H 26 | #include 27 | #endif 28 | #include 29 | 30 | #include 31 | #include 32 | 33 | int test_okay = 1; 34 | int called = 0; 35 | 36 | static void 37 | read_cb(int fd, short event, void *arg) 38 | { 39 | char buf[256]; 40 | int len; 41 | 42 | len = recv(fd, buf, sizeof(buf), 0); 43 | 44 | printf("%s: read %d%s\n", __func__, 45 | len, len ? "" : " - means EOF"); 46 | 47 | if (len) { 48 | if (!called) 49 | event_add(arg, NULL); 50 | } else if (called == 1) 51 | test_okay = 0; 52 | 53 | called++; 54 | } 55 | 56 | #ifndef SHUT_WR 57 | #define SHUT_WR 1 58 | #endif 59 | 60 | int 61 | main (int argc, char **argv) 62 | { 63 | struct event ev; 64 | const char *test = "test string"; 65 | int pair[2]; 66 | 67 | if (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) 68 | return (1); 69 | 70 | 71 | send(pair[0], test, strlen(test)+1, 0); 72 | shutdown(pair[0], SHUT_WR); 73 | 74 | /* Initalize the event library */ 75 | event_init(); 76 | 77 | /* Initalize one event */ 78 | event_set(&ev, pair[1], EV_READ, read_cb, &ev); 79 | 80 | event_add(&ev, NULL); 81 | 82 | event_dispatch(); 83 | 84 | return (test_okay); 85 | } 86 | 87 | -------------------------------------------------------------------------------- /test/test-weof.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Compile with: 3 | * cc -I/usr/local/include -o time-test time-test.c -L/usr/local/lib -levent 4 | */ 5 | #ifdef HAVE_CONFIG_H 6 | #include "config.h" 7 | #endif 8 | 9 | 10 | #ifdef WIN32 11 | #include 12 | #endif 13 | #include 14 | #include 15 | #ifdef HAVE_SYS_TIME_H 16 | #include 17 | #endif 18 | #ifdef HAVE_SYS_SOCKET_H 19 | #include 20 | #endif 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #ifdef HAVE_UNISTD_H 27 | #include 28 | #endif 29 | #include 30 | 31 | #include 32 | #include 33 | 34 | int pair[2]; 35 | int test_okay = 1; 36 | int called = 0; 37 | 38 | static void 39 | write_cb(int fd, short event, void *arg) 40 | { 41 | const char *test = "test string"; 42 | int len; 43 | 44 | len = send(fd, test, strlen(test) + 1, 0); 45 | 46 | printf("%s: write %d%s\n", __func__, 47 | len, len ? "" : " - means EOF"); 48 | 49 | if (len > 0) { 50 | if (!called) 51 | event_add(arg, NULL); 52 | EVUTIL_CLOSESOCKET(pair[0]); 53 | } else if (called == 1) 54 | test_okay = 0; 55 | 56 | called++; 57 | } 58 | 59 | int 60 | main (int argc, char **argv) 61 | { 62 | struct event ev; 63 | 64 | #ifndef WIN32 65 | if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) 66 | return (1); 67 | #endif 68 | 69 | if (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) 70 | return (1); 71 | 72 | /* Initalize the event library */ 73 | event_init(); 74 | 75 | /* Initalize one event */ 76 | event_set(&ev, pair[1], EV_WRITE, write_cb, &ev); 77 | 78 | event_add(&ev, NULL); 79 | 80 | event_dispatch(); 81 | 82 | return (test_okay); 83 | } 84 | 85 | -------------------------------------------------------------------------------- /test/regress.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2004 Niels Provos 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | #ifndef _REGRESS_H_ 28 | #define _REGRESS_H_ 29 | 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif 33 | 34 | void http_suite(void); 35 | void http_basic_test(void); 36 | 37 | void rpc_suite(void); 38 | 39 | void dns_suite(void); 40 | 41 | #ifdef __cplusplus 42 | } 43 | #endif 44 | 45 | #endif /* _REGRESS_H_ */ 46 | -------------------------------------------------------------------------------- /epoll_sub.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2003 Niels Provos 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | #include 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | int 36 | epoll_create(int size) 37 | { 38 | return (syscall(__NR_epoll_create, size)); 39 | } 40 | 41 | int 42 | epoll_ctl(int epfd, int op, int fd, struct epoll_event* event) 43 | { 44 | 45 | return (syscall(__NR_epoll_ctl, epfd, op, fd, event)); 46 | } 47 | 48 | int 49 | epoll_wait(int epfd, struct epoll_event* events, int maxevents, int timeout) 50 | { 51 | return (syscall(__NR_epoll_wait, epfd, events, maxevents, timeout)); 52 | } 53 | -------------------------------------------------------------------------------- /log.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2004 Niels Provos 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | #ifndef _LOG_H_ 28 | #define _LOG_H_ 29 | 30 | #ifdef __GNUC__ 31 | #define EV_CHECK_FMT(a,b) __attribute__((format(printf, a, b))) 32 | #else 33 | #define EV_CHECK_FMT(a,b) 34 | #endif 35 | 36 | void event_err(int eval, const char* fmt, ...) EV_CHECK_FMT(2, 3); 37 | void event_warn(const char* fmt, ...) EV_CHECK_FMT(1, 2); 38 | void event_errx(int eval, const char* fmt, ...) EV_CHECK_FMT(2, 3); 39 | void event_warnx(const char* fmt, ...) EV_CHECK_FMT(1, 2); 40 | void event_msgx(const char* fmt, ...) EV_CHECK_FMT(1, 2); 41 | void _event_debugx(const char* fmt, ...) EV_CHECK_FMT(1, 2); 42 | 43 | #ifdef USE_DEBUG 44 | #define event_debug(x) _event_debugx x 45 | #else 46 | #define event_debug(x) do {;} while (0) 47 | #endif 48 | 49 | #undef EV_CHECK_FMT 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /evsignal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2002 Niels Provos 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | #ifndef _EVSIGNAL_H_ 28 | #define _EVSIGNAL_H_ 29 | 30 | typedef void (*ev_sighandler_t)(int); 31 | 32 | struct evsignal_info { 33 | // EVLIST_INTERNAL EV_PERSIST 34 | struct event ev_signal; 35 | // ev_signal_pair[1]作为read放入事件循环中监听,当有信号发生的时候, 36 | // 通过写入ev_signal_pair[0],可以唤醒并回调与ev_signal_pair[1]关联 37 | // 的事件回调,这样的作用是可以让所有回调在事件循环中 38 | // 执行,不用担心中断问题,同时有多个信号发生的时候, 39 | // 处理更快,因为只需要往ev_signal_pair[1]写入一个字节进行 40 | // 通知即可,memcache源码中master线程唤醒worker线程处理客户 41 | // 客户连接也是这么做 42 | int ev_signal_pair[2]; 43 | // ev_signal是否已经放入event loop当中 44 | int ev_signal_added; 45 | // 表示已经捕捉到信号,不管什么信号 46 | volatile sig_atomic_t evsignal_caught; 47 | // 监听不同信号的event,每种信号一个链表,多个event可以监听同一个信号 48 | struct event_list evsigevents[NSIG]; 49 | 50 | // 不同信号捕捉到的次数 51 | sig_atomic_t evsigcaught[NSIG]; 52 | 53 | // 一个信号一个信号处理回调,HAVE_SIGACTION是否有sigaction函数 54 | // 用于保存之前的信号信息,以信号值为下标取对应的元素 55 | #ifdef HAVE_SIGACTION 56 | struct sigaction** sh_old; 57 | #else 58 | ev_sighandler_t** sh_old; 59 | #endif 60 | // 信号类型的最大值 61 | int sh_old_max; 62 | }; 63 | int evsignal_init(struct event_base*); 64 | void evsignal_process(struct event_base*); 65 | int evsignal_add(struct event*); 66 | int evsignal_del(struct event*); 67 | void evsignal_dealloc(struct event_base*); 68 | 69 | #endif /* _EVSIGNAL_H_ */ 70 | -------------------------------------------------------------------------------- /strlcpy.c: -------------------------------------------------------------------------------- 1 | /* $OpenBSD: strlcpy.c,v 1.5 2001/05/13 15:40:16 deraadt Exp $ */ 2 | 3 | /* 4 | * Copyright (c) 1998 Todd C. Miller 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 3. The name of the author may not be used to endorse or promote products 16 | * derived from this software without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 19 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 20 | * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21 | * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 22 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 24 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 26 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 27 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | #if defined(LIBC_SCCS) && !defined(lint) 31 | static char* rcsid = "$OpenBSD: strlcpy.c,v 1.5 2001/05/13 15:40:16 deraadt Exp $"; 32 | #endif /* LIBC_SCCS and not lint */ 33 | 34 | #include 35 | 36 | #ifdef HAVE_CONFIG_H 37 | #include "config.h" 38 | #endif /* HAVE_CONFIG_H */ 39 | 40 | #ifndef HAVE_STRLCPY 41 | #include "strlcpy-internal.h" 42 | 43 | /* 44 | * Copy src to string dst of size siz. At most siz-1 characters 45 | * will be copied. Always NUL terminates (unless siz == 0). 46 | * Returns strlen(src); if retval >= siz, truncation occurred. 47 | */ 48 | size_t 49 | _event_strlcpy(dst, src, siz) 50 | char* dst; 51 | const char* src; 52 | size_t siz; 53 | { 54 | register char* d = dst; 55 | register const char* s = src; 56 | register size_t n = siz; 57 | 58 | /* Copy as many bytes as will fit */ 59 | if (n != 0 && --n != 0) { 60 | do { 61 | if ((*d++ = *s++) == 0) 62 | break; 63 | } while (--n != 0); 64 | } 65 | 66 | /* Not enough room in dst, add NUL and traverse rest of src */ 67 | if (n == 0) { 68 | if (siz != 0) 69 | *d = '\0'; /* NUL-terminate dst */ 70 | while (*s++) 71 | ; 72 | } 73 | 74 | return (s - src - 1); /* count does not include NUL */ 75 | } 76 | #endif 77 | -------------------------------------------------------------------------------- /evrpc-internal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006 Niels Provos 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | #ifndef _EVRPC_INTERNAL_H_ 28 | #define _EVRPC_INTERNAL_H_ 29 | 30 | #include "http-internal.h" 31 | 32 | struct evrpc; 33 | 34 | #define EVRPC_URI_PREFIX "/.rpc." 35 | 36 | struct evrpc_hook { 37 | TAILQ_ENTRY(evrpc_hook) (next); 38 | 39 | /* returns -1; if the rpc should be aborted, is allowed to rewrite */ 40 | int (*process)(struct evhttp_request*, struct evbuffer*, void*); 41 | void* process_arg; 42 | }; 43 | 44 | TAILQ_HEAD(evrpc_hook_list, evrpc_hook); 45 | 46 | /* 47 | * this is shared between the base and the pool, so that we can reuse 48 | * the hook adding functions; we alias both evrpc_pool and evrpc_base 49 | * to this common structure. 50 | */ 51 | struct _evrpc_hooks { 52 | /* hooks for processing outbound and inbound rpcs */ 53 | struct evrpc_hook_list in_hooks; 54 | struct evrpc_hook_list out_hooks; 55 | }; 56 | 57 | #define input_hooks common.in_hooks 58 | #define output_hooks common.out_hooks 59 | 60 | struct evrpc_base { 61 | struct _evrpc_hooks common; 62 | 63 | /* the HTTP server under which we register our RPC calls */ 64 | struct evhttp* http_server; 65 | 66 | /* a list of all RPCs registered with us */ 67 | TAILQ_HEAD(evrpc_list, evrpc) registered_rpcs; 68 | }; 69 | 70 | struct evrpc_req_generic; 71 | void evrpc_reqstate_free(struct evrpc_req_generic* rpc_state); 72 | 73 | /* A pool for holding evhttp_connection objects */ 74 | struct evrpc_pool { 75 | struct _evrpc_hooks common; 76 | 77 | struct event_base* base; 78 | 79 | struct evconq connections; 80 | 81 | int timeout; 82 | 83 | TAILQ_HEAD(evrpc_requestq, evrpc_request_wrapper) requests; 84 | }; 85 | 86 | 87 | #endif /* _EVRPC_INTERNAL_H_ */ 88 | -------------------------------------------------------------------------------- /sample/event-test.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Compile with: 3 | * cc -I/usr/local/include -o event-test event-test.c -L/usr/local/lib -levent 4 | */ 5 | 6 | #ifdef HAVE_CONFIG_H 7 | #include "config.h" 8 | #endif 9 | 10 | #include 11 | #include 12 | #ifndef WIN32 13 | #include 14 | #include 15 | #include 16 | #else 17 | #include 18 | #endif 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | 27 | static void 28 | fifo_read(int fd, short event, void *arg) 29 | { 30 | char buf[255]; 31 | int len; 32 | struct event *ev = arg; 33 | #ifdef WIN32 34 | DWORD dwBytesRead; 35 | #endif 36 | 37 | /* Reschedule this event */ 38 | event_add(ev, NULL); 39 | 40 | fprintf(stderr, "fifo_read called with fd: %d, event: %d, arg: %p\n", 41 | fd, event, arg); 42 | #ifdef WIN32 43 | len = ReadFile((HANDLE)fd, buf, sizeof(buf) - 1, &dwBytesRead, NULL); 44 | 45 | // Check for end of file. 46 | if(len && dwBytesRead == 0) { 47 | fprintf(stderr, "End Of File"); 48 | event_del(ev); 49 | return; 50 | } 51 | 52 | buf[dwBytesRead] = '\0'; 53 | #else 54 | len = read(fd, buf, sizeof(buf) - 1); 55 | 56 | if (len == -1) { 57 | perror("read"); 58 | return; 59 | } else if (len == 0) { 60 | fprintf(stderr, "Connection closed\n"); 61 | return; 62 | } 63 | 64 | buf[len] = '\0'; 65 | #endif 66 | fprintf(stdout, "Read: %s\n", buf); 67 | } 68 | 69 | int 70 | main (int argc, char **argv) 71 | { 72 | struct event evfifo; 73 | #ifdef WIN32 74 | HANDLE socket; 75 | // Open a file. 76 | socket = CreateFileA("test.txt", // open File 77 | GENERIC_READ, // open for reading 78 | 0, // do not share 79 | NULL, // no security 80 | OPEN_EXISTING, // existing file only 81 | FILE_ATTRIBUTE_NORMAL, // normal file 82 | NULL); // no attr. template 83 | 84 | if(socket == INVALID_HANDLE_VALUE) 85 | return 1; 86 | 87 | #else 88 | struct stat st; 89 | const char *fifo = "event.fifo"; 90 | int socket; 91 | 92 | if (lstat (fifo, &st) == 0) { 93 | if ((st.st_mode & S_IFMT) == S_IFREG) { 94 | errno = EEXIST; 95 | perror("lstat"); 96 | exit (1); 97 | } 98 | } 99 | 100 | unlink (fifo); 101 | if (mkfifo (fifo, 0600) == -1) { 102 | perror("mkfifo"); 103 | exit (1); 104 | } 105 | 106 | /* Linux pipes are broken, we need O_RDWR instead of O_RDONLY */ 107 | #ifdef __linux 108 | socket = open (fifo, O_RDWR | O_NONBLOCK, 0); 109 | #else 110 | socket = open (fifo, O_RDONLY | O_NONBLOCK, 0); 111 | #endif 112 | 113 | if (socket == -1) { 114 | perror("open"); 115 | exit (1); 116 | } 117 | 118 | fprintf(stderr, "Write data to %s\n", fifo); 119 | #endif 120 | /* Initalize the event library */ 121 | event_init(); 122 | 123 | /* Initalize one event */ 124 | #ifdef WIN32 125 | event_set(&evfifo, (int)socket, EV_READ, fifo_read, &evfifo); 126 | #else 127 | event_set(&evfifo, socket, EV_READ, fifo_read, &evfifo); 128 | #endif 129 | 130 | /* Add it to the active events, without a timeout */ 131 | event_add(&evfifo, NULL); 132 | 133 | event_dispatch(); 134 | #ifdef WIN32 135 | CloseHandle(socket); 136 | #endif 137 | return (0); 138 | } 139 | 140 | -------------------------------------------------------------------------------- /event-internal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2004 Niels Provos 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | #ifndef _EVENT_INTERNAL_H_ 28 | #define _EVENT_INTERNAL_H_ 29 | 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif 33 | 34 | #include "config.h" 35 | #include "min_heap.h" 36 | #include "evsignal.h" 37 | 38 | struct eventop { 39 | const char* name; 40 | void* (*init)(struct event_base*); 41 | int (*add)(void*, struct event*); 42 | int (*del)(void*, struct event*); 43 | int (*dispatch)(struct event_base*, void*, struct timeval*); 44 | void (*dealloc)(struct event_base*, void*); 45 | /* set if we need to reinitialize the event base */ 46 | int need_reinit; 47 | }; 48 | 49 | struct event_base { 50 | // 与操作系统相关的io多路复用模型 51 | const struct eventop* evsel; 52 | //调用i/o模型evsel->init返回的变量,相当于io多路复用模型上线文,之后调用与evsel相关的io模型函数都会将该变量传入 53 | void* evbase; 54 | //当前注册的事件event总数 55 | int event_count; /* counts number of total events */ 56 | //处于活动队列的事件event总数,这部分事件已经触发即将被回调 57 | int event_count_active; /* counts number of active events */ 58 | 59 | int event_gotterm; /* Set to terminate loop 正常退出dispatch*/ 60 | int event_break; /* Set to terminate loop immediately 马上退出dispatch*/ 61 | 62 | /* active event management */ 63 | //1. active list active队里,事件已经触发等待回调通知 64 | // - 注册一个2s计时器,2s过后该event会被放到active队列等待回调 65 | // - 注册一个socket读事件,当socket可读会将socket读事件放到active队列等待回调 66 | //2. 指针数组的原因是要实现优先级功能 67 | //3. 越靠前优先级越大 68 | struct event_list** activequeues; 69 | // 优先级队列数 70 | int nactivequeues; 71 | 72 | /* signal handling info */ 73 | struct evsignal_info sig; //信号相关 74 | 75 | struct event_list eventqueue; //添加到事件循环中的所有event 76 | struct timeval event_tv; 77 | 78 | struct min_heap timeheap; //最小二叉堆用于处理计时器 79 | 80 | struct timeval tv_cache; 81 | }; 82 | 83 | /* Internal use only: Functions that might be missing from */ 84 | #ifndef HAVE_TAILQFOREACH 85 | #define TAILQ_FIRST(head) ((head)->tqh_first) 86 | #define TAILQ_END(head) NULL 87 | #define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) 88 | #define TAILQ_FOREACH(var, head, field) \ 89 | for((var) = TAILQ_FIRST(head); \ 90 | (var) != TAILQ_END(head); \ 91 | (var) = TAILQ_NEXT(var, field)) 92 | #define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ 93 | (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ 94 | (elm)->field.tqe_next = (listelm); \ 95 | *(listelm)->field.tqe_prev = (elm); \ 96 | (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ 97 | } while (0) 98 | #endif /* TAILQ_FOREACH */ 99 | 100 | int _evsignal_set_handler(struct event_base* base, int evsignal, 101 | void (*fn)(int)); 102 | int _evsignal_restore_handler(struct event_base* base, int evsignal); 103 | 104 | /* defined in evutil.c */ 105 | const char* evutil_getenv(const char* varname); 106 | 107 | #ifdef __cplusplus 108 | } 109 | #endif 110 | 111 | #endif /* _EVENT_INTERNAL_H_ */ 112 | -------------------------------------------------------------------------------- /m4/ltsugar.m4: -------------------------------------------------------------------------------- 1 | # ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- 2 | # 3 | # Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. 4 | # Written by Gary V. Vaughan, 2004 5 | # 6 | # This file is free software; the Free Software Foundation gives 7 | # unlimited permission to copy and/or distribute it, with or without 8 | # modifications, as long as this notice is preserved. 9 | 10 | # serial 6 ltsugar.m4 11 | 12 | # This is to help aclocal find these macros, as it can't see m4_define. 13 | AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) 14 | 15 | 16 | # lt_join(SEP, ARG1, [ARG2...]) 17 | # ----------------------------- 18 | # Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their 19 | # associated separator. 20 | # Needed until we can rely on m4_join from Autoconf 2.62, since all earlier 21 | # versions in m4sugar had bugs. 22 | m4_define([lt_join], 23 | [m4_if([$#], [1], [], 24 | [$#], [2], [[$2]], 25 | [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) 26 | m4_define([_lt_join], 27 | [m4_if([$#$2], [2], [], 28 | [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) 29 | 30 | 31 | # lt_car(LIST) 32 | # lt_cdr(LIST) 33 | # ------------ 34 | # Manipulate m4 lists. 35 | # These macros are necessary as long as will still need to support 36 | # Autoconf-2.59 which quotes differently. 37 | m4_define([lt_car], [[$1]]) 38 | m4_define([lt_cdr], 39 | [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], 40 | [$#], 1, [], 41 | [m4_dquote(m4_shift($@))])]) 42 | m4_define([lt_unquote], $1) 43 | 44 | 45 | # lt_append(MACRO-NAME, STRING, [SEPARATOR]) 46 | # ------------------------------------------ 47 | # Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'. 48 | # Note that neither SEPARATOR nor STRING are expanded; they are appended 49 | # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). 50 | # No SEPARATOR is output if MACRO-NAME was previously undefined (different 51 | # than defined and empty). 52 | # 53 | # This macro is needed until we can rely on Autoconf 2.62, since earlier 54 | # versions of m4sugar mistakenly expanded SEPARATOR but not STRING. 55 | m4_define([lt_append], 56 | [m4_define([$1], 57 | m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) 58 | 59 | 60 | 61 | # lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) 62 | # ---------------------------------------------------------- 63 | # Produce a SEP delimited list of all paired combinations of elements of 64 | # PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list 65 | # has the form PREFIXmINFIXSUFFIXn. 66 | # Needed until we can rely on m4_combine added in Autoconf 2.62. 67 | m4_define([lt_combine], 68 | [m4_if(m4_eval([$# > 3]), [1], 69 | [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl 70 | [[m4_foreach([_Lt_prefix], [$2], 71 | [m4_foreach([_Lt_suffix], 72 | ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, 73 | [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) 74 | 75 | 76 | # lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) 77 | # ----------------------------------------------------------------------- 78 | # Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited 79 | # by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. 80 | m4_define([lt_if_append_uniq], 81 | [m4_ifdef([$1], 82 | [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], 83 | [lt_append([$1], [$2], [$3])$4], 84 | [$5])], 85 | [lt_append([$1], [$2], [$3])$4])]) 86 | 87 | 88 | # lt_dict_add(DICT, KEY, VALUE) 89 | # ----------------------------- 90 | m4_define([lt_dict_add], 91 | [m4_define([$1($2)], [$3])]) 92 | 93 | 94 | # lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) 95 | # -------------------------------------------- 96 | m4_define([lt_dict_add_subkey], 97 | [m4_define([$1($2:$3)], [$4])]) 98 | 99 | 100 | # lt_dict_fetch(DICT, KEY, [SUBKEY]) 101 | # ---------------------------------- 102 | m4_define([lt_dict_fetch], 103 | [m4_ifval([$3], 104 | m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), 105 | m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) 106 | 107 | 108 | # lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) 109 | # ----------------------------------------------------------------- 110 | m4_define([lt_if_dict_fetch], 111 | [m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], 112 | [$5], 113 | [$6])]) 114 | 115 | 116 | # lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) 117 | # -------------------------------------------------------------- 118 | m4_define([lt_dict_filter], 119 | [m4_if([$5], [], [], 120 | [lt_join(m4_quote(m4_default([$4], [[, ]])), 121 | lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), 122 | [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl 123 | ]) 124 | -------------------------------------------------------------------------------- /test/bench.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2003 Niels Provos 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 4. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | * 27 | * 28 | * Mon 03/10/2003 - Modified by Davide Libenzi 29 | * 30 | * Added chain event propagation to improve the sensitivity of 31 | * the measure respect to the event loop efficency. 32 | * 33 | * 34 | */ 35 | 36 | #ifdef HAVE_CONFIG_H 37 | #include "config.h" 38 | #endif 39 | 40 | #include 41 | #include 42 | #include 43 | #ifdef WIN32 44 | #include 45 | #else 46 | #include 47 | #include 48 | #include 49 | #endif 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | 57 | #include 58 | #include 59 | 60 | 61 | static int count, writes, fired; 62 | static int *pipes; 63 | static int num_pipes, num_active, num_writes; 64 | static struct event *events; 65 | 66 | static void 67 | read_cb(int fd, short which, void *arg) 68 | { 69 | long idx = (long) arg, widx = idx + 1; 70 | u_char ch; 71 | 72 | count += read(fd, &ch, sizeof(ch)); 73 | if (writes) { 74 | if (widx >= num_pipes) 75 | widx -= num_pipes; 76 | write(pipes[2 * widx + 1], "e", 1); 77 | writes--; 78 | fired++; 79 | } 80 | } 81 | 82 | static struct timeval * 83 | run_once(void) 84 | { 85 | int *cp, space; 86 | long i; 87 | static struct timeval ts, te; 88 | 89 | for (cp = pipes, i = 0; i < num_pipes; i++, cp += 2) { 90 | event_del(&events[i]); 91 | event_set(&events[i], cp[0], EV_READ | EV_PERSIST, read_cb, (void *) i); 92 | event_add(&events[i], NULL); 93 | } 94 | 95 | event_loop(EVLOOP_ONCE | EVLOOP_NONBLOCK); 96 | 97 | fired = 0; 98 | space = num_pipes / num_active; 99 | space = space * 2; 100 | for (i = 0; i < num_active; i++, fired++) 101 | write(pipes[i * space + 1], "e", 1); 102 | 103 | count = 0; 104 | writes = num_writes; 105 | { int xcount = 0; 106 | gettimeofday(&ts, NULL); 107 | do { 108 | event_loop(EVLOOP_ONCE | EVLOOP_NONBLOCK); 109 | xcount++; 110 | } while (count != fired); 111 | gettimeofday(&te, NULL); 112 | 113 | if (xcount != count) fprintf(stderr, "Xcount: %d, Rcount: %d\n", xcount, count); 114 | } 115 | 116 | evutil_timersub(&te, &ts, &te); 117 | 118 | return (&te); 119 | } 120 | 121 | int 122 | main (int argc, char **argv) 123 | { 124 | #ifndef WIN32 125 | struct rlimit rl; 126 | #endif 127 | int i, c; 128 | struct timeval *tv; 129 | int *cp; 130 | 131 | num_pipes = 100; 132 | num_active = 1; 133 | num_writes = num_pipes; 134 | while ((c = getopt(argc, argv, "n:a:w:")) != -1) { 135 | switch (c) { 136 | case 'n': 137 | num_pipes = atoi(optarg); 138 | break; 139 | case 'a': 140 | num_active = atoi(optarg); 141 | break; 142 | case 'w': 143 | num_writes = atoi(optarg); 144 | break; 145 | default: 146 | fprintf(stderr, "Illegal argument \"%c\"\n", c); 147 | exit(1); 148 | } 149 | } 150 | 151 | #ifndef WIN32 152 | rl.rlim_cur = rl.rlim_max = num_pipes * 2 + 50; 153 | if (setrlimit(RLIMIT_NOFILE, &rl) == -1) { 154 | perror("setrlimit"); 155 | exit(1); 156 | } 157 | #endif 158 | 159 | events = calloc(num_pipes, sizeof(struct event)); 160 | pipes = calloc(num_pipes * 2, sizeof(int)); 161 | if (events == NULL || pipes == NULL) { 162 | perror("malloc"); 163 | exit(1); 164 | } 165 | 166 | event_init(); 167 | 168 | for (cp = pipes, i = 0; i < num_pipes; i++, cp += 2) { 169 | #ifdef USE_PIPES 170 | if (pipe(cp) == -1) { 171 | #else 172 | if (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, cp) == -1) { 173 | #endif 174 | perror("pipe"); 175 | exit(1); 176 | } 177 | } 178 | 179 | for (i = 0; i < 25; i++) { 180 | tv = run_once(); 181 | if (tv == NULL) 182 | exit(1); 183 | fprintf(stdout, "%ld\n", 184 | tv->tv_sec * 1000000L + tv->tv_usec); 185 | } 186 | 187 | exit(0); 188 | } 189 | -------------------------------------------------------------------------------- /log.c: -------------------------------------------------------------------------------- 1 | /* $OpenBSD: err.c,v 1.2 2002/06/25 15:50:15 mickey Exp $ */ 2 | 3 | /* 4 | * log.c 5 | * 6 | * Based on err.c, which was adapted from OpenBSD libc *err* *warn* code. 7 | * 8 | * Copyright (c) 2005 Nick Mathewson 9 | * 10 | * Copyright (c) 2000 Dug Song 11 | * 12 | * Copyright (c) 1993 13 | * The Regents of the University of California. All rights reserved. 14 | * 15 | * Redistribution and use in source and binary forms, with or without 16 | * modification, are permitted provided that the following conditions 17 | * are met: 18 | * 1. Redistributions of source code must retain the above copyright 19 | * notice, this list of conditions and the following disclaimer. 20 | * 2. Redistributions in binary form must reproduce the above copyright 21 | * notice, this list of conditions and the following disclaimer in the 22 | * documentation and/or other materials provided with the distribution. 23 | * 3. Neither the name of the University nor the names of its contributors 24 | * may be used to endorse or promote products derived from this software 25 | * without specific prior written permission. 26 | * 27 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 | * SUCH DAMAGE. 38 | */ 39 | 40 | #ifdef HAVE_CONFIG_H 41 | #include "config.h" 42 | #endif 43 | 44 | #ifdef WIN32 45 | #define WIN32_LEAN_AND_MEAN 46 | #include 47 | #undef WIN32_LEAN_AND_MEAN 48 | #endif 49 | #include 50 | #ifdef HAVE_SYS_TIME_H 51 | #include 52 | #else 53 | #include 54 | #endif 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | #include "event.h" 61 | 62 | #include "log.h" 63 | #include "evutil.h" 64 | 65 | static void _warn_helper(int severity, int log_errno, const char* fmt, 66 | va_list ap); 67 | static void event_log(int severity, const char* msg); 68 | 69 | void 70 | event_err(int eval, const char* fmt, ...) 71 | { 72 | va_list ap; 73 | 74 | va_start(ap, fmt); 75 | _warn_helper(_EVENT_LOG_ERR, errno, fmt, ap); 76 | va_end(ap); 77 | exit(eval); 78 | } 79 | 80 | void 81 | event_warn(const char* fmt, ...) 82 | { 83 | va_list ap; 84 | 85 | va_start(ap, fmt); 86 | _warn_helper(_EVENT_LOG_WARN, errno, fmt, ap); 87 | va_end(ap); 88 | } 89 | 90 | void 91 | event_errx(int eval, const char* fmt, ...) 92 | { 93 | va_list ap; 94 | 95 | va_start(ap, fmt); 96 | _warn_helper(_EVENT_LOG_ERR, -1, fmt, ap); 97 | va_end(ap); 98 | exit(eval); 99 | } 100 | 101 | void 102 | event_warnx(const char* fmt, ...) 103 | { 104 | va_list ap; 105 | 106 | va_start(ap, fmt); 107 | _warn_helper(_EVENT_LOG_WARN, -1, fmt, ap); 108 | va_end(ap); 109 | } 110 | 111 | void 112 | event_msgx(const char* fmt, ...) 113 | { 114 | va_list ap; 115 | 116 | va_start(ap, fmt); 117 | _warn_helper(_EVENT_LOG_MSG, -1, fmt, ap); 118 | va_end(ap); 119 | } 120 | 121 | void 122 | _event_debugx(const char* fmt, ...) 123 | { 124 | va_list ap; 125 | 126 | va_start(ap, fmt); 127 | _warn_helper(_EVENT_LOG_DEBUG, -1, fmt, ap); 128 | va_end(ap); 129 | } 130 | 131 | static void 132 | _warn_helper(int severity, int log_errno, const char* fmt, va_list ap) 133 | { 134 | char buf[1024]; 135 | size_t len; 136 | 137 | if (fmt != NULL) 138 | evutil_vsnprintf(buf, sizeof(buf), fmt, ap); 139 | else 140 | buf[0] = '\0'; 141 | 142 | if (log_errno >= 0) { 143 | len = strlen(buf); 144 | if (len < sizeof(buf) - 3) { 145 | evutil_snprintf(buf + len, sizeof(buf) - len, ": %s", 146 | strerror(log_errno)); 147 | } 148 | } 149 | 150 | event_log(severity, buf); 151 | } 152 | 153 | static event_log_cb log_fn = NULL; 154 | 155 | void 156 | event_set_log_callback(event_log_cb cb) 157 | { 158 | log_fn = cb; 159 | } 160 | 161 | static void 162 | event_log(int severity, const char* msg) 163 | { 164 | if (log_fn) 165 | log_fn(severity, msg); 166 | else { 167 | const char* severity_str; 168 | switch (severity) { 169 | case _EVENT_LOG_DEBUG: 170 | severity_str = "debug"; 171 | break; 172 | case _EVENT_LOG_MSG: 173 | severity_str = "msg"; 174 | break; 175 | case _EVENT_LOG_WARN: 176 | severity_str = "warn"; 177 | break; 178 | case _EVENT_LOG_ERR: 179 | severity_str = "err"; 180 | break; 181 | default: 182 | severity_str = "???"; 183 | break; 184 | } 185 | (void)fprintf(stderr, "[%s] %s\n", severity_str, msg); 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /compat/sys/_libevent_time.h: -------------------------------------------------------------------------------- 1 | /* $OpenBSD: time.h,v 1.11 2000/10/10 13:36:48 itojun Exp $ */ 2 | /* $NetBSD: time.h,v 1.18 1996/04/23 10:29:33 mycroft Exp $ */ 3 | 4 | /* 5 | * Copyright (c) 1982, 1986, 1993 6 | * The Regents of the University of California. All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions 10 | * are met: 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 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 | * 3. Neither the name of the University nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 | * SUCH DAMAGE. 31 | * 32 | * @(#)time.h 8.2 (Berkeley) 7/10/94 33 | */ 34 | 35 | #ifndef _SYS_TIME_H_ 36 | #define _SYS_TIME_H_ 37 | 38 | #include 39 | 40 | /* 41 | * Structure returned by gettimeofday(2) system call, 42 | * and used in other calls. 43 | */ 44 | struct timeval { 45 | long tv_sec; /* seconds */ 46 | long tv_usec; /* and microseconds */ 47 | }; 48 | 49 | /* 50 | * Structure defined by POSIX.1b to be like a timeval. 51 | */ 52 | struct timespec { 53 | time_t tv_sec; /* seconds */ 54 | long tv_nsec; /* and nanoseconds */ 55 | }; 56 | 57 | #define TIMEVAL_TO_TIMESPEC(tv, ts) { \ 58 | (ts)->tv_sec = (tv)->tv_sec; \ 59 | (ts)->tv_nsec = (tv)->tv_usec * 1000; \ 60 | } 61 | #define TIMESPEC_TO_TIMEVAL(tv, ts) { \ 62 | (tv)->tv_sec = (ts)->tv_sec; \ 63 | (tv)->tv_usec = (ts)->tv_nsec / 1000; \ 64 | } 65 | 66 | struct timezone { 67 | int tz_minuteswest; /* minutes west of Greenwich */ 68 | int tz_dsttime; /* type of dst correction */ 69 | }; 70 | #define DST_NONE 0 /* not on dst */ 71 | #define DST_USA 1 /* USA style dst */ 72 | #define DST_AUST 2 /* Australian style dst */ 73 | #define DST_WET 3 /* Western European dst */ 74 | #define DST_MET 4 /* Middle European dst */ 75 | #define DST_EET 5 /* Eastern European dst */ 76 | #define DST_CAN 6 /* Canada */ 77 | 78 | /* Operations on timevals. */ 79 | #define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0 80 | #define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec) 81 | #define timercmp(tvp, uvp, cmp) \ 82 | (((tvp)->tv_sec == (uvp)->tv_sec) ? \ 83 | ((tvp)->tv_usec cmp (uvp)->tv_usec) : \ 84 | ((tvp)->tv_sec cmp (uvp)->tv_sec)) 85 | #define timeradd(tvp, uvp, vvp) \ 86 | do { \ 87 | (vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec; \ 88 | (vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec; \ 89 | if ((vvp)->tv_usec >= 1000000) { \ 90 | (vvp)->tv_sec++; \ 91 | (vvp)->tv_usec -= 1000000; \ 92 | } \ 93 | } while (0) 94 | #define timersub(tvp, uvp, vvp) \ 95 | do { \ 96 | (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \ 97 | (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \ 98 | if ((vvp)->tv_usec < 0) { \ 99 | (vvp)->tv_sec--; \ 100 | (vvp)->tv_usec += 1000000; \ 101 | } \ 102 | } while (0) 103 | 104 | /* Operations on timespecs. */ 105 | #define timespecclear(tsp) (tsp)->tv_sec = (tsp)->tv_nsec = 0 106 | #define timespecisset(tsp) ((tsp)->tv_sec || (tsp)->tv_nsec) 107 | #define timespeccmp(tsp, usp, cmp) \ 108 | (((tsp)->tv_sec == (usp)->tv_sec) ? \ 109 | ((tsp)->tv_nsec cmp (usp)->tv_nsec) : \ 110 | ((tsp)->tv_sec cmp (usp)->tv_sec)) 111 | #define timespecadd(tsp, usp, vsp) \ 112 | do { \ 113 | (vsp)->tv_sec = (tsp)->tv_sec + (usp)->tv_sec; \ 114 | (vsp)->tv_nsec = (tsp)->tv_nsec + (usp)->tv_nsec; \ 115 | if ((vsp)->tv_nsec >= 1000000000L) { \ 116 | (vsp)->tv_sec++; \ 117 | (vsp)->tv_nsec -= 1000000000L; \ 118 | } \ 119 | } while (0) 120 | #define timespecsub(tsp, usp, vsp) \ 121 | do { \ 122 | (vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec; \ 123 | (vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec; \ 124 | if ((vsp)->tv_nsec < 0) { \ 125 | (vsp)->tv_sec--; \ 126 | (vsp)->tv_nsec += 1000000000L; \ 127 | } \ 128 | } while (0) 129 | 130 | /* 131 | * Names of the interval timers, and structure 132 | * defining a timer setting. 133 | */ 134 | #define ITIMER_REAL 0 135 | #define ITIMER_VIRTUAL 1 136 | #define ITIMER_PROF 2 137 | 138 | struct itimerval { 139 | struct timeval it_interval; /* timer interval */ 140 | struct timeval it_value; /* current value */ 141 | }; 142 | 143 | /* 144 | * Getkerninfo clock information structure 145 | */ 146 | struct clockinfo { 147 | int hz; /* clock frequency */ 148 | int tick; /* micro-seconds per hz tick */ 149 | int tickadj; /* clock skew rate for adjtime() */ 150 | int stathz; /* statistics clock frequency */ 151 | int profhz; /* profiling clock frequency */ 152 | }; 153 | 154 | #define CLOCK_REALTIME 0 155 | #define CLOCK_VIRTUAL 1 156 | #define CLOCK_PROF 2 157 | 158 | #define TIMER_RELTIME 0x0 /* relative timer */ 159 | #define TIMER_ABSTIME 0x1 /* absolute timer */ 160 | 161 | /* --- stuff got cut here - niels --- */ 162 | 163 | #endif /* !_SYS_TIME_H_ */ 164 | -------------------------------------------------------------------------------- /min_heap.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006 Maxim Yegorushkin 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | #ifndef _MIN_HEAP_H_ 28 | #define _MIN_HEAP_H_ 29 | 30 | #include "event.h" 31 | #include "evutil.h" 32 | 33 | typedef struct min_heap { 34 | struct event** p; 35 | unsigned n, a; 36 | } min_heap_t; 37 | 38 | static inline void min_heap_ctor(min_heap_t* s); 39 | static inline void min_heap_dtor(min_heap_t* s); 40 | static inline void min_heap_elem_init(struct event* e); 41 | static inline int min_heap_elem_greater(struct event* a, struct event* b); 42 | static inline int min_heap_empty(min_heap_t* s); 43 | static inline unsigned min_heap_size(min_heap_t* s); 44 | static inline struct event* min_heap_top(min_heap_t* s); 45 | static inline int min_heap_reserve(min_heap_t* s, unsigned n); 46 | static inline int min_heap_push(min_heap_t* s, struct event* e); 47 | static inline struct event* min_heap_pop(min_heap_t* s); 48 | static inline int min_heap_erase(min_heap_t* s, struct event* e); 49 | static inline void min_heap_shift_up_(min_heap_t* s, unsigned hole_index, struct event* e); 50 | static inline void min_heap_shift_down_(min_heap_t* s, unsigned hole_index, struct event* e); 51 | 52 | int min_heap_elem_greater(struct event* a, struct event* b) 53 | { 54 | return evutil_timercmp(&a->ev_timeout, &b->ev_timeout, > ); 55 | } 56 | 57 | void min_heap_ctor(min_heap_t* s) 58 | { 59 | s->p = 0; 60 | s->n = 0; 61 | s->a = 0; 62 | } 63 | void min_heap_dtor(min_heap_t* s) 64 | { 65 | if (s->p) free(s->p); 66 | } 67 | void min_heap_elem_init(struct event* e) 68 | { 69 | e->min_heap_idx = -1; 70 | } 71 | int min_heap_empty(min_heap_t* s) 72 | { 73 | return 0u == s->n; 74 | } 75 | unsigned min_heap_size(min_heap_t* s) 76 | { 77 | return s->n; 78 | } 79 | struct event* min_heap_top(min_heap_t* s) 80 | { 81 | return s->n ? *s->p : 0; 82 | } 83 | 84 | int min_heap_push(min_heap_t* s, struct event* e) 85 | { 86 | if (min_heap_reserve(s, s->n + 1)) 87 | return -1; 88 | min_heap_shift_up_(s, s->n++, e); 89 | return 0; 90 | } 91 | 92 | struct event* min_heap_pop(min_heap_t* s) 93 | { 94 | if (s->n) { 95 | struct event* e = *s->p; 96 | min_heap_shift_down_(s, 0u, s->p[--s->n]); 97 | e->min_heap_idx = -1; 98 | return e; 99 | } 100 | return 0; 101 | } 102 | 103 | int min_heap_erase(min_heap_t* s, struct event* e) 104 | { 105 | if (((unsigned int) - 1) != e->min_heap_idx) { 106 | struct event* last = s->p[--s->n]; 107 | unsigned parent = (e->min_heap_idx - 1) / 2; 108 | /* we replace e with the last element in the heap. We might need to 109 | shift it upward if it is less than its parent, or downward if it is 110 | greater than one or both its children. Since the children are known 111 | to be less than the parent, it can't need to shift both up and 112 | down. */ 113 | if (e->min_heap_idx > 0 && min_heap_elem_greater(s->p[parent], last)) 114 | min_heap_shift_up_(s, e->min_heap_idx, last); 115 | else 116 | min_heap_shift_down_(s, e->min_heap_idx, last); 117 | e->min_heap_idx = -1; 118 | return 0; 119 | } 120 | return -1; 121 | } 122 | 123 | int min_heap_reserve(min_heap_t* s, unsigned n) 124 | { 125 | if (s->a < n) { 126 | struct event** p; 127 | unsigned a = s->a ? s->a * 2 : 8; 128 | if (a < n) 129 | a = n; 130 | if (!(p = (struct event**)realloc(s->p, a * sizeof * p))) 131 | return -1; 132 | s->p = p; 133 | s->a = a; 134 | } 135 | return 0; 136 | } 137 | 138 | void min_heap_shift_up_(min_heap_t* s, unsigned hole_index, struct event* e) 139 | { 140 | unsigned parent = (hole_index - 1) / 2; 141 | while (hole_index && min_heap_elem_greater(s->p[parent], e)) { 142 | (s->p[hole_index] = s->p[parent])->min_heap_idx = hole_index; 143 | hole_index = parent; 144 | parent = (hole_index - 1) / 2; 145 | } 146 | (s->p[hole_index] = e)->min_heap_idx = hole_index; 147 | } 148 | 149 | void min_heap_shift_down_(min_heap_t* s, unsigned hole_index, struct event* e) 150 | { 151 | unsigned min_child = 2 * (hole_index + 1); 152 | while (min_child <= s->n) { 153 | min_child -= min_child == s->n || min_heap_elem_greater(s->p[min_child], s->p[min_child - 1]); 154 | if (!(min_heap_elem_greater(e, s->p[min_child]))) 155 | break; 156 | (s->p[hole_index] = s->p[min_child])->min_heap_idx = hole_index; 157 | hole_index = min_child; 158 | min_child = 2 * (hole_index + 1); 159 | } 160 | min_heap_shift_up_(s, hole_index, e); 161 | } 162 | 163 | #endif /* _MIN_HEAP_H_ */ 164 | -------------------------------------------------------------------------------- /m4/lt~obsolete.m4: -------------------------------------------------------------------------------- 1 | # lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- 2 | # 3 | # Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc. 4 | # Written by Scott James Remnant, 2004. 5 | # 6 | # This file is free software; the Free Software Foundation gives 7 | # unlimited permission to copy and/or distribute it, with or without 8 | # modifications, as long as this notice is preserved. 9 | 10 | # serial 5 lt~obsolete.m4 11 | 12 | # These exist entirely to fool aclocal when bootstrapping libtool. 13 | # 14 | # In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) 15 | # which have later been changed to m4_define as they aren't part of the 16 | # exported API, or moved to Autoconf or Automake where they belong. 17 | # 18 | # The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN 19 | # in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us 20 | # using a macro with the same name in our local m4/libtool.m4 it'll 21 | # pull the old libtool.m4 in (it doesn't see our shiny new m4_define 22 | # and doesn't know about Autoconf macros at all.) 23 | # 24 | # So we provide this file, which has a silly filename so it's always 25 | # included after everything else. This provides aclocal with the 26 | # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything 27 | # because those macros already exist, or will be overwritten later. 28 | # We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. 29 | # 30 | # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. 31 | # Yes, that means every name once taken will need to remain here until 32 | # we give up compatibility with versions before 1.7, at which point 33 | # we need to keep only those names which we still refer to. 34 | 35 | # This is to help aclocal find these macros, as it can't see m4_define. 36 | AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) 37 | 38 | m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) 39 | m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) 40 | m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) 41 | m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) 42 | m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) 43 | m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) 44 | m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) 45 | m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) 46 | m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) 47 | m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) 48 | m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) 49 | m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) 50 | m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) 51 | m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) 52 | m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) 53 | m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) 54 | m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) 55 | m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) 56 | m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) 57 | m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) 58 | m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) 59 | m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) 60 | m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) 61 | m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) 62 | m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) 63 | m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) 64 | m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) 65 | m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) 66 | m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) 67 | m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) 68 | m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) 69 | m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) 70 | m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) 71 | m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) 72 | m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) 73 | m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) 74 | m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) 75 | m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) 76 | m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) 77 | m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) 78 | m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) 79 | m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) 80 | m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) 81 | m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) 82 | m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) 83 | m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) 84 | m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) 85 | m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) 86 | m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) 87 | m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) 88 | m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) 89 | m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) 90 | m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) 91 | m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) 92 | m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) 93 | m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) 94 | m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) 95 | m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) 96 | m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) 97 | m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) 98 | m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) 99 | -------------------------------------------------------------------------------- /test/regress.gen.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Automatically generated from ./regress.rpc 3 | */ 4 | 5 | #ifndef ___REGRESS_RPC_ 6 | #define ___REGRESS_RPC_ 7 | 8 | #include 9 | #ifdef _EVENT_HAVE_STDINT_H 10 | #include 11 | #endif 12 | #define EVTAG_HAS(msg, member) ((msg)->member##_set == 1) 13 | #ifdef __GNUC__ 14 | #define EVTAG_ASSIGN(msg, member, args...) (*(msg)->base->member##_assign)(msg, ## args) 15 | #define EVTAG_GET(msg, member, args...) (*(msg)->base->member##_get)(msg, ## args) 16 | #else 17 | #define EVTAG_ASSIGN(msg, member, ...) (*(msg)->base->member##_assign)(msg, ## __VA_ARGS__) 18 | #define EVTAG_GET(msg, member, ...) (*(msg)->base->member##_get)(msg, ## __VA_ARGS__) 19 | #endif 20 | #define EVTAG_ADD(msg, member) (*(msg)->base->member##_add)(msg) 21 | #define EVTAG_LEN(msg, member) ((msg)->member##_length) 22 | 23 | struct msg; 24 | struct kill; 25 | struct run; 26 | 27 | /* Tag definition for msg */ 28 | enum msg_ { 29 | MSG_FROM_NAME=1, 30 | MSG_TO_NAME=2, 31 | MSG_ATTACK=3, 32 | MSG_RUN=4, 33 | MSG_MAX_TAGS 34 | }; 35 | 36 | /* Structure declaration for msg */ 37 | struct msg_access_ { 38 | int (*from_name_assign)(struct msg *, const char *); 39 | int (*from_name_get)(struct msg *, char * *); 40 | int (*to_name_assign)(struct msg *, const char *); 41 | int (*to_name_get)(struct msg *, char * *); 42 | int (*attack_assign)(struct msg *, const struct kill*); 43 | int (*attack_get)(struct msg *, struct kill* *); 44 | int (*run_assign)(struct msg *, int, const struct run *); 45 | int (*run_get)(struct msg *, int, struct run * *); 46 | struct run * (*run_add)(struct msg *); 47 | }; 48 | 49 | struct msg { 50 | struct msg_access_ *base; 51 | 52 | char *from_name_data; 53 | char *to_name_data; 54 | struct kill* attack_data; 55 | struct run **run_data; 56 | int run_length; 57 | int run_num_allocated; 58 | 59 | ev_uint8_t from_name_set; 60 | ev_uint8_t to_name_set; 61 | ev_uint8_t attack_set; 62 | ev_uint8_t run_set; 63 | }; 64 | 65 | struct msg *msg_new(void); 66 | void msg_free(struct msg *); 67 | void msg_clear(struct msg *); 68 | void msg_marshal(struct evbuffer *, const struct msg *); 69 | int msg_unmarshal(struct msg *, struct evbuffer *); 70 | int msg_complete(struct msg *); 71 | void evtag_marshal_msg(struct evbuffer *, ev_uint32_t, 72 | const struct msg *); 73 | int evtag_unmarshal_msg(struct evbuffer *, ev_uint32_t, 74 | struct msg *); 75 | int msg_from_name_assign(struct msg *, const char *); 76 | int msg_from_name_get(struct msg *, char * *); 77 | int msg_to_name_assign(struct msg *, const char *); 78 | int msg_to_name_get(struct msg *, char * *); 79 | int msg_attack_assign(struct msg *, const struct kill*); 80 | int msg_attack_get(struct msg *, struct kill* *); 81 | int msg_run_assign(struct msg *, int, const struct run *); 82 | int msg_run_get(struct msg *, int, struct run * *); 83 | struct run * msg_run_add(struct msg *); 84 | /* --- msg done --- */ 85 | 86 | /* Tag definition for kill */ 87 | enum kill_ { 88 | KILL_WEAPON=65825, 89 | KILL_ACTION=2, 90 | KILL_HOW_OFTEN=3, 91 | KILL_MAX_TAGS 92 | }; 93 | 94 | /* Structure declaration for kill */ 95 | struct kill_access_ { 96 | int (*weapon_assign)(struct kill *, const char *); 97 | int (*weapon_get)(struct kill *, char * *); 98 | int (*action_assign)(struct kill *, const char *); 99 | int (*action_get)(struct kill *, char * *); 100 | int (*how_often_assign)(struct kill *, const ev_uint32_t); 101 | int (*how_often_get)(struct kill *, ev_uint32_t *); 102 | }; 103 | 104 | struct kill { 105 | struct kill_access_ *base; 106 | 107 | char *weapon_data; 108 | char *action_data; 109 | ev_uint32_t how_often_data; 110 | 111 | ev_uint8_t weapon_set; 112 | ev_uint8_t action_set; 113 | ev_uint8_t how_often_set; 114 | }; 115 | 116 | struct kill *kill_new(void); 117 | void kill_free(struct kill *); 118 | void kill_clear(struct kill *); 119 | void kill_marshal(struct evbuffer *, const struct kill *); 120 | int kill_unmarshal(struct kill *, struct evbuffer *); 121 | int kill_complete(struct kill *); 122 | void evtag_marshal_kill(struct evbuffer *, ev_uint32_t, 123 | const struct kill *); 124 | int evtag_unmarshal_kill(struct evbuffer *, ev_uint32_t, 125 | struct kill *); 126 | int kill_weapon_assign(struct kill *, const char *); 127 | int kill_weapon_get(struct kill *, char * *); 128 | int kill_action_assign(struct kill *, const char *); 129 | int kill_action_get(struct kill *, char * *); 130 | int kill_how_often_assign(struct kill *, const ev_uint32_t); 131 | int kill_how_often_get(struct kill *, ev_uint32_t *); 132 | /* --- kill done --- */ 133 | 134 | /* Tag definition for run */ 135 | enum run_ { 136 | RUN_HOW=1, 137 | RUN_SOME_BYTES=2, 138 | RUN_FIXED_BYTES=3, 139 | RUN_MAX_TAGS 140 | }; 141 | 142 | /* Structure declaration for run */ 143 | struct run_access_ { 144 | int (*how_assign)(struct run *, const char *); 145 | int (*how_get)(struct run *, char * *); 146 | int (*some_bytes_assign)(struct run *, const ev_uint8_t *, ev_uint32_t); 147 | int (*some_bytes_get)(struct run *, ev_uint8_t * *, ev_uint32_t *); 148 | int (*fixed_bytes_assign)(struct run *, const ev_uint8_t *); 149 | int (*fixed_bytes_get)(struct run *, ev_uint8_t **); 150 | }; 151 | 152 | struct run { 153 | struct run_access_ *base; 154 | 155 | char *how_data; 156 | ev_uint8_t *some_bytes_data; 157 | ev_uint32_t some_bytes_length; 158 | ev_uint8_t fixed_bytes_data[24]; 159 | 160 | ev_uint8_t how_set; 161 | ev_uint8_t some_bytes_set; 162 | ev_uint8_t fixed_bytes_set; 163 | }; 164 | 165 | struct run *run_new(void); 166 | void run_free(struct run *); 167 | void run_clear(struct run *); 168 | void run_marshal(struct evbuffer *, const struct run *); 169 | int run_unmarshal(struct run *, struct evbuffer *); 170 | int run_complete(struct run *); 171 | void evtag_marshal_run(struct evbuffer *, ev_uint32_t, 172 | const struct run *); 173 | int evtag_unmarshal_run(struct evbuffer *, ev_uint32_t, 174 | struct run *); 175 | int run_how_assign(struct run *, const char *); 176 | int run_how_get(struct run *, char * *); 177 | int run_some_bytes_assign(struct run *, const ev_uint8_t *, ev_uint32_t); 178 | int run_some_bytes_get(struct run *, ev_uint8_t * *, ev_uint32_t *); 179 | int run_fixed_bytes_assign(struct run *, const ev_uint8_t *); 180 | int run_fixed_bytes_get(struct run *, ev_uint8_t **); 181 | /* --- run done --- */ 182 | 183 | #endif /* ___REGRESS_RPC_ */ 184 | -------------------------------------------------------------------------------- /evutil.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007 Niels Provos 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | #ifndef _EVUTIL_H_ 28 | #define _EVUTIL_H_ 29 | 30 | /** @file evutil.h 31 | 32 | Common convenience functions for cross-platform portability and 33 | related socket manipulations. 34 | 35 | */ 36 | 37 | #ifdef __cplusplus 38 | extern "C" { 39 | #endif 40 | 41 | #include 42 | #ifdef _EVENT_HAVE_SYS_TIME_H 43 | #include 44 | #endif 45 | #ifdef _EVENT_HAVE_STDINT_H 46 | #include 47 | #elif defined(_EVENT_HAVE_INTTYPES_H) 48 | #include 49 | #endif 50 | #ifdef _EVENT_HAVE_SYS_TYPES_H 51 | #include 52 | #endif 53 | #include 54 | 55 | #ifdef _EVENT_HAVE_UINT64_T 56 | #define ev_uint64_t uint64_t 57 | #define ev_int64_t int64_t 58 | #elif defined(WIN32) 59 | #define ev_uint64_t unsigned __int64 60 | #define ev_int64_t signed __int64 61 | #elif _EVENT_SIZEOF_LONG_LONG == 8 62 | #define ev_uint64_t unsigned long long 63 | #define ev_int64_t long long 64 | #elif _EVENT_SIZEOF_LONG == 8 65 | #define ev_uint64_t unsigned long 66 | #define ev_int64_t long 67 | #else 68 | #error "No way to define ev_uint64_t" 69 | #endif 70 | 71 | #ifdef _EVENT_HAVE_UINT32_T 72 | #define ev_uint32_t uint32_t 73 | #elif defined(WIN32) 74 | #define ev_uint32_t unsigned int 75 | #elif _EVENT_SIZEOF_LONG == 4 76 | #define ev_uint32_t unsigned long 77 | #elif _EVENT_SIZEOF_INT == 4 78 | #define ev_uint32_t unsigned int 79 | #else 80 | #error "No way to define ev_uint32_t" 81 | #endif 82 | 83 | #ifdef _EVENT_HAVE_UINT16_T 84 | #define ev_uint16_t uint16_t 85 | #elif defined(WIN32) 86 | #define ev_uint16_t unsigned short 87 | #elif _EVENT_SIZEOF_INT == 2 88 | #define ev_uint16_t unsigned int 89 | #elif _EVENT_SIZEOF_SHORT == 2 90 | #define ev_uint16_t unsigned short 91 | #else 92 | #error "No way to define ev_uint16_t" 93 | #endif 94 | 95 | #ifdef _EVENT_HAVE_UINT8_T 96 | #define ev_uint8_t uint8_t 97 | #else 98 | #define ev_uint8_t unsigned char 99 | #endif 100 | 101 | int evutil_socketpair(int d, int type, int protocol, int sv[2]); 102 | int evutil_make_socket_nonblocking(int sock); 103 | #ifdef WIN32 104 | #define EVUTIL_CLOSESOCKET(s) closesocket(s) 105 | #else 106 | #define EVUTIL_CLOSESOCKET(s) close(s) 107 | #endif 108 | 109 | #ifdef WIN32 110 | #define EVUTIL_SOCKET_ERROR() WSAGetLastError() 111 | #define EVUTIL_SET_SOCKET_ERROR(errcode) \ 112 | do { WSASetLastError(errcode); } while (0) 113 | #else 114 | #define EVUTIL_SOCKET_ERROR() (errno) 115 | #define EVUTIL_SET_SOCKET_ERROR(errcode) \ 116 | do { errno = (errcode); } while (0) 117 | #endif 118 | 119 | /* 120 | * Manipulation functions for struct timeval 121 | */ 122 | #ifdef _EVENT_HAVE_TIMERADD 123 | #define evutil_timeradd(tvp, uvp, vvp) timeradd((tvp), (uvp), (vvp)) 124 | #define evutil_timersub(tvp, uvp, vvp) timersub((tvp), (uvp), (vvp)) 125 | #else 126 | #define evutil_timeradd(tvp, uvp, vvp) \ 127 | do { \ 128 | (vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec; \ 129 | (vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec; \ 130 | if ((vvp)->tv_usec >= 1000000) { \ 131 | (vvp)->tv_sec++; \ 132 | (vvp)->tv_usec -= 1000000; \ 133 | } \ 134 | } while (0) 135 | #define evutil_timersub(tvp, uvp, vvp) \ 136 | do { \ 137 | (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \ 138 | (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \ 139 | if ((vvp)->tv_usec < 0) { \ 140 | (vvp)->tv_sec--; \ 141 | (vvp)->tv_usec += 1000000; \ 142 | } \ 143 | } while (0) 144 | #endif /* !_EVENT_HAVE_HAVE_TIMERADD */ 145 | 146 | #ifdef _EVENT_HAVE_TIMERCLEAR 147 | #define evutil_timerclear(tvp) timerclear(tvp) 148 | #else 149 | #define evutil_timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0 150 | #endif 151 | 152 | #define evutil_timercmp(tvp, uvp, cmp) \ 153 | (((tvp)->tv_sec == (uvp)->tv_sec) ? \ 154 | ((tvp)->tv_usec cmp (uvp)->tv_usec) : \ 155 | ((tvp)->tv_sec cmp (uvp)->tv_sec)) 156 | 157 | #ifdef _EVENT_HAVE_TIMERISSET 158 | #define evutil_timerisset(tvp) timerisset(tvp) 159 | #else 160 | #define evutil_timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec) 161 | #endif 162 | 163 | 164 | /* big-int related functions */ 165 | ev_int64_t evutil_strtoll(const char* s, char** endptr, int base); 166 | 167 | 168 | #ifdef _EVENT_HAVE_GETTIMEOFDAY 169 | #define evutil_gettimeofday(tv, tz) gettimeofday((tv), (tz)) 170 | #else 171 | struct timezone; 172 | int evutil_gettimeofday(struct timeval* tv, struct timezone* tz); 173 | #endif 174 | 175 | int evutil_snprintf(char* buf, size_t buflen, const char* format, ...) 176 | #ifdef __GNUC__ 177 | __attribute__((format(printf, 3, 4))) 178 | #endif 179 | ; 180 | int evutil_vsnprintf(char* buf, size_t buflen, const char* format, va_list ap); 181 | 182 | #ifdef __cplusplus 183 | } 184 | #endif 185 | 186 | #endif /* _EVUTIL_H_ */ 187 | -------------------------------------------------------------------------------- /WIN32-Code/config.h: -------------------------------------------------------------------------------- 1 | /* config.h. Generated by configure. */ 2 | /* config.h.in. Generated from configure.in by autoheader. */ 3 | 4 | /* Define if clock_gettime is available in libc */ 5 | /* #undef DNS_USE_CPU_CLOCK_FOR_ID */ 6 | 7 | /* Define if no secure id variant is available */ 8 | #define DNS_USE_FTIME_FOR_ID 1 9 | 10 | /* Define if no secure id variant is available */ 11 | /* #define DNS_USE_GETTIMEOFDAY_FOR_ID 1 */ 12 | 13 | /* Define to 1 if you have the `clock_gettime' function. */ 14 | /* #undef HAVE_CLOCK_GETTIME */ 15 | 16 | /* Define if /dev/poll is available */ 17 | /* #undef HAVE_DEVPOLL */ 18 | 19 | /* Define to 1 if you have the header file. */ 20 | /* #undef HAVE_DLFCN_H */ 21 | 22 | /* Define if your system supports the epoll system calls */ 23 | /* #undef HAVE_EPOLL */ 24 | 25 | /* Define to 1 if you have the `epoll_ctl' function. */ 26 | /* #undef HAVE_EPOLL_CTL */ 27 | 28 | /* Define if your system supports event ports */ 29 | /* #undef HAVE_EVENT_PORTS */ 30 | 31 | /* Define to 1 if you have the `fcntl' function. */ 32 | /* #undef HAVE_FCNTL */ 33 | 34 | /* Define to 1 if you have the header file. */ 35 | #define HAVE_FCNTL_H 1 36 | 37 | /* Define to 1 if you have the `getaddrinfo' function. */ 38 | /* #undef HAVE_GETADDRINFO */ 39 | 40 | /* Define to 1 if you have the `getnameinfo' function. */ 41 | /* #undef HAVE_GETNAMEINFO */ 42 | 43 | /* Define to 1 if you have the `gettimeofday' function. */ 44 | /* #define HAVE_GETTIMEOFDAY 1 */ 45 | 46 | /* Define to 1 if you have the `inet_ntop' function. */ 47 | /* #undef HAVE_INET_NTOP */ 48 | 49 | /* Define to 1 if you have the header file. */ 50 | /* #undef HAVE_INTTYPES_H 1 */ 51 | 52 | /* Define to 1 if you have the `kqueue' function. */ 53 | /* #undef HAVE_KQUEUE */ 54 | 55 | /* Define to 1 if you have the `nsl' library (-lnsl). */ 56 | /* #undef HAVE_LIBNSL */ 57 | 58 | /* Define to 1 if you have the `resolv' library (-lresolv). */ 59 | /* #undef HAVE_LIBRESOLV */ 60 | 61 | /* Define to 1 if you have the `rt' library (-lrt). */ 62 | /* #undef HAVE_LIBRT */ 63 | 64 | /* Define to 1 if you have the `socket' library (-lsocket). */ 65 | /* #undef HAVE_LIBSOCKET */ 66 | 67 | /* Define to 1 if you have the header file. */ 68 | #define HAVE_MEMORY_H 1 69 | 70 | /* Define to 1 if you have the header file. */ 71 | /* #undef HAVE_NETINET_IN6_H */ 72 | 73 | /* Define to 1 if you have the `poll' function. */ 74 | /* #undef HAVE_POLL */ 75 | 76 | /* Define to 1 if you have the header file. */ 77 | /* #undef HAVE_POLL_H */ 78 | 79 | /* Define to 1 if you have the `port_create' function. */ 80 | /* #undef HAVE_PORT_CREATE */ 81 | 82 | /* Define to 1 if you have the header file. */ 83 | /* #undef HAVE_PORT_H */ 84 | 85 | /* Define to 1 if you have the `select' function. */ 86 | /* #undef HAVE_SELECT */ 87 | 88 | /* Define if F_SETFD is defined in */ 89 | /* #undef HAVE_SETFD */ 90 | 91 | /* Define to 1 if you have the `sigaction' function. */ 92 | /* #undef HAVE_SIGACTION */ 93 | 94 | /* Define to 1 if you have the `signal' function. */ 95 | #define HAVE_SIGNAL 1 96 | 97 | /* Define to 1 if you have the header file. */ 98 | #define HAVE_SIGNAL_H 1 99 | 100 | /* Define to 1 if you have the header file. */ 101 | #define HAVE_STDARG_H 1 102 | 103 | /* Define to 1 if you have the header file. */ 104 | /* #define HAVE_STDINT_H 1 */ 105 | 106 | /* Define to 1 if you have the header file. */ 107 | #define HAVE_STDLIB_H 1 108 | 109 | /* Define to 1 if you have the header file. */ 110 | #define HAVE_STRINGS_H 1 111 | 112 | /* Define to 1 if you have the header file. */ 113 | #define HAVE_STRING_H 1 114 | 115 | /* Define to 1 if you have the `strlcpy' function. */ 116 | /* #undef HAVE_STRLCPY */ 117 | 118 | /* Define to 1 if you have the `strsep' function. */ 119 | /* #undef HAVE_STRSEP */ 120 | 121 | /* Define to 1 if you have the `strtok_r' function. */ 122 | /* #undef HAVE_STRTOK_R */ 123 | 124 | /* Define to 1 if the system has the type `struct in6_addr'. */ 125 | #define HAVE_STRUCT_IN6_ADDR 1 126 | 127 | /* Define to 1 if you have the header file. */ 128 | /* #undef HAVE_SYS_DEVPOLL_H */ 129 | 130 | /* Define to 1 if you have the header file. */ 131 | /* #undef HAVE_SYS_EPOLL_H */ 132 | 133 | /* Define to 1 if you have the header file. */ 134 | /* #undef HAVE_SYS_EVENT_H */ 135 | 136 | /* Define to 1 if you have the header file. */ 137 | /* #undef HAVE_SYS_IOCTL_H */ 138 | 139 | /* Define to 1 if you have the header file. */ 140 | /* #undef HAVE_SYS_QUEUE_H */ 141 | 142 | /* Define to 1 if you have the header file. */ 143 | /* #undef HAVE_SYS_SELECT_H */ 144 | 145 | /* Define to 1 if you have the header file. */ 146 | /* #undef HAVE_SYS_SOCKET_H */ 147 | 148 | /* Define to 1 if you have the header file. */ 149 | /* #define HAVE_SYS_STAT_H 1 */ 150 | 151 | /* Define to 1 if you have the header file. */ 152 | /* #define HAVE_SYS_TIME_H 1 */ 153 | 154 | /* Define to 1 if you have the header file. */ 155 | /* #define HAVE_SYS_TYPES_H 1 */ 156 | 157 | /* Define if TAILQ_FOREACH is defined in */ 158 | /* #undef HAVE_TAILQFOREACH */ 159 | 160 | /* Define if timeradd is defined in */ 161 | /* #undef HAVE_TIMERADD */ 162 | 163 | /* Define if timerclear is defined in */ 164 | /* #define HAVE_TIMERCLEAR 1 */ 165 | 166 | /* Define if timercmp is defined in */ 167 | #define HAVE_TIMERCMP 1 168 | 169 | /* Define if timerisset is defined in */ 170 | #define HAVE_TIMERISSET 1 171 | 172 | /* Define to 1 if you have the header file. */ 173 | /* #define HAVE_UNISTD_H 1 */ 174 | 175 | /* Define to 1 if you have the `vasprintf' function. */ 176 | /* #undef HAVE_VASPRINTF */ 177 | 178 | /* Define if kqueue works correctly with pipes */ 179 | /* #undef HAVE_WORKING_KQUEUE */ 180 | 181 | /* Name of package */ 182 | #define PACKAGE "libevent" 183 | 184 | /* Define to the address where bug reports for this package should be sent. */ 185 | #define PACKAGE_BUGREPORT "" 186 | 187 | /* Define to the full name of this package. */ 188 | #define PACKAGE_NAME "" 189 | 190 | /* Define to the full name and version of this package. */ 191 | #define PACKAGE_STRING "" 192 | 193 | /* Define to the one symbol short name of this package. */ 194 | #define PACKAGE_TARNAME "" 195 | 196 | /* Define to the version of this package. */ 197 | #define PACKAGE_VERSION "" 198 | 199 | /* Define to 1 if you have the ANSI C header files. */ 200 | #define STDC_HEADERS 1 201 | 202 | /* Define to 1 if you can safely include both and . */ 203 | #define TIME_WITH_SYS_TIME 1 204 | 205 | /* Version number of package */ 206 | #define VERSION "1.4.15-stable" 207 | 208 | /* Define to appropriate substitue if compiler doesnt have __func__ */ 209 | #if defined(_MSC_VER) && _MSC_VER < 1300 210 | #define __func__ "??" 211 | #else 212 | #define __func__ __FUNCTION__ 213 | #endif 214 | 215 | /* Define to empty if `const' does not conform to ANSI C. */ 216 | /* #undef const */ 217 | 218 | /* Define to `__inline__' or `__inline' if that's what the C compiler 219 | calls it, or to nothing if 'inline' is not supported under any name. */ 220 | #ifndef __cplusplus 221 | #define inline __inline 222 | #endif 223 | 224 | /* Define to `int' if does not define. */ 225 | /* #undef pid_t */ 226 | 227 | /* Define to `unsigned' if does not define. */ 228 | /* #undef size_t */ 229 | 230 | /* Define to unsigned int if you dont have it */ 231 | #define socklen_t unsigned int 232 | 233 | /* Define to `unsigned short' if does not define. */ 234 | #define uint16_t unsigned short 235 | 236 | /* Define to `unsigned int' if does not define. */ 237 | #define uint32_t unsigned int 238 | 239 | /* Define to `unsigned long long' if does not define. */ 240 | #define uint64_t __uint64_t 241 | 242 | /* Define to `unsigned char' if does not define. */ 243 | #define uint8_t unsigned char 244 | -------------------------------------------------------------------------------- /config.h: -------------------------------------------------------------------------------- 1 | /* config.h.in. Generated from configure.in by autoheader. */ 2 | 3 | /* Define if clock_gettime is available in libc */ 4 | #undef DNS_USE_CPU_CLOCK_FOR_ID 5 | 6 | /* Define is no secure id variant is available */ 7 | #undef DNS_USE_GETTIMEOFDAY_FOR_ID 8 | 9 | /* Define to 1 if you have the `clock_gettime' function. */ 10 | #undef HAVE_CLOCK_GETTIME 11 | 12 | /* Define if /dev/poll is available */ 13 | #undef HAVE_DEVPOLL 14 | 15 | /* Define to 1 if you have the header file. */ 16 | #undef HAVE_DLFCN_H 17 | 18 | /* Define if your system supports the epoll system calls */ 19 | #undef HAVE_EPOLL 20 | 21 | /* Define to 1 if you have the `epoll_ctl' function. */ 22 | #undef HAVE_EPOLL_CTL 23 | 24 | /* Define if your system supports event ports */ 25 | #undef HAVE_EVENT_PORTS 26 | 27 | /* Define to 1 if you have the `fcntl' function. */ 28 | #undef HAVE_FCNTL 29 | 30 | /* Define to 1 if you have the header file. */ 31 | #undef HAVE_FCNTL_H 32 | 33 | /* Define to 1 if the system has the type `fd_mask'. */ 34 | #undef HAVE_FD_MASK 35 | 36 | /* Define to 1 if you have the `getaddrinfo' function. */ 37 | #undef HAVE_GETADDRINFO 38 | 39 | /* Define to 1 if you have the `getegid' function. */ 40 | #undef HAVE_GETEGID 41 | 42 | /* Define to 1 if you have the `geteuid' function. */ 43 | #undef HAVE_GETEUID 44 | 45 | /* Define to 1 if you have the `getnameinfo' function. */ 46 | #undef HAVE_GETNAMEINFO 47 | 48 | /* Define to 1 if you have the `gettimeofday' function. */ 49 | #undef HAVE_GETTIMEOFDAY 50 | 51 | /* Define to 1 if you have the `inet_ntop' function. */ 52 | #undef HAVE_INET_NTOP 53 | 54 | /* Define to 1 if you have the header file. */ 55 | #undef HAVE_INTTYPES_H 56 | 57 | /* Define to 1 if you have the `issetugid' function. */ 58 | #undef HAVE_ISSETUGID 59 | 60 | /* Define to 1 if you have the `kqueue' function. */ 61 | #undef HAVE_KQUEUE 62 | 63 | /* Define to 1 if you have the `nsl' library (-lnsl). */ 64 | #undef HAVE_LIBNSL 65 | 66 | /* Define to 1 if you have the `resolv' library (-lresolv). */ 67 | #undef HAVE_LIBRESOLV 68 | 69 | /* Define to 1 if you have the `rt' library (-lrt). */ 70 | #undef HAVE_LIBRT 71 | 72 | /* Define to 1 if you have the `socket' library (-lsocket). */ 73 | #undef HAVE_LIBSOCKET 74 | 75 | /* Define to 1 if you have the header file. */ 76 | #undef HAVE_MEMORY_H 77 | 78 | /* Define to 1 if you have the header file. */ 79 | #undef HAVE_NETINET_IN6_H 80 | 81 | /* Define to 1 if you have the `poll' function. */ 82 | #undef HAVE_POLL 83 | 84 | /* Define to 1 if you have the header file. */ 85 | #undef HAVE_POLL_H 86 | 87 | /* Define to 1 if you have the `port_create' function. */ 88 | #undef HAVE_PORT_CREATE 89 | 90 | /* Define to 1 if you have the header file. */ 91 | #undef HAVE_PORT_H 92 | 93 | /* Define to 1 if you have the `select' function. */ 94 | #undef HAVE_SELECT 95 | 96 | /* Define if F_SETFD is defined in */ 97 | #undef HAVE_SETFD 98 | 99 | /* Define to 1 if you have the `sigaction' function. */ 100 | #undef HAVE_SIGACTION 101 | 102 | /* Define to 1 if you have the `signal' function. */ 103 | #undef HAVE_SIGNAL 104 | 105 | /* Define to 1 if you have the header file. */ 106 | #undef HAVE_SIGNAL_H 107 | 108 | /* Define to 1 if you have the header file. */ 109 | #undef HAVE_STDARG_H 110 | 111 | /* Define to 1 if you have the header file. */ 112 | #undef HAVE_STDINT_H 113 | 114 | /* Define to 1 if you have the header file. */ 115 | #undef HAVE_STDLIB_H 116 | 117 | /* Define to 1 if you have the header file. */ 118 | #undef HAVE_STRINGS_H 119 | 120 | /* Define to 1 if you have the header file. */ 121 | #undef HAVE_STRING_H 122 | 123 | /* Define to 1 if you have the `strlcpy' function. */ 124 | #undef HAVE_STRLCPY 125 | 126 | /* Define to 1 if you have the `strsep' function. */ 127 | #undef HAVE_STRSEP 128 | 129 | /* Define to 1 if you have the `strtok_r' function. */ 130 | #undef HAVE_STRTOK_R 131 | 132 | /* Define to 1 if you have the `strtoll' function. */ 133 | #undef HAVE_STRTOLL 134 | 135 | /* Define to 1 if the system has the type `struct in6_addr'. */ 136 | #undef HAVE_STRUCT_IN6_ADDR 137 | 138 | /* Define to 1 if you have the header file. */ 139 | #undef HAVE_SYS_DEVPOLL_H 140 | 141 | /* Define to 1 if you have the header file. */ 142 | #undef HAVE_SYS_EPOLL_H 143 | 144 | /* Define to 1 if you have the header file. */ 145 | #undef HAVE_SYS_EVENT_H 146 | 147 | /* Define to 1 if you have the header file. */ 148 | #undef HAVE_SYS_IOCTL_H 149 | 150 | /* Define to 1 if you have the header file. */ 151 | #undef HAVE_SYS_PARAM_H 152 | 153 | /* Define to 1 if you have the header file. */ 154 | #undef HAVE_SYS_QUEUE_H 155 | 156 | /* Define to 1 if you have the header file. */ 157 | #undef HAVE_SYS_SELECT_H 158 | 159 | /* Define to 1 if you have the header file. */ 160 | #undef HAVE_SYS_SOCKET_H 161 | 162 | /* Define to 1 if you have the header file. */ 163 | #undef HAVE_SYS_STAT_H 164 | 165 | /* Define to 1 if you have the header file. */ 166 | #undef HAVE_SYS_TIME_H 167 | 168 | /* Define to 1 if you have the header file. */ 169 | #undef HAVE_SYS_TYPES_H 170 | 171 | /* Define if TAILQ_FOREACH is defined in */ 172 | #undef HAVE_TAILQFOREACH 173 | 174 | /* Define if timeradd is defined in */ 175 | #undef HAVE_TIMERADD 176 | 177 | /* Define if timerclear is defined in */ 178 | #undef HAVE_TIMERCLEAR 179 | 180 | /* Define if timercmp is defined in */ 181 | #undef HAVE_TIMERCMP 182 | 183 | /* Define if timerisset is defined in */ 184 | #undef HAVE_TIMERISSET 185 | 186 | /* Define to 1 if the system has the type `uint16_t'. */ 187 | #undef HAVE_UINT16_T 188 | 189 | /* Define to 1 if the system has the type `uint32_t'. */ 190 | #undef HAVE_UINT32_T 191 | 192 | /* Define to 1 if the system has the type `uint64_t'. */ 193 | #undef HAVE_UINT64_T 194 | 195 | /* Define to 1 if the system has the type `uint8_t'. */ 196 | #undef HAVE_UINT8_T 197 | 198 | /* Define to 1 if you have the header file. */ 199 | #undef HAVE_UNISTD_H 200 | 201 | /* Define to 1 if you have the `vasprintf' function. */ 202 | #undef HAVE_VASPRINTF 203 | 204 | /* Define if kqueue works correctly with pipes */ 205 | #undef HAVE_WORKING_KQUEUE 206 | 207 | /* Define to the sub-directory in which libtool stores uninstalled libraries. 208 | */ 209 | #undef LT_OBJDIR 210 | 211 | /* Numeric representation of the version */ 212 | #undef NUMERIC_VERSION 213 | 214 | /* Name of package */ 215 | #undef PACKAGE 216 | 217 | /* Define to the address where bug reports for this package should be sent. */ 218 | #undef PACKAGE_BUGREPORT 219 | 220 | /* Define to the full name of this package. */ 221 | #undef PACKAGE_NAME 222 | 223 | /* Define to the full name and version of this package. */ 224 | #undef PACKAGE_STRING 225 | 226 | /* Define to the one symbol short name of this package. */ 227 | #undef PACKAGE_TARNAME 228 | 229 | /* Define to the home page for this package. */ 230 | #undef PACKAGE_URL 231 | 232 | /* Define to the version of this package. */ 233 | #undef PACKAGE_VERSION 234 | 235 | /* The size of `int', as computed by sizeof. */ 236 | #undef SIZEOF_INT 237 | 238 | /* The size of `long', as computed by sizeof. */ 239 | #undef SIZEOF_LONG 240 | 241 | /* The size of `long long', as computed by sizeof. */ 242 | #undef SIZEOF_LONG_LONG 243 | 244 | /* The size of `short', as computed by sizeof. */ 245 | #undef SIZEOF_SHORT 246 | 247 | /* Define to 1 if you have the ANSI C header files. */ 248 | #undef STDC_HEADERS 249 | 250 | /* Define to 1 if you can safely include both and . */ 251 | #undef TIME_WITH_SYS_TIME 252 | 253 | /* Version number of package */ 254 | #undef VERSION 255 | 256 | /* Define to appropriate substitue if compiler doesnt have __func__ */ 257 | #undef __func__ 258 | 259 | /* Define to empty if `const' does not conform to ANSI C. */ 260 | #undef const 261 | 262 | /* Define to `__inline__' or `__inline' if that's what the C compiler 263 | calls it, or to nothing if 'inline' is not supported under any name. */ 264 | #ifndef __cplusplus 265 | #undef inline 266 | #endif 267 | 268 | /* Define to `int' if does not define. */ 269 | #undef pid_t 270 | 271 | /* Define to `unsigned int' if does not define. */ 272 | #undef size_t 273 | 274 | /* Define to unsigned int if you dont have it */ 275 | #undef socklen_t 276 | -------------------------------------------------------------------------------- /WIN32-Code/event-config.h: -------------------------------------------------------------------------------- 1 | /* event-config.h 2 | * Generated by autoconf; post-processed by libevent. 3 | * Do not edit this file. 4 | * Do not rely on macros in this file existing in later versions. 5 | */ 6 | #ifndef _EVENT_CONFIG_H_ 7 | #define _EVENT_CONFIG_H_ 8 | /* config.h. Generated by configure. */ 9 | /* config.h.in. Generated from configure.in by autoheader. */ 10 | 11 | /* Define if clock_gettime is available in libc */ 12 | /* #undef _EVENT_DNS_USE_CPU_CLOCK_FOR_ID */ 13 | 14 | /* Define is no secure id variant is available */ 15 | #define _EVENT_DNS_USE_GETTIMEOFDAY_FOR_ID 1 16 | 17 | /* Define to 1 if you have the `clock_gettime' function. */ 18 | /* #undef _EVENT_HAVE_CLOCK_GETTIME */ 19 | 20 | /* Define if /dev/poll is available */ 21 | /* #undef _EVENT_HAVE_DEVPOLL */ 22 | 23 | /* Define to 1 if you have the header file. */ 24 | /* #undef _EVENT_HAVE_DLFCN_H */ 25 | 26 | /* Define if your system supports the epoll system calls */ 27 | /* #undef _EVENT_HAVE_EPOLL */ 28 | 29 | /* Define to 1 if you have the `epoll_ctl' function. */ 30 | /* #undef _EVENT_HAVE_EPOLL_CTL */ 31 | 32 | /* Define if your system supports event ports */ 33 | /* #undef _EVENT_HAVE_EVENT_PORTS */ 34 | 35 | /* Define to 1 if you have the `fcntl' function. */ 36 | /* #undef _EVENT_HAVE_FCNTL */ 37 | 38 | /* Define to 1 if you have the header file. */ 39 | #define _EVENT_HAVE_FCNTL_H 1 40 | 41 | /* Define to 1 if you have the `getaddrinfo' function. */ 42 | /* #undef _EVENT_HAVE_GETADDRINFO */ 43 | 44 | /* Define to 1 if you have the `getnameinfo' function. */ 45 | /* #undef _EVENT_HAVE_GETNAMEINFO */ 46 | 47 | /* Define to 1 if you have the `gettimeofday' function. */ 48 | /* #define _EVENT_HAVE_GETTIMEOFDAY 1 */ 49 | 50 | /* Define to 1 if you have the `inet_ntop' function. */ 51 | /* #undef _EVENT_HAVE_INET_NTOP */ 52 | 53 | /* Define to 1 if you have the header file. */ 54 | /* #undef _EVENT_HAVE_INTTYPES_H 1 */ 55 | 56 | /* Define to 1 if you have the `kqueue' function. */ 57 | /* #undef _EVENT_HAVE_KQUEUE */ 58 | 59 | /* Define to 1 if you have the `nsl' library (-lnsl). */ 60 | /* #undef _EVENT_HAVE_LIBNSL */ 61 | 62 | /* Define to 1 if you have the `resolv' library (-lresolv). */ 63 | /* #undef _EVENT_HAVE_LIBRESOLV */ 64 | 65 | /* Define to 1 if you have the `rt' library (-lrt). */ 66 | /* #undef _EVENT_HAVE_LIBRT */ 67 | 68 | /* Define to 1 if you have the `socket' library (-lsocket). */ 69 | /* #undef _EVENT_HAVE_LIBSOCKET */ 70 | 71 | /* Define to 1 if you have the header file. */ 72 | #define _EVENT_HAVE_MEMORY_H 1 73 | 74 | /* Define to 1 if you have the header file. */ 75 | /* #undef _EVENT_HAVE_NETINET_IN6_H */ 76 | 77 | /* Define to 1 if you have the `poll' function. */ 78 | /* #undef _EVENT_HAVE_POLL */ 79 | 80 | /* Define to 1 if you have the header file. */ 81 | /* #undef _EVENT_HAVE_POLL_H */ 82 | 83 | /* Define to 1 if you have the `port_create' function. */ 84 | /* #undef _EVENT_HAVE_PORT_CREATE */ 85 | 86 | /* Define to 1 if you have the header file. */ 87 | /* #undef _EVENT_HAVE_PORT_H */ 88 | 89 | /* Define to 1 if you have the `select' function. */ 90 | /* #undef _EVENT_HAVE_SELECT */ 91 | 92 | /* Define if F_SETFD is defined in */ 93 | /* #undef _EVENT_HAVE_SETFD */ 94 | 95 | /* Define to 1 if you have the `sigaction' function. */ 96 | /* #undef _EVENT_HAVE_SIGACTION */ 97 | 98 | /* Define to 1 if you have the `signal' function. */ 99 | #define _EVENT_HAVE_SIGNAL 1 100 | 101 | /* Define to 1 if you have the header file. */ 102 | #define _EVENT_HAVE_SIGNAL_H 1 103 | 104 | /* Define to 1 if you have the header file. */ 105 | #define _EVENT_HAVE_STDARG_H 1 106 | 107 | /* Define to 1 if you have the header file. */ 108 | /* #define _EVENT_HAVE_STDINT_H 1 */ 109 | 110 | /* Define to 1 if you have the header file. */ 111 | #define _EVENT_HAVE_STDLIB_H 1 112 | 113 | /* Define to 1 if you have the header file. */ 114 | #define _EVENT_HAVE_STRINGS_H 1 115 | 116 | /* Define to 1 if you have the header file. */ 117 | #define _EVENT_HAVE_STRING_H 1 118 | 119 | /* Define to 1 if you have the `strlcpy' function. */ 120 | /* #undef _EVENT_HAVE_STRLCPY */ 121 | 122 | /* Define to 1 if you have the `strsep' function. */ 123 | /* #undef _EVENT_HAVE_STRSEP */ 124 | 125 | /* Define to 1 if you have the `strtok_r' function. */ 126 | /* #undef _EVENT_HAVE_STRTOK_R */ 127 | 128 | /* Define to 1 if the system has the type `struct in6_addr'. */ 129 | #define _EVENT_HAVE_STRUCT_IN6_ADDR 1 130 | 131 | /* Define to 1 if you have the header file. */ 132 | /* #undef _EVENT_HAVE_SYS_DEVPOLL_H */ 133 | 134 | /* Define to 1 if you have the header file. */ 135 | /* #undef _EVENT_HAVE_SYS_EPOLL_H */ 136 | 137 | /* Define to 1 if you have the header file. */ 138 | /* #undef _EVENT_HAVE_SYS_EVENT_H */ 139 | 140 | /* Define to 1 if you have the header file. */ 141 | /* #undef _EVENT_HAVE_SYS_IOCTL_H */ 142 | 143 | /* Define to 1 if you have the header file. */ 144 | /* #undef _EVENT_HAVE_SYS_QUEUE_H */ 145 | 146 | /* Define to 1 if you have the header file. */ 147 | /* #undef _EVENT_HAVE_SYS_SELECT_H */ 148 | 149 | /* Define to 1 if you have the header file. */ 150 | /* #undef _EVENT_HAVE_SYS_SOCKET_H */ 151 | 152 | /* Define to 1 if you have the header file. */ 153 | #define _EVENT_HAVE_SYS_STAT_H 1 154 | 155 | /* Define to 1 if you have the header file. */ 156 | /* #define _EVENT_HAVE_SYS_TIME_H 1 */ 157 | 158 | /* Define to 1 if you have the header file. */ 159 | /* #define _EVENT_HAVE_SYS_TYPES_H 1 */ 160 | 161 | /* Define if TAILQ_FOREACH is defined in */ 162 | /* #undef _EVENT_HAVE_TAILQFOREACH */ 163 | 164 | /* Define if timeradd is defined in */ 165 | /* #undef _EVENT_HAVE_TIMERADD */ 166 | 167 | /* Define if timerclear is defined in */ 168 | /* #define _EVENT_HAVE_TIMERCLEAR 1 */ 169 | 170 | /* Define if timercmp is defined in */ 171 | #define _EVENT_HAVE_TIMERCMP 1 172 | 173 | /* Define if timerisset is defined in */ 174 | #define _EVENT_HAVE_TIMERISSET 1 175 | 176 | /* Define to 1 if you have the header file. */ 177 | /* #define _EVENT_HAVE_UNISTD_H 1 */ 178 | 179 | /* Define to 1 if you have the `vasprintf' function. */ 180 | /* #undef _EVENT_HAVE_VASPRINTF */ 181 | 182 | /* Define if kqueue works correctly with pipes */ 183 | /* #undef _EVENT_HAVE_WORKING_KQUEUE */ 184 | 185 | /* Name of package */ 186 | #define _EVENT_PACKAGE "libevent" 187 | 188 | /* Define to the address where bug reports for this package should be sent. */ 189 | #define _EVENT_PACKAGE_BUGREPORT "" 190 | 191 | /* Define to the full name of this package. */ 192 | #define _EVENT_PACKAGE_NAME "" 193 | 194 | /* Define to the full name and version of this package. */ 195 | #define _EVENT_PACKAGE_STRING "" 196 | 197 | /* Define to the one symbol short name of this package. */ 198 | #define _EVENT_PACKAGE_TARNAME "" 199 | 200 | /* Define to the version of this package. */ 201 | #define _EVENT_PACKAGE_VERSION "" 202 | 203 | /* Define to 1 if you have the ANSI C header files. */ 204 | #define _EVENT_STDC_HEADERS 1 205 | 206 | /* Define to 1 if you can safely include both and . */ 207 | #define _EVENT_TIME_WITH_SYS_TIME 1 208 | 209 | /* Version number of package */ 210 | #define _EVENT_VERSION "1.4.14b-stable" 211 | 212 | #define _EVENT_NUMERIC_VERSION 0x01040e00 213 | 214 | /* Define to appropriate substitue if compiler doesnt have __func__ */ 215 | /* #undef _EVENT___func__ */ 216 | 217 | /* Define to empty if `const' does not conform to ANSI C. */ 218 | /* #undef _EVENT_const */ 219 | 220 | /* Define to `__inline__' or `__inline' if that's what the C compiler 221 | calls it, or to nothing if 'inline' is not supported under any name. */ 222 | #ifndef _EVENT___cplusplus 223 | #define _EVENT_inline __inline 224 | #endif 225 | 226 | #define _EVENT___func__ __FUNCTION__ 227 | 228 | /* Define to `int' if does not define. */ 229 | /* #undef _EVENT_pid_t */ 230 | 231 | /* Define to `unsigned' if does not define. */ 232 | /* #undef _EVENT_size_t */ 233 | 234 | /* Define to unsigned int if you dont have it */ 235 | #define _EVENT_socklen_t unsigned int 236 | 237 | /* Define to `unsigned short' if does not define. */ 238 | /* #undef _EVENT_uint16_t */ 239 | 240 | /* Define to `unsigned int' if does not define. */ 241 | /* #undef _EVENT_uint32_t */ 242 | 243 | /* Define to `unsigned long long' if does not define. */ 244 | /* #undef _EVENT_uint64_t */ 245 | 246 | /* Define to `unsigned char' if does not define. */ 247 | /* #undef _EVENT_uint8_t */ 248 | #endif 249 | -------------------------------------------------------------------------------- /evutil.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007 Niels Provos 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | #ifdef HAVE_CONFIG_H 28 | #include "config.h" 29 | #endif 30 | 31 | #ifdef WIN32 32 | #include 33 | #define WIN32_LEAN_AND_MEAN 34 | #include 35 | #undef WIN32_LEAN_AND_MEAN 36 | #endif 37 | 38 | #include 39 | #ifdef HAVE_SYS_SOCKET_H 40 | #include 41 | #endif 42 | #ifdef HAVE_UNISTD_H 43 | #include 44 | #endif 45 | #ifdef HAVE_FCNTL_H 46 | #include 47 | #endif 48 | #ifdef HAVE_STDLIB_H 49 | #include 50 | #endif 51 | #include 52 | #if defined WIN32 && !defined(HAVE_GETTIMEOFDAY_H) 53 | #include 54 | #endif 55 | #include 56 | #include 57 | 58 | #include 59 | #include "event.h" 60 | #include "event-internal.h" 61 | #include "evutil.h" 62 | #include "log.h" 63 | 64 | int 65 | evutil_socketpair(int family, int type, int protocol, int fd[2]) 66 | { 67 | #ifndef WIN32 68 | return socketpair(family, type, protocol, fd); 69 | #else 70 | /* This code is originally from Tor. Used with permission. */ 71 | 72 | /* This socketpair does not work when localhost is down. So 73 | * it's really not the same thing at all. But it's close enough 74 | * for now, and really, when localhost is down sometimes, we 75 | * have other problems too. 76 | */ 77 | int listener = -1; 78 | int connector = -1; 79 | int acceptor = -1; 80 | struct sockaddr_in listen_addr; 81 | struct sockaddr_in connect_addr; 82 | int size; 83 | int saved_errno = -1; 84 | 85 | if (protocol 86 | #ifdef AF_UNIX 87 | || family != AF_UNIX 88 | #endif 89 | ) { 90 | EVUTIL_SET_SOCKET_ERROR(WSAEAFNOSUPPORT); 91 | return -1; 92 | } 93 | if (!fd) { 94 | EVUTIL_SET_SOCKET_ERROR(WSAEINVAL); 95 | return -1; 96 | } 97 | 98 | listener = socket(AF_INET, type, 0); 99 | if (listener < 0) 100 | return -1; 101 | memset(&listen_addr, 0, sizeof(listen_addr)); 102 | listen_addr.sin_family = AF_INET; 103 | listen_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 104 | listen_addr.sin_port = 0; /* kernel chooses port. */ 105 | if (bind(listener, (struct sockaddr*) &listen_addr, sizeof (listen_addr)) 106 | == -1) 107 | goto tidy_up_and_fail; 108 | if (listen(listener, 1) == -1) 109 | goto tidy_up_and_fail; 110 | 111 | connector = socket(AF_INET, type, 0); 112 | if (connector < 0) 113 | goto tidy_up_and_fail; 114 | /* We want to find out the port number to connect to. */ 115 | size = sizeof(connect_addr); 116 | if (getsockname(listener, (struct sockaddr*) &connect_addr, &size) == -1) 117 | goto tidy_up_and_fail; 118 | if (size != sizeof (connect_addr)) 119 | goto abort_tidy_up_and_fail; 120 | if (connect(connector, (struct sockaddr*) &connect_addr, 121 | sizeof(connect_addr)) == -1) 122 | goto tidy_up_and_fail; 123 | 124 | size = sizeof(listen_addr); 125 | acceptor = accept(listener, (struct sockaddr*) &listen_addr, &size); 126 | if (acceptor < 0) 127 | goto tidy_up_and_fail; 128 | if (size != sizeof(listen_addr)) 129 | goto abort_tidy_up_and_fail; 130 | EVUTIL_CLOSESOCKET(listener); 131 | /* Now check we are talking to ourself by matching port and host on the 132 | two sockets. */ 133 | if (getsockname(connector, (struct sockaddr*) &connect_addr, &size) == -1) 134 | goto tidy_up_and_fail; 135 | if (size != sizeof (connect_addr) 136 | || listen_addr.sin_family != connect_addr.sin_family 137 | || listen_addr.sin_addr.s_addr != connect_addr.sin_addr.s_addr 138 | || listen_addr.sin_port != connect_addr.sin_port) 139 | goto abort_tidy_up_and_fail; 140 | fd[0] = connector; 141 | fd[1] = acceptor; 142 | 143 | return 0; 144 | 145 | abort_tidy_up_and_fail: 146 | saved_errno = WSAECONNABORTED; 147 | tidy_up_and_fail: 148 | if (saved_errno < 0) 149 | saved_errno = WSAGetLastError(); 150 | if (listener != -1) 151 | EVUTIL_CLOSESOCKET(listener); 152 | if (connector != -1) 153 | EVUTIL_CLOSESOCKET(connector); 154 | if (acceptor != -1) 155 | EVUTIL_CLOSESOCKET(acceptor); 156 | 157 | EVUTIL_SET_SOCKET_ERROR(saved_errno); 158 | return -1; 159 | #endif 160 | } 161 | 162 | int 163 | evutil_make_socket_nonblocking(int fd) 164 | { 165 | #ifdef WIN32 166 | { 167 | unsigned long nonblocking = 1; 168 | ioctlsocket(fd, FIONBIO, (unsigned long*) &nonblocking); 169 | } 170 | #else 171 | { 172 | int flags; 173 | if ((flags = fcntl(fd, F_GETFL, NULL)) < 0) { 174 | event_warn("fcntl(%d, F_GETFL)", fd); 175 | return -1; 176 | } 177 | if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) { 178 | event_warn("fcntl(%d, F_SETFL)", fd); 179 | return -1; 180 | } 181 | } 182 | #endif 183 | return 0; 184 | } 185 | 186 | ev_int64_t 187 | evutil_strtoll(const char* s, char** endptr, int base) 188 | { 189 | #ifdef HAVE_STRTOLL 190 | return (ev_int64_t)strtoll(s, endptr, base); 191 | #elif SIZEOF_LONG == 8 192 | return (ev_int64_t)strtol(s, endptr, base); 193 | #elif defined(WIN32) && defined(_MSC_VER) && _MSC_VER < 1300 194 | /* XXXX on old versions of MS APIs, we only support base 195 | * 10. */ 196 | ev_int64_t r; 197 | if (base != 10) 198 | return 0; 199 | r = (ev_int64_t) _atoi64(s); 200 | while (isspace(*s)) 201 | ++s; 202 | while (isdigit(*s)) 203 | ++s; 204 | if (endptr) 205 | *endptr = (char*) s; 206 | return r; 207 | #elif defined(WIN32) 208 | return (ev_int64_t) _strtoi64(s, endptr, base); 209 | #else 210 | #error "I don't know how to parse 64-bit integers." 211 | #endif 212 | } 213 | 214 | #ifndef _EVENT_HAVE_GETTIMEOFDAY 215 | int 216 | evutil_gettimeofday(struct timeval* tv, struct timezone* tz) 217 | { 218 | struct _timeb tb; 219 | 220 | if (tv == NULL) 221 | return -1; 222 | 223 | _ftime(&tb); 224 | tv->tv_sec = (long) tb.time; 225 | tv->tv_usec = ((int) tb.millitm) * 1000; 226 | return 0; 227 | } 228 | #endif 229 | 230 | int 231 | evutil_snprintf(char* buf, size_t buflen, const char* format, ...) 232 | { 233 | int r; 234 | va_list ap; 235 | va_start(ap, format); 236 | r = evutil_vsnprintf(buf, buflen, format, ap); 237 | va_end(ap); 238 | return r; 239 | } 240 | 241 | int 242 | evutil_vsnprintf(char* buf, size_t buflen, const char* format, va_list ap) 243 | { 244 | #ifdef _MSC_VER 245 | int r = _vsnprintf(buf, buflen, format, ap); 246 | buf[buflen - 1] = '\0'; 247 | if (r >= 0) 248 | return r; 249 | else 250 | return _vscprintf(format, ap); 251 | #else 252 | int r = vsnprintf(buf, buflen, format, ap); 253 | buf[buflen - 1] = '\0'; 254 | return r; 255 | #endif 256 | } 257 | 258 | static int 259 | evutil_issetugid(void) 260 | { 261 | #ifdef _EVENT_HAVE_ISSETUGID 262 | return issetugid(); 263 | #else 264 | 265 | #ifdef _EVENT_HAVE_GETEUID 266 | if (getuid() != geteuid()) 267 | return 1; 268 | #endif 269 | #ifdef _EVENT_HAVE_GETEGID 270 | if (getgid() != getegid()) 271 | return 1; 272 | #endif 273 | return 0; 274 | #endif 275 | } 276 | 277 | const char* 278 | evutil_getenv(const char* varname) 279 | { 280 | if (evutil_issetugid()) 281 | return NULL; 282 | 283 | return getenv(varname); 284 | } 285 | -------------------------------------------------------------------------------- /epoll.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2003 Niels Provos 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | #ifdef HAVE_CONFIG_H 28 | #include "config.h" 29 | #endif 30 | 31 | #include 32 | #include 33 | #include 34 | #ifdef HAVE_SYS_TIME_H 35 | #include 36 | #else 37 | #include 38 | #endif 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #ifdef HAVE_FCNTL_H 48 | #include 49 | #endif 50 | 51 | #include "event.h" 52 | #include "event-internal.h" 53 | #include "evsignal.h" 54 | #include "log.h" 55 | 56 | /* due to limitations in the epoll interface, we need to keep track of 57 | * all file descriptors outself. 58 | */ 59 | struct evepoll { 60 | struct event* evread; 61 | struct event* evwrite; 62 | }; 63 | 64 | struct epollop { 65 | // 对应的event管理,通过fds[sock_fd]得到与socket关联的evepoll 66 | struct evepoll* fds; 67 | // fds的数量 68 | int nfds; 69 | 70 | // epoll相关 71 | struct epoll_event* events; 72 | int nevents; 73 | int epfd /*epoll_create(32000)*/; 74 | }; 75 | 76 | static void* epoll_init (struct event_base*); 77 | static int epoll_add (void*, struct event*); 78 | static int epoll_del (void*, struct event*); 79 | static int epoll_dispatch (struct event_base*, void*, struct timeval*); 80 | static void epoll_dealloc (struct event_base*, void*); 81 | 82 | const struct eventop epollops = { 83 | "epoll", 84 | epoll_init, 85 | epoll_add, 86 | epoll_del, 87 | epoll_dispatch, 88 | epoll_dealloc, 89 | 1 /* need reinit */ 90 | }; 91 | 92 | #ifdef HAVE_SETFD 93 | #define FD_CLOSEONEXEC(x) do { \ 94 | if (fcntl(x, F_SETFD, 1) == -1) \ 95 | event_warn("fcntl(%d, F_SETFD)", x); \ 96 | } while (0) 97 | #else 98 | #define FD_CLOSEONEXEC(x) 99 | #endif 100 | 101 | /* On Linux kernels at least up to 2.6.24.4, epoll can't handle timeout 102 | * values bigger than (LONG_MAX - 999ULL)/HZ. HZ in the wild can be 103 | * as big as 1000, and LONG_MAX can be as small as (1<<31)-1, so the 104 | * largest number of msec we can support here is 2147482. Let's 105 | * round that down by 47 seconds. 106 | */ 107 | #define MAX_EPOLL_TIMEOUT_MSEC (35*60*1000) 108 | 109 | #define INITIAL_NFILES 32 110 | #define INITIAL_NEVENTS 32 111 | #define MAX_NEVENTS 4096 112 | 113 | static void* 114 | epoll_init(struct event_base* base) 115 | { 116 | int epfd; 117 | struct epollop* epollop; 118 | 119 | /* Disable epollueue when this environment variable is set */ 120 | if (evutil_getenv("EVENT_NOEPOLL")) 121 | return (NULL); 122 | 123 | /* Initalize the kernel queue */ 124 | if ((epfd = epoll_create(32000)) == -1) { 125 | if (errno != ENOSYS) 126 | event_warn("epoll_create"); 127 | return (NULL); 128 | } 129 | 130 | FD_CLOSEONEXEC(epfd); 131 | 132 | if (!(epollop = calloc(1, sizeof(struct epollop)))) 133 | return (NULL); 134 | 135 | epollop->epfd = epfd; 136 | 137 | /* Initalize fields */ 138 | epollop->events = malloc(INITIAL_NEVENTS * sizeof(struct epoll_event)); 139 | if (epollop->events == NULL) { 140 | free(epollop); 141 | return (NULL); 142 | } 143 | epollop->nevents = INITIAL_NEVENTS; 144 | 145 | epollop->fds = calloc(INITIAL_NFILES, sizeof(struct evepoll)); 146 | if (epollop->fds == NULL) { 147 | free(epollop->events); 148 | free(epollop); 149 | return (NULL); 150 | } 151 | epollop->nfds = INITIAL_NFILES; 152 | 153 | evsignal_init(base); 154 | 155 | return (epollop); 156 | } 157 | 158 | 159 | // 重新分配max大小存储event的数组 160 | static int 161 | epoll_recalc(struct event_base* base, void* arg, int max) 162 | { 163 | struct epollop* epollop = arg; 164 | 165 | if (max >= epollop->nfds) { 166 | struct evepoll* fds; 167 | int nfds; 168 | 169 | nfds = epollop->nfds; 170 | while (nfds <= max) 171 | nfds <<= 1; 172 | 173 | fds = realloc(epollop->fds, nfds * sizeof(struct evepoll)); 174 | if (fds == NULL) { 175 | event_warn("realloc"); 176 | return (-1); 177 | } 178 | epollop->fds = fds; 179 | // 清空后面数组 180 | memset(fds + epollop->nfds, 0, 181 | (nfds - epollop->nfds) * sizeof(struct evepoll)); 182 | epollop->nfds = nfds; 183 | } 184 | 185 | return (0); 186 | } 187 | 188 | static int 189 | epoll_dispatch(struct event_base* base, void* arg, struct timeval* tv) 190 | { 191 | struct epollop* epollop = arg; 192 | struct epoll_event* events = epollop->events; 193 | struct evepoll* evep; 194 | int i, res, timeout = -1; 195 | // 得到毫秒msecond 196 | if (tv != NULL) 197 | timeout = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000; 198 | 199 | if (timeout > MAX_EPOLL_TIMEOUT_MSEC) { 200 | /* Linux kernels can wait forever if the timeout is too big; 201 | * see comment on MAX_EPOLL_TIMEOUT_MSEC. */ 202 | timeout = MAX_EPOLL_TIMEOUT_MSEC; 203 | } 204 | 205 | res = epoll_wait(epollop->epfd, events, epollop->nevents, timeout); 206 | 207 | if (res == -1) { 208 | if (errno != EINTR) { 209 | event_warn("epoll_wait"); 210 | return (-1); 211 | } 212 | // 产生中断,处理信号 213 | evsignal_process(base); 214 | return (0); 215 | } else if (base->sig.evsignal_caught) { 216 | // 捕捉到信号 217 | evsignal_process(base); 218 | } 219 | 220 | event_debug(("%s: epoll_wait reports %d", __func__, res)); 221 | // 处理socket读写 222 | for (i = 0; i < res; i++) { 223 | int what = events[i].events; 224 | struct event* evread = NULL, *evwrite = NULL; 225 | int fd = events[i].data.fd; 226 | 227 | if (fd < 0 || fd >= epollop->nfds) 228 | continue; 229 | evep = &epollop->fds[fd]; 230 | 231 | if (what & (EPOLLHUP | EPOLLERR)) { 232 | evread = evep->evread; 233 | evwrite = evep->evwrite; 234 | } else { 235 | if (what & EPOLLIN) { 236 | evread = evep->evread; 237 | } 238 | 239 | if (what & EPOLLOUT) { 240 | evwrite = evep->evwrite; 241 | } 242 | } 243 | 244 | if (!(evread || evwrite)) 245 | continue; 246 | 247 | if (evread != NULL) 248 | event_active(evread, EV_READ, 1); 249 | if (evwrite != NULL) 250 | event_active(evwrite, EV_WRITE, 1); 251 | } 252 | 253 | if (res == epollop->nevents && epollop->nevents < MAX_NEVENTS) { 254 | /* We used all of the event space this time. We should 255 | be ready for more events next time. */ 256 | int new_nevents = epollop->nevents * 2; 257 | struct epoll_event* new_events; 258 | 259 | new_events = realloc(epollop->events, 260 | new_nevents * sizeof(struct epoll_event)); 261 | if (new_events) { 262 | epollop->events = new_events; 263 | epollop->nevents = new_nevents; 264 | } 265 | } 266 | 267 | return (0); 268 | } 269 | 270 | 271 | static int 272 | epoll_add(void* arg, struct event* ev) 273 | { 274 | struct epollop* epollop = arg; 275 | struct epoll_event epev = {0, {0}}; 276 | struct evepoll* evep; 277 | int fd, op, events; 278 | // 信号处理 279 | if (ev->ev_events & EV_SIGNAL) 280 | return (evsignal_add(ev)); 281 | 282 | fd = ev->ev_fd; 283 | if (fd >= epollop->nfds) { 284 | /* Extent the file descriptor array as necessary */ 285 | if (epoll_recalc(ev->ev_base, epollop, fd) == -1) 286 | return (-1); 287 | } 288 | evep = &epollop->fds[fd]; 289 | op = EPOLL_CTL_ADD; 290 | events = 0; 291 | if (evep->evread != NULL) { 292 | events |= EPOLLIN; 293 | op = EPOLL_CTL_MOD; 294 | } 295 | if (evep->evwrite != NULL) { 296 | events |= EPOLLOUT; 297 | op = EPOLL_CTL_MOD; 298 | } 299 | 300 | if (ev->ev_events & EV_READ) 301 | events |= EPOLLIN; 302 | if (ev->ev_events & EV_WRITE) 303 | events |= EPOLLOUT; 304 | 305 | epev.data.fd = fd; 306 | epev.events = events; 307 | // 假如epoll 308 | if (epoll_ctl(epollop->epfd, op, ev->ev_fd, &epev) == -1) 309 | return (-1); 310 | 311 | /* Update events responsible */ 312 | if (ev->ev_events & EV_READ) 313 | evep->evread = ev; 314 | if (ev->ev_events & EV_WRITE) 315 | evep->evwrite = ev; 316 | 317 | return (0); 318 | } 319 | 320 | static int 321 | epoll_del(void* arg, struct event* ev) 322 | { 323 | struct epollop* epollop = arg; 324 | struct epoll_event epev = {0, {0}}; 325 | struct evepoll* evep; 326 | int fd, events, op; 327 | int needwritedelete = 1, needreaddelete = 1; 328 | 329 | if (ev->ev_events & EV_SIGNAL) 330 | return (evsignal_del(ev)); 331 | 332 | fd = ev->ev_fd; 333 | if (fd >= epollop->nfds) 334 | return (0); 335 | evep = &epollop->fds[fd]; 336 | 337 | op = EPOLL_CTL_DEL; 338 | events = 0; 339 | 340 | if (ev->ev_events & EV_READ) 341 | events |= EPOLLIN; 342 | if (ev->ev_events & EV_WRITE) 343 | events |= EPOLLOUT; 344 | // 读写中的一个或者一个都没有 345 | if ((events & (EPOLLIN | EPOLLOUT)) != (EPOLLIN | EPOLLOUT)) { 346 | // 下面没看懂~ 347 | if ((events & EPOLLIN) && evep->evwrite != NULL) {// 读 348 | needwritedelete = 0; 349 | events = EPOLLOUT; 350 | op = EPOLL_CTL_MOD; 351 | } else if ((events & EPOLLOUT) && evep->evread != NULL) {//写 352 | needreaddelete = 0; 353 | events = EPOLLIN; 354 | op = EPOLL_CTL_MOD; 355 | } 356 | } 357 | 358 | epev.events = events; 359 | epev.data.fd = fd; 360 | 361 | if (needreaddelete) 362 | evep->evread = NULL; 363 | if (needwritedelete) 364 | evep->evwrite = NULL; 365 | 366 | if (epoll_ctl(epollop->epfd, op, fd, &epev) == -1) 367 | return (-1); 368 | 369 | return (0); 370 | } 371 | 372 | static void 373 | epoll_dealloc(struct event_base* base, void* arg) 374 | { 375 | struct epollop* epollop = arg; 376 | 377 | evsignal_dealloc(base); 378 | if (epollop->fds) 379 | free(epollop->fds); 380 | if (epollop->events) 381 | free(epollop->events); 382 | if (epollop->epfd >= 0) 383 | close(epollop->epfd); 384 | 385 | memset(epollop, 0, sizeof(struct epollop)); 386 | free(epollop); 387 | } 388 | -------------------------------------------------------------------------------- /poll.c: -------------------------------------------------------------------------------- 1 | /* $OpenBSD: poll.c,v 1.2 2002/06/25 15:50:15 mickey Exp $ */ 2 | 3 | /* 4 | * Copyright 2000-2003 Niels Provos 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 3. The name of the author may not be used to endorse or promote products 16 | * derived from this software without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | #ifdef HAVE_CONFIG_H 30 | #include "config.h" 31 | #endif 32 | 33 | #include 34 | #ifdef HAVE_SYS_TIME_H 35 | #include 36 | #else 37 | #include 38 | #endif 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #ifdef CHECK_INVARIANTS 48 | #include 49 | #endif 50 | 51 | #include "event.h" 52 | #include "event-internal.h" 53 | #include "evsignal.h" 54 | #include "log.h" 55 | 56 | struct pollop { 57 | int event_count; /* Highest number alloc */ 58 | int nfds; /* Size of event_* */ 59 | int fd_count; /* Size of idxplus1_by_fd */ 60 | struct pollfd* event_set; 61 | struct event** event_r_back; 62 | struct event** event_w_back; 63 | int* idxplus1_by_fd; /* Index into event_set by fd; we add 1 so 64 | * that 0 (which is easy to memset) can mean 65 | * "no entry." */ 66 | }; 67 | 68 | static void* poll_init (struct event_base*); 69 | static int poll_add (void*, struct event*); 70 | static int poll_del (void*, struct event*); 71 | static int poll_dispatch (struct event_base*, void*, struct timeval*); 72 | static void poll_dealloc (struct event_base*, void*); 73 | 74 | const struct eventop pollops = { 75 | "poll", 76 | poll_init, 77 | poll_add, 78 | poll_del, 79 | poll_dispatch, 80 | poll_dealloc, 81 | 0 82 | }; 83 | 84 | static void* 85 | poll_init(struct event_base* base) 86 | { 87 | struct pollop* pollop; 88 | 89 | /* Disable poll when this environment variable is set */ 90 | if (evutil_getenv("EVENT_NOPOLL")) 91 | return (NULL); 92 | 93 | if (!(pollop = calloc(1, sizeof(struct pollop)))) 94 | return (NULL); 95 | 96 | evsignal_init(base); 97 | 98 | return (pollop); 99 | } 100 | 101 | #ifdef CHECK_INVARIANTS 102 | static void 103 | poll_check_ok(struct pollop* pop) 104 | { 105 | int i, idx; 106 | struct event* ev; 107 | 108 | for (i = 0; i < pop->fd_count; ++i) { 109 | idx = pop->idxplus1_by_fd[i] - 1; 110 | if (idx < 0) 111 | continue; 112 | assert(pop->event_set[idx].fd == i); 113 | if (pop->event_set[idx].events & POLLIN) { 114 | ev = pop->event_r_back[idx]; 115 | assert(ev); 116 | assert(ev->ev_events & EV_READ); 117 | assert(ev->ev_fd == i); 118 | } 119 | if (pop->event_set[idx].events & POLLOUT) { 120 | ev = pop->event_w_back[idx]; 121 | assert(ev); 122 | assert(ev->ev_events & EV_WRITE); 123 | assert(ev->ev_fd == i); 124 | } 125 | } 126 | for (i = 0; i < pop->nfds; ++i) { 127 | struct pollfd* pfd = &pop->event_set[i]; 128 | assert(pop->idxplus1_by_fd[pfd->fd] == i + 1); 129 | } 130 | } 131 | #else 132 | #define poll_check_ok(pop) 133 | #endif 134 | 135 | static int 136 | poll_dispatch(struct event_base* base, void* arg, struct timeval* tv) 137 | { 138 | int res, i, j, msec = -1, nfds; 139 | struct pollop* pop = arg; 140 | 141 | poll_check_ok(pop); 142 | 143 | if (tv != NULL) 144 | msec = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000; 145 | 146 | nfds = pop->nfds; 147 | res = poll(pop->event_set, nfds, msec); 148 | 149 | if (res == -1) { 150 | if (errno != EINTR) { 151 | event_warn("poll"); 152 | return (-1); 153 | } 154 | 155 | evsignal_process(base); 156 | return (0); 157 | } else if (base->sig.evsignal_caught) { 158 | evsignal_process(base); 159 | } 160 | 161 | event_debug(("%s: poll reports %d", __func__, res)); 162 | 163 | if (res == 0 || nfds == 0) 164 | return (0); 165 | 166 | i = random() % nfds; 167 | for (j = 0; j < nfds; j++) { 168 | struct event* r_ev = NULL, *w_ev = NULL; 169 | int what; 170 | if (++i == nfds) 171 | i = 0; 172 | what = pop->event_set[i].revents; 173 | 174 | if (!what) 175 | continue; 176 | 177 | res = 0; 178 | 179 | /* If the file gets closed notify */ 180 | if (what & (POLLHUP | POLLERR)) 181 | what |= POLLIN | POLLOUT; 182 | if (what & POLLIN) { 183 | res |= EV_READ; 184 | r_ev = pop->event_r_back[i]; 185 | } 186 | if (what & POLLOUT) { 187 | res |= EV_WRITE; 188 | w_ev = pop->event_w_back[i]; 189 | } 190 | if (res == 0) 191 | continue; 192 | 193 | if (r_ev && (res & r_ev->ev_events)) { 194 | event_active(r_ev, res & r_ev->ev_events, 1); 195 | } 196 | if (w_ev && w_ev != r_ev && (res & w_ev->ev_events)) { 197 | event_active(w_ev, res & w_ev->ev_events, 1); 198 | } 199 | } 200 | 201 | return (0); 202 | } 203 | 204 | static int 205 | poll_add(void* arg, struct event* ev) 206 | { 207 | struct pollop* pop = arg; 208 | struct pollfd* pfd = NULL; 209 | int i; 210 | 211 | if (ev->ev_events & EV_SIGNAL) 212 | return (evsignal_add(ev)); 213 | if (!(ev->ev_events & (EV_READ | EV_WRITE))) 214 | return (0); 215 | 216 | poll_check_ok(pop); 217 | if (pop->nfds + 1 >= pop->event_count) { 218 | struct pollfd* tmp_event_set; 219 | struct event** tmp_event_r_back; 220 | struct event** tmp_event_w_back; 221 | int tmp_event_count; 222 | 223 | if (pop->event_count < 32) 224 | tmp_event_count = 32; 225 | else 226 | tmp_event_count = pop->event_count * 2; 227 | 228 | /* We need more file descriptors */ 229 | tmp_event_set = realloc(pop->event_set, 230 | tmp_event_count * sizeof(struct pollfd)); 231 | if (tmp_event_set == NULL) { 232 | event_warn("realloc"); 233 | return (-1); 234 | } 235 | pop->event_set = tmp_event_set; 236 | 237 | tmp_event_r_back = realloc(pop->event_r_back, 238 | tmp_event_count * sizeof(struct event*)); 239 | if (tmp_event_r_back == NULL) { 240 | /* event_set overallocated; that's okay. */ 241 | event_warn("realloc"); 242 | return (-1); 243 | } 244 | pop->event_r_back = tmp_event_r_back; 245 | 246 | tmp_event_w_back = realloc(pop->event_w_back, 247 | tmp_event_count * sizeof(struct event*)); 248 | if (tmp_event_w_back == NULL) { 249 | /* event_set and event_r_back overallocated; that's 250 | * okay. */ 251 | event_warn("realloc"); 252 | return (-1); 253 | } 254 | pop->event_w_back = tmp_event_w_back; 255 | 256 | pop->event_count = tmp_event_count; 257 | } 258 | if (ev->ev_fd >= pop->fd_count) { 259 | int* tmp_idxplus1_by_fd; 260 | int new_count; 261 | if (pop->fd_count < 32) 262 | new_count = 32; 263 | else 264 | new_count = pop->fd_count * 2; 265 | while (new_count <= ev->ev_fd) 266 | new_count *= 2; 267 | tmp_idxplus1_by_fd = 268 | realloc(pop->idxplus1_by_fd, new_count * sizeof(int)); 269 | if (tmp_idxplus1_by_fd == NULL) { 270 | event_warn("realloc"); 271 | return (-1); 272 | } 273 | pop->idxplus1_by_fd = tmp_idxplus1_by_fd; 274 | memset(pop->idxplus1_by_fd + pop->fd_count, 275 | 0, sizeof(int) * (new_count - pop->fd_count)); 276 | pop->fd_count = new_count; 277 | } 278 | 279 | i = pop->idxplus1_by_fd[ev->ev_fd] - 1; 280 | if (i >= 0) { 281 | pfd = &pop->event_set[i]; 282 | } else { 283 | i = pop->nfds++; 284 | pfd = &pop->event_set[i]; 285 | pfd->events = 0; 286 | pfd->fd = ev->ev_fd; 287 | pop->event_w_back[i] = pop->event_r_back[i] = NULL; 288 | pop->idxplus1_by_fd[ev->ev_fd] = i + 1; 289 | } 290 | 291 | pfd->revents = 0; 292 | if (ev->ev_events & EV_WRITE) { 293 | pfd->events |= POLLOUT; 294 | pop->event_w_back[i] = ev; 295 | } 296 | if (ev->ev_events & EV_READ) { 297 | pfd->events |= POLLIN; 298 | pop->event_r_back[i] = ev; 299 | } 300 | poll_check_ok(pop); 301 | 302 | return (0); 303 | } 304 | 305 | /* 306 | * Nothing to be done here. 307 | */ 308 | 309 | static int 310 | poll_del(void* arg, struct event* ev) 311 | { 312 | struct pollop* pop = arg; 313 | struct pollfd* pfd = NULL; 314 | int i; 315 | 316 | if (ev->ev_events & EV_SIGNAL) 317 | return (evsignal_del(ev)); 318 | 319 | if (!(ev->ev_events & (EV_READ | EV_WRITE))) 320 | return (0); 321 | 322 | poll_check_ok(pop); 323 | i = pop->idxplus1_by_fd[ev->ev_fd] - 1; 324 | if (i < 0) 325 | return (-1); 326 | 327 | /* Do we still want to read or write? */ 328 | pfd = &pop->event_set[i]; 329 | if (ev->ev_events & EV_READ) { 330 | pfd->events &= ~POLLIN; 331 | pop->event_r_back[i] = NULL; 332 | } 333 | if (ev->ev_events & EV_WRITE) { 334 | pfd->events &= ~POLLOUT; 335 | pop->event_w_back[i] = NULL; 336 | } 337 | poll_check_ok(pop); 338 | if (pfd->events) 339 | /* Another event cares about that fd. */ 340 | return (0); 341 | 342 | /* Okay, so we aren't interested in that fd anymore. */ 343 | pop->idxplus1_by_fd[ev->ev_fd] = 0; 344 | 345 | --pop->nfds; 346 | if (i != pop->nfds) { 347 | /* 348 | * Shift the last pollfd down into the now-unoccupied 349 | * position. 350 | */ 351 | memcpy(&pop->event_set[i], &pop->event_set[pop->nfds], 352 | sizeof(struct pollfd)); 353 | pop->event_r_back[i] = pop->event_r_back[pop->nfds]; 354 | pop->event_w_back[i] = pop->event_w_back[pop->nfds]; 355 | pop->idxplus1_by_fd[pop->event_set[i].fd] = i + 1; 356 | } 357 | 358 | poll_check_ok(pop); 359 | return (0); 360 | } 361 | 362 | static void 363 | poll_dealloc(struct event_base* base, void* arg) 364 | { 365 | struct pollop* pop = arg; 366 | 367 | evsignal_dealloc(base); 368 | if (pop->event_set) 369 | free(pop->event_set); 370 | if (pop->event_r_back) 371 | free(pop->event_r_back); 372 | if (pop->event_w_back) 373 | free(pop->event_w_back); 374 | if (pop->idxplus1_by_fd) 375 | free(pop->idxplus1_by_fd); 376 | 377 | memset(pop, 0, sizeof(struct pollop)); 378 | free(pop); 379 | } 380 | -------------------------------------------------------------------------------- /select.c: -------------------------------------------------------------------------------- 1 | /* $OpenBSD: select.c,v 1.2 2002/06/25 15:50:15 mickey Exp $ */ 2 | 3 | /* 4 | * Copyright 2000-2002 Niels Provos 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 3. The name of the author may not be used to endorse or promote products 16 | * derived from this software without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | #ifdef HAVE_CONFIG_H 30 | #include "config.h" 31 | #endif 32 | 33 | #include 34 | #ifdef HAVE_SYS_TIME_H 35 | #include 36 | #else 37 | #include 38 | #endif 39 | #ifdef HAVE_SYS_SELECT_H 40 | #include 41 | #endif 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #ifdef CHECK_INVARIANTS 50 | #include 51 | #endif 52 | 53 | #include "event.h" 54 | #include "evutil.h" 55 | #include "event-internal.h" 56 | #include "evsignal.h" 57 | #include "log.h" 58 | 59 | #ifndef howmany 60 | #define howmany(x, y) (((x)+((y)-1))/(y)) 61 | #endif 62 | 63 | #ifndef _EVENT_HAVE_FD_MASK 64 | /* This type is mandatory, but Android doesn't define it. */ 65 | #undef NFDBITS 66 | //32个bit位 67 | #define NFDBITS (sizeof(long)*8) 68 | typedef unsigned long fd_mask; 69 | #endif 70 | 71 | struct selectop { 72 | //select函数中最大的socket值 73 | int event_fds; /* Highest fd in fd set */ 74 | 75 | // 集合中的字节数,1个字节表示8位能存储8个socket,下面四个结合大小都一样 76 | int event_fdsz; 77 | // select输出集合 78 | fd_set* event_readset_in; 79 | fd_set* event_writeset_in; 80 | // select结果结合 81 | fd_set* event_readset_out; 82 | fd_set* event_writeset_out; 83 | //文件描述符作为索引,获取与该文件描述相关的event 84 | struct event** event_r_by_fd; 85 | struct event** event_w_by_fd; 86 | }; 87 | 88 | static void* select_init (struct event_base*); 89 | static int select_add (void*, struct event*); 90 | static int select_del (void*, struct event*); 91 | static int select_dispatch (struct event_base*, void*, struct timeval*); 92 | static void select_dealloc (struct event_base*, void*); 93 | 94 | const struct eventop selectops = { 95 | "select", 96 | select_init, 97 | select_add, 98 | select_del, 99 | select_dispatch, 100 | select_dealloc, 101 | 0 102 | }; 103 | 104 | static int select_resize(struct selectop* sop, int fdsz); 105 | 106 | static void* 107 | select_init(struct event_base* base) 108 | { 109 | struct selectop* sop; 110 | 111 | /* Disable select when this environment variable is set */ 112 | if (evutil_getenv("EVENT_NOSELECT")) 113 | return (NULL); 114 | 115 | if (!(sop = calloc(1, sizeof(struct selectop)))) 116 | return (NULL); 117 | 118 | select_resize(sop, howmany(32 + 1, NFDBITS)*sizeof(fd_mask)); 119 | 120 | evsignal_init(base); 121 | 122 | return (sop); 123 | } 124 | 125 | #ifdef CHECK_INVARIANTS 126 | static void 127 | check_selectop(struct selectop* sop) 128 | { 129 | int i; 130 | for (i = 0; i <= sop->event_fds; ++i) { 131 | if (FD_ISSET(i, sop->event_readset_in)) { 132 | assert(sop->event_r_by_fd[i]); 133 | assert(sop->event_r_by_fd[i]->ev_events & EV_READ); 134 | assert(sop->event_r_by_fd[i]->ev_fd == i); 135 | } else { 136 | assert(! sop->event_r_by_fd[i]); 137 | } 138 | if (FD_ISSET(i, sop->event_writeset_in)) { 139 | assert(sop->event_w_by_fd[i]); 140 | assert(sop->event_w_by_fd[i]->ev_events & EV_WRITE); 141 | assert(sop->event_w_by_fd[i]->ev_fd == i); 142 | } else { 143 | assert(! sop->event_w_by_fd[i]); 144 | } 145 | } 146 | 147 | } 148 | #else 149 | #define check_selectop(sop) do { (void) sop; } while (0) 150 | #endif 151 | 152 | static int 153 | select_dispatch(struct event_base* base, void* arg, struct timeval* tv) 154 | { 155 | int res, i, j; 156 | struct selectop* sop = arg; 157 | 158 | check_selectop(sop); 159 | 160 | memcpy(sop->event_readset_out, sop->event_readset_in, 161 | sop->event_fdsz); 162 | memcpy(sop->event_writeset_out, sop->event_writeset_in, 163 | sop->event_fdsz); 164 | 165 | res = select(sop->event_fds + 1, sop->event_readset_out, 166 | sop->event_writeset_out, NULL, tv); 167 | 168 | check_selectop(sop); 169 | 170 | if (res == -1) { 171 | if (errno != EINTR) { 172 | event_warn("select"); 173 | return (-1); 174 | } 175 | 176 | evsignal_process(base); 177 | return (0); 178 | } else if (base->sig.evsignal_caught) { 179 | evsignal_process(base); 180 | } 181 | 182 | event_debug(("%s: select reports %d", __func__, res)); 183 | 184 | check_selectop(sop); 185 | i = random() % (sop->event_fds + 1); 186 | for (j = 0; j <= sop->event_fds; ++j) { 187 | struct event* r_ev = NULL, *w_ev = NULL; 188 | if (++i >= sop->event_fds + 1) 189 | i = 0; 190 | 191 | res = 0; 192 | if (FD_ISSET(i, sop->event_readset_out)) { 193 | r_ev = sop->event_r_by_fd[i]; 194 | res |= EV_READ; 195 | } 196 | if (FD_ISSET(i, sop->event_writeset_out)) { 197 | w_ev = sop->event_w_by_fd[i]; 198 | res |= EV_WRITE; 199 | } 200 | if (r_ev && (res & r_ev->ev_events)) { 201 | event_active(r_ev, res & r_ev->ev_events, 1); 202 | } 203 | if (w_ev && w_ev != r_ev && (res & w_ev->ev_events)) { 204 | event_active(w_ev, res & w_ev->ev_events, 1); 205 | } 206 | } 207 | check_selectop(sop); 208 | 209 | return (0); 210 | } 211 | 212 | 213 | // 将集合调整到fdsz大小 214 | static int 215 | select_resize(struct selectop* sop, int fdsz) 216 | { 217 | int n_events, n_events_old; 218 | 219 | fd_set* readset_in = NULL; 220 | fd_set* writeset_in = NULL; 221 | fd_set* readset_out = NULL; 222 | fd_set* writeset_out = NULL; 223 | struct event** r_by_fd = NULL; 224 | struct event** w_by_fd = NULL; 225 | // select中使用bit来表示socket是否加入到集合中,如果bits[socket] == 1说明socket 226 | // 在select集合当中,libevent没有使用默认的fd_set_t结构体,而是自己实现一个 227 | 228 | // 4字节即sizeof(fd_mask)可以存储NFDBITS个event 229 | n_events = (fdsz / sizeof(fd_mask)) * NFDBITS; 230 | n_events_old = (sop->event_fdsz / sizeof(fd_mask)) * NFDBITS; 231 | 232 | if (sop->event_readset_in) 233 | check_selectop(sop); 234 | 235 | if ((readset_in = realloc(sop->event_readset_in, fdsz)) == NULL) 236 | goto error; 237 | sop->event_readset_in = readset_in; 238 | if ((readset_out = realloc(sop->event_readset_out, fdsz)) == NULL) 239 | goto error; 240 | sop->event_readset_out = readset_out; 241 | if ((writeset_in = realloc(sop->event_writeset_in, fdsz)) == NULL) 242 | goto error; 243 | sop->event_writeset_in = writeset_in; 244 | if ((writeset_out = realloc(sop->event_writeset_out, fdsz)) == NULL) 245 | goto error; 246 | sop->event_writeset_out = writeset_out; 247 | if ((r_by_fd = realloc(sop->event_r_by_fd, 248 | n_events * sizeof(struct event*))) == NULL) 249 | goto error; 250 | sop->event_r_by_fd = r_by_fd; 251 | if ((w_by_fd = realloc(sop->event_w_by_fd, 252 | n_events * sizeof(struct event*))) == NULL) 253 | goto error; 254 | sop->event_w_by_fd = w_by_fd; 255 | 256 | memset((char*)sop->event_readset_in + sop->event_fdsz, 0, 257 | fdsz - sop->event_fdsz); 258 | memset((char*)sop->event_writeset_in + sop->event_fdsz, 0, 259 | fdsz - sop->event_fdsz); 260 | memset(sop->event_r_by_fd + n_events_old, 0, 261 | (n_events - n_events_old) * sizeof(struct event*)); 262 | memset(sop->event_w_by_fd + n_events_old, 0, 263 | (n_events - n_events_old) * sizeof(struct event*)); 264 | 265 | sop->event_fdsz = fdsz; 266 | check_selectop(sop); 267 | 268 | return (0); 269 | 270 | error: 271 | event_warn("malloc"); 272 | return (-1); 273 | } 274 | 275 | //arg 是select_init返回的void* 276 | //ev read、write或者singal,也可以使他们中的任意组合比如ev同时监测某个socket的读/写 277 | static int 278 | select_add(void* arg, struct event* ev) 279 | { 280 | struct selectop* sop = arg; 281 | 282 | if (ev->ev_events & EV_SIGNAL) //信号事件集成在每一个OS的IO模型模块中 283 | return (evsignal_add(ev)); //直接调用singnal.c模块 284 | 285 | check_selectop(sop); 286 | /* 287 | * Keep track of the highest fd, so that we can calculate the size 288 | * of the fd_sets for select(2) 289 | * selectop->event_fds是传给API select的所有文件符fds中的最大值 290 | */ 291 | if (sop->event_fds < ev->ev_fd) { 292 | int fdsz = sop->event_fdsz; 293 | //一个fd_mask有32位,内保存32个文件描述符 294 | if (fdsz < sizeof(fd_mask)) 295 | fdsz = sizeof(fd_mask); 296 | 297 | //howmany(x,y)将x向上取整y的倍数 298 | while (fdsz < 299 | (howmany(ev->ev_fd + 1, NFDBITS) * sizeof(fd_mask)))//加一个ev_fd进来会不会放不下 300 | fdsz *= 2; 301 | 302 | if (fdsz != sop->event_fdsz) { 303 | if (select_resize(sop, fdsz)) {//将selectop中的各个set的缓冲区扩充 304 | check_selectop(sop); 305 | return (-1); 306 | } 307 | } 308 | 309 | //添加进来的fds文件描述符大于当前保存的文件描述符 310 | //更新sop->event_fds 311 | sop->event_fds = ev->ev_fd; 312 | } 313 | 314 | //将不同ev的文件描述符添加到select的不同set中 315 | //读event添加到readset,写event添加到writeset 316 | //将文件描述符作为索引,保存到selectop->event_*_by_fd[ev->ev_fd]=ev中 317 | if (ev->ev_events & EV_READ) { 318 | FD_SET(ev->ev_fd, sop->event_readset_in); 319 | sop->event_r_by_fd[ev->ev_fd] = ev; 320 | } 321 | if (ev->ev_events & EV_WRITE) { 322 | FD_SET(ev->ev_fd, sop->event_writeset_in); 323 | sop->event_w_by_fd[ev->ev_fd] = ev; 324 | } 325 | check_selectop(sop); 326 | 327 | return (0); 328 | } 329 | 330 | /* 331 | * Nothing to be done here. 332 | */ 333 | 334 | static int 335 | select_del(void* arg, struct event* ev) 336 | { 337 | struct selectop* sop = arg; 338 | 339 | check_selectop(sop); 340 | if (ev->ev_events & EV_SIGNAL) 341 | return (evsignal_del(ev)); 342 | 343 | if (sop->event_fds < ev->ev_fd) { 344 | check_selectop(sop); 345 | return (0); 346 | } 347 | 348 | if (ev->ev_events & EV_READ) { 349 | FD_CLR(ev->ev_fd, sop->event_readset_in); 350 | sop->event_r_by_fd[ev->ev_fd] = NULL; 351 | } 352 | 353 | if (ev->ev_events & EV_WRITE) { 354 | FD_CLR(ev->ev_fd, sop->event_writeset_in); 355 | sop->event_w_by_fd[ev->ev_fd] = NULL; 356 | } 357 | 358 | check_selectop(sop); 359 | return (0); 360 | } 361 | 362 | static void 363 | select_dealloc(struct event_base* base, void* arg) 364 | { 365 | struct selectop* sop = arg; 366 | 367 | evsignal_dealloc(base); 368 | if (sop->event_readset_in) 369 | free(sop->event_readset_in); 370 | if (sop->event_writeset_in) 371 | free(sop->event_writeset_in); 372 | if (sop->event_readset_out) 373 | free(sop->event_readset_out); 374 | if (sop->event_writeset_out) 375 | free(sop->event_writeset_out); 376 | if (sop->event_r_by_fd) 377 | free(sop->event_r_by_fd); 378 | if (sop->event_w_by_fd) 379 | free(sop->event_w_by_fd); 380 | 381 | memset(sop, 0, sizeof(struct selectop)); 382 | free(sop); 383 | } 384 | -------------------------------------------------------------------------------- /event_tagging.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003, 2004 Niels Provos 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifdef HAVE_CONFIG_H 29 | #include "config.h" 30 | #endif 31 | 32 | #ifdef HAVE_SYS_TYPES_H 33 | #include 34 | #endif 35 | #ifdef HAVE_SYS_PARAM_H 36 | #include 37 | #endif 38 | 39 | #ifdef WIN32 40 | #define WIN32_LEAN_AND_MEAN 41 | #include 42 | #include 43 | #undef WIN32_LEAN_AND_MEAN 44 | #else 45 | #include 46 | #endif 47 | 48 | #include 49 | #ifdef HAVE_SYS_TIME_H 50 | #include 51 | #endif 52 | 53 | #include 54 | #include 55 | #include 56 | #include 57 | #ifndef WIN32 58 | #include 59 | #endif 60 | #ifdef HAVE_UNISTD_H 61 | #include 62 | #endif 63 | 64 | #include "event.h" 65 | #include "evutil.h" 66 | #include "log.h" 67 | 68 | int evtag_decode_int(ev_uint32_t* pnumber, struct evbuffer* evbuf); 69 | int evtag_encode_tag(struct evbuffer* evbuf, ev_uint32_t tag); 70 | int evtag_decode_tag(ev_uint32_t* ptag, struct evbuffer* evbuf); 71 | 72 | static struct evbuffer* _buf; /* not thread safe */ 73 | 74 | void 75 | evtag_init(void) 76 | { 77 | if (_buf != NULL) 78 | return; 79 | 80 | if ((_buf = evbuffer_new()) == NULL) 81 | event_err(1, "%s: malloc", __func__); 82 | } 83 | 84 | /* 85 | * We encode integer's by nibbles; the first nibble contains the number 86 | * of significant nibbles - 1; this allows us to encode up to 64-bit 87 | * integers. This function is byte-order independent. 88 | */ 89 | 90 | void 91 | encode_int(struct evbuffer* evbuf, ev_uint32_t number) 92 | { 93 | int off = 1, nibbles = 0; 94 | ev_uint8_t data[5]; 95 | 96 | memset(data, 0, sizeof(ev_uint32_t) + 1); 97 | while (number) { 98 | if (off & 0x1) 99 | data[off / 2] = (data[off / 2] & 0xf0) | (number & 0x0f); 100 | else 101 | data[off / 2] = (data[off / 2] & 0x0f) | 102 | ((number & 0x0f) << 4); 103 | number >>= 4; 104 | off++; 105 | } 106 | 107 | if (off > 2) 108 | nibbles = off - 2; 109 | 110 | /* Off - 1 is the number of encoded nibbles */ 111 | data[0] = (data[0] & 0x0f) | ((nibbles & 0x0f) << 4); 112 | 113 | evbuffer_add(evbuf, data, (off + 1) / 2); 114 | } 115 | 116 | /* 117 | * Support variable length encoding of tags; we use the high bit in each 118 | * octet as a continuation signal. 119 | */ 120 | 121 | int 122 | evtag_encode_tag(struct evbuffer* evbuf, ev_uint32_t tag) 123 | { 124 | int bytes = 0; 125 | ev_uint8_t data[5]; 126 | 127 | memset(data, 0, sizeof(data)); 128 | do { 129 | ev_uint8_t lower = tag & 0x7f; 130 | tag >>= 7; 131 | 132 | if (tag) 133 | lower |= 0x80; 134 | 135 | data[bytes++] = lower; 136 | } while (tag); 137 | 138 | if (evbuf != NULL) 139 | evbuffer_add(evbuf, data, bytes); 140 | 141 | return (bytes); 142 | } 143 | 144 | static int 145 | decode_tag_internal(ev_uint32_t* ptag, struct evbuffer* evbuf, int dodrain) 146 | { 147 | ev_uint32_t number = 0; 148 | ev_uint8_t* data = EVBUFFER_DATA(evbuf); 149 | int len = EVBUFFER_LENGTH(evbuf); 150 | int count = 0, shift = 0, done = 0; 151 | 152 | while (count++ < len) { 153 | ev_uint8_t lower = *data++; 154 | number |= (lower & 0x7f) << shift; 155 | shift += 7; 156 | 157 | if (!(lower & 0x80)) { 158 | done = 1; 159 | break; 160 | } 161 | } 162 | 163 | if (!done) 164 | return (-1); 165 | 166 | if (dodrain) 167 | evbuffer_drain(evbuf, count); 168 | 169 | if (ptag != NULL) 170 | *ptag = number; 171 | 172 | return (count); 173 | } 174 | 175 | int 176 | evtag_decode_tag(ev_uint32_t* ptag, struct evbuffer* evbuf) 177 | { 178 | return (decode_tag_internal(ptag, evbuf, 1 /* dodrain */)); 179 | } 180 | 181 | /* 182 | * Marshal a data type, the general format is as follows: 183 | * 184 | * tag number: one byte; length: var bytes; payload: var bytes 185 | */ 186 | 187 | void 188 | evtag_marshal(struct evbuffer* evbuf, ev_uint32_t tag, 189 | const void* data, ev_uint32_t len) 190 | { 191 | evtag_encode_tag(evbuf, tag); 192 | encode_int(evbuf, len); 193 | evbuffer_add(evbuf, (void*)data, len); 194 | } 195 | 196 | /* Marshaling for integers */ 197 | void 198 | evtag_marshal_int(struct evbuffer* evbuf, ev_uint32_t tag, ev_uint32_t integer) 199 | { 200 | evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf)); 201 | encode_int(_buf, integer); 202 | 203 | evtag_encode_tag(evbuf, tag); 204 | encode_int(evbuf, EVBUFFER_LENGTH(_buf)); 205 | evbuffer_add_buffer(evbuf, _buf); 206 | } 207 | 208 | void 209 | evtag_marshal_string(struct evbuffer* buf, ev_uint32_t tag, const char* string) 210 | { 211 | evtag_marshal(buf, tag, string, strlen(string)); 212 | } 213 | 214 | void 215 | evtag_marshal_timeval(struct evbuffer* evbuf, ev_uint32_t tag, struct timeval* tv) 216 | { 217 | evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf)); 218 | 219 | encode_int(_buf, tv->tv_sec); 220 | encode_int(_buf, tv->tv_usec); 221 | 222 | evtag_marshal(evbuf, tag, EVBUFFER_DATA(_buf), 223 | EVBUFFER_LENGTH(_buf)); 224 | } 225 | 226 | static int 227 | decode_int_internal(ev_uint32_t* pnumber, struct evbuffer* evbuf, int dodrain) 228 | { 229 | ev_uint32_t number = 0; 230 | ev_uint8_t* data = EVBUFFER_DATA(evbuf); 231 | int len = EVBUFFER_LENGTH(evbuf); 232 | int nibbles = 0; 233 | 234 | if (!len) 235 | return (-1); 236 | 237 | nibbles = ((data[0] & 0xf0) >> 4) + 1; 238 | if (nibbles > 8 || (nibbles >> 1) + 1 > len) 239 | return (-1); 240 | len = (nibbles >> 1) + 1; 241 | 242 | while (nibbles > 0) { 243 | number <<= 4; 244 | if (nibbles & 0x1) 245 | number |= data[nibbles >> 1] & 0x0f; 246 | else 247 | number |= (data[nibbles >> 1] & 0xf0) >> 4; 248 | nibbles--; 249 | } 250 | 251 | if (dodrain) 252 | evbuffer_drain(evbuf, len); 253 | 254 | *pnumber = number; 255 | 256 | return (len); 257 | } 258 | 259 | int 260 | evtag_decode_int(ev_uint32_t* pnumber, struct evbuffer* evbuf) 261 | { 262 | return (decode_int_internal(pnumber, evbuf, 1) == -1 ? -1 : 0); 263 | } 264 | 265 | int 266 | evtag_peek(struct evbuffer* evbuf, ev_uint32_t* ptag) 267 | { 268 | return (decode_tag_internal(ptag, evbuf, 0 /* dodrain */)); 269 | } 270 | 271 | int 272 | evtag_peek_length(struct evbuffer* evbuf, ev_uint32_t* plength) 273 | { 274 | struct evbuffer tmp; 275 | int res, len; 276 | 277 | len = decode_tag_internal(NULL, evbuf, 0 /* dodrain */); 278 | if (len == -1) 279 | return (-1); 280 | 281 | tmp = *evbuf; 282 | tmp.buffer += len; 283 | tmp.off -= len; 284 | 285 | res = decode_int_internal(plength, &tmp, 0); 286 | if (res == -1) 287 | return (-1); 288 | 289 | *plength += res + len; 290 | 291 | return (0); 292 | } 293 | 294 | int 295 | evtag_payload_length(struct evbuffer* evbuf, ev_uint32_t* plength) 296 | { 297 | struct evbuffer tmp; 298 | int res, len; 299 | 300 | len = decode_tag_internal(NULL, evbuf, 0 /* dodrain */); 301 | if (len == -1) 302 | return (-1); 303 | 304 | tmp = *evbuf; 305 | tmp.buffer += len; 306 | tmp.off -= len; 307 | 308 | res = decode_int_internal(plength, &tmp, 0); 309 | if (res == -1) 310 | return (-1); 311 | 312 | return (0); 313 | } 314 | 315 | int 316 | evtag_consume(struct evbuffer* evbuf) 317 | { 318 | ev_uint32_t len; 319 | if (decode_tag_internal(NULL, evbuf, 1 /* dodrain */) == -1) 320 | return (-1); 321 | if (evtag_decode_int(&len, evbuf) == -1) 322 | return (-1); 323 | evbuffer_drain(evbuf, len); 324 | 325 | return (0); 326 | } 327 | 328 | /* Reads the data type from an event buffer */ 329 | 330 | int 331 | evtag_unmarshal(struct evbuffer* src, ev_uint32_t* ptag, struct evbuffer* dst) 332 | { 333 | ev_uint32_t len; 334 | ev_uint32_t integer; 335 | 336 | if (decode_tag_internal(ptag, src, 1 /* dodrain */) == -1) 337 | return (-1); 338 | if (evtag_decode_int(&integer, src) == -1) 339 | return (-1); 340 | len = integer; 341 | 342 | if (EVBUFFER_LENGTH(src) < len) 343 | return (-1); 344 | 345 | if (evbuffer_add(dst, EVBUFFER_DATA(src), len) == -1) 346 | return (-1); 347 | 348 | evbuffer_drain(src, len); 349 | 350 | return (len); 351 | } 352 | 353 | /* Marshaling for integers */ 354 | 355 | int 356 | evtag_unmarshal_int(struct evbuffer* evbuf, ev_uint32_t need_tag, 357 | ev_uint32_t* pinteger) 358 | { 359 | ev_uint32_t tag; 360 | ev_uint32_t len; 361 | ev_uint32_t integer; 362 | 363 | if (decode_tag_internal(&tag, evbuf, 1 /* dodrain */) == -1) 364 | return (-1); 365 | if (need_tag != tag) 366 | return (-1); 367 | if (evtag_decode_int(&integer, evbuf) == -1) 368 | return (-1); 369 | len = integer; 370 | 371 | if (EVBUFFER_LENGTH(evbuf) < len) 372 | return (-1); 373 | 374 | evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf)); 375 | if (evbuffer_add(_buf, EVBUFFER_DATA(evbuf), len) == -1) 376 | return (-1); 377 | 378 | evbuffer_drain(evbuf, len); 379 | 380 | return (evtag_decode_int(pinteger, _buf)); 381 | } 382 | 383 | /* Unmarshal a fixed length tag */ 384 | 385 | int 386 | evtag_unmarshal_fixed(struct evbuffer* src, ev_uint32_t need_tag, void* data, 387 | size_t len) 388 | { 389 | ev_uint32_t tag; 390 | 391 | /* Initialize this event buffer so that we can read into it */ 392 | evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf)); 393 | 394 | /* Now unmarshal a tag and check that it matches the tag we want */ 395 | if (evtag_unmarshal(src, &tag, _buf) == -1 || tag != need_tag) 396 | return (-1); 397 | 398 | if (EVBUFFER_LENGTH(_buf) != len) 399 | return (-1); 400 | 401 | memcpy(data, EVBUFFER_DATA(_buf), len); 402 | return (0); 403 | } 404 | 405 | int 406 | evtag_unmarshal_string(struct evbuffer* evbuf, ev_uint32_t need_tag, 407 | char** pstring) 408 | { 409 | ev_uint32_t tag; 410 | 411 | evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf)); 412 | 413 | if (evtag_unmarshal(evbuf, &tag, _buf) == -1 || tag != need_tag) 414 | return (-1); 415 | 416 | *pstring = calloc(EVBUFFER_LENGTH(_buf) + 1, 1); 417 | if (*pstring == NULL) 418 | event_err(1, "%s: calloc", __func__); 419 | evbuffer_remove(_buf, *pstring, EVBUFFER_LENGTH(_buf)); 420 | 421 | return (0); 422 | } 423 | 424 | int 425 | evtag_unmarshal_timeval(struct evbuffer* evbuf, ev_uint32_t need_tag, 426 | struct timeval* ptv) 427 | { 428 | ev_uint32_t tag; 429 | ev_uint32_t integer; 430 | 431 | evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf)); 432 | if (evtag_unmarshal(evbuf, &tag, _buf) == -1 || tag != need_tag) 433 | return (-1); 434 | 435 | if (evtag_decode_int(&integer, _buf) == -1) 436 | return (-1); 437 | ptv->tv_sec = integer; 438 | if (evtag_decode_int(&integer, _buf) == -1) 439 | return (-1); 440 | ptv->tv_usec = integer; 441 | 442 | return (0); 443 | } 444 | -------------------------------------------------------------------------------- /signal.c: -------------------------------------------------------------------------------- 1 | /* $OpenBSD: select.c,v 1.2 2002/06/25 15:50:15 mickey Exp $ */ 2 | 3 | /* 4 | * Copyright 2000-2002 Niels Provos 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 3. The name of the author may not be used to endorse or promote products 16 | * derived from this software without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | #ifdef HAVE_CONFIG_H 30 | #include "config.h" 31 | #endif 32 | 33 | #ifdef WIN32 34 | #define WIN32_LEAN_AND_MEAN 35 | #include 36 | #include 37 | #undef WIN32_LEAN_AND_MEAN 38 | #endif 39 | #include 40 | #ifdef HAVE_SYS_TIME_H 41 | #include 42 | #endif 43 | #include 44 | #ifdef HAVE_SYS_SOCKET_H 45 | #include 46 | #endif 47 | #include 48 | #include 49 | #include 50 | #include 51 | #ifdef HAVE_UNISTD_H 52 | #include 53 | #endif 54 | #include 55 | #ifdef HAVE_FCNTL_H 56 | #include 57 | #endif 58 | #include 59 | 60 | #include "event.h" 61 | #include "event-internal.h" 62 | #include "evsignal.h" 63 | #include "evutil.h" 64 | #include "log.h" 65 | 66 | struct event_base* evsignal_base = NULL; 67 | 68 | static void evsignal_handler(int sig); 69 | 70 | #ifdef WIN32 71 | #define error_is_eagain(err) \ 72 | ((err) == EAGAIN || (err) == WSAEWOULDBLOCK) 73 | #else 74 | #define error_is_eagain(err) ((err) == EAGAIN) 75 | #endif 76 | 77 | 78 | // 仅仅用于唤醒,读取socket里面的缓冲数据然后丢弃 79 | /* Callback for when the signal handler write a byte to our signaling socket */ 80 | static void 81 | evsignal_cb(int fd, short what, void* arg) 82 | { 83 | static char signals[1]; 84 | #ifdef WIN32 85 | SSIZE_T n; 86 | #else 87 | ssize_t n; 88 | #endif 89 | 90 | n = recv(fd, signals, sizeof(signals), 0); 91 | if (n == -1) { 92 | int err = EVUTIL_SOCKET_ERROR(); 93 | if (! error_is_eagain(err)) 94 | event_err(1, "%s: read", __func__); 95 | } 96 | } 97 | 98 | #ifdef HAVE_SETFD 99 | #define FD_CLOSEONEXEC(x) do { \ 100 | if (fcntl(x, F_SETFD, 1) == -1) \ 101 | event_warn("fcntl(%d, F_SETFD)", x); \ 102 | } while (0) 103 | #else 104 | #define FD_CLOSEONEXEC(x) 105 | #endif 106 | 107 | int 108 | evsignal_init(struct event_base* base) 109 | { 110 | int i; 111 | 112 | /* 113 | * Our signal handler is going to write to one end of the socket 114 | * pair to wake up our event loop. The event loop then scans for 115 | * signals that got delivered. 116 | */ 117 | if (evutil_socketpair( 118 | AF_UNIX, SOCK_STREAM, 0, base->sig.ev_signal_pair) == -1) { 119 | #ifdef WIN32 120 | /* Make this nonfatal on win32, where sometimes people 121 | have localhost firewalled. */ 122 | event_warn("%s: socketpair", __func__); 123 | #else 124 | event_err(1, "%s: socketpair", __func__); 125 | #endif 126 | return -1; 127 | } 128 | 129 | FD_CLOSEONEXEC(base->sig.ev_signal_pair[0]); 130 | FD_CLOSEONEXEC(base->sig.ev_signal_pair[1]); 131 | base->sig.sh_old = NULL; 132 | base->sig.sh_old_max = 0; 133 | base->sig.evsignal_caught = 0; 134 | memset(&base->sig.evsigcaught, 0, sizeof(sig_atomic_t)*NSIG); 135 | /* initialize the queues for all events */ 136 | for (i = 0; i < NSIG; ++i) 137 | TAILQ_INIT(&base->sig.evsigevents[i]); 138 | 139 | evutil_make_socket_nonblocking(base->sig.ev_signal_pair[0]); // write端 140 | evutil_make_socket_nonblocking(base->sig.ev_signal_pair[1]); // read端 141 | 142 | event_set(&base->sig.ev_signal, base->sig.ev_signal_pair[1], 143 | EV_READ | EV_PERSIST, evsignal_cb, &base->sig.ev_signal); 144 | base->sig.ev_signal.ev_base = base; 145 | base->sig.ev_signal.ev_flags |= EVLIST_INTERNAL; 146 | 147 | return 0; 148 | } 149 | 150 | /* Helper: set the signal handler for evsignal to handler in base, so that 151 | * we can restore the original handler when we clear the current one. */ 152 | int 153 | _evsignal_set_handler(struct event_base* base, 154 | int evsignal, void (*handler)(int)) 155 | { 156 | #ifdef HAVE_SIGACTION 157 | struct sigaction sa; 158 | #else 159 | ev_sighandler_t sh; 160 | #endif 161 | struct evsignal_info* sig = &base->sig; 162 | void* p; 163 | 164 | /* 165 | * resize saved signal handler array up to the highest signal number. 166 | * a dynamic array is used to keep footprint on the low side. 167 | */ 168 | // 超过当前能存储的容量,重新分配内存 169 | if (evsignal >= sig->sh_old_max) { 170 | int new_max = evsignal + 1; 171 | event_debug(("%s: evsignal (%d) >= sh_old_max (%d), resizing", 172 | __func__, evsignal, sig->sh_old_max)); 173 | p = realloc(sig->sh_old, new_max * sizeof(*sig->sh_old)); 174 | if (p == NULL) { 175 | event_warn("realloc"); 176 | return (-1); 177 | } 178 | // 清空后面内存 179 | memset((char*)p + sig->sh_old_max * sizeof(*sig->sh_old), 180 | 0, (new_max - sig->sh_old_max) * sizeof(*sig->sh_old)); 181 | 182 | sig->sh_old_max = new_max; 183 | sig->sh_old = p; 184 | } 185 | 186 | /* allocate space for previous handler out of dynamic array */ 187 | sig->sh_old[evsignal] = malloc(sizeof * sig->sh_old[evsignal]); 188 | if (sig->sh_old[evsignal] == NULL) { 189 | event_warn("malloc"); 190 | return (-1); 191 | } 192 | 193 | /* save previous handler and setup new handler */ 194 | #ifdef HAVE_SIGACTION 195 | memset(&sa, 0, sizeof(sa)); 196 | sa.sa_handler = handler; 197 | sa.sa_flags |= SA_RESTART; 198 | sigfillset(&sa.sa_mask); 199 | 200 | if (sigaction(evsignal, &sa, sig->sh_old[evsignal]) == -1) { 201 | event_warn("sigaction"); 202 | free(sig->sh_old[evsignal]); 203 | sig->sh_old[evsignal] = NULL; 204 | return (-1); 205 | } 206 | #else 207 | // 处理没有sigaction API的情况,只需要管理一个回调 208 | if ((sh = signal(evsignal, handler)) == SIG_ERR) { 209 | event_warn("signal"); 210 | free(sig->sh_old[evsignal]); 211 | sig->sh_old[evsignal] = NULL; 212 | return (-1); 213 | } 214 | *sig->sh_old[evsignal] = sh; 215 | #endif 216 | 217 | return (0); 218 | } 219 | 220 | int 221 | evsignal_add(struct event* ev) 222 | { 223 | int evsignal; 224 | struct event_base* base = ev->ev_base; 225 | struct evsignal_info* sig = &ev->ev_base->sig; 226 | 227 | if (ev->ev_events & (EV_READ | EV_WRITE)) 228 | event_errx(1, "%s: EV_SIGNAL incompatible use", __func__); 229 | evsignal = EVENT_SIGNAL(ev); // 得到监听的信号值 230 | assert(evsignal >= 0 && evsignal < NSIG); 231 | if (TAILQ_EMPTY(&sig->evsigevents[evsignal])) { 232 | event_debug(("%s: %p: changing signal handler", __func__, ev)); 233 | if (_evsignal_set_handler( // posix函数signal设置信号回调evsignal_handler 234 | base, evsignal, evsignal_handler) == -1) 235 | return (-1); 236 | 237 | /* catch signals if they happen quickly */ 238 | evsignal_base = base; 239 | // 添加到事件循环 240 | if (!sig->ev_signal_added) { 241 | if (event_add(&sig->ev_signal, NULL)) 242 | return (-1); 243 | sig->ev_signal_added = 1; 244 | } 245 | } 246 | 247 | /* multiple events may listen to the same signal */ 248 | TAILQ_INSERT_TAIL(&sig->evsigevents[evsignal], ev, ev_signal_next); 249 | 250 | return (0); 251 | } 252 | 253 | // 设置会sh_old存储的信号处理信息 254 | int 255 | _evsignal_restore_handler(struct event_base* base, int evsignal) 256 | { 257 | int ret = 0; 258 | struct evsignal_info* sig = &base->sig; 259 | #ifdef HAVE_SIGACTION 260 | struct sigaction* sh; 261 | #else 262 | ev_sighandler_t* sh; 263 | #endif 264 | 265 | /* restore previous handler */ 266 | sh = sig->sh_old[evsignal]; 267 | sig->sh_old[evsignal] = NULL; 268 | #ifdef HAVE_SIGACTION 269 | if (sigaction(evsignal, sh, NULL) == -1) { 270 | event_warn("sigaction"); 271 | ret = -1; 272 | } 273 | #else 274 | if (signal(evsignal, *sh) == SIG_ERR) { 275 | event_warn("signal"); 276 | ret = -1; 277 | } 278 | #endif 279 | free(sh); 280 | 281 | return ret; 282 | } 283 | 284 | int 285 | evsignal_del(struct event* ev) 286 | { 287 | struct event_base* base = ev->ev_base; 288 | struct evsignal_info* sig = &base->sig; 289 | int evsignal = EVENT_SIGNAL(ev); 290 | 291 | assert(evsignal >= 0 && evsignal < NSIG); 292 | 293 | /* multiple events may listen to the same signal */ 294 | TAILQ_REMOVE(&sig->evsigevents[evsignal], ev, ev_signal_next); 295 | 296 | if (!TAILQ_EMPTY(&sig->evsigevents[evsignal])) 297 | return (0); 298 | 299 | event_debug(("%s: %p: restoring signal handler", __func__, ev)); 300 | // 还原之前的信号处理 301 | return (_evsignal_restore_handler(ev->ev_base, EVENT_SIGNAL(ev))); 302 | } 303 | 304 | // 所有的信号处理都由该回调函数完成 305 | static void 306 | evsignal_handler(int sig) 307 | { 308 | int save_errno = errno; 309 | 310 | if (evsignal_base == NULL) { 311 | event_warn( 312 | "%s: received signal %d, but have no base configured", 313 | __func__, sig); 314 | return; 315 | } 316 | // 记录捕捉到信号的信息 317 | evsignal_base->sig.evsigcaught[sig]++; 318 | evsignal_base->sig.evsignal_caught = 1; 319 | 320 | #ifndef HAVE_SIGACTION 321 | // 继续捕捉该信号 322 | signal(sig, evsignal_handler); 323 | #endif 324 | 325 | /* Wake up our notification mechanism */ 326 | // 通知唤醒event loop 处理信号回调 327 | send(evsignal_base->sig.ev_signal_pair[0], "a", 1, 0); 328 | errno = save_errno; 329 | } 330 | 331 | void 332 | evsignal_process(struct event_base* base) 333 | { 334 | struct evsignal_info* sig = &base->sig; 335 | struct event* ev, *next_ev; 336 | sig_atomic_t ncalls; 337 | int i; 338 | 339 | base->sig.evsignal_caught = 0; 340 | for (i = 1; i < NSIG; ++i) { 341 | // 捕捉到多少次,就要回调对应的event对调多少次 342 | ncalls = sig->evsigcaught[i]; 343 | if (ncalls == 0) 344 | continue; 345 | sig->evsigcaught[i] -= ncalls; 346 | // 将监听信号对应的所有event放入活动队列中 347 | for (ev = TAILQ_FIRST(&sig->evsigevents[i]); 348 | ev != NULL; ev = next_ev) { 349 | next_ev = TAILQ_NEXT(ev, ev_signal_next); 350 | // 非永久事件需要删除,因此只会通知一次, 351 | if (!(ev->ev_events & EV_PERSIST)) 352 | event_del(ev); 353 | event_active(ev, EV_SIGNAL, ncalls); 354 | } 355 | 356 | } 357 | } 358 | 359 | void 360 | evsignal_dealloc(struct event_base* base) 361 | { 362 | int i = 0; 363 | if (base->sig.ev_signal_added) { 364 | event_del(&base->sig.ev_signal); 365 | base->sig.ev_signal_added = 0; 366 | } 367 | // 还原之前的信号处理回调 368 | for (i = 0; i < NSIG; ++i) { 369 | if (i < base->sig.sh_old_max && base->sig.sh_old[i] != NULL) 370 | _evsignal_restore_handler(base, i); 371 | } 372 | 373 | if (base->sig.ev_signal_pair[0] != -1) { 374 | EVUTIL_CLOSESOCKET(base->sig.ev_signal_pair[0]); 375 | base->sig.ev_signal_pair[0] = -1; 376 | } 377 | if (base->sig.ev_signal_pair[1] != -1) { 378 | EVUTIL_CLOSESOCKET(base->sig.ev_signal_pair[1]); 379 | base->sig.ev_signal_pair[1] = -1; 380 | } 381 | base->sig.sh_old_max = 0; 382 | 383 | /* per index frees are handled in evsig_del() */ 384 | if (base->sig.sh_old) { 385 | free(base->sig.sh_old); 386 | base->sig.sh_old = NULL; 387 | } 388 | } 389 | -------------------------------------------------------------------------------- /devpoll.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2000-2004 Niels Provos 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | #ifdef HAVE_CONFIG_H 28 | #include "config.h" 29 | #endif 30 | 31 | #include 32 | #include 33 | #ifdef HAVE_SYS_TIME_H 34 | #include 35 | #else 36 | #include 37 | #endif 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | 49 | #include "event.h" 50 | #include "event-internal.h" 51 | #include "evsignal.h" 52 | #include "log.h" 53 | 54 | /* due to limitations in the devpoll interface, we need to keep track of 55 | * all file descriptors outself. 56 | */ 57 | struct evdevpoll { 58 | struct event* evread; 59 | struct event* evwrite; 60 | }; 61 | 62 | struct devpollop { 63 | struct evdevpoll* fds; 64 | int nfds; 65 | struct pollfd* events; 66 | int nevents; 67 | int dpfd; 68 | struct pollfd* changes; 69 | int nchanges; 70 | }; 71 | 72 | static void* devpoll_init (struct event_base*); 73 | static int devpoll_add (void*, struct event*); 74 | static int devpoll_del (void*, struct event*); 75 | static int devpoll_dispatch (struct event_base*, void*, struct timeval*); 76 | static void devpoll_dealloc (struct event_base*, void*); 77 | 78 | const struct eventop devpollops = { 79 | "devpoll", 80 | devpoll_init, 81 | devpoll_add, 82 | devpoll_del, 83 | devpoll_dispatch, 84 | devpoll_dealloc, 85 | 1 /* need reinit */ 86 | }; 87 | 88 | #define NEVENT 32000 89 | 90 | static int 91 | devpoll_commit(struct devpollop* devpollop) 92 | { 93 | /* 94 | * Due to a bug in Solaris, we have to use pwrite with an offset of 0. 95 | * Write is limited to 2GB of data, until it will fail. 96 | */ 97 | if (pwrite(devpollop->dpfd, devpollop->changes, 98 | sizeof(struct pollfd) * devpollop->nchanges, 0) == -1) 99 | return (-1); 100 | 101 | devpollop->nchanges = 0; 102 | return (0); 103 | } 104 | 105 | static int 106 | devpoll_queue(struct devpollop* devpollop, int fd, int events) 107 | { 108 | struct pollfd* pfd; 109 | 110 | if (devpollop->nchanges >= devpollop->nevents) { 111 | /* 112 | * Change buffer is full, must commit it to /dev/poll before 113 | * adding more 114 | */ 115 | if (devpoll_commit(devpollop) != 0) 116 | return (-1); 117 | } 118 | 119 | pfd = &devpollop->changes[devpollop->nchanges++]; 120 | pfd->fd = fd; 121 | pfd->events = events; 122 | pfd->revents = 0; 123 | 124 | return (0); 125 | } 126 | 127 | static void* 128 | devpoll_init(struct event_base* base) 129 | { 130 | int dpfd, nfiles = NEVENT; 131 | struct rlimit rl; 132 | struct devpollop* devpollop; 133 | 134 | /* Disable devpoll when this environment variable is set */ 135 | if (evutil_getenv("EVENT_NODEVPOLL")) 136 | return (NULL); 137 | 138 | if (!(devpollop = calloc(1, sizeof(struct devpollop)))) 139 | return (NULL); 140 | 141 | if (getrlimit(RLIMIT_NOFILE, &rl) == 0 && 142 | rl.rlim_cur != RLIM_INFINITY) 143 | nfiles = rl.rlim_cur; 144 | 145 | /* Initialize the kernel queue */ 146 | if ((dpfd = open("/dev/poll", O_RDWR)) == -1) { 147 | event_warn("open: /dev/poll"); 148 | free(devpollop); 149 | return (NULL); 150 | } 151 | 152 | devpollop->dpfd = dpfd; 153 | 154 | /* Initialize fields */ 155 | devpollop->events = calloc(nfiles, sizeof(struct pollfd)); 156 | if (devpollop->events == NULL) { 157 | free(devpollop); 158 | close(dpfd); 159 | return (NULL); 160 | } 161 | devpollop->nevents = nfiles; 162 | 163 | devpollop->fds = calloc(nfiles, sizeof(struct evdevpoll)); 164 | if (devpollop->fds == NULL) { 165 | free(devpollop->events); 166 | free(devpollop); 167 | close(dpfd); 168 | return (NULL); 169 | } 170 | devpollop->nfds = nfiles; 171 | 172 | devpollop->changes = calloc(nfiles, sizeof(struct pollfd)); 173 | if (devpollop->changes == NULL) { 174 | free(devpollop->fds); 175 | free(devpollop->events); 176 | free(devpollop); 177 | close(dpfd); 178 | return (NULL); 179 | } 180 | 181 | evsignal_init(base); 182 | 183 | return (devpollop); 184 | } 185 | 186 | static int 187 | devpoll_recalc(struct event_base* base, void* arg, int max) 188 | { 189 | struct devpollop* devpollop = arg; 190 | 191 | if (max >= devpollop->nfds) { 192 | struct evdevpoll* fds; 193 | int nfds; 194 | 195 | nfds = devpollop->nfds; 196 | while (nfds <= max) 197 | nfds <<= 1; 198 | 199 | fds = realloc(devpollop->fds, nfds * sizeof(struct evdevpoll)); 200 | if (fds == NULL) { 201 | event_warn("realloc"); 202 | return (-1); 203 | } 204 | devpollop->fds = fds; 205 | memset(fds + devpollop->nfds, 0, 206 | (nfds - devpollop->nfds) * sizeof(struct evdevpoll)); 207 | devpollop->nfds = nfds; 208 | } 209 | 210 | return (0); 211 | } 212 | 213 | static int 214 | devpoll_dispatch(struct event_base* base, void* arg, struct timeval* tv) 215 | { 216 | struct devpollop* devpollop = arg; 217 | struct pollfd* events = devpollop->events; 218 | struct dvpoll dvp; 219 | struct evdevpoll* evdp; 220 | int i, res, timeout = -1; 221 | 222 | if (devpollop->nchanges) 223 | devpoll_commit(devpollop); 224 | 225 | if (tv != NULL) 226 | timeout = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000; 227 | 228 | dvp.dp_fds = devpollop->events; 229 | dvp.dp_nfds = devpollop->nevents; 230 | dvp.dp_timeout = timeout; 231 | 232 | res = ioctl(devpollop->dpfd, DP_POLL, &dvp); 233 | 234 | if (res == -1) { 235 | if (errno != EINTR) { 236 | event_warn("ioctl: DP_POLL"); 237 | return (-1); 238 | } 239 | 240 | evsignal_process(base); 241 | return (0); 242 | } else if (base->sig.evsignal_caught) { 243 | evsignal_process(base); 244 | } 245 | 246 | event_debug(("%s: devpoll_wait reports %d", __func__, res)); 247 | 248 | for (i = 0; i < res; i++) { 249 | int which = 0; 250 | int what = events[i].revents; 251 | struct event* evread = NULL, *evwrite = NULL; 252 | 253 | assert(events[i].fd < devpollop->nfds); 254 | evdp = &devpollop->fds[events[i].fd]; 255 | 256 | if (what & POLLHUP) 257 | what |= POLLIN | POLLOUT; 258 | else if (what & POLLERR) 259 | what |= POLLIN | POLLOUT; 260 | 261 | if (what & POLLIN) { 262 | evread = evdp->evread; 263 | which |= EV_READ; 264 | } 265 | 266 | if (what & POLLOUT) { 267 | evwrite = evdp->evwrite; 268 | which |= EV_WRITE; 269 | } 270 | 271 | if (!which) 272 | continue; 273 | 274 | if (evread != NULL && !(evread->ev_events & EV_PERSIST)) 275 | event_del(evread); 276 | if (evwrite != NULL && evwrite != evread && 277 | !(evwrite->ev_events & EV_PERSIST)) 278 | event_del(evwrite); 279 | 280 | if (evread != NULL) 281 | event_active(evread, EV_READ, 1); 282 | if (evwrite != NULL) 283 | event_active(evwrite, EV_WRITE, 1); 284 | } 285 | 286 | return (0); 287 | } 288 | 289 | 290 | static int 291 | devpoll_add(void* arg, struct event* ev) 292 | { 293 | struct devpollop* devpollop = arg; 294 | struct evdevpoll* evdp; 295 | int fd, events; 296 | 297 | if (ev->ev_events & EV_SIGNAL) 298 | return (evsignal_add(ev)); 299 | 300 | fd = ev->ev_fd; 301 | if (fd >= devpollop->nfds) { 302 | /* Extend the file descriptor array as necessary */ 303 | if (devpoll_recalc(ev->ev_base, devpollop, fd) == -1) 304 | return (-1); 305 | } 306 | evdp = &devpollop->fds[fd]; 307 | 308 | /* 309 | * It's not necessary to OR the existing read/write events that we 310 | * are currently interested in with the new event we are adding. 311 | * The /dev/poll driver ORs any new events with the existing events 312 | * that it has cached for the fd. 313 | */ 314 | 315 | events = 0; 316 | if (ev->ev_events & EV_READ) { 317 | if (evdp->evread && evdp->evread != ev) { 318 | /* There is already a different read event registered */ 319 | return (-1); 320 | } 321 | events |= POLLIN; 322 | } 323 | 324 | if (ev->ev_events & EV_WRITE) { 325 | if (evdp->evwrite && evdp->evwrite != ev) { 326 | /* There is already a different write event registered */ 327 | return (-1); 328 | } 329 | events |= POLLOUT; 330 | } 331 | 332 | if (devpoll_queue(devpollop, fd, events) != 0) 333 | return (-1); 334 | 335 | /* Update events responsible */ 336 | if (ev->ev_events & EV_READ) 337 | evdp->evread = ev; 338 | if (ev->ev_events & EV_WRITE) 339 | evdp->evwrite = ev; 340 | 341 | return (0); 342 | } 343 | 344 | static int 345 | devpoll_del(void* arg, struct event* ev) 346 | { 347 | struct devpollop* devpollop = arg; 348 | struct evdevpoll* evdp; 349 | int fd, events; 350 | int needwritedelete = 1, needreaddelete = 1; 351 | 352 | if (ev->ev_events & EV_SIGNAL) 353 | return (evsignal_del(ev)); 354 | 355 | fd = ev->ev_fd; 356 | if (fd >= devpollop->nfds) 357 | return (0); 358 | evdp = &devpollop->fds[fd]; 359 | 360 | events = 0; 361 | if (ev->ev_events & EV_READ) 362 | events |= POLLIN; 363 | if (ev->ev_events & EV_WRITE) 364 | events |= POLLOUT; 365 | 366 | /* 367 | * The only way to remove an fd from the /dev/poll monitored set is 368 | * to use POLLREMOVE by itself. This removes ALL events for the fd 369 | * provided so if we care about two events and are only removing one 370 | * we must re-add the other event after POLLREMOVE. 371 | */ 372 | 373 | if (devpoll_queue(devpollop, fd, POLLREMOVE) != 0) 374 | return (-1); 375 | 376 | if ((events & (POLLIN | POLLOUT)) != (POLLIN | POLLOUT)) { 377 | /* 378 | * We're not deleting all events, so we must resubmit the 379 | * event that we are still interested in if one exists. 380 | */ 381 | 382 | if ((events & POLLIN) && evdp->evwrite != NULL) { 383 | /* Deleting read, still care about write */ 384 | devpoll_queue(devpollop, fd, POLLOUT); 385 | needwritedelete = 0; 386 | } else if ((events & POLLOUT) && evdp->evread != NULL) { 387 | /* Deleting write, still care about read */ 388 | devpoll_queue(devpollop, fd, POLLIN); 389 | needreaddelete = 0; 390 | } 391 | } 392 | 393 | if (needreaddelete) 394 | evdp->evread = NULL; 395 | if (needwritedelete) 396 | evdp->evwrite = NULL; 397 | 398 | return (0); 399 | } 400 | 401 | static void 402 | devpoll_dealloc(struct event_base* base, void* arg) 403 | { 404 | struct devpollop* devpollop = arg; 405 | 406 | evsignal_dealloc(base); 407 | if (devpollop->fds) 408 | free(devpollop->fds); 409 | if (devpollop->events) 410 | free(devpollop->events); 411 | if (devpollop->changes) 412 | free(devpollop->changes); 413 | if (devpollop->dpfd >= 0) 414 | close(devpollop->dpfd); 415 | 416 | memset(devpollop, 0, sizeof(struct devpollop)); 417 | free(devpollop); 418 | } 419 | -------------------------------------------------------------------------------- /m4/ltoptions.m4: -------------------------------------------------------------------------------- 1 | # Helper functions for option handling. -*- Autoconf -*- 2 | # 3 | # Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, 4 | # Inc. 5 | # Written by Gary V. Vaughan, 2004 6 | # 7 | # This file is free software; the Free Software Foundation gives 8 | # unlimited permission to copy and/or distribute it, with or without 9 | # modifications, as long as this notice is preserved. 10 | 11 | # serial 7 ltoptions.m4 12 | 13 | # This is to help aclocal find these macros, as it can't see m4_define. 14 | AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) 15 | 16 | 17 | # _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) 18 | # ------------------------------------------ 19 | m4_define([_LT_MANGLE_OPTION], 20 | [[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) 21 | 22 | 23 | # _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) 24 | # --------------------------------------- 25 | # Set option OPTION-NAME for macro MACRO-NAME, and if there is a 26 | # matching handler defined, dispatch to it. Other OPTION-NAMEs are 27 | # saved as a flag. 28 | m4_define([_LT_SET_OPTION], 29 | [m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl 30 | m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), 31 | _LT_MANGLE_DEFUN([$1], [$2]), 32 | [m4_warning([Unknown $1 option `$2'])])[]dnl 33 | ]) 34 | 35 | 36 | # _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) 37 | # ------------------------------------------------------------ 38 | # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. 39 | m4_define([_LT_IF_OPTION], 40 | [m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) 41 | 42 | 43 | # _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) 44 | # ------------------------------------------------------- 45 | # Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME 46 | # are set. 47 | m4_define([_LT_UNLESS_OPTIONS], 48 | [m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), 49 | [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), 50 | [m4_define([$0_found])])])[]dnl 51 | m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 52 | ])[]dnl 53 | ]) 54 | 55 | 56 | # _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) 57 | # ---------------------------------------- 58 | # OPTION-LIST is a space-separated list of Libtool options associated 59 | # with MACRO-NAME. If any OPTION has a matching handler declared with 60 | # LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about 61 | # the unknown option and exit. 62 | m4_defun([_LT_SET_OPTIONS], 63 | [# Set options 64 | m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), 65 | [_LT_SET_OPTION([$1], _LT_Option)]) 66 | 67 | m4_if([$1],[LT_INIT],[ 68 | dnl 69 | dnl Simply set some default values (i.e off) if boolean options were not 70 | dnl specified: 71 | _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no 72 | ]) 73 | _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no 74 | ]) 75 | dnl 76 | dnl If no reference was made to various pairs of opposing options, then 77 | dnl we run the default mode handler for the pair. For example, if neither 78 | dnl `shared' nor `disable-shared' was passed, we enable building of shared 79 | dnl archives by default: 80 | _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) 81 | _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) 82 | _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) 83 | _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], 84 | [_LT_ENABLE_FAST_INSTALL]) 85 | ]) 86 | ])# _LT_SET_OPTIONS 87 | 88 | 89 | ## --------------------------------- ## 90 | ## Macros to handle LT_INIT options. ## 91 | ## --------------------------------- ## 92 | 93 | # _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) 94 | # ----------------------------------------- 95 | m4_define([_LT_MANGLE_DEFUN], 96 | [[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) 97 | 98 | 99 | # LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) 100 | # ----------------------------------------------- 101 | m4_define([LT_OPTION_DEFINE], 102 | [m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl 103 | ])# LT_OPTION_DEFINE 104 | 105 | 106 | # dlopen 107 | # ------ 108 | LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes 109 | ]) 110 | 111 | AU_DEFUN([AC_LIBTOOL_DLOPEN], 112 | [_LT_SET_OPTION([LT_INIT], [dlopen]) 113 | AC_DIAGNOSE([obsolete], 114 | [$0: Remove this warning and the call to _LT_SET_OPTION when you 115 | put the `dlopen' option into LT_INIT's first parameter.]) 116 | ]) 117 | 118 | dnl aclocal-1.4 backwards compatibility: 119 | dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) 120 | 121 | 122 | # win32-dll 123 | # --------- 124 | # Declare package support for building win32 dll's. 125 | LT_OPTION_DEFINE([LT_INIT], [win32-dll], 126 | [enable_win32_dll=yes 127 | 128 | case $host in 129 | *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) 130 | AC_CHECK_TOOL(AS, as, false) 131 | AC_CHECK_TOOL(DLLTOOL, dlltool, false) 132 | AC_CHECK_TOOL(OBJDUMP, objdump, false) 133 | ;; 134 | esac 135 | 136 | test -z "$AS" && AS=as 137 | _LT_DECL([], [AS], [1], [Assembler program])dnl 138 | 139 | test -z "$DLLTOOL" && DLLTOOL=dlltool 140 | _LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl 141 | 142 | test -z "$OBJDUMP" && OBJDUMP=objdump 143 | _LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl 144 | ])# win32-dll 145 | 146 | AU_DEFUN([AC_LIBTOOL_WIN32_DLL], 147 | [AC_REQUIRE([AC_CANONICAL_HOST])dnl 148 | _LT_SET_OPTION([LT_INIT], [win32-dll]) 149 | AC_DIAGNOSE([obsolete], 150 | [$0: Remove this warning and the call to _LT_SET_OPTION when you 151 | put the `win32-dll' option into LT_INIT's first parameter.]) 152 | ]) 153 | 154 | dnl aclocal-1.4 backwards compatibility: 155 | dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) 156 | 157 | 158 | # _LT_ENABLE_SHARED([DEFAULT]) 159 | # ---------------------------- 160 | # implement the --enable-shared flag, and supports the `shared' and 161 | # `disable-shared' LT_INIT options. 162 | # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. 163 | m4_define([_LT_ENABLE_SHARED], 164 | [m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl 165 | AC_ARG_ENABLE([shared], 166 | [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], 167 | [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], 168 | [p=${PACKAGE-default} 169 | case $enableval in 170 | yes) enable_shared=yes ;; 171 | no) enable_shared=no ;; 172 | *) 173 | enable_shared=no 174 | # Look at the argument we got. We use all the common list separators. 175 | lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," 176 | for pkg in $enableval; do 177 | IFS="$lt_save_ifs" 178 | if test "X$pkg" = "X$p"; then 179 | enable_shared=yes 180 | fi 181 | done 182 | IFS="$lt_save_ifs" 183 | ;; 184 | esac], 185 | [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) 186 | 187 | _LT_DECL([build_libtool_libs], [enable_shared], [0], 188 | [Whether or not to build shared libraries]) 189 | ])# _LT_ENABLE_SHARED 190 | 191 | LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) 192 | LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) 193 | 194 | # Old names: 195 | AC_DEFUN([AC_ENABLE_SHARED], 196 | [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) 197 | ]) 198 | 199 | AC_DEFUN([AC_DISABLE_SHARED], 200 | [_LT_SET_OPTION([LT_INIT], [disable-shared]) 201 | ]) 202 | 203 | AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) 204 | AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) 205 | 206 | dnl aclocal-1.4 backwards compatibility: 207 | dnl AC_DEFUN([AM_ENABLE_SHARED], []) 208 | dnl AC_DEFUN([AM_DISABLE_SHARED], []) 209 | 210 | 211 | 212 | # _LT_ENABLE_STATIC([DEFAULT]) 213 | # ---------------------------- 214 | # implement the --enable-static flag, and support the `static' and 215 | # `disable-static' LT_INIT options. 216 | # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. 217 | m4_define([_LT_ENABLE_STATIC], 218 | [m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl 219 | AC_ARG_ENABLE([static], 220 | [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], 221 | [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], 222 | [p=${PACKAGE-default} 223 | case $enableval in 224 | yes) enable_static=yes ;; 225 | no) enable_static=no ;; 226 | *) 227 | enable_static=no 228 | # Look at the argument we got. We use all the common list separators. 229 | lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," 230 | for pkg in $enableval; do 231 | IFS="$lt_save_ifs" 232 | if test "X$pkg" = "X$p"; then 233 | enable_static=yes 234 | fi 235 | done 236 | IFS="$lt_save_ifs" 237 | ;; 238 | esac], 239 | [enable_static=]_LT_ENABLE_STATIC_DEFAULT) 240 | 241 | _LT_DECL([build_old_libs], [enable_static], [0], 242 | [Whether or not to build static libraries]) 243 | ])# _LT_ENABLE_STATIC 244 | 245 | LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) 246 | LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) 247 | 248 | # Old names: 249 | AC_DEFUN([AC_ENABLE_STATIC], 250 | [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) 251 | ]) 252 | 253 | AC_DEFUN([AC_DISABLE_STATIC], 254 | [_LT_SET_OPTION([LT_INIT], [disable-static]) 255 | ]) 256 | 257 | AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) 258 | AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) 259 | 260 | dnl aclocal-1.4 backwards compatibility: 261 | dnl AC_DEFUN([AM_ENABLE_STATIC], []) 262 | dnl AC_DEFUN([AM_DISABLE_STATIC], []) 263 | 264 | 265 | 266 | # _LT_ENABLE_FAST_INSTALL([DEFAULT]) 267 | # ---------------------------------- 268 | # implement the --enable-fast-install flag, and support the `fast-install' 269 | # and `disable-fast-install' LT_INIT options. 270 | # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. 271 | m4_define([_LT_ENABLE_FAST_INSTALL], 272 | [m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl 273 | AC_ARG_ENABLE([fast-install], 274 | [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], 275 | [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], 276 | [p=${PACKAGE-default} 277 | case $enableval in 278 | yes) enable_fast_install=yes ;; 279 | no) enable_fast_install=no ;; 280 | *) 281 | enable_fast_install=no 282 | # Look at the argument we got. We use all the common list separators. 283 | lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," 284 | for pkg in $enableval; do 285 | IFS="$lt_save_ifs" 286 | if test "X$pkg" = "X$p"; then 287 | enable_fast_install=yes 288 | fi 289 | done 290 | IFS="$lt_save_ifs" 291 | ;; 292 | esac], 293 | [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) 294 | 295 | _LT_DECL([fast_install], [enable_fast_install], [0], 296 | [Whether or not to optimize for fast installation])dnl 297 | ])# _LT_ENABLE_FAST_INSTALL 298 | 299 | LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) 300 | LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) 301 | 302 | # Old names: 303 | AU_DEFUN([AC_ENABLE_FAST_INSTALL], 304 | [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) 305 | AC_DIAGNOSE([obsolete], 306 | [$0: Remove this warning and the call to _LT_SET_OPTION when you put 307 | the `fast-install' option into LT_INIT's first parameter.]) 308 | ]) 309 | 310 | AU_DEFUN([AC_DISABLE_FAST_INSTALL], 311 | [_LT_SET_OPTION([LT_INIT], [disable-fast-install]) 312 | AC_DIAGNOSE([obsolete], 313 | [$0: Remove this warning and the call to _LT_SET_OPTION when you put 314 | the `disable-fast-install' option into LT_INIT's first parameter.]) 315 | ]) 316 | 317 | dnl aclocal-1.4 backwards compatibility: 318 | dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) 319 | dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) 320 | 321 | 322 | # _LT_WITH_PIC([MODE]) 323 | # -------------------- 324 | # implement the --with-pic flag, and support the `pic-only' and `no-pic' 325 | # LT_INIT options. 326 | # MODE is either `yes' or `no'. If omitted, it defaults to `both'. 327 | m4_define([_LT_WITH_PIC], 328 | [AC_ARG_WITH([pic], 329 | [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], 330 | [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], 331 | [lt_p=${PACKAGE-default} 332 | case $withval in 333 | yes|no) pic_mode=$withval ;; 334 | *) 335 | pic_mode=default 336 | # Look at the argument we got. We use all the common list separators. 337 | lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," 338 | for lt_pkg in $withval; do 339 | IFS="$lt_save_ifs" 340 | if test "X$lt_pkg" = "X$lt_p"; then 341 | pic_mode=yes 342 | fi 343 | done 344 | IFS="$lt_save_ifs" 345 | ;; 346 | esac], 347 | [pic_mode=default]) 348 | 349 | test -z "$pic_mode" && pic_mode=m4_default([$1], [default]) 350 | 351 | _LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl 352 | ])# _LT_WITH_PIC 353 | 354 | LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) 355 | LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) 356 | 357 | # Old name: 358 | AU_DEFUN([AC_LIBTOOL_PICMODE], 359 | [_LT_SET_OPTION([LT_INIT], [pic-only]) 360 | AC_DIAGNOSE([obsolete], 361 | [$0: Remove this warning and the call to _LT_SET_OPTION when you 362 | put the `pic-only' option into LT_INIT's first parameter.]) 363 | ]) 364 | 365 | dnl aclocal-1.4 backwards compatibility: 366 | dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) 367 | 368 | ## ----------------- ## 369 | ## LTDL_INIT Options ## 370 | ## ----------------- ## 371 | 372 | m4_define([_LTDL_MODE], []) 373 | LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], 374 | [m4_define([_LTDL_MODE], [nonrecursive])]) 375 | LT_OPTION_DEFINE([LTDL_INIT], [recursive], 376 | [m4_define([_LTDL_MODE], [recursive])]) 377 | LT_OPTION_DEFINE([LTDL_INIT], [subproject], 378 | [m4_define([_LTDL_MODE], [subproject])]) 379 | 380 | m4_define([_LTDL_TYPE], []) 381 | LT_OPTION_DEFINE([LTDL_INIT], [installable], 382 | [m4_define([_LTDL_TYPE], [installable])]) 383 | LT_OPTION_DEFINE([LTDL_INIT], [convenience], 384 | [m4_define([_LTDL_TYPE], [convenience])]) 385 | -------------------------------------------------------------------------------- /evbuffer.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2002-2004 Niels Provos 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #include 29 | 30 | #ifdef HAVE_CONFIG_H 31 | #include "config.h" 32 | #endif 33 | 34 | #ifdef HAVE_SYS_TIME_H 35 | #include 36 | #endif 37 | 38 | #include 39 | #include 40 | #include 41 | #include 42 | #ifdef HAVE_STDARG_H 43 | #include 44 | #endif 45 | 46 | #ifdef WIN32 47 | #include 48 | #endif 49 | 50 | #include "evutil.h" 51 | #include "event.h" 52 | 53 | 54 | // bufferevent 读写缓冲区,当读完成或者写完成的时候,就会通知用户 55 | // 这样就相当于一个异步的接口,虽然本质上是同步,但是极大的方便 56 | // 上层代码的编写与使用,bufferevent需要用户提供readcb/writecb/errorcb 57 | // 三个回调接口用于通知,同时还提供了一种高低水位的概念: 58 | // 1. 读的高低水位表示当缓冲区数据高于高水位就不在读,低于低水位不再通知用户读成功; 59 | // 2. 写的高低水位表示当缓冲区数据低于低水位之后,写成功事件才会通知用户,这样以便用户 60 | // 继续往缓冲区填写数据,高水位没有用,因为只要缓冲区有数据就会被写 61 | 62 | /* prototypes */ 63 | 64 | void bufferevent_read_pressure_cb(struct evbuffer*, size_t, size_t, void*); 65 | 66 | static int 67 | bufferevent_add(struct event* ev, int timeout) 68 | { 69 | struct timeval tv, *ptv = NULL; 70 | 71 | if (timeout) { 72 | evutil_timerclear(&tv); 73 | tv.tv_sec = timeout; 74 | ptv = &tv; 75 | } 76 | 77 | return (event_add(ev, ptv)); 78 | } 79 | 80 | /* 81 | * This callback is executed when the size of the input buffer changes. 82 | * We use it to apply back pressure on the reading side. 83 | * evbuffer 大小改变的时候会被调用 84 | */ 85 | 86 | void 87 | bufferevent_read_pressure_cb(struct evbuffer* buf, size_t old, size_t now, 88 | void* arg) 89 | { 90 | struct bufferevent* bufev = arg; 91 | /* 92 | * If we are below the watermark then reschedule reading if it's 93 | * still enabled. 94 | */ 95 | if (bufev->wm_read.high == 0 || now < bufev->wm_read.high) { 96 | evbuffer_setcb(buf, NULL, NULL); 97 | 98 | if (bufev->enabled & EV_READ) 99 | bufferevent_add(&bufev->ev_read, bufev->timeout_read); 100 | } 101 | } 102 | 103 | static void 104 | bufferevent_readcb(int fd, short event, void* arg) 105 | { 106 | struct bufferevent* bufev = arg; 107 | int res = 0; 108 | short what = EVBUFFER_READ; 109 | size_t len; 110 | int howmuch = -1; 111 | 112 | if (event == EV_TIMEOUT) { 113 | what |= EVBUFFER_TIMEOUT; 114 | goto error; 115 | } 116 | 117 | /* 118 | * If we have a high watermark configured then we don't want to 119 | * read more data than would make us reach the watermark. 120 | */ 121 | if (bufev->wm_read.high != 0) { 122 | howmuch = bufev->wm_read.high - EVBUFFER_LENGTH(bufev->input); 123 | /* we might have lowered the watermark, stop reading */ 124 | // 缓冲区数据太多,高于高水位,停止读,不要在灌水了 125 | if (howmuch <= 0) { 126 | struct evbuffer* buf = bufev->input; 127 | event_del(&bufev->ev_read); 128 | evbuffer_setcb(buf, 129 | bufferevent_read_pressure_cb, bufev); 130 | return; 131 | } 132 | } 133 | // howmuch 为-1或者距离高水位的值 134 | res = evbuffer_read(bufev->input, fd, howmuch); 135 | if (res == -1) { 136 | if (errno == EAGAIN || errno == EINTR) 137 | goto reschedule; 138 | /* error case */ 139 | what |= EVBUFFER_ERROR; 140 | } else if (res == 0) { 141 | /* eof case */ 142 | what |= EVBUFFER_EOF; 143 | } 144 | 145 | if (res <= 0) 146 | goto error; 147 | 148 | bufferevent_add(&bufev->ev_read, bufev->timeout_read); 149 | 150 | /* See if this callbacks meets the water marks */ 151 | len = EVBUFFER_LENGTH(bufev->input); 152 | // 小于低水位,不做处理,只用高于低水位才会通知用户读成功 153 | if (bufev->wm_read.low != 0 && len < bufev->wm_read.low) 154 | return; 155 | // 大于高水位者不在从socket中读取,直到水位降下 156 | if (bufev->wm_read.high != 0 && len >= bufev->wm_read.high) { 157 | struct evbuffer* buf = bufev->input; 158 | event_del(&bufev->ev_read); 159 | 160 | /* Now schedule a callback for us when the buffer changes */ 161 | evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev); 162 | } 163 | 164 | /* Invoke the user callback - must always be called last */ 165 | if (bufev->readcb != NULL) 166 | (*bufev->readcb)(bufev, bufev->cbarg); 167 | return; 168 | 169 | reschedule: 170 | bufferevent_add(&bufev->ev_read, bufev->timeout_read); 171 | return; 172 | 173 | error: 174 | (*bufev->errorcb)(bufev, what, bufev->cbarg); 175 | } 176 | 177 | static void 178 | bufferevent_writecb(int fd, short event, void* arg) 179 | { 180 | struct bufferevent* bufev = arg; 181 | int res = 0; 182 | short what = EVBUFFER_WRITE; 183 | 184 | if (event == EV_TIMEOUT) { 185 | what |= EVBUFFER_TIMEOUT; 186 | goto error; 187 | } 188 | // 有数据就写 189 | if (EVBUFFER_LENGTH(bufev->output)) { 190 | res = evbuffer_write(bufev->output, fd); 191 | if (res == -1) { 192 | #ifndef WIN32 193 | /*todo. evbuffer uses WriteFile when WIN32 is set. WIN32 system calls do not 194 | *set errno. thus this error checking is not portable*/ 195 | if (errno == EAGAIN || 196 | errno == EINTR || 197 | errno == EINPROGRESS) 198 | goto reschedule; 199 | /* error case */ 200 | what |= EVBUFFER_ERROR; 201 | 202 | #else 203 | goto reschedule; 204 | #endif 205 | 206 | } else if (res == 0) { 207 | /* eof case */ 208 | what |= EVBUFFER_EOF; 209 | } 210 | if (res <= 0) 211 | goto error; 212 | } 213 | 214 | // 还有数据需要写 215 | if (EVBUFFER_LENGTH(bufev->output) != 0) 216 | bufferevent_add(&bufev->ev_write, bufev->timeout_write); 217 | 218 | /* 219 | * Invoke the user callback if our buffer is drained or below the 220 | * low watermark. 221 | */ 222 | // 输出缓冲区已经降到底水位,通知用户充水 223 | if (bufev->writecb != NULL && 224 | EVBUFFER_LENGTH(bufev->output) <= bufev->wm_write.low) 225 | (*bufev->writecb)(bufev, bufev->cbarg); 226 | 227 | return; 228 | 229 | reschedule: 230 | if (EVBUFFER_LENGTH(bufev->output) != 0) 231 | bufferevent_add(&bufev->ev_write, bufev->timeout_write); 232 | return; 233 | 234 | error: 235 | (*bufev->errorcb)(bufev, what, bufev->cbarg); 236 | } 237 | 238 | /* 239 | * Create a new buffered event object. 240 | * 241 | * The read callback is invoked whenever we read new data. 242 | * The write callback is invoked whenever the output buffer is drained. 243 | * The error callback is invoked on a write/read error or on EOF. 244 | * 245 | * Both read and write callbacks maybe NULL. The error callback is not 246 | * allowed to be NULL and have to be provided always. 247 | */ 248 | 249 | struct bufferevent* 250 | bufferevent_new(int fd, evbuffercb readcb, evbuffercb writecb, 251 | everrorcb errorcb, void* cbarg) 252 | { 253 | struct bufferevent* bufev; 254 | 255 | if ((bufev = calloc(1, sizeof(struct bufferevent))) == NULL) 256 | return (NULL); 257 | 258 | if ((bufev->input = evbuffer_new()) == NULL) { 259 | free(bufev); 260 | return (NULL); 261 | } 262 | 263 | if ((bufev->output = evbuffer_new()) == NULL) { 264 | evbuffer_free(bufev->input); 265 | free(bufev); 266 | return (NULL); 267 | } 268 | 269 | event_set(&bufev->ev_read, fd, EV_READ, bufferevent_readcb, bufev); 270 | event_set(&bufev->ev_write, fd, EV_WRITE, bufferevent_writecb, bufev); 271 | 272 | bufferevent_setcb(bufev, readcb, writecb, errorcb, cbarg); 273 | 274 | /* 275 | * Set to EV_WRITE so that using bufferevent_write is going to 276 | * trigger a callback. Reading needs to be explicitly enabled 277 | * because otherwise no data will be available. 278 | */ 279 | bufev->enabled = EV_WRITE; 280 | 281 | return (bufev); 282 | } 283 | 284 | void 285 | bufferevent_setcb(struct bufferevent* bufev, 286 | evbuffercb readcb, evbuffercb writecb, everrorcb errorcb, void* cbarg) 287 | { 288 | bufev->readcb = readcb; 289 | bufev->writecb = writecb; 290 | bufev->errorcb = errorcb; 291 | 292 | bufev->cbarg = cbarg; 293 | } 294 | 295 | void 296 | bufferevent_setfd(struct bufferevent* bufev, int fd) 297 | { 298 | event_del(&bufev->ev_read); 299 | event_del(&bufev->ev_write); 300 | 301 | event_set(&bufev->ev_read, fd, EV_READ, bufferevent_readcb, bufev); 302 | event_set(&bufev->ev_write, fd, EV_WRITE, bufferevent_writecb, bufev); 303 | if (bufev->ev_base != NULL) { 304 | event_base_set(bufev->ev_base, &bufev->ev_read); 305 | event_base_set(bufev->ev_base, &bufev->ev_write); 306 | } 307 | 308 | /* might have to manually trigger event registration */ 309 | } 310 | 311 | int 312 | bufferevent_priority_set(struct bufferevent* bufev, int priority) 313 | { 314 | if (event_priority_set(&bufev->ev_read, priority) == -1) 315 | return (-1); 316 | if (event_priority_set(&bufev->ev_write, priority) == -1) 317 | return (-1); 318 | 319 | return (0); 320 | } 321 | 322 | /* Closing the file descriptor is the responsibility of the caller */ 323 | 324 | void 325 | bufferevent_free(struct bufferevent* bufev) 326 | { 327 | event_del(&bufev->ev_read); 328 | event_del(&bufev->ev_write); 329 | 330 | evbuffer_free(bufev->input); 331 | evbuffer_free(bufev->output); 332 | 333 | free(bufev); 334 | } 335 | 336 | /* 337 | * Returns 0 on success; 338 | * -1 on failure. 339 | */ 340 | 341 | int 342 | bufferevent_write(struct bufferevent* bufev, const void* data, size_t size) 343 | { 344 | int res; 345 | 346 | res = evbuffer_add(bufev->output, data, size); 347 | 348 | if (res == -1) 349 | return (res); 350 | 351 | /* If everything is okay, we need to schedule a write */ 352 | if (size > 0 && (bufev->enabled & EV_WRITE)) 353 | bufferevent_add(&bufev->ev_write, bufev->timeout_write); 354 | 355 | return (res); 356 | } 357 | 358 | int 359 | bufferevent_write_buffer(struct bufferevent* bufev, struct evbuffer* buf) 360 | { 361 | int res; 362 | 363 | res = bufferevent_write(bufev, buf->buffer, buf->off); 364 | if (res != -1) 365 | evbuffer_drain(buf, buf->off); 366 | 367 | return (res); 368 | } 369 | 370 | size_t 371 | bufferevent_read(struct bufferevent* bufev, void* data, size_t size) 372 | { 373 | struct evbuffer* buf = bufev->input; 374 | 375 | if (buf->off < size) 376 | size = buf->off; 377 | 378 | /* Copy the available data to the user buffer */ 379 | memcpy(data, buf->buffer, size); 380 | 381 | if (size) 382 | evbuffer_drain(buf, size); 383 | 384 | return (size); 385 | } 386 | 387 | int 388 | bufferevent_enable(struct bufferevent* bufev, short event) 389 | { 390 | if (event & EV_READ) { 391 | if (bufferevent_add(&bufev->ev_read, bufev->timeout_read) == -1) 392 | return (-1); 393 | } 394 | if (event & EV_WRITE) { 395 | if (bufferevent_add(&bufev->ev_write, bufev->timeout_write) == -1) 396 | return (-1); 397 | } 398 | 399 | bufev->enabled |= event; 400 | return (0); 401 | } 402 | 403 | int 404 | bufferevent_disable(struct bufferevent* bufev, short event) 405 | { 406 | if (event & EV_READ) { 407 | if (event_del(&bufev->ev_read) == -1) 408 | return (-1); 409 | } 410 | if (event & EV_WRITE) { 411 | if (event_del(&bufev->ev_write) == -1) 412 | return (-1); 413 | } 414 | 415 | bufev->enabled &= ~event; 416 | return (0); 417 | } 418 | 419 | /* 420 | * Sets the read and write timeout for a buffered event. 421 | */ 422 | 423 | void 424 | bufferevent_settimeout(struct bufferevent* bufev, 425 | int timeout_read, int timeout_write) 426 | { 427 | bufev->timeout_read = timeout_read; 428 | bufev->timeout_write = timeout_write; 429 | 430 | if (event_pending(&bufev->ev_read, EV_READ, NULL)) 431 | bufferevent_add(&bufev->ev_read, timeout_read); 432 | if (event_pending(&bufev->ev_write, EV_WRITE, NULL)) 433 | bufferevent_add(&bufev->ev_write, timeout_write); 434 | } 435 | 436 | /* 437 | * Sets the water marks 438 | */ 439 | 440 | void 441 | bufferevent_setwatermark(struct bufferevent* bufev, short events, 442 | size_t lowmark, size_t highmark) 443 | { 444 | if (events & EV_READ) { 445 | bufev->wm_read.low = lowmark; 446 | bufev->wm_read.high = highmark; 447 | } 448 | 449 | if (events & EV_WRITE) { 450 | bufev->wm_write.low = lowmark; 451 | bufev->wm_write.high = highmark; 452 | } 453 | 454 | /* If the watermarks changed then see if we should call read again */ 455 | bufferevent_read_pressure_cb(bufev->input, 456 | 0, EVBUFFER_LENGTH(bufev->input), bufev); 457 | } 458 | 459 | int 460 | bufferevent_base_set(struct event_base* base, struct bufferevent* bufev) 461 | { 462 | int res; 463 | 464 | bufev->ev_base = base; 465 | 466 | res = event_base_set(base, &bufev->ev_read); 467 | if (res == -1) 468 | return (res); 469 | 470 | res = event_base_set(base, &bufev->ev_write); 471 | return (res); 472 | } 473 | --------------------------------------------------------------------------------