]> arthur.barton.de Git - netatalk.git/commitdiff
Update libevent to 2.0.12
authorFrank Lahm <franklahm@googlemail.com>
Wed, 20 Jul 2011 08:17:20 +0000 (10:17 +0200)
committerFrank Lahm <franklahm@googlemail.com>
Wed, 20 Jul 2011 08:17:20 +0000 (10:17 +0200)
54 files changed:
libevent/ChangeLog
libevent/Makefile.am
libevent/README
libevent/WIN32-Code/event2/event-config.h
libevent/arc4random.c
libevent/bufferevent-internal.h
libevent/bufferevent.c
libevent/bufferevent_async.c
libevent/bufferevent_filter.c
libevent/bufferevent_openssl.c
libevent/bufferevent_sock.c
libevent/configure.in
libevent/evdns.c
libevent/event-internal.h
libevent/event.c
libevent/event_iocp.c
libevent/evmap.c
libevent/evport.c
libevent/evrpc.c
libevent/evthread.c
libevent/evthread_win32.c
libevent/evutil.c
libevent/http.c
libevent/include/Makefile.am
libevent/include/event2/event.h
libevent/include/event2/http.h
libevent/ipv6-internal.h
libevent/kqueue.c
libevent/libevent_openssl.pc.in
libevent/listener.c
libevent/sample/Makefile.am
libevent/sample/dns-example.c
libevent/sample/hello-world.c
libevent/sample/http-server.c
libevent/select.c
libevent/test/Makefile.am
libevent/test/bench.c
libevent/test/bench_cascade.c
libevent/test/bench_httpclient.c
libevent/test/regress.c
libevent/test/regress_buffer.c
libevent/test/regress_bufferevent.c
libevent/test/regress_dns.c
libevent/test/regress_http.c
libevent/test/regress_listener.c
libevent/test/regress_ssl.c
libevent/test/regress_testutils.c
libevent/test/regress_zlib.c
libevent/test/test-eof.c
libevent/test/test-ratelim.c
libevent/test/test.sh
libevent/test/tinytest_local.h
libevent/util-internal.h
libevent/whatsnew-2.0.txt

index 18e4a6b0f09ad99dfbb296676a97d33af4af8f1a..d8dc3b1cd4f084807f860147eaaed964cd3114c6 100644 (file)
@@ -1,3 +1,123 @@
+Changes in version 2.0.12-stable (4 Jun 2011)
+BUGFIXES
+ o Fix a warn-and-fail bug in kqueue by providing kevent() room to report errors (28317a0)
+ o Fix an assert-inducing fencepost bug in the select backend (d90149d)
+ o Fix failing http assertion introducd in commit 0d6622e (0848814 Kevin Ko)
+ o Fix a bug that prevented us from configuring IPv6 nameservers. (74760f1)
+ o Prevent size_t overflow in evhttp_htmlescape. (06c51cd Mansour Moufid)
+ o Added several checks for under/overflow conditions in evhttp_handle_chunked_read (a279272 Mark Ellzey)
+ o Added overflow checks in evhttp_read_body and evhttp_get_body (84560fc Mark Ellzey)
+
+DOCUMENTATION:
+ o Add missing words to EVLOOP_NONBLOCK documentation (9556a7d)
+
+BUILD FIXES
+ o libssl depends on libcrypto, not the other way around. (274dd03 Peter Rosin)
+ o Libtool brings in the dependencies of libevent_openssl.la automatically (7b819f2 Peter Rosin)
+ o Use OPENSSL_LIBS in Makefile.am (292092e Sebastian Hahn)
+ o Move the win32 detection in configure.in (ceb03b9 Sebastian Hahn)
+ o Correctly detect openssl on windows (6619385 Sebastian Hahn)
+ o Fix a compile warning with zlib 1.2.4 and 1.2.5 (5786b91 Sebastian Hahn)
+ o Fix compilation with GCC 2, which had no __builtin_expect (09d39a1 Dave Hart)
+ o Fix new warnings from GCC 4.6 (06a714f)
+ o Link with -lshell32 and -ladvapi32 on Win32. (86090ee Peter Rosin)
+ o Make the tests build when OpenSSL is not available. (07c41be Peter Rosin)
+ o Bring in the compile script from automake, if needed. (f3c7a4c Peter Rosin)
+ o MSVC does not provide S_ISDIR, so provide it manually. (70be7d1 Peter Rosin)
+ o unistd.h and sys/time.h might not exist. (fe93022 Peter Rosin)
+ o Make sure TINYTEST_LOCAL is defined when building tinytest.c (8fa030c Peter Rosin)
+ o Fix winsock2.h #include issues with MSVC (3d768dc Peter Rosin)
+ o Use evutil_gettimeofday instead of relying on the system gettimeofday. (0de87fe Peter Rosin)
+ o Always use evutil_snprintf, even if OS provides it (d1b2d11 Sebastian Hahn)
+ o InitializeCriticalSectionAndSpinCount requires _WIN32_WINNT >= 0x0403. (816115a Peter Rosin)
+ o cygwin: make it possible to build DLLs (d54d3fc)
+
+
+
+Changes in version 2.0.11-stable (27 Apr 2011)
+  [Autogenerated from the Git log, sorted and cleaned by hand.]
+BUGFIXES:
+ o Fix evport handling of POLLHUP and POLLERR (b42ce4b)
+ o Fix compilation on Windows with NDEBUG (cb8059d)
+ o Check for POLLERR, POLLHUP and POLLNVAL for Solaris event ports (0144886 Trond Norbye)
+ o Detect and handle more allocation failures. (666b096 Jardel Weyrich)
+ o Use event_err() only if the failure is truly unrecoverable. (3f8d22a Jardel Weyrich)
+ o Handle resize failures in the select backend better. (83e805a)
+ o Correctly free selectop fields when select_resize fails in select_init (0c0ec0b)
+ o Make --enable-gcc-warnings a no-op if not using gcc (3267703)
+ o Fix a type error in our (unused) arc4random_stir() (f736198)
+ o Correctly detect and stop non-chunked http requests when the body is too long (63a715e)
+ o Have event_base_gettimeofday_cached() always return wall-clock time (a459ef7)
+ o Workaround for http crash bug 3078187 (5dc5662 Tomash Brechko)
+ o Fix incorrect assertions and possible use-after-free in evrpc_free() (4b8f02f Christophe Fillot)
+ o Reset outgoing http connection when read data in idle state. (272823f Tomash Brechko)
+ o Fix subtle recursion in evhttp_connection_cb_cleanup(). (218cf19 Tomash Brechko)
+ o Fix the case when failed evhttp_make_request() leaved request in the queue. (0d6622e Tomash Brechko)
+ o Fix a crash bug in evdns server circular list code (00e91b3)
+ o Handle calloc failure in evdns. (Found by Dave Hart) (364291e)
+ o Fix a memory leak on win32 socket->event map. (b4f89f0)
+ o Add a forgotten NULL check to evhttp_parse_headers (12311ff Sebastian Hahn)
+ o Fix possible NULL-deref in evdns_cancel_request (5208544 Sebastian Hahn)
+
+PORTABILITY:
+ o Fall back to sscanf if we have no other way to implement strtoll (453317b)
+ o Build correctly on platforms without sockaddr_storage (9184563)
+ o Try to build correctly on platforms with no IPv6 support (713c254)
+ o Build on systems without AI_PASSIVE (cb92113)
+ o Fix http unit test on non-windows platforms without getaddrinfo (6092f12)
+ o Do not check for gethostbyname_r versions if we have getaddrinfo (c1260b0)
+ o Include arpa/inet.h as needed on HPUX (10c834c Harlan Stenn)
+ o Include util-internal.h as needed to build on platforms with no sockaddr_storage (bbf5515 Harlan Stenn)
+ o Check for getservbyname even if not on win32. (af08a94 Harlan Stenn)
+ o Add -D_OSF_SOURCE to fix hpux builds (0b33479 Harlan Stenn)
+ o Check for allocation failures in apply_socktype_protocol_hack (637d17a)
+ o Fix the check for multicast or broadcast addresses in evutil_check_interfaces (1a21d7b)
+ o Avoid a free(NULL) if out-of-memory in evdns_getaddrinfo. Found by Dave Hart (3417f68)
+
+DEFENSIVE PROGRAMMING:
+ o Add compile-time check for AF_UNSPEC==PF_UNSPEC (3c8f4e7)
+
+BUGS IN TESTS:
+ o Fix test.sh output on solaris (b4f89b6 Dave Hart)
+ o Make test-eof fail with a timeout if we never get an eof. (05a2c22 Harlan Stenn)
+ o Use %s with printf in test.sh (039b9bd)
+ o Add an assert to appease clang's static analyzer (b0ff7eb Sebastian Hahn)
+ o Add a forgotten return value check in the unit tests (3819b62 Sebastian Hahn)
+ o Actually send NULL request in http_bad_request_test (b693c32 Sebastian Hahn)
+ o add some (void) casts for unused variables (65707d7 Sebastian Hahn)
+ o Refactor test_getaddrinfo_async_cancel_stress() (48c44a6 Sebastian Hahn)
+ o Be nice and "handle" error return values in sample code (4bac793 Sebastian Hahn)
+ o Check return value of evbuffer_add_cb in tests (93a1abb Sebastian Hahn)
+ o Remote some dead code from dns-example.c (744c745 Sebastian Hahn)
+ o Zero a struct sockaddr_in before using it (646f9fe Sebastian Hahn)
+
+BUILD FIXES:
+ o Fix warnings about AC_LANG_PROGRAM usage (f663112 Sebastian Hahn)
+ o Skip check for zlib if we have no zlib.h (a317c06 Harlan Stenn)
+ o Fix autoconf bracket issues; make check for getaddrinfo include netdb.h (833e5e9 Harlan Stenn)
+ o Correct an AM_CFLAGS to an AM_CPPFLAGS in test/Makefile.am (9c469db Dave Hart)
+ o Fix make distcheck & installation of libevent 1 headers (b5a1f9f Dave Hart)
+ o Fix compilation under LLVM/clang with --enable-gcc-warnings (ad9ff58 Sebastian Hahn)
+
+FEATURES:
+ o Make URI parser able to tolerate nonconformant URIs. (95060b5)
+
+DOCUMENTATION:
+ o Clarify event_set_mem_functions doc (926f816)
+ o Correct evhttp_del_accept_socket documentation on whether socket is closed (f665924)
+ o fix spelling mistake in whatsnew-2.0.txt (deb2f73)
+ o Fix sample/http-server ipv6 fixes (eb692be)
+ o Comment internal headers used in sample code. (4eb281c)
+ o Be explicit about how long event loops run in event.h documentation (f95bafb)
+ o Add comment to configure.in to explain gc-sections test logic (c621359)
+ o Fix a couple of memory leaks in samples/http-server.c. Found by Dave Hart. (2e9f665)
+
+BUILD IMPROVEMENTS:
+ o Use the gcc -ffunction-segments feature to allow gc when linking with static libevent (0965c56 Dave Hart)
+ o Add configure options to disable installation, regression tests (49e9bb7 Dave Hart)
+
+
+
 Changes in version 2.0.10-stable (16 Dec 2010)
   [Autogenerated from the Git log, sorted and cleaned by hand.]
 BUGFIXES
index dda19b22096aca57523c13289ba4d8110aeaac6b..bf3ae50084796269ad3e39737000001baa6d96e7 100644 (file)
@@ -32,7 +32,7 @@ RELEASE = -release 2.0
 #
 # Once an RC is out, DO NOT MAKE ANY ABI-BREAKING CHANGES IN THAT SERIES
 # UNLESS YOU REALLY REALLY HAVE TO.
-VERSION_INFO = 5:1:0
+VERSION_INFO = 6:1:1
 
 # History:          RELEASE    VERSION_INFO
 #  2.0.1-alpha --     2.0        1:0:0
@@ -44,8 +44,9 @@ VERSION_INFO = 5:1:0
 #  2.0.7-rc    --     2.0        3:0:1
 #  2.0.8-rc    --     2.0        4:0:2
 #  2.0.9-rc    --     2.0        5:0:0 (ABI changed slightly)
-# Planned:
 #  2.0.10-stable--    2.0        5:1:0 (No ABI change)
+#  2.0.11-stable--    2.0        6:0:1 (ABI changed, backward-compatible)
+#  2.0.12-stable--    2.0        6:1:1 (No ABI change)
 #
 # For Libevent 2.1:
 #  2.1.1-alpha --     2.1        1:0:0
@@ -72,7 +73,7 @@ VERSION_INFO = 5:1:0
 dist_bin_SCRIPTS = event_rpcgen.py
 
 pkgconfigdir=$(libdir)/pkgconfig
-pkgconfig_DATA=libevent.pc
+LIBEVENT_PKGCONFIG=libevent.pc
 
 # These sources are conditionally added by configure.in or conditionally
 # included from other files.
@@ -89,21 +90,28 @@ EXTRA_DIST = \
        Makefile.nmake test/Makefile.nmake \
        $(PLATFORM_DEPENDENT_SRC)
 
-lib_LTLIBRARIES = libevent.la libevent_core.la libevent_extra.la
+LIBEVENT_LIBS_LA = libevent.la libevent_core.la libevent_extra.la
 if PTHREADS
-lib_LTLIBRARIES += libevent_pthreads.la
-pkgconfig_DATA += libevent_pthreads.pc
+LIBEVENT_LIBS_LA += libevent_pthreads.la
+LIBEVENT_PKGCONFIG += libevent_pthreads.pc
 endif
 if OPENSSL
-lib_LTLIBRARIES += libevent_openssl.la
-pkgconfig_DATA += libevent_openssl.pc
+LIBEVENT_LIBS_LA += libevent_openssl.la
+LIBEVENT_PKGCONFIG += libevent_openssl.pc
+endif
+
+if INSTALL_LIBEVENT
+lib_LTLIBRARIES = $(LIBEVENT_LIBS_LA)
+pkgconfig_DATA = $(LIBEVENT_PKGCONFIG)
+else
+noinst_LTLIBRARIES =  $(LIBEVENT_LIBS_LA)
 endif
 
 SUBDIRS = . include sample test
 
 if BUILD_WIN32
 
-SYS_LIBS = -lws2_32
+SYS_LIBS = -lws2_32 -lshell32 -ladvapi32
 SYS_SRC = win32select.c evthread_win32.c buffer_iocp.c event_iocp.c \
        bufferevent_async.c
 SYS_INCLUDES = -IWIN32-Code
@@ -165,7 +173,7 @@ CORE_SRC = event.c evthread.c buffer.c \
        evmap.c log.c evutil.c evutil_rand.c strlcpy.c $(SYS_SRC)
 EXTRA_SRC = event_tagging.c http.c evdns.c evrpc.c
 
-if BUILD_WIN32
+if BUILD_WITH_NO_UNDEFINED
 NO_UNDEFINED = -no-undefined
 MAYBE_CORE = libevent_core.la
 else
@@ -173,7 +181,7 @@ NO_UNDEFINED =
 MAYBE_CORE =
 endif
 
-GENERIC_LDFLAGS = -static
+GENERIC_LDFLAGS = -version-info $(VERSION_INFO) $(RELEASE) $(NO_UNDEFINED)
 
 libevent_la_SOURCES = $(CORE_SRC) $(EXTRA_SRC)
 libevent_la_LIBADD = @LTLIBOBJS@ $(SYS_LIBS)
@@ -185,6 +193,7 @@ libevent_core_la_LDFLAGS = $(GENERIC_LDFLAGS)
 
 if PTHREADS
 libevent_pthreads_la_SOURCES = evthread_pthread.c
+libevent_pthreads_la_LIBADD = $(MAYBE_CORE)
 libevent_pthreads_la_LDFLAGS = $(GENERIC_LDFLAGS)
 endif
 
@@ -194,7 +203,7 @@ libevent_extra_la_LDFLAGS = $(GENERIC_LDFLAGS)
 
 if OPENSSL
 libevent_openssl_la_SOURCES = bufferevent_openssl.c
-libevent_openssl_la_LIBADD = $(MAYBE_CORE) -lcrypto -lssl
+libevent_openssl_la_LIBADD = $(MAYBE_CORE) $(OPENSSL_LIBS)
 libevent_openssl_la_LDFLAGS = $(GENERIC_LDFLAGS)
 endif
 
@@ -209,9 +218,15 @@ noinst_HEADERS = util-internal.h mm-internal.h ipv6-internal.h \
        WIN32-Code/tree.h \
        compat/sys/queue.h
 
-include_HEADERS = event.h evhttp.h evdns.h evrpc.h evutil.h
+EVENT1_HDRS = event.h evhttp.h evdns.h evrpc.h evutil.h
 
-INCLUDES = -I$(srcdir)/compat -I$(srcdir)/include -I./include $(SYS_INCLUDES)
+if INSTALL_LIBEVENT
+include_HEADERS = $(EVENT1_HDRS)
+else
+noinst_HEADERS += $(EVENT1_HDRS)
+endif
+
+AM_CPPFLAGS = -I$(srcdir)/compat -I$(srcdir)/include -I./include $(SYS_INCLUDES)
 
 verify: check
 
@@ -221,5 +236,3 @@ FORCE:
 
 DISTCLEANFILES = *~ libevent.pc ./include/event2/event-config.h
 
-install:
-
index 5ee7d969f241be7c49e9332f9b892743bb82be1c..bed2121a307818ca41642a1ba00113567f3d58ff 100644 (file)
@@ -82,6 +82,7 @@ fixing bugs:
   Denis Bilenko
   Julien Blache
   Kevin Bowling
+  Tomash Brechko
   Kelly Brock
   Ralph Castain
   Shuo Chen
@@ -92,20 +93,24 @@ fixing bugs:
   Mihai Draghicioiu
   Mark Ellzey
   Shie Erlich
+  Christophe Fillot
   Alexander von Gernler
   Artur Grabowski
+  Dave Hart
   Michael Herf
   Sebastian Hahn
   Aaron Hopkins
   Tani Hosokawa
   Claudio Jeker
   Evan Jones
-  Valery Kyholodov
+  Phua Keat
+  Kevin Ko
+  Brian Koehmstedt
   Marko Kreen
+  Valery Kyholodov
   Scott Lamb
   Christopher Layne
   Adam Langley
-  Christopher Layne
   Philip Lewis
   Zhou Li
   David Libenzi
@@ -119,6 +124,7 @@ fixing bugs:
   Andrey Matveev
   Caitlin Mercer
   Dagobert Michelsen
+  Mansour Moufid
   Felix Nawothnig
   Trond Norbye
   Linus Nordberg
@@ -133,18 +139,23 @@ fixing bugs:
   Dimitre Piskyulev
   Pavel Plesov
   Jon Poland
+  Robert Ransom
   Bert JW Regeer
+  Peter Rosin
   Hanna Schroeter
   Ralf Schmitt
   Mike Smellie
   Kevin Springborn
+  Harlan Stenn
   Ferenc Szalai
   Dug Song
+  Dongsheng Song
   Brodie Thiesfield
   Jason Toffaletti
   Bas Verhoeven
   Constantine Verutin
   Zack Weinberg
+  Jardel Weyrich
   Taral
   propanbutan
   mmadia
index 8a441074652245f9b4eeeacfe06af9d6b6f79c49..7c022d6513d136a7310b2f89434dbf7caeee94fe 100644 (file)
 /* Define to 1 if `sin_len' is member of `struct sockaddr_in'. */
 /* #undef _EVENT_HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
 
+/* Define to 1 if the system has the type `struct sockaddr_storage'. */
+#define _EVENT_HAVE_STRUCT_SOCKADDR_STORAGE 1
+
 /* Define to 1 if you have the <sys/devpoll.h> header file. */
 /* #undef _EVENT_HAVE_SYS_DEVPOLL_H */
 
 /* #undef _EVENT_HAVE_WORKING_KQUEUE */
 
 /* Numeric representation of the version */
-#define _EVENT_NUMERIC_VERSION 0x02000a00
+#define _EVENT_NUMERIC_VERSION 0x02000c00
 
 /* Name of package */
 #define _EVENT_PACKAGE "libevent"
 #define _EVENT_TIME_WITH_SYS_TIME 1
 
 /* Version number of package */
-#define _EVENT_VERSION "2.0.10-stable"
+#define _EVENT_VERSION "2.0.12-stable"
 
 /* Define to appropriate substitue if compiler doesnt have __func__ */
 #define _EVENT___func__ __FUNCTION__
index b6d2c5b339e845766260c0b19b67c0113940f452..4833169a2e963f58ea32f3d47efdeaf209a2d3d1 100644 (file)
@@ -352,7 +352,7 @@ arc4_seed(void)
        return ok ? 0 : -1;
 }
 
-static void
+static int
 arc4_stir(void)
 {
        int     i;
@@ -363,6 +363,8 @@ arc4_stir(void)
        }
 
        arc4_seed();
+       if (!arc4_seeded_ok)
+               return -1;
 
        /*
         * Discard early keystream, as per recommendations in
@@ -385,6 +387,8 @@ arc4_stir(void)
        for (i = 0; i < 12*256; i++)
                (void)arc4_getbyte();
        arc4_count = BYTES_BEFORE_RESEED;
+
+       return 0;
 }
 
 
index 9d84e739e710ddc724ec6e2e4d2bc798fdc26cab..71711a36497e7fc396e5d17553d20ee6ebf28d51 100644 (file)
@@ -36,6 +36,7 @@ extern "C" {
 #include "evthread-internal.h"
 #include "event2/thread.h"
 #include "ratelim-internal.h"
+#include "event2/bufferevent_struct.h"
 
 /* These flags are reasons that we might be declining to actually enable
    reading or writing on a bufferevent.
@@ -287,6 +288,20 @@ void bufferevent_unsuspend_write(struct bufferevent *bufev, bufferevent_suspend_
 #define bufferevent_wm_unsuspend_read(b) \
        bufferevent_unsuspend_read((b), BEV_SUSPEND_WM)
 
+/*
+  Disable a bufferevent.  Equivalent to bufferevent_disable(), but
+  first resets 'connecting' flag to force EV_WRITE down for sure.
+
+  XXXX this method will go away in the future; try not to add new users.
+    See comment in evhttp_connection_reset() for discussion.
+
+  @param bufev the bufferevent to be disabled
+  @param event any combination of EV_READ | EV_WRITE.
+  @return 0 if successful, or -1 if an error occurred
+  @see bufferevent_disable()
+ */
+int bufferevent_disable_hard(struct bufferevent *bufev, short event);
+
 /** Internal: Set up locking on a bufferevent.  If lock is set, use it.
  * Otherwise, use a new lock. */
 int bufferevent_enable_locking(struct bufferevent *bufev, void *lock);
index 4c9e38fa1abca07dab2a7f8ceb1497e5470c5df7..9855d18322c1d93db961d72b65effa4a621f040d 100644 (file)
@@ -473,6 +473,24 @@ bufferevent_settimeout(struct bufferevent *bufev,
 }
 
 
+int
+bufferevent_disable_hard(struct bufferevent *bufev, short event)
+{
+       int r = 0;
+       struct bufferevent_private *bufev_private =
+           EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
+
+       BEV_LOCK(bufev);
+       bufev->enabled &= ~event;
+
+       bufev_private->connecting = 0;
+       if (bufev->be_ops->disable(bufev, event) < 0)
+               r = -1;
+
+       BEV_UNLOCK(bufev);
+       return r;
+}
+
 int
 bufferevent_disable(struct bufferevent *bufev, short event)
 {
index b7284fda6cb2dbeab9fcfcdb5b68a14445e3a02b..76a161623bf708850ebca374a43b0d6d061a9c07 100644 (file)
 #include "util-internal.h"
 #include "iocp-internal.h"
 
+#ifndef SO_UPDATE_CONNECT_CONTEXT
+/* Mingw is sometimes missing this */
+#define SO_UPDATE_CONNECT_CONTEXT 0x7010
+#endif
+
 /* prototypes */
 static int be_async_enable(struct bufferevent *, short);
 static int be_async_disable(struct bufferevent *, short);
@@ -403,11 +408,15 @@ connect_complete(struct event_overlapped *eo, ev_uintptr_t key,
 {
        struct bufferevent_async *bev_a = upcast_connect(eo);
        struct bufferevent *bev = &bev_a->bev.bev;
+       evutil_socket_t sock;
 
        BEV_LOCK(bev);
 
        EVUTIL_ASSERT(bev_a->bev.connecting);
        bev_a->bev.connecting = 0;
+       sock = _evbuffer_overlapped_get_fd(bev_a->bev.bev.input);
+       /* XXXX Handle error? */
+       setsockopt(sock, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0);
 
        if (ok)
                bufferevent_async_set_connected(bev);
index 6886aca0fa666c9d08381142b35d4bdca8baabbb..7f19eb9afd888bbae8f74abdeb6da47cd8b47a68 100644 (file)
@@ -428,6 +428,7 @@ be_filter_readcb(struct bufferevent *underlying, void *_me)
 
        /* XXXX use return value */
        res = be_filter_process_input(bevf, state, &processed_any);
+       (void)res;
 
        /* XXX This should be in process_input, not here.  There are
         * other places that can call process-input, and they should
index 3d9a77012f0e396314500a645d9b3f89aaefa610..02a6222a87b06f01c9cf14a17bce8550f5e74eba 100644 (file)
@@ -1013,6 +1013,7 @@ be_openssl_outbuf_cb(struct evbuffer *buf,
                consider_writing(bev_ssl);
        }
        /* XXX Handle r < 0 */
+        (void)r;
 }
 
 
index 1d76ea14b0b6bf0a936bdd303f379b75e50e3c74..6aff91ea83d7b809f5e90cd0eee950dfb1cf995c 100644 (file)
@@ -451,6 +451,7 @@ bufferevent_connect_getaddrinfo_cb(int result, struct evutil_addrinfo *ai,
        /* XXX use the other addrinfos? */
        /* XXX use this return value */
        r = bufferevent_socket_connect(bev, ai->ai_addr, (int)ai->ai_addrlen);
+       (void)r;
        _bufferevent_decref_and_unlock(bev);
        evutil_freeaddrinfo(ai);
 }
index 7b8f2af6461cc2efa3cf88dd495abcf6aa1dcc05..5e142c90a67ecae9afa05561228c797b8c3f6d23 100644 (file)
@@ -5,17 +5,30 @@ AC_INIT(event.c)
 
 AC_CONFIG_MACRO_DIR([m4])
 
-AM_INIT_AUTOMAKE(libevent,2.0.10-stable)
+AM_INIT_AUTOMAKE(libevent,2.0.12-stable)
 AM_CONFIG_HEADER(config.h)
-AC_DEFINE(NUMERIC_VERSION, 0x02000a00, [Numeric representation of the version])
+AC_DEFINE(NUMERIC_VERSION, 0x02000c00, [Numeric representation of the version])
 
 dnl Initialize prefix.
 if test "$prefix" = "NONE"; then
    prefix="/usr/local"
 fi
 
+AC_CANONICAL_BUILD
+AC_CANONICAL_HOST
+dnl the 'build' machine is where we run configure and compile
+dnl the 'host' machine is where the resulting stuff runs.
+
+case "$host_os" in
+
+ osf5*)
+    CFLAGS="$CFLAGS -D_OSF_SOURCE"
+    ;;
+esac
+
 dnl Checks for programs.
 AC_PROG_CC
+AM_PROG_CC_C_O
 AC_PROG_INSTALL
 AC_PROG_LN_S
 AC_PROG_MKDIR_P
@@ -44,6 +57,16 @@ AC_ARG_ENABLE(openssl,
 AC_ARG_ENABLE(debug-mode,
      AS_HELP_STRING(--disable-debug-mode, disable support for running in debug mode),
         [], [enable_debug_mode=yes])
+AC_ARG_ENABLE([libevent-install],
+     AS_HELP_STRING([--disable-libevent-install, disable installation of libevent]),
+       [], [enable_libevent_install=yes])
+AC_ARG_ENABLE([libevent-regress],
+     AS_HELP_STRING([--disable-libevent-regress, skip regress in make check]),
+       [], [enable_libevent_regress=yes])
+AC_ARG_ENABLE([function-sections],
+     AS_HELP_STRING([--enable-function-sections, make static library allow smaller binaries with --gc-sections]),
+       [], [enable_function_sections=no])
+
 
 AC_PROG_LIBTOOL
 
@@ -53,6 +76,8 @@ dnl   the command line with --enable-shared and --disable-shared.
 dnl AC_DISABLE_SHARED
 AC_SUBST(LIBTOOL_DEPS)
 
+AM_CONDITIONAL([BUILD_REGRESS], [test "$enable_libevent_regress" = "yes"])
+
 dnl Checks for libraries.
 AC_SEARCH_LIBS([inet_ntoa], [nsl])
 AC_SEARCH_LIBS([socket], [socket])
@@ -60,6 +85,35 @@ AC_SEARCH_LIBS([inet_aton], [resolv])
 AC_SEARCH_LIBS([clock_gettime], [rt])
 AC_SEARCH_LIBS([sendfile], [sendfile])
 
+dnl - check if the macro WIN32 is defined on this compiler.
+dnl - (this is how we check for a windows version of GCC)
+AC_MSG_CHECKING(for WIN32)
+AC_TRY_COMPILE(,
+       [
+#ifndef WIN32
+die horribly
+#endif
+       ],
+       bwin32=true; AC_MSG_RESULT(yes),
+       bwin32=false; AC_MSG_RESULT(no),
+)
+
+dnl - check if the macro __CYGWIN__ is defined on this compiler.
+dnl - (this is how we check for a cygwin version of GCC)
+AC_MSG_CHECKING(for CYGWIN)
+AC_TRY_COMPILE(,
+       [
+#ifndef __CYGWIN__
+die horribly
+#endif
+       ],
+       cygwin=true; AC_MSG_RESULT(yes),
+       cygwin=false; AC_MSG_RESULT(no),
+)
+
+AC_CHECK_HEADERS([zlib.h])
+
+if test "x$ac_cv_header_zlib_h" = "xyes"; then
 dnl Determine if we have zlib for regression tests
 dnl Don't put this one in LIBS
 save_LIBS="$LIBS"
@@ -72,25 +126,40 @@ AC_SEARCH_LIBS([inflateEnd], [z],
        AC_DEFINE(HAVE_LIBZ, 1, [Define if the system has zlib])])
 LIBS="$save_LIBS"
 AC_SUBST(ZLIB_LIBS)
+fi
 AM_CONDITIONAL(ZLIB_REGRESS, [test "$have_zlib" = "yes"])
 
 dnl See if we have openssl.  This doesn't go in LIBS either.
+if test "$bwin32" = true; then
+  EV_LIB_WS32=-lws2_32
+  EV_LIB_GDI=-lgdi32
+else
+  EV_LIB_WS32=
+  EV_LIB_GDI=
+fi
+AC_SUBST(EV_LIB_WS32)
+AC_SUBST(EV_LIB_GDI)
+
+AC_CHECK_HEADERS([openssl/bio.h])
+
 if test "$enable_openssl" = "yes"; then
 save_LIBS="$LIBS"
 LIBS=""
 OPENSSL_LIBS=""
 have_openssl=no
 AC_SEARCH_LIBS([SSL_new], [ssl],
-               [have_openssl=yes
-               OPENSSL_LIBS="$LIBS"
-               AC_DEFINE(HAVE_OPENSSL, 1, [Define if the system has openssl])])
+       [have_openssl=yes
+       OPENSSL_LIBS="$LIBS -lcrypto $EV_LIB_GDI $EV_LIB_WS32"
+       AC_DEFINE(HAVE_OPENSSL, 1, [Define if the system has openssl])],
+       [have_openssl=no],
+       [-lcrypto $EV_LIB_GDI $EV_LIB_WS32])
 LIBS="$save_LIBS"
 AC_SUBST(OPENSSL_LIBS)
 fi
 
 dnl Checks for header files.
 AC_HEADER_STDC
-AC_CHECK_HEADERS(fcntl.h stdarg.h inttypes.h stdint.h stddef.h poll.h unistd.h sys/epoll.h sys/time.h sys/queue.h sys/event.h sys/param.h sys/ioctl.h sys/select.h sys/devpoll.h port.h netinet/in.h netinet/in6.h sys/socket.h sys/uio.h arpa/inet.h sys/eventfd.h sys/mman.h sys/sendfile.h sys/wait.h netdb.h)
+AC_CHECK_HEADERS([fcntl.h stdarg.h inttypes.h stdint.h stddef.h poll.h unistd.h sys/epoll.h sys/time.h sys/queue.h sys/event.h sys/param.h sys/ioctl.h sys/select.h sys/devpoll.h port.h netinet/in.h netinet/in6.h sys/socket.h sys/uio.h arpa/inet.h sys/eventfd.h sys/mman.h sys/sendfile.h sys/wait.h netdb.h])
 AC_CHECK_HEADERS(sys/sysctl.h, [], [], [
 #ifdef HAVE_SYS_PARAM_H
 #include <sys/param.h>
@@ -174,20 +243,9 @@ if test "x$ac_cv_header_sys_sysctl_h" = "xyes"; then
        )
 fi
 
-dnl - check if the macro WIN32 is defined on this compiler.
-dnl - (this is how we check for a windows version of GCC)
-AC_MSG_CHECKING(for WIN32)
-AC_TRY_COMPILE(,
-       [
-#ifndef WIN32
-die horribly
-#endif
-       ],
-       bwin32=true; AC_MSG_RESULT(yes),
-       bwin32=false; AC_MSG_RESULT(no),
-)
-
 AM_CONDITIONAL(BUILD_WIN32, test x$bwin32 = xtrue)
+AM_CONDITIONAL(BUILD_CYGWIN, test x$cygwin = xtrue)
+AM_CONDITIONAL(BUILD_WITH_NO_UNDEFINED, test x$bwin32 = xtrue || test x$cygwin = xtrue)
 
 if test x$bwin32 = xtrue; then
    AC_SEARCH_LIBS([getservbyname],[ws2_32])
@@ -199,8 +257,32 @@ AC_C_INLINE
 AC_HEADER_TIME
 
 dnl Checks for library functions.
-AC_CHECK_FUNCS(gettimeofday vasprintf fcntl clock_gettime strtok_r strsep getaddrinfo getnameinfo strlcpy inet_ntop inet_pton signal sigaction strtoll inet_aton pipe eventfd sendfile mmap splice arc4random arc4random_buf issetugid geteuid getegid getservbyname getprotobynumber setenv unsetenv putenv)
+AC_CHECK_FUNCS([gettimeofday vasprintf fcntl clock_gettime strtok_r strsep])
+AC_CHECK_FUNCS([getnameinfo strlcpy inet_ntop inet_pton signal sigaction strtoll inet_aton pipe eventfd sendfile mmap splice arc4random arc4random_buf issetugid geteuid getegid getprotobynumber setenv unsetenv putenv])
+
+AC_CACHE_CHECK(
+    [for getaddrinfo],
+    [libevent_cv_getaddrinfo],
+    [AC_LINK_IFELSE(
+       [AC_LANG_PROGRAM(
+           [[
+               #ifdef HAVE_NETDB_H
+               #include <netdb.h>
+               #endif
+           ]],
+           [[
+               getaddrinfo;
+           ]]
+       )],
+       [libevent_cv_getaddrinfo=yes],
+       [libevent_cv_getaddrinfo=no]
+    )]
+)
+if test "$libevent_cv_getaddrinfo" = "yes" ; then
+    AC_DEFINE([HAVE_GETADDRINFO], [1], [Do we have getaddrinfo()?])
+else
 
+AC_CHECK_FUNCS([getservbyname])
 # Check for gethostbyname_r in all its glorious incompatible versions.
 #   (This is cut-and-pasted from Tor, which based its logic on
 #   Python's configure.in.)
@@ -211,14 +293,14 @@ AC_CHECK_FUNC(gethostbyname_r, [
   AC_MSG_CHECKING([how many arguments gethostbyname_r() wants])
   OLD_CFLAGS=$CFLAGS
   CFLAGS="$CFLAGS $MY_CPPFLAGS $MY_THREAD_CPPFLAGS $MY_CFLAGS"
-  AC_COMPILE_IFELSE(AC_LANG_PROGRAM([
+  AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
 #include <netdb.h>
   ], [[
     char *cp1, *cp2;
     struct hostent *h1, *h2;
     int i1, i2;
     (void)gethostbyname_r(cp1,h1,cp2,i1,&h2,&i2);
-  ]]),[
+  ]])],[
     AC_DEFINE(HAVE_GETHOSTBYNAME_R)
     AC_DEFINE(HAVE_GETHOSTBYNAME_R_6_ARG, 1,
      [Define this if gethostbyname_r takes 6 arguments])
@@ -257,6 +339,7 @@ AC_CHECK_FUNC(gethostbyname_r, [
  CFLAGS=$OLD_CFLAGS
 ])
 
+fi
 
 AC_CHECK_SIZEOF(long)
 
@@ -443,7 +526,7 @@ AC_CHECK_SIZEOF(short)
 AC_CHECK_SIZEOF(size_t)
 AC_CHECK_SIZEOF(void *)
 
-AC_CHECK_TYPES([struct in6_addr, struct sockaddr_in6, sa_family_t, struct addrinfo], , ,
+AC_CHECK_TYPES([struct in6_addr, struct sockaddr_in6, sa_family_t, struct addrinfo, struct sockaddr_storage], , ,
 [#define _GNU_SOURCE
 #include <sys/types.h>
 #ifdef HAVE_NETINET_IN_H
@@ -559,22 +642,32 @@ AM_CONDITIONAL(OPENSSL, [test "$enable_openssl" != "no" && test "$have_openssl"
 
 # Add some more warnings which we use in development but not in the
 # released versions.  (Some relevant gcc versions can't handle these.)
-if test x$enable_gcc_warnings = xyes; then
+if test x$enable_gcc_warnings = xyes && test "$GCC" = "yes"; then
 
-  AC_COMPILE_IFELSE(AC_LANG_PROGRAM([], [
+  AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [
 #if !defined(__GNUC__) || (__GNUC__ < 4)
 #error
-#endif]), have_gcc4=yes, have_gcc4=no)
+#endif])], have_gcc4=yes, have_gcc4=no)
 
-  AC_COMPILE_IFELSE(AC_LANG_PROGRAM([], [
+  AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [
 #if !defined(__GNUC__) || (__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 2)
 #error
-#endif]), have_gcc42=yes, have_gcc42=no)
+#endif])], have_gcc42=yes, have_gcc42=no)
 
-  AC_COMPILE_IFELSE(AC_LANG_PROGRAM([], [
+  AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [
 #if !defined(__GNUC__) || (__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 5)
 #error
-#endif]), have_gcc45=yes, have_gcc45=no)
+#endif])], have_gcc45=yes, have_gcc45=no)
+
+  AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [
+#if !defined(__clang__)
+#error
+#endif])], have_clang=yes, have_clang=no)
+
+  AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [
+#if !defined(__clang__) || (__clang_major__ > 2) || (__clang_major__ == 2 && __clang_minor__ > 9)
+#error
+#endif])], have_clang29orlower=yes, have_clang29orlower=no)
 
   CFLAGS="$CFLAGS -W -Wfloat-equal -Wundef -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes -Wwrite-strings -Wredundant-decls -Wchar-subscripts -Wcomment -Wformat -Wwrite-strings -Wmissing-declarations -Wredundant-decls -Wnested-externs -Wbad-function-cast -Wswitch-enum -Werror"
   CFLAGS="$CFLAGS -Wno-unused-parameter -Wstrict-aliasing"
@@ -587,17 +680,106 @@ if test x$enable_gcc_warnings = xyes; then
 
   if test x$have_gcc42 = xyes ; then
     # These warnings break gcc 4.0.2 and work on gcc 4.2
-    CFLAGS="$CFLAGS -Waddress -Wnormalized=id -Woverride-init"
+    CFLAGS="$CFLAGS -Waddress"
+  fi
+
+  if test x$have_gcc42 = xyes && test x$have_clang29orlower = xno; then
+    # These warnings break gcc 4.0.2 and clang, but work on gcc 4.2
+    # We only disable these for clang 2.9 and lower, in case they are
+    # supported in later versions.
+    CFLAGS="$CFLAGS -Wnormalized=id -Woverride-init"
   fi
 
   if test x$have_gcc45 = xyes ; then
     # These warnings work on gcc 4.5
     CFLAGS="$CFLAGS -Wlogical-op"
   fi
+
+  if test x$have_clang = xyes; then
+    # Disable the unused-function warnings, because these trigger
+    # for minheap-internal.h related code.
+    CFLAGS="$CFLAGS -Wno-unused-function"
+  fi
+
 ##This will break the world on some 64-bit architectures
 # CFLAGS="$CFLAGS -Winline"
 
 fi
 
+LIBEVENT_GC_SECTIONS=
+if test "$GCC" = yes && test "$enable_function_sections" = yes ; then
+    AC_CACHE_CHECK(
+       [if linker supports omitting unused code and data],
+       [libevent_cv_gc_sections_runs],
+       [
+           dnl  NetBSD will link but likely not run with --gc-sections
+           dnl  http://bugs.ntp.org/1844
+           dnl  http://gnats.netbsd.org/40401
+           dnl  --gc-sections causes attempt to load as linux elf, with
+           dnl  wrong syscalls in place.  Test a little gauntlet of
+           dnl  simple stdio read code checking for errors, expecting
+           dnl  enough syscall differences that the NetBSD code will
+           dnl  fail even with Linux emulation working as designed.
+           dnl  A shorter test could be refined by someone with access
+           dnl  to a NetBSD host with Linux emulation working.
+           origCFLAGS="$CFLAGS"
+           CFLAGS="$CFLAGS -Wl,--gc-sections"
+           AC_LINK_IFELSE(
+               [AC_LANG_PROGRAM(
+                   [[
+                       #include <stdlib.h>
+                       #include <stdio.h>
+                   ]],
+                   [[
+                       FILE *  fpC;
+                       char    buf[32];
+                       size_t  cch;
+                       int     read_success_once;
+
+                       fpC = fopen("conftest.c", "r");
+                       if (NULL == fpC)
+                               exit(1);
+                       do {
+                               cch = fread(buf, sizeof(buf), 1, fpC);
+                               read_success_once |= (0 != cch);
+                       } while (0 != cch);
+                       if (!read_success_once)
+                               exit(2);
+                       if (!feof(fpC))
+                               exit(3);
+                       if (0 != fclose(fpC))
+                               exit(4);
+
+                       exit(EXIT_SUCCESS);
+                   ]]
+               )],
+               [
+                    dnl We have to do this invocation manually so that we can
+                    dnl get the output of conftest.err to make sure it doesn't
+                    dnl mention gc-sections.
+                   if test "X$cross_compiling" = "Xyes" || grep gc-sections conftest.err ; then
+                       libevent_cv_gc_sections_runs=no
+                   else
+                       libevent_cv_gc_sections_runs=no
+                       ./conftest >/dev/null 2>&1 && libevent_cv_gc_sections_runs=yes
+                   fi
+               ],
+               [libevent_cv_gc_sections_runs=no]
+           )
+           CFLAGS="$origCFLAGS"
+           AS_UNSET([origCFLAGS])
+       ]
+    )
+    case "$libevent_cv_gc_sections_runs" in
+     yes)
+       CFLAGS="-ffunction-sections -fdata-sections $CFLAGS"
+       LIBEVENT_GC_SECTIONS="-Wl,--gc-sections"
+       ;;
+    esac
+fi
+AC_SUBST([LIBEVENT_GC_SECTIONS])
+
+AM_CONDITIONAL([INSTALL_LIBEVENT], [test "$enable_libevent_install" = "yes"])
+
 AC_CONFIG_FILES( [libevent.pc libevent_openssl.pc libevent_pthreads.pc] )
 AC_OUTPUT(Makefile include/Makefile test/Makefile sample/Makefile)
index a1636a14e1a2b9cca29f6ee62ed728155dd3f27e..6dd3dc92e8734f5eeb086c9167b3e2dccdb151dc 100644 (file)
@@ -794,6 +794,12 @@ reply_schedule_callback(struct request *const req, u32 ttl, u32 err, struct repl
 {
        struct deferred_reply_callback *d = mm_calloc(1, sizeof(*d));
 
+       if (!d) {
+               event_warn("%s: Couldn't allocate space for deferred callback.",
+                   __func__);
+               return;
+       }
+
        ASSERT_LOCKED(req->base);
 
        d->request_type = req->request_type;
@@ -1144,6 +1150,9 @@ request_parse(u8 *packet, int length, struct evdns_server_port *port, struct soc
        GET16(answers);
        GET16(authority);
        GET16(additional);
+       (void)answers;
+       (void)additional;
+       (void)authority;
 
        if (flags & 0x8000) return -1; /* Must not be an answer. */
        flags &= 0x0110; /* Only RD and CD get preserved. */
@@ -1993,7 +2002,7 @@ server_request_free(struct server_request *req)
                EVDNS_LOCK(req->port);
                lock=1;
                if (req->port->pending_replies == req) {
-                       if (req->next_pending)
+                       if (req->next_pending && req->next_pending != req)
                                req->port->pending_replies = req->next_pending;
                        else
                                req->port->pending_replies = NULL;
@@ -2387,7 +2396,7 @@ _evdns_nameserver_add_impl(struct evdns_base *base, const struct sockaddr *addre
 
        evtimer_assign(&ns->timeout_event, ns->base->event_base, nameserver_prod_callback, ns);
 
-       ns->socket = socket(PF_INET, SOCK_DGRAM, 0);
+       ns->socket = socket(address->sa_family, SOCK_DGRAM, 0);
        if (ns->socket < 0) { err = 1; goto out1; }
        evutil_make_socket_closeonexec(ns->socket);
        evutil_make_socket_nonblocking(ns->socket);
@@ -2693,10 +2702,13 @@ evdns_cancel_request(struct evdns_base *base, struct evdns_request *handle)
 {
        struct request *req;
 
+       if (!handle->current_req)
+               return;
+
        if (!base) {
                /* This redundancy is silly; can we fix it? (Not for 2.0) XXXX */
                base = handle->base;
-               if (!base && handle->current_req)
+               if (!base)
                        base = handle->current_req->base;
        }
 
@@ -3069,6 +3081,10 @@ search_request_new(struct evdns_base *base, struct evdns_request *handle,
                }
                EVUTIL_ASSERT(handle->search_origname == NULL);
                handle->search_origname = mm_strdup(name);
+               if (handle->search_origname == NULL) {
+                       /* XXX Should we dealloc req? If yes, how? */
+                       return NULL;
+               }
                handle->search_state = base->global_search_state;
                handle->search_flags = flags;
                base->global_search_state->refcount++;
@@ -4306,7 +4322,8 @@ evdns_getaddrinfo_gotresolve(int result, char type, int count,
                                evdns_cancel_request(NULL, other_req->r);
                        }
                        data->user_cb(EVUTIL_EAI_MEMORY, NULL, data->user_data);
-                       evutil_freeaddrinfo(res);
+                       if (res)
+                               evutil_freeaddrinfo(res);
 
                        if (other_req->r == NULL)
                                free_getaddrinfo_request(data);
index e3da33da724ed8ac21f68b30931ee00682d19e3e..12ca8bc194d09a9498cdb7c4c85c98620d7fdc9f 100644 (file)
@@ -32,6 +32,7 @@ extern "C" {
 #endif
 
 #include "event2/event-config.h"
+#include <time.h>
 #include <sys/queue.h>
 #include "event2/event_struct.h"
 #include "minheap-internal.h"
@@ -235,9 +236,18 @@ struct event_base {
        /** Priority queue of events with timeouts. */
        struct min_heap timeheap;
 
-       /** Stored timeval: used to avoid calling gettimeofday too often. */
+       /** Stored timeval: used to avoid calling gettimeofday/clock_gettime
+        * too often. */
        struct timeval tv_cache;
 
+#if defined(_EVENT_HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
+       /** Difference between internal time (maybe from clock_gettime) and
+        * gettimeofday. */
+       struct timeval tv_clock_diff;
+       /** Second in which we last updated tv_clock_diff, in monotonic time. */
+       time_t last_updated_clock_diff;
+#endif
+
 #ifndef _EVENT_DISABLE_THREAD_SUPPORT
        /* threading support */
        /** The thread currently running the event_loop for this base */
index fedb9c73cfa293adb776bc3e6815669699880f90..41c7d8f4fd86023948944fc12c53c96e69b9161f 100644 (file)
@@ -330,6 +330,10 @@ detect_monotonic(void)
 #endif
 }
 
+/* How often (in seconds) do we check for changes in wall clock time relative
+ * to monotonic time?  Set this to -1 for 'never.' */
+#define CLOCK_SYNC_INTERVAL -1
+
 /** Set 'tp' to the current time according to 'base'.  We must hold the lock
  * on 'base'.  If there is a cached time, return it.  Otherwise, use
  * clock_gettime or gettimeofday as appropriate to find out the right time.
@@ -354,6 +358,14 @@ gettime(struct event_base *base, struct timeval *tp)
 
                tp->tv_sec = ts.tv_sec;
                tp->tv_usec = ts.tv_nsec / 1000;
+               if (base->last_updated_clock_diff + CLOCK_SYNC_INTERVAL
+                   < ts.tv_sec) {
+                       struct timeval tv;
+                       evutil_gettimeofday(&tv,NULL);
+                       evutil_timersub(&tv, tp, &base->tv_clock_diff);
+                       base->last_updated_clock_diff = ts.tv_sec;
+               }
+
                return (0);
        }
 #endif
@@ -372,7 +384,16 @@ event_base_gettimeofday_cached(struct event_base *base, struct timeval *tv)
        }
 
        EVBASE_ACQUIRE_LOCK(base, th_base_lock);
-       r = gettime(base, tv);
+       if (base->tv_cache.tv_sec == 0) {
+               r = evutil_gettimeofday(tv, NULL);
+       } else {
+#if defined(_EVENT_HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
+               evutil_timeradd(&base->tv_cache, &base->tv_clock_diff, tv);
+#else
+               *tv = base->tv_cache;
+#endif
+               r = 0;
+       }
        EVBASE_RELEASE_LOCK(base, th_base_lock);
        return r;
 }
@@ -1778,7 +1799,6 @@ event_priority_set(struct event *ev, int pri)
 int
 event_pending(const struct event *ev, short event, struct timeval *tv)
 {
-       struct timeval  now, res;
        int flags = 0;
 
        _event_debug_assert_is_setup(ev);
@@ -1795,12 +1815,13 @@ event_pending(const struct event *ev, short event, struct timeval *tv)
        /* See if there is a timeout that we should report */
        if (tv != NULL && (flags & event & EV_TIMEOUT)) {
                struct timeval tmp = ev->ev_timeout;
-               event_base_gettimeofday_cached(ev->ev_base, &now);
                tmp.tv_usec &= MICROSECONDS_MASK;
-               evutil_timersub(&tmp, &now, &res);
-               /* correctly remap to real time */
-               evutil_gettimeofday(&now, NULL);
-               evutil_timeradd(&now, &res, tv);
+#if defined(_EVENT_HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
+               /* correctly remamp to real time */
+               evutil_timeradd(&ev->ev_base->tv_clock_diff, &tmp, tv);
+#else
+               *tv = tmp;
+#endif
        }
 
        return (flags & event);
index 254ed90dcfe4feadb954d889c659b17e9a9291ec..75fe4627eb00c6df3c25bb5ac72ed4e8d73250c7 100644 (file)
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#ifndef _WIN32_WINNT
+/* Minimum required for InitializeCriticalSectionAndSpinCount */
+#define _WIN32_WINNT 0x0403
+#endif
 #include <winsock2.h>
 #include <windows.h>
 #include <process.h>
index 5521626cf2431137f542c94d406801fef2833328..ebedb7881437e9c4e04d198cfb155da5eea6bd62 100644 (file)
@@ -148,6 +148,7 @@ void evmap_io_clear(struct event_io_map *ctx)
                next = HT_NEXT_RMV(event_io_map, ctx, ent);
                mm_free(this);
        }
+       HT_CLEAR(event_io_map, ctx); /* remove all storage held by the ctx. */
 }
 #endif
 
@@ -163,7 +164,6 @@ void evmap_io_clear(struct event_io_map *ctx)
 #define GET_SIGNAL_SLOT_AND_CTOR(x, map, slot, type, ctor, fdinfo_len) \
        do {                                                            \
                if ((map)->entries[slot] == NULL) {                     \
-                       EVUTIL_ASSERT(ctor != NULL);                            \
                        (map)->entries[slot] =                          \
                            mm_calloc(1,sizeof(struct type)+fdinfo_len); \
                        EVUTIL_ASSERT((map)->entries[slot] != NULL);            \
index 4301a39c7f3213ea81664ad97ade568fbb2be725..f1da73d5671ea4232b962b58af6a451d646004f0 100644 (file)
@@ -336,10 +336,20 @@ evport_dispatch(struct event_base *base, struct timeval *tv)
                 * (because we have to pass this to the callback)
                 */
                res = 0;
-               if (pevt->portev_events & POLLIN)
-                       res |= EV_READ;
-               if (pevt->portev_events & POLLOUT)
-                       res |= EV_WRITE;
+               if (pevt->portev_events & (POLLERR|POLLHUP)) {
+                       res = EV_READ | EV_WRITE;
+               } else {
+                       if (pevt->portev_events & POLLIN)
+                               res |= EV_READ;
+                       if (pevt->portev_events & POLLOUT)
+                               res |= EV_WRITE;
+               }
+
+               /*
+                * Check for the error situations or a hangup situation
+                */
+               if (pevt->portev_events & (POLLERR|POLLHUP|POLLNVAL))
+                       res |= EV_READ|EV_WRITE;
 
                EVUTIL_ASSERT(epdp->ed_nevents > fd);
                fdi = &(epdp->ed_fds[fd]);
index 9d69299490cbaf2108413c75b857bcbaab54be0e..e11892dcc07175cee690dec8bf9898b8a4014fa6 100644 (file)
@@ -98,7 +98,7 @@ evrpc_free(struct evrpc_base *base)
 
        while ((rpc = TAILQ_FIRST(&base->registered_rpcs)) != NULL) {
                r = evrpc_unregister_rpc(base, rpc->uri);
-               EVUTIL_ASSERT(r);
+               EVUTIL_ASSERT(r == 0);
        }
        while ((pause = TAILQ_FIRST(&base->paused_requests)) != NULL) {
                TAILQ_REMOVE(&base->paused_requests, pause, next);
@@ -263,9 +263,6 @@ evrpc_unregister_rpc(struct evrpc_base *base, const char *name)
        }
        TAILQ_REMOVE(&base->registered_rpcs, rpc, next);
 
-       mm_free((char *)rpc->uri);
-       mm_free(rpc);
-
        registered_uri = evrpc_construct_uri(name);
 
        /* remove the http server callback */
@@ -273,6 +270,9 @@ evrpc_unregister_rpc(struct evrpc_base *base, const char *name)
        EVUTIL_ASSERT(r == 0);
 
        mm_free(registered_uri);
+
+       mm_free((char *)rpc->uri);
+       mm_free(rpc);
        return (0);
 }
 
index 35f14b2b2e8dffa7e1f0725c013d5e228fb0dc9c..2cfb76e9103d1a36e406277e5b4ffd98f54033a2 100644 (file)
@@ -217,6 +217,7 @@ debug_cond_wait(void *_cond, void *_lock, const struct timeval *tv)
 {
        int r;
        struct debug_lock *lock = _lock;
+       EVUTIL_ASSERT(lock);
        EVLOCK_ASSERT_LOCKED(_lock);
        evthread_debug_lock_mark_unlocked(0, lock);
        r = _original_cond_fns.wait_condition(_cond, lock->lock, tv);
index bd72be15e5ac9877988a16bbbf3c744b935d38b9..18dca6d4391a8c0c69dba59874d5337c8879808c 100644 (file)
 #include "event2/event-config.h"
 
 #ifdef WIN32
+#ifndef _WIN32_WINNT
+/* Minimum required for InitializeCriticalSectionAndSpinCount */
+#define _WIN32_WINNT 0x0403
+#endif
 #include <winsock2.h>
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h>
index b769acc2b323fa7f90a42074d5bc81af8b395e06..9d9863a23c5f374cf97f87295c5e1d3b2f7c955b 100644 (file)
@@ -351,6 +351,8 @@ evutil_strtoll(const char *s, char **endptr, int base)
        r = (ev_int64_t) _atoi64(s);
        while (isspace(*s))
                ++s;
+       if (*s == '-')
+               ++s;
        while (isdigit(*s))
                ++s;
        if (endptr)
@@ -358,6 +360,36 @@ evutil_strtoll(const char *s, char **endptr, int base)
        return r;
 #elif defined(WIN32)
        return (ev_int64_t) _strtoi64(s, endptr, base);
+#elif defined(_EVENT_SIZEOF_LONG_LONG) && _EVENT_SIZEOF_LONG_LONG == 8
+       long long r;
+       int n;
+       if (base != 10 && base != 16)
+               return 0;
+       if (base == 10) {
+               n = sscanf(s, "%lld", &r);
+       } else {
+               unsigned long long ru=0;
+               n = sscanf(s, "%llx", &ru);
+               if (ru > EV_INT64_MAX)
+                       return 0;
+               r = (long long) ru;
+       }
+       if (n != 1)
+               return 0;
+       while (EVUTIL_ISSPACE(*s))
+               ++s;
+       if (*s == '-')
+               ++s;
+       if (base == 10) {
+               while (EVUTIL_ISDIGIT(*s))
+                       ++s;
+       } else {
+               while (EVUTIL_ISXDIGIT(*s))
+                       ++s;
+       }
+       if (endptr)
+               *endptr = (char*) s;
+       return r;
 #else
 #error "I don't know how to parse 64-bit integers."
 #endif
@@ -479,6 +511,15 @@ evutil_socket_finished_connecting(evutil_socket_t fd)
    set by evutil_check_interfaces. */
 static int have_checked_interfaces, had_ipv4_address, had_ipv6_address;
 
+/* Macro: True iff the IPv4 address 'addr', in host order, is in 127.0.0.0/8
+ */
+#define EVUTIL_V4ADDR_IS_LOCALHOST(addr) (((addr)>>24) == 127)
+
+/* Macro: True iff the IPv4 address 'addr', in host order, is a class D
+ * (multiclass) address.
+ */
+#define EVUTIL_V4ADDR_IS_CLASSD(addr) ((((addr)>>24) & 0xf0) == 0xe0)
+
 /* Test whether we have an ipv4 interface and an ipv6 interface.  Return 0 if
  * the test seemed successful. */
 static int
@@ -522,8 +563,9 @@ evutil_check_interfaces(int force_recheck)
            getsockname(fd, (struct sockaddr*)&sin_out, &sin_out_len) == 0) {
                /* We might have an IPv4 interface. */
                ev_uint32_t addr = ntohl(sin_out.sin_addr.s_addr);
-               if (addr == 0 || (addr&0xff000000) == 127 ||
-                   (addr & 0xff) == 255 || (addr & 0xf0) == 14) {
+               if (addr == 0 ||
+                   EVUTIL_V4ADDR_IS_LOCALHOST(addr) ||
+                   EVUTIL_V4ADDR_IS_CLASSD(addr)) {
                        evutil_inet_ntop(AF_INET, &sin_out.sin_addr,
                            buf, sizeof(buf));
                        /* This is a reserved, ipv4compat, ipv4map, loopback,
@@ -721,6 +763,10 @@ evutil_getaddrinfo_infer_protocols(struct evutil_addrinfo *hints)
        }
 }
 
+#if AF_UNSPEC != PF_UNSPEC
+#error "I cannot build on a system where AF_UNSPEC != PF_UNSPEC"
+#endif
+
 /** Implements the part of looking up hosts by name that's common to both
  * the blocking and nonblocking resolver:
  *   - Adjust 'hints' to have a reasonable socktype and protocol.
@@ -771,7 +817,7 @@ evutil_getaddrinfo_common(const char *nodename, const char *servname,
                        memset(&sin6, 0, sizeof(sin6));
                        sin6.sin6_family = AF_INET6;
                        sin6.sin6_port = htons(port);
-                       if (hints->ai_flags & AI_PASSIVE) {
+                       if (hints->ai_flags & EVUTIL_AI_PASSIVE) {
                                /* Bind to :: */
                        } else {
                                /* connect to ::1 */
@@ -788,7 +834,7 @@ evutil_getaddrinfo_common(const char *nodename, const char *servname,
                        memset(&sin, 0, sizeof(sin));
                        sin.sin_family = AF_INET;
                        sin.sin_port = htons(port);
-                       if (hints->ai_flags & AI_PASSIVE) {
+                       if (hints->ai_flags & EVUTIL_AI_PASSIVE) {
                                /* Bind to 0.0.0.0 */
                        } else {
                                /* connect to 127.0.0.1 */
@@ -958,8 +1004,13 @@ addrinfo_from_hostent(const struct hostent *ent,
                res = evutil_addrinfo_append(res, ai);
        }
 
-       if (res && ((hints->ai_flags & EVUTIL_AI_CANONNAME) && ent->h_name))
+       if (res && ((hints->ai_flags & EVUTIL_AI_CANONNAME) && ent->h_name)) {
                res->ai_canonname = mm_strdup(ent->h_name);
+               if (res->ai_canonname == NULL) {
+                       evutil_freeaddrinfo(res);
+                       return NULL;
+               }
+       }
 
        return res;
 }
@@ -1083,7 +1134,7 @@ apply_numeric_port_hack(int port, struct evutil_addrinfo **ai)
        }
 }
 
-static void
+static int
 apply_socktype_protocol_hack(struct evutil_addrinfo *ai)
 {
        struct evutil_addrinfo *ai_new;
@@ -1092,6 +1143,8 @@ apply_socktype_protocol_hack(struct evutil_addrinfo *ai)
                if (ai->ai_socktype || ai->ai_protocol)
                        continue;
                ai_new = mm_malloc(sizeof(*ai_new));
+               if (!ai_new)
+                       return -1;
                memcpy(ai_new, ai, sizeof(*ai_new));
                ai->ai_socktype = SOCK_STREAM;
                ai->ai_protocol = IPPROTO_TCP;
@@ -1101,6 +1154,7 @@ apply_socktype_protocol_hack(struct evutil_addrinfo *ai)
                ai_new->ai_next = ai->ai_next;
                ai->ai_next = ai_new;
        }
+       return 0;
 }
 #endif
 
@@ -1191,7 +1245,11 @@ evutil_getaddrinfo(const char *nodename, const char *servname,
                apply_numeric_port_hack(portnum, res);
 
        if (need_socktype_protocol_hack()) {
-               apply_socktype_protocol_hack(*res);
+               if (apply_socktype_protocol_hack(*res) < 0) {
+                       evutil_freeaddrinfo(*res);
+                       *res = NULL;
+                       return EVUTIL_EAI_MEMORY;
+               }
        }
        return err;
 #else
index f8de3b37f808e32cf85fd118cb1e40f410e035ca..b97485f65e00ebd75a76a41bc6652be8405cde1a 100644 (file)
@@ -56,6 +56,9 @@
 #ifdef _EVENT_HAVE_NETINET_IN_H
 #include <netinet/in.h>
 #endif
+#ifdef _EVENT_HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
 #ifdef _EVENT_HAVE_NETDB_H
 #include <netdb.h>
 #endif
 #include "util-internal.h"
 #include "http-internal.h"
 #include "mm-internal.h"
+#include "bufferevent-internal.h"
 
 #ifndef _EVENT_HAVE_GETNAMEINFO
 #define NI_MAXSERV 32
@@ -215,29 +219,30 @@ strsep(char **s, const char *del)
 }
 #endif
 
-static const char *
-html_replace(char ch, char *buf)
+static size_t
+html_replace(const char ch, const char **escaped)
 {
        switch (ch) {
        case '<':
-               return "&lt;";
+               *escaped = "&lt;";
+               return 4;
        case '>':
-               return "&gt;";
+               *escaped = "&gt;";
+               return 4;
        case '"':
-               return "&quot;";
+               *escaped = "&quot;";
+               return 6;
        case '\'':
-               return "&#039;";
+               *escaped = "&#039;";
+               return 6;
        case '&':
-               return "&amp;";
+               *escaped = "&amp;";
+               return 5;
        default:
                break;
        }
 
-       /* Echo the character back */
-       buf[0] = ch;
-       buf[1] = '\0';
-
-       return buf;
+       return 1;
 }
 
 /*
@@ -251,21 +256,34 @@ char *
 evhttp_htmlescape(const char *html)
 {
        size_t i;
-       size_t new_size = 0, old_size = strlen(html);
+       size_t new_size = 0, old_size = 0;
        char *escaped_html, *p;
-       char scratch_space[2];
 
-       for (i = 0; i < old_size; ++i)
-               new_size += strlen(html_replace(html[i], scratch_space));
+       if (html == NULL)
+               return (NULL);
+
+       old_size = strlen(html);
+       for (i = 0; i < old_size; ++i) {
+               const char *replaced = NULL;
+               const size_t replace_size = html_replace(html[i], &replaced);
+               if (replace_size > EV_SIZE_MAX - new_size) {
+                       event_warn("%s: html_replace overflow", __func__);
+                       return (NULL);
+               }
+               new_size += replace_size;
+       }
 
+       if (new_size == EV_SIZE_MAX)
+               return (NULL);
        p = escaped_html = mm_malloc(new_size + 1);
        if (escaped_html == NULL) {
-               event_warn("%s: malloc(%ld)", __func__, (long)(new_size + 1));
+               event_warn("%s: malloc(%lu)", __func__,
+                          (unsigned long)(new_size + 1));
                return (NULL);
        }
        for (i = 0; i < old_size; ++i) {
-               const char *replaced = html_replace(html[i], scratch_space);
-               size_t len = strlen(replaced);
+               const char *replaced = &html[i];
+               const size_t len = html_replace(html[i], &replaced);
                memcpy(p, replaced, len);
                p += len;
        }
@@ -822,9 +840,23 @@ evhttp_connection_done(struct evhttp_connection *evcon)
 static enum message_read_status
 evhttp_handle_chunked_read(struct evhttp_request *req, struct evbuffer *buf)
 {
-       ev_ssize_t len;
+       if (req == NULL || buf == NULL) {
+           return DATA_CORRUPTED;
+       }
+
+       while (1) {
+               size_t buflen;
+
+               if ((buflen = evbuffer_get_length(buf)) == 0) {
+                       break;
+               }
+
+               /* evbuffer_get_length returns size_t, but len variable is ssize_t,
+                * check for overflow conditions */
+               if (buflen > EV_SSIZE_MAX) {
+                       return DATA_CORRUPTED;
+               }
 
-       while ((len = evbuffer_get_length(buf)) > 0) {
                if (req->ntoread < 0) {
                        /* Read chunk size */
                        ev_int64_t ntoread;
@@ -847,11 +879,18 @@ evhttp_handle_chunked_read(struct evhttp_request *req, struct evbuffer *buf)
                                /* could not get chunk size */
                                return (DATA_CORRUPTED);
                        }
+
+                       /* ntoread is signed int64, body_size is unsigned size_t, check for under/overflow conditions */
+                       if ((ev_uint64_t)ntoread > EV_SIZE_MAX - req->body_size) {
+                           return DATA_CORRUPTED;
+                       }
+
                        if (req->body_size + (size_t)ntoread > req->evcon->max_body_size) {
                                /* failed body length test */
                                event_debug(("Request body is too long"));
                                return (DATA_TOO_LONG);
                        }
+
                        req->body_size += (size_t)ntoread;
                        req->ntoread = ntoread;
                        if (req->ntoread == 0) {
@@ -861,12 +900,17 @@ evhttp_handle_chunked_read(struct evhttp_request *req, struct evbuffer *buf)
                        continue;
                }
 
+               /* req->ntoread is signed int64, len is ssize_t, based on arch,
+                * ssize_t could only be 32b, check for these conditions */
+               if (req->ntoread > EV_SSIZE_MAX) {
+                       return DATA_CORRUPTED;
+               }
+
                /* don't have enough to complete a chunk; wait for more */
-               if (len < req->ntoread)
+               if (req->ntoread > 0 && buflen < (ev_uint64_t)req->ntoread)
                        return (MORE_DATA_EXPECTED);
 
                /* Completed chunk */
-               /* XXXX fixme: what if req->ntoread is > SIZE_T_MAX? */
                evbuffer_remove_buffer(buf, req->input_buffer, (size_t)req->ntoread);
                req->ntoread = -1;
                if (req->chunk_cb != NULL) {
@@ -934,13 +978,19 @@ evhttp_read_body(struct evhttp_connection *evcon, struct evhttp_request *req)
                }
        } else if (req->ntoread < 0) {
                /* Read until connection close. */
+               if ((size_t)(req->body_size + evbuffer_get_length(buf)) < req->body_size) {
+                       evhttp_connection_fail(evcon, EVCON_HTTP_INVALID_HEADER);
+                       return;
+               }
+
                req->body_size += evbuffer_get_length(buf);
                evbuffer_add_buffer(req->input_buffer, buf);
-       } else if (req->chunk_cb != NULL ||
-           evbuffer_get_length(buf) >= (size_t)req->ntoread) {
+       } else if (req->chunk_cb != NULL || evbuffer_get_length(buf) >= (size_t)req->ntoread) {
+               /* XXX: the above get_length comparison has to be fixed for overflow conditions! */
                /* We've postponed moving the data until now, but we're
                 * about to use it. */
                size_t n = evbuffer_get_length(buf);
+
                if (n > (size_t) req->ntoread)
                        n = (size_t) req->ntoread;
                req->ntoread -= n;
@@ -948,7 +998,10 @@ evhttp_read_body(struct evhttp_connection *evcon, struct evhttp_request *req)
                evbuffer_remove_buffer(buf, req->input_buffer, n);
        }
 
-       if (req->body_size > req->evcon->max_body_size) {
+       if (req->body_size > req->evcon->max_body_size ||
+           (!req->chunked && req->ntoread >= 0 &&
+               (size_t)req->ntoread > req->evcon->max_body_size)) {
+               /* XXX: The above casted comparison must checked for overflow */
                /* failed body length test */
                event_debug(("Request body is too long"));
                evhttp_connection_fail(evcon,
@@ -1015,9 +1068,24 @@ evhttp_read_cb(struct bufferevent *bufev, void *arg)
        case EVCON_READING_TRAILER:
                evhttp_read_trailer(evcon, req);
                break;
+       case EVCON_IDLE:
+               {
+#ifdef USE_DEBUG
+                       struct evbuffer *input;
+                       size_t total_len;
+
+                       input = bufferevent_get_input(evcon->bufev);
+                       total_len = evbuffer_get_length(input);
+                       event_debug(("%s: read %d bytes in EVCON_IDLE state,"
+                                    " resetting connection",
+                                       __func__, (int)total_len));
+#endif
+
+                       evhttp_connection_reset(evcon);
+               }
+               break;
        case EVCON_DISCONNECTED:
        case EVCON_CONNECTING:
-       case EVCON_IDLE:
        case EVCON_WRITING:
        default:
                event_errx(1, "%s: illegal connection state %d",
@@ -1110,7 +1178,7 @@ evhttp_connection_set_local_address(struct evhttp_connection *evcon,
        if (evcon->bind_address)
                mm_free(evcon->bind_address);
        if ((evcon->bind_address = mm_strdup(address)) == NULL)
-               event_err(1, "%s: strdup", __func__);
+               event_warn("%s: strdup", __func__);
 }
 
 void
@@ -1151,7 +1219,18 @@ evhttp_connection_reset(struct evhttp_connection *evcon)
 {
        struct evbuffer *tmp;
 
-       bufferevent_disable(evcon->bufev, EV_READ|EV_WRITE);
+       /* XXXX This is not actually an optimal fix.  Instead we ought to have
+          an API for "stop connecting", or use bufferevent_setfd to turn off
+          connecting.  But for Libevent 2.0, this seems like a minimal change
+          least likely to disrupt the rest of the bufferevent and http code.
+
+          Why is this here?  If the fd is set in the bufferevent, and the
+          bufferevent is connecting, then you can't actually stop the
+          bufferevent from trying to connect with bufferevent_disable().  The
+          connect will never trigger, since we close the fd, but the timeout
+          might.  That caused an assertion failure in evhttp_connection_fail.
+       */
+       bufferevent_disable_hard(evcon->bufev, EV_READ|EV_WRITE);
 
        if (evcon->fd != -1) {
                /* inform interested parties about connection close */
@@ -1200,6 +1279,8 @@ evhttp_connection_retry(evutil_socket_t fd, short what, void *arg)
 static void
 evhttp_connection_cb_cleanup(struct evhttp_connection *evcon)
 {
+       struct evcon_requestq requests;
+
        if (evcon->retry_max < 0 || evcon->retry_cnt < evcon->retry_max) {
                evtimer_assign(&evcon->retry_ev, evcon->base, evhttp_connection_retry, evcon);
                /* XXXX handle failure from evhttp_add_event */
@@ -1211,10 +1292,23 @@ evhttp_connection_cb_cleanup(struct evhttp_connection *evcon)
        }
        evhttp_connection_reset(evcon);
 
-       /* for now, we just signal all requests by executing their callbacks */
+       /*
+        * User callback can do evhttp_make_request() on the same
+        * evcon so new request will be added to evcon->requests.  To
+        * avoid freeing it prematurely we iterate over the copy of
+        * the queue.
+        */
+       TAILQ_INIT(&requests);
        while (TAILQ_FIRST(&evcon->requests) != NULL) {
                struct evhttp_request *request = TAILQ_FIRST(&evcon->requests);
                TAILQ_REMOVE(&evcon->requests, request, next);
+               TAILQ_INSERT_TAIL(&requests, request, next);
+       }
+
+       /* for now, we just signal all requests by executing their callbacks */
+       while (TAILQ_FIRST(&requests) != NULL) {
+               struct evhttp_request *request = TAILQ_FIRST(&requests);
+               TAILQ_REMOVE(&requests, request, next);
                request->evcon = NULL;
 
                /* we might want to set an error here */
@@ -1472,7 +1566,8 @@ evhttp_parse_request_line(struct evhttp_request *req, char *line)
                return (-1);
        }
 
-       if ((req->uri_elems = evhttp_uri_parse(req->uri)) == NULL) {
+       if ((req->uri_elems = evhttp_uri_parse_with_flags(req->uri,
+                   EVHTTP_URI_NONCONFORMANT)) == NULL) {
                return -1;
        }
 
@@ -1731,7 +1826,8 @@ evhttp_parse_headers(struct evhttp_request *req, struct evbuffer* buffer)
        }
 
        if (status == MORE_DATA_EXPECTED) {
-               if (req->headers_size + evbuffer_get_length(buffer) > req->evcon->max_headers_size)
+               if (req->evcon != NULL &&
+               req->headers_size + evbuffer_get_length(buffer) > req->evcon->max_headers_size)
                        return (DATA_TOO_LONG);
        }
 
@@ -1846,11 +1942,12 @@ evhttp_get_body(struct evhttp_connection *evcon, struct evhttp_request *req)
                                   no, we should respond with an error. For
                                   now, just optimistically tell the client to
                                   send their message body. */
-                               if (req->ntoread > 0 &&
-                                   (size_t)req->ntoread > req->evcon->max_body_size) {
-                                       evhttp_send_error(req, HTTP_ENTITYTOOLARGE,
-                                                         NULL);
-                                       return;
+                               if (req->ntoread > 0) {
+                                       /* ntoread is ev_int64_t, max_body_size is ev_uint64_t */ 
+                                       if ((req->evcon->max_body_size <= EV_INT64_MAX) && (ev_uint64_t)req->ntoread > req->evcon->max_body_size) {
+                                               evhttp_send_error(req, HTTP_ENTITYTOOLARGE, NULL);
+                                               return;
+                                       }
                                }
                                if (!evbuffer_get_length(bufferevent_get_input(evcon->bufev)))
                                        evhttp_send_continue(evcon, req);
@@ -2145,11 +2242,20 @@ evhttp_make_request(struct evhttp_connection *evcon,
        req->evcon = evcon;
        EVUTIL_ASSERT(!(req->flags & EVHTTP_REQ_OWN_CONNECTION));
 
-       TAILQ_INSERT_TAIL(&evcon->requests, req, next);
+       TAILQ_INSERT_TAIL(&evcon->requests, req, next);
 
        /* If the connection object is not connected; make it so */
-       if (!evhttp_connected(evcon))
-               return (evhttp_connection_connect(evcon));
+       if (!evhttp_connected(evcon)) {
+               int res = evhttp_connection_connect(evcon);
+              /* evhttp_connection_fail(), which is called through
+               * evhttp_connection_connect(), assumes that req lies in
+               * evcon->requests.  Thus, enqueue the request in advance and r
+               * it in the error case. */
+              if (res != 0)
+                      TAILQ_REMOVE(&evcon->requests, req, next);
+
+               return res;
+       }
 
        /*
         * If it's connected already and we are the first in the queue,
@@ -2491,6 +2597,10 @@ evhttp_response_code(struct evhttp_request *req, int code, const char *reason)
        if (reason == NULL)
                reason = evhttp_response_phrase_internal(code);
        req->response_code_line = mm_strdup(reason);
+       if (req->response_code_line == NULL) {
+               event_warn("%s: strdup", __func__);
+               /* XXX what else can we do? */
+       }
 }
 
 void
@@ -3280,6 +3390,11 @@ evhttp_set_cb(struct evhttp *http, const char *uri,
        }
 
        http_cb->what = mm_strdup(uri);
+       if (http_cb->what == NULL) {
+               event_warn("%s: strdup", __func__);
+               mm_free(http_cb);
+               return (-3);
+       }
        http_cb->cb = cb;
        http_cb->cbarg = cbarg;
 
@@ -3768,6 +3883,7 @@ bind_socket(const char *address, ev_uint16_t port, int reuse)
 }
 
 struct evhttp_uri {
+       unsigned flags;
        char *scheme; /* scheme; e.g http, ftp etc */
        char *userinfo; /* userinfo (typically username:pass), or NULL */
        char *host; /* hostname, IP address, or NULL */
@@ -3786,7 +3902,13 @@ evhttp_uri_new(void)
        return uri;
 }
 
-/* Return true of the string starting at s and ending immediately before eos
+void
+evhttp_uri_set_flags(struct evhttp_uri *uri, unsigned flags)
+{
+       uri->flags = flags;
+}
+
+/* Return true if the string starting at s and ending immediately before eos
  * is a valid URI scheme according to RFC3986
  */
 static int
@@ -3911,6 +4033,10 @@ parse_authority(struct evhttp_uri *uri, char *s, char *eos)
        EVUTIL_ASSERT(eos);
        if (eos == s) {
                uri->host = mm_strdup("");
+               if (uri->host == NULL) {
+                       event_warn("%s: strdup", __func__);
+                       return -1;
+               }
                return 0;
        }
 
@@ -3922,6 +4048,10 @@ parse_authority(struct evhttp_uri *uri, char *s, char *eos)
                        return -1;
                *cp++ = '\0';
                uri->userinfo = mm_strdup(s);
+               if (uri->userinfo == NULL) {
+                       event_warn("%s: strdup", __func__);
+                       return -1;
+               }
        } else {
                cp = s;
        }
@@ -3949,6 +4079,10 @@ parse_authority(struct evhttp_uri *uri, char *s, char *eos)
                        return -1;
        }
        uri->host = mm_malloc(eos-cp+1);
+       if (uri->host == NULL) {
+               event_warn("%s: malloc", __func__);
+               return -1;
+       }
        memcpy(uri->host, cp, eos-cp);
        uri->host[eos-cp] = '\0';
        return 0;
@@ -3966,13 +4100,41 @@ end_of_authority(char *cp)
        return cp;
 }
 
+enum uri_part {
+       PART_PATH,
+       PART_QUERY,
+       PART_FRAGMENT
+};
+
 /* Return the character after the longest prefix of 'cp' that matches...
  *   *pchar / "/" if allow_qchars is false, or
- *   *(pchar / "/" / "?") if allow_chars is true.
+ *   *(pchar / "/" / "?") if allow_qchars is true.
  */
 static char *
-end_of_path(char *cp, int allow_qchars)
+end_of_path(char *cp, enum uri_part part, unsigned flags)
 {
+       if (flags & EVHTTP_URI_NONCONFORMANT) {
+               /* If NONCONFORMANT:
+                *   Path is everything up to a # or ? or nul.
+                *   Query is everything up a # or nul
+                *   Fragment is everything up to a nul.
+                */
+               switch (part) {
+               case PART_PATH:
+                       while (*cp && *cp != '#' && *cp != '?')
+                               ++cp;
+                       break;
+               case PART_QUERY:
+                       while (*cp && *cp != '#')
+                               ++cp;
+                       break;
+               case PART_FRAGMENT:
+                       cp += strlen(cp);
+                       break;
+               };
+               return cp;
+       }
+
        while (*cp) {
                if (CHAR_IS_UNRESERVED(*cp) ||
                    strchr(SUBDELIMS, *cp) ||
@@ -3981,7 +4143,7 @@ end_of_path(char *cp, int allow_qchars)
                else if (*cp == '%' && EVUTIL_ISXDIGIT(cp[1]) &&
                    EVUTIL_ISXDIGIT(cp[2]))
                        cp += 3;
-               else if (*cp == '?' && allow_qchars)
+               else if (*cp == '?' && part != PART_PATH)
                        ++cp;
                else
                        return cp;
@@ -4004,6 +4166,12 @@ path_matches_noscheme(const char *cp)
 
 struct evhttp_uri *
 evhttp_uri_parse(const char *source_uri)
+{
+       return evhttp_uri_parse_with_flags(source_uri, 0);
+}
+
+struct evhttp_uri *
+evhttp_uri_parse_with_flags(const char *source_uri, unsigned flags)
 {
        char *readbuf = NULL, *readp = NULL, *token = NULL, *query = NULL;
        char *path = NULL, *fragment = NULL;
@@ -4011,14 +4179,15 @@ evhttp_uri_parse(const char *source_uri)
 
        struct evhttp_uri *uri = mm_calloc(1, sizeof(struct evhttp_uri));
        if (uri == NULL) {
-               event_err(1, "%s: calloc", __func__);
+               event_warn("%s: calloc", __func__);
                goto err;
        }
        uri->port = -1;
+       uri->flags = flags;
 
        readbuf = mm_strdup(source_uri);
        if (readbuf == NULL) {
-               event_err(1, "%s: strdup", __func__);
+               event_warn("%s: strdup", __func__);
                goto err;
        }
 
@@ -4031,7 +4200,6 @@ evhttp_uri_parse(const char *source_uri)
              URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
 
              relative-ref  = relative-part [ "?" query ] [ "#" fragment ]
-
         */
 
        /* 1. scheme: */
@@ -4039,7 +4207,10 @@ evhttp_uri_parse(const char *source_uri)
        if (token && scheme_ok(readp,token)) {
                *token = '\0';
                uri->scheme = mm_strdup(readp);
-
+               if (uri->scheme == NULL) {
+                       event_warn("%s: strdup", __func__);
+                       goto err;
+               }
                readp = token+1; /* eat : */
        }
 
@@ -4058,21 +4229,21 @@ evhttp_uri_parse(const char *source_uri)
        /* 3. Query: path-abempty, path-absolute, path-rootless, or path-empty
         */
        path = readp;
-       readp = end_of_path(path, 0);
+       readp = end_of_path(path, PART_PATH, flags);
 
        /* Query */
        if (*readp == '?') {
                *readp = '\0';
                ++readp;
                query = readp;
-               readp = end_of_path(readp, 1);
+               readp = end_of_path(readp, PART_QUERY, flags);
        }
        /* fragment */
        if (*readp == '#') {
                *readp = '\0';
                ++readp;
                fragment = readp;
-               readp = end_of_path(readp, 1);
+               readp = end_of_path(readp, PART_FRAGMENT, flags);
        }
        if (*readp != '\0') {
                goto err;
@@ -4096,11 +4267,25 @@ evhttp_uri_parse(const char *source_uri)
 
        EVUTIL_ASSERT(path);
        uri->path = mm_strdup(path);
+       if (uri->path == NULL) {
+               event_warn("%s: strdup", __func__);
+               goto err;
+       }
 
-       if (query)
+       if (query) {
                uri->query = mm_strdup(query);
-       if (fragment)
+               if (uri->query == NULL) {
+                       event_warn("%s: strdup", __func__);
+                       goto err;
+               }
+       }
+       if (fragment) {
                uri->fragment = mm_strdup(fragment);
+               if (uri->fragment == NULL) {
+                       event_warn("%s: strdup", __func__);
+                       goto err;
+               }
+       }
 
        mm_free(readbuf);
 
@@ -4286,12 +4471,13 @@ evhttp_uri_set_port(struct evhttp_uri *uri, int port)
        uri->port = port;
        return 0;
 }
-#define end_of_cpath(cp,aq) ((const char*)(end_of_path(((char*)(cp)), (aq))))
+#define end_of_cpath(cp,p,f) \
+       ((const char*)(end_of_path(((char*)(cp)), (p), (f))))
 
 int
 evhttp_uri_set_path(struct evhttp_uri *uri, const char *path)
 {
-       if (path && end_of_cpath(path, 0) != path+strlen(path))
+       if (path && end_of_cpath(path, PART_PATH, uri->flags) != path+strlen(path))
                return -1;
 
        _URI_SET_STR(path);
@@ -4300,7 +4486,7 @@ evhttp_uri_set_path(struct evhttp_uri *uri, const char *path)
 int
 evhttp_uri_set_query(struct evhttp_uri *uri, const char *query)
 {
-       if (query && end_of_cpath(query, 1) != query+strlen(query))
+       if (query && end_of_cpath(query, PART_QUERY, uri->flags) != query+strlen(query))
                return -1;
        _URI_SET_STR(query);
        return 0;
@@ -4308,7 +4494,7 @@ evhttp_uri_set_query(struct evhttp_uri *uri, const char *query)
 int
 evhttp_uri_set_fragment(struct evhttp_uri *uri, const char *fragment)
 {
-       if (fragment && end_of_cpath(fragment, 1) != fragment+strlen(fragment))
+       if (fragment && end_of_cpath(fragment, PART_FRAGMENT, uri->flags) != fragment+strlen(fragment))
                return -1;
        _URI_SET_STR(fragment);
        return 0;
index b109ff797a30840c7e6bc2203aa64cf6b12c73d5..fbf459ebb7c707746d4c75376b04c7f14d752382 100644 (file)
@@ -28,7 +28,14 @@ EVENT2_EXPORT = \
 
 EXTRA_SRC = $(EVENT2_EXPORT)
 
-nobase_include_HEADERS = $(EVENT2_EXPORT)
+## Without the nobase_ prefixing, Automake would strip "event2/" from
+## the source header filename to derive the installed header filename.
+## With nobase_ the installed path is $(includedir)/event2/ev*.h.
 
+if INSTALL_LIBEVENT
+nobase_include_HEADERS =       $(EVENT2_EXPORT)
 nobase_nodist_include_HEADERS = ./event2/event-config.h
-
+else
+noinst_HEADERS =               $(EVENT2_EXPORT)
+nodist_noinst_HEADERS =                ./event2/event-config.h
+endif
index 4b05b32538cfb589a1d60b3a9c4f9eb25c263b04..3850318f47ffd83d2d5867603dfa9294cb88ad82 100644 (file)
@@ -107,6 +107,10 @@ int event_reinit(struct event_base *base);
 /**
   Threadsafe event dispatching loop.
 
+  This loop will run the event base until either there are no more added
+  events, or until something calls event_base_loopbreak() or
+  evenet_base_loopexit().
+
   @param eb the event_base structure returned by event_init()
   @see event_init(), event_dispatch()
  */
@@ -322,14 +326,14 @@ void event_set_fatal_callback(event_fatal_cb cb);
 int event_base_set(struct event_base *, struct event *);
 
 /**
- event_loop() flags
+ event_base_loop() flags
  */
 /*@{*/
 /** Block until we have an active event, then exit once all active events
  * have had their callbacks run. */
 #define EVLOOP_ONCE    0x01
 /** Do not block: see which events are ready now, run the callbacks
- * highest-priority ones, then exit. */
+ * of the highest-priority ones, then exit. */
 #define EVLOOP_NONBLOCK        0x02
 /*@}*/
 
@@ -338,6 +342,11 @@ int event_base_set(struct event_base *, struct event *);
 
   This is a more flexible version of event_base_dispatch().
 
+  By default, this loop will run the event base until either there are no more
+  added events, or until something calls event_base_loopbreak() or
+  evenet_base_loopexit().  You can override this behavior with the 'flags'
+  argument.
+
   @param eb the event_base structure returned by event_init()
   @param flags any combination of EVLOOP_ONCE | EVLOOP_NONBLOCK
   @return 0 if successful, -1 if an error occurred, or 1 if no events were
@@ -748,8 +757,9 @@ const struct timeval *event_base_init_common_timeout(struct event_base *base,
 
  Note that all memory returned from Libevent will be allocated by the
  replacement functions rather than by malloc() and realloc().  Thus, if you
- have replaced those functions, it may not be appropriate to free() memory
- that you get from Libevent.
+ have replaced those functions, it will not be appropriate to free() memory
+ that you get from Libevent.  Instead, you must use the free_fn replacement
+ that you provided.
 
  @param malloc_fn A replacement for malloc.
  @param realloc_fn A replacement for realloc
index e05c3bffaa6fca1d2c4b51b537e754459f95de4f..322240d9317073f202da1f038782b77e7f0c73ce 100644 (file)
@@ -154,7 +154,10 @@ struct evconnlistener *evhttp_bound_socket_get_listener(struct evhttp_bound_sock
  * This may be useful when a socket has been sent via file descriptor passing
  * and is no longer needed by the current process.
  *
- * This function does not close the socket.
+ * If you created this bound socket with evhttp_bind_socket_with_handle or
+ * evhttp_accept_socket_with_handle, this function closes the fd you provided.
+ * If you created this bound socket with evhttp_bind_listener, this function
+ * frees the listener you provided.
  *
  * \a bound_socket is an invalid pointer after this call returns.
  *
@@ -707,6 +710,12 @@ char *evhttp_htmlescape(const char *html);
  */
 struct evhttp_uri *evhttp_uri_new(void);
 
+/**
+ * Changes the flags set on a given URI.  See EVHTTP_URI_* for
+ * a list of flags.
+ **/
+void evhttp_uri_set_flags(struct evhttp_uri *uri, unsigned flags);
+
 /** Return the scheme of an evhttp_uri, or NULL if there is no scheme has
  * been set and the evhttp_uri contains a Relative-Ref. */
 const char *evhttp_uri_get_scheme(const struct evhttp_uri *uri);
@@ -792,9 +801,29 @@ int evhttp_uri_set_fragment(struct evhttp_uri *uri, const char *fragment);
  * accepts all of them as valid.
  *
  * @param source_uri the request URI
+ * @param flags Zero or more EVHTTP_URI_* flags to affect the behavior
+ *              of the parser.
  * @return uri container to hold parsed data, or NULL if there is error
  * @see evhttp_uri_free()
  */
+struct evhttp_uri *evhttp_uri_parse_with_flags(const char *source_uri,
+    unsigned flags);
+
+/** Tolerate URIs that do not conform to RFC3986.
+ *
+ * Unfortunately, some HTTP clients generate URIs that, according to RFC3986,
+ * are not conformant URIs.  If you need to support these URIs, you can
+ * do so by passing this flag to evhttp_uri_parse_with_flags.
+ *
+ * Currently, these changes are:
+ * <ul>
+ *   <li> Nonconformant URIs are allowed to contain otherwise unreasonable
+ *        characters in their path, query, and fragment components.
+ * </ul>
+ */
+#define EVHTTP_URI_NONCONFORMANT 0x01
+
+/** Alias for evhttp_uri_parse_with_flags(source_uri, 0) */
 struct evhttp_uri *evhttp_uri_parse(const char *source_uri);
 
 /**
@@ -817,7 +846,7 @@ void evhttp_uri_free(struct evhttp_uri *uri);
  * @param buf destination buffer
  * @param limit destination buffer size
  * @return an joined uri as string or NULL on error
  @see evhttp_uri_parse()
* @see evhttp_uri_parse()
  */
 char *evhttp_uri_join(struct evhttp_uri *uri, char *buf, size_t limit);
 
index 7d6fb7361b3f80d18bed814f89afa28de869ffc9..1f272a0d0ce4aabdd8b959fa4ac389e8a1e51e54 100644 (file)
@@ -59,12 +59,21 @@ typedef int sa_family_t;
 
 #ifndef _EVENT_HAVE_STRUCT_SOCKADDR_IN6
 struct sockaddr_in6 {
+       /* This will fail if we find a struct sockaddr that doesn't have
+        * sa_family as the first element. */
        sa_family_t sin6_family;
        ev_uint16_t sin6_port;
        struct in6_addr sin6_addr;
 };
 #endif
 
+#ifndef AF_INET6
+#define AF_INET6 3333
+#endif
+#ifndef PF_INET6
+#define PF_INET6 AF_INET6
+#endif
+
 #ifdef __cplusplus
 }
 #endif
index 920129826f46a6dbe009c3c6d095f8e564e69bee..8b4863465ad2e10be4843944780702053bc2f0d5 100644 (file)
@@ -228,6 +228,23 @@ kq_build_changes_list(const struct event_changelist *changelist,
        return n_changes;
 }
 
+static int
+kq_grow_events(struct kqop *kqop, size_t new_size)
+{
+       struct kevent *newresult;
+
+       newresult = mm_realloc(kqop->events,
+           new_size * sizeof(struct kevent));
+
+       if (newresult) {
+               kqop->events = newresult;
+               kqop->events_size = new_size;
+               return 0;
+       } else {
+               return -1;
+       }
+}
+
 static int
 kq_dispatch(struct event_base *base, struct timeval *tv)
 {
@@ -255,6 +272,25 @@ kq_dispatch(struct event_base *base, struct timeval *tv)
        changes = kqop->changes;
        kqop->changes = NULL;
 
+       /* Make sure that 'events' is at least as long as the list of changes:
+        * otherwise errors in the changes can get reported as a -1 return
+        * value from kevent() rather than as EV_ERROR events in the events
+        * array.
+        *
+        * (We could instead handle -1 return values from kevent() by
+        * retrying with a smaller changes array or a larger events array,
+        * but this approach seems less risky for now.)
+        */
+       if (kqop->events_size < n_changes) {
+               int new_size = kqop->events_size;
+               do {
+                       new_size *= 2;
+               } while (new_size < n_changes);
+
+               kq_grow_events(kqop, new_size);
+               events = kqop->events;
+       }
+
        EVBASE_RELEASE_LOCK(base, th_base_lock);
 
        res = kevent(kqop->kq, changes, n_changes,
@@ -319,17 +355,9 @@ kq_dispatch(struct event_base *base, struct timeval *tv)
        }
 
        if (res == kqop->events_size) {
-               struct kevent *newresult;
-               int size = kqop->events_size;
                /* We used all the events space that we have. Maybe we should
                   make it bigger. */
-               size *= 2;
-               newresult = mm_realloc(kqop->events,
-                   size * sizeof(struct kevent));
-               if (newresult) {
-                       kqop->events = newresult;
-                       kqop->events_size = size;
-               }
+               kq_grow_events(kqop, kqop->events_size * 2);
        }
 
        return (0);
index 0fe7cb6013f5e1ad309aa7c5f74b0d106eac45e8..9624cf2497650afc5342ab685c74e89e74ead72f 100644 (file)
@@ -11,6 +11,6 @@ Version: @VERSION@
 Requires: libevent
 Conflicts:
 Libs: -L${libdir} -levent_openssl
-Libs.private: @LIBS@ -lcrypto -lssl
+Libs.private: @LIBS@ -lssl -lcrypto
 Cflags: -I${includedir}
 
index d0911bdb8dad1b5bfbe3354354029a0510ce22ef..5db2cb733b313a7945aeb82ccfcdb2fdba63d3d4 100644 (file)
 #include "event2/event-config.h"
 
 #ifdef WIN32
+#ifndef _WIN32_WINNT
+/* Minimum required for InitializeCriticalSectionAndSpinCount */
+#define _WIN32_WINNT 0x0403
+#endif
 #include <winsock2.h>
 #include <ws2tcpip.h>
 #include <mswsock.h>
index 0071d26f2776fcc2231e3f3f83c71180ad52a7db..4ade6aab992ee3193e861fbf5b38dcccbe8e686f 100644 (file)
@@ -1,6 +1,6 @@
 AUTOMAKE_OPTIONS = foreign no-dependencies
 
-LDADD = ../libevent.la
+LDADD = $(LIBEVENT_GC_SECTIONS) ../libevent.la
 AM_CFLAGS = -I$(top_srcdir) -I$(top_srcdir)/compat -I$(top_srcdir)/include -I../include
 
 noinst_PROGRAMS = event-test time-test signal-test dns-example hello-world http-server
@@ -15,7 +15,7 @@ http_server_sources = http-server.c
 if OPENSSL
 noinst_PROGRAMS += le-proxy
 le_proxy_sources = le-proxy.c
-le_proxy_LDADD = $(LDADD) ../libevent_openssl.la -lcrypto -lssl
+le_proxy_LDADD = $(LDADD) ../libevent_openssl.la
 endif
 
 verify:
index 5531821576a746a9d56e5c0cdf2fd16c2f4a2ec1..f2c1e020a0072ae76cda95ed5a215adb77102fb6 100644 (file)
@@ -7,6 +7,9 @@
 
 #include <event2/event-config.h>
 
+/* Compatibility for possible missing IPv6 declarations */
+#include "../ipv6-internal.h"
+
 #include <sys/types.h>
 
 #ifdef WIN32
@@ -69,7 +72,6 @@ static void
 gai_callback(int err, struct evutil_addrinfo *ai, void *arg)
 {
        const char *name = arg;
-       struct evutil_addrinfo *ai_first = NULL;
        int i;
        if (err) {
                printf("%s: %s\n", name, evutil_gai_strerror(err));
@@ -92,8 +94,6 @@ gai_callback(int err, struct evutil_addrinfo *ai, void *arg)
                        printf("[%d] %s: %s\n",i,name,buf);
                }
        }
-       if (ai_first)
-               evutil_freeaddrinfo(ai_first);
 }
 
 static void
@@ -117,6 +117,8 @@ evdns_server_callback(struct evdns_server_request *req, void *data)
                        printf(" -- replying for %s (PTR)\n", req->questions[i]->name);
                        r = evdns_server_request_add_ptr_reply(req, NULL, req->questions[i]->name,
                                                                                        "foo.bar.example.com", 10);
+                       if (r<0)
+                               printf("ugh, no luck");
                } else {
                        printf(" -- skipping %s [%d %d]\n", req->questions[i]->name,
                                   req->questions[i]->type, req->questions[i]->dns_question_class);
index 90df85f7048f08343c16a8bb6c57166c27361301..d40af5296f4d28205b11218d0ef0bb27f287cac6 100644 (file)
@@ -13,6 +13,9 @@
 #include <signal.h>
 #ifndef WIN32
 #include <netinet/in.h>
+# ifdef _XOPEN_SOURCE_EXTENDED
+#  include <arpa/inet.h>
+# endif
 #include <sys/socket.h>
 #endif
 
index f9e84d1c9e79bdee245d2fd4670ed05d7a1730fe..75caa414e2bce4168ee3aa5f15470e52239c3293 100644 (file)
@@ -19,6 +19,9 @@
 #include <windows.h>
 #include <io.h>
 #include <fcntl.h>
+#ifndef S_ISDIR
+#define S_ISDIR(x) (((x) & S_IFMT) == S_IFDIR)
+#endif
 #else
 #include <sys/stat.h>
 #include <sys/socket.h>
 
 #ifdef _EVENT_HAVE_NETINET_IN_H
 #include <netinet/in.h>
+# ifdef _XOPEN_SOURCE_EXTENDED
+#  include <arpa/inet.h>
+# endif
 #endif
 
+/* Compatibility for possible missing IPv6 declarations */
+#include "../util-internal.h"
+
 #ifdef WIN32
 #define stat _stat
 #define fstat _fstat
@@ -138,7 +147,7 @@ dump_request_cb(struct evhttp_request *req, void *arg)
 static void
 send_document_cb(struct evhttp_request *req, void *arg)
 {
-       struct evbuffer *evb;
+       struct evbuffer *evb = NULL;
        const char *docroot = arg;
        const char *uri = evhttp_request_get_uri(req);
        struct evhttp_uri *decoded = NULL;
@@ -223,7 +232,6 @@ send_document_cb(struct evhttp_request *req, void *arg)
                if (!(d = opendir(whole_path)))
                        goto err;
 #endif
-               close(fd);
 
                evbuffer_add_printf(evb, "<html>\n <head>\n"
                    "  <title>%s</title>\n"
@@ -280,18 +288,20 @@ send_document_cb(struct evhttp_request *req, void *arg)
        }
 
        evhttp_send_reply(req, 200, "OK", evb);
-       evbuffer_free(evb);
-       return;
+       goto done;
 err:
        evhttp_send_error(req, 404, "Document was not found");
        if (fd>=0)
                close(fd);
+done:
        if (decoded)
                evhttp_uri_free(decoded);
        if (decoded_path)
                free(decoded_path);
        if (whole_path)
                free(whole_path);
+       if (evb)
+               evbuffer_free(evb);
 }
 
 static void
index 527462ca26ba167533cbaf48651e969c25f9bfad..892ddfaf222aa0541bdc77a02364559e523f1d4c 100644 (file)
@@ -90,6 +90,7 @@ const struct eventop selectops = {
 };
 
 static int select_resize(struct selectop *sop, int fdsz);
+static void select_free_selectop(struct selectop *sop);
 
 static void *
 select_init(struct event_base *base)
@@ -99,7 +100,10 @@ select_init(struct event_base *base)
        if (!(sop = mm_calloc(1, sizeof(struct selectop))))
                return (NULL);
 
-       select_resize(sop, howmany(32 + 1, NFDBITS)*sizeof(fd_mask));
+       if (select_resize(sop, howmany(32 + 1, NFDBITS)*sizeof(fd_mask))) {
+               select_free_selectop(sop);
+               return (NULL);
+       }
 
        evsig_init(base);
 
@@ -128,11 +132,14 @@ select_dispatch(struct event_base *base, struct timeval *tv)
                size_t sz = sop->event_fdsz;
                if (!(readset_out = mm_realloc(sop->event_readset_out, sz)))
                        return (-1);
+               sop->event_readset_out = readset_out;
                if (!(writeset_out = mm_realloc(sop->event_writeset_out, sz))) {
-                       mm_free(readset_out);
+                       /* We don't free readset_out here, since it was
+                        * already successfully reallocated. The next time
+                        * we call select_dispatch, the realloc will be a
+                        * no-op. */
                        return (-1);
                }
-               sop->event_readset_out = readset_out;
                sop->event_writeset_out = writeset_out;
                sop->resize_out_sets = 0;
        }
@@ -165,9 +172,9 @@ select_dispatch(struct event_base *base, struct timeval *tv)
        event_debug(("%s: select reports %d", __func__, res));
 
        check_selectop(sop);
-       i = random() % (nfds+1);
-       for (j = 0; j <= nfds; ++j) {
-               if (++i >= nfds+1)
+       i = random() % nfds;
+       for (j = 0; j < nfds; ++j) {
+               if (++i >= nfds)
                        i = 0;
                res = 0;
                if (FD_ISSET(i, sop->event_readset_out))
@@ -185,7 +192,6 @@ select_dispatch(struct event_base *base, struct timeval *tv)
        return (0);
 }
 
-
 static int
 select_resize(struct selectop *sop, int fdsz)
 {
@@ -198,8 +204,15 @@ select_resize(struct selectop *sop, int fdsz)
        if ((readset_in = mm_realloc(sop->event_readset_in, fdsz)) == NULL)
                goto error;
        sop->event_readset_in = readset_in;
-       if ((writeset_in = mm_realloc(sop->event_writeset_in, fdsz)) == NULL)
+       if ((writeset_in = mm_realloc(sop->event_writeset_in, fdsz)) == NULL) {
+               /* Note that this will leave event_readset_in expanded.
+                * That's okay; we wouldn't want to free it, since that would
+                * change the semantics of select_resize from "expand the
+                * readset_in and writeset_in, or return -1" to "expand the
+                * *set_in members, or trash them and return -1."
+                */
                goto error;
+       }
        sop->event_writeset_in = writeset_in;
        sop->resize_out_sets = 1;
 
@@ -292,11 +305,8 @@ select_del(struct event_base *base, int fd, short old, short events, void *p)
 }
 
 static void
-select_dealloc(struct event_base *base)
+select_free_selectop(struct selectop *sop)
 {
-       struct selectop *sop = base->evbase;
-
-       evsig_dealloc(base);
        if (sop->event_readset_in)
                mm_free(sop->event_readset_in);
        if (sop->event_writeset_in)
@@ -309,3 +319,11 @@ select_dealloc(struct event_base *base)
        memset(sop, 0, sizeof(struct selectop));
        mm_free(sop);
 }
+
+static void
+select_dealloc(struct event_base *base)
+{
+       evsig_dealloc(base);
+
+       select_free_selectop(base->evbase);
+}
index 97682fb467c8be968504ac266be1bd356f6f8bc1..b867501f016750c69cf09e6f261c6ce65768a70e 100644 (file)
@@ -1,17 +1,25 @@
 AUTOMAKE_OPTIONS = foreign
 
-AM_CFLAGS = -I$(top_srcdir) -I$(top_srcdir)/compat -I$(top_srcdir)/include -I../include -DTINYTEST_LOCAL
+AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/compat -I$(top_srcdir)/include -I../include -DTINYTEST_LOCAL
 
 EXTRA_DIST = regress.rpc regress.gen.h regress.gen.c test.sh
 
-noinst_PROGRAMS = test-init test-eof test-weof test-time regress \
+noinst_PROGRAMS = test-init test-eof test-weof test-time \
        bench bench_cascade bench_http bench_httpclient test-ratelim \
        test-changelist
+if BUILD_REGRESS
+noinst_PROGRAMS += regress
+endif
+EXTRA_PROGRAMS = regress
 noinst_HEADERS = tinytest.h tinytest_macros.h regress.h tinytest_local.h
 
 TESTS = $(top_srcdir)/test/test.sh
 
-BUILT_SOURCES = regress.gen.c regress.gen.h
+BUILT_SOURCES =
+if BUILD_REGRESS
+BUILT_SOURCES += regress.gen.c regress.gen.h
+endif
+
 test_init_SOURCES = test-init.c
 test_init_LDADD = ../libevent_core.la
 test_eof_SOURCES = test-eof.c
@@ -45,24 +53,23 @@ if BUILD_WIN32
 regress_SOURCES += regress_iocp.c
 endif
 
-regress_LDADD = ../libevent.la $(PTHREAD_LIBS) $(ZLIB_LIBS)
-regress_CFLAGS = -I$(top_srcdir) -I$(top_srcdir)/compat \
-       -I$(top_srcdir)/include -I../include $(PTHREAD_CFLAGS) $(ZLIB_CFLAGS)
+regress_LDADD = $(LIBEVENT_GC_SECTIONS) ../libevent.la $(PTHREAD_LIBS) $(ZLIB_LIBS)
+regress_CPPFLAGS = $(AM_CPPFLAGS) $(PTHREAD_CFLAGS) $(ZLIB_CFLAGS)
 regress_LDFLAGS = $(PTHREAD_CFLAGS)
 
 if OPENSSL
 regress_SOURCES += regress_ssl.c
-regress_LDADD += ../libevent_openssl.la -lcrypto -lssl
+regress_LDADD += ../libevent_openssl.la
 endif
 
 bench_SOURCES = bench.c
-bench_LDADD = ../libevent.la
+bench_LDADD = $(LIBEVENT_GC_SECTIONS) ../libevent.la
 bench_cascade_SOURCES = bench_cascade.c
-bench_cascade_LDADD = ../libevent.la
+bench_cascade_LDADD = $(LIBEVENT_GC_SECTIONS) ../libevent.la
 bench_http_SOURCES = bench_http.c
-bench_http_LDADD = ../libevent.la
+bench_http_LDADD = $(LIBEVENT_GC_SECTIONS) ../libevent.la
 bench_httpclient_SOURCES = bench_httpclient.c
-bench_httpclient_LDADD = ../libevent_core.la
+bench_httpclient_LDADD = $(LIBEVENT_GC_SECTIONS) ../libevent_core.la
 
 regress.gen.c regress.gen.h: regress.rpc $(top_srcdir)/event_rpcgen.py
        $(top_srcdir)/event_rpcgen.py $(srcdir)/regress.rpc || echo "No Python installed"
index 59cb6df5362009643ffdc34c0842129a81a6dd69..d0f831b9f80723889c3270e14371dd4fd78099bd 100644 (file)
 
 #include <sys/types.h>
 #include <sys/stat.h>
+#ifdef _EVENT_HAVE_SYS_TIME_H
 #include <sys/time.h>
+#endif
 #ifdef WIN32
+#define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 #else
 #include <sys/socket.h>
@@ -49,7 +52,9 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#ifdef _EVENT_HAVE_UNISTD_H
 #include <unistd.h>
+#endif
 #include <errno.h>
 
 #include <event.h>
@@ -102,12 +107,12 @@ run_once(void)
        count = 0;
        writes = num_writes;
        { int xcount = 0;
-       gettimeofday(&ts, NULL);
+       evutil_gettimeofday(&ts, NULL);
        do {
                event_loop(EVLOOP_ONCE | EVLOOP_NONBLOCK);
                xcount++;
        } while (count != fired);
-       gettimeofday(&te, NULL);
+       evutil_gettimeofday(&te, NULL);
 
        if (xcount != count) fprintf(stderr, "Xcount: %d, Rcount: %d\n", xcount, count);
        }
index 6b508ef13aba5ca88c8aa5df859ffa6f722bf8fb..c25255edd244bf42cba173a65ac2e8cab490e4df 100644 (file)
 
 #include <sys/types.h>
 #include <sys/stat.h>
+#ifdef _EVENT_HAVE_SYS_TIME_H
 #include <sys/time.h>
+#endif
 #ifdef WIN32
+#define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 #else
 #include <sys/socket.h>
@@ -41,7 +44,9 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#ifdef _EVENT_HAVE_UNISTD_H
 #include <unistd.h>
+#endif
 #include <errno.h>
 
 #include <event.h>
@@ -92,7 +97,7 @@ run_once(int num_pipes)
        }
 
        /* measurements includes event setup */
-       gettimeofday(&ts, NULL);
+       evutil_gettimeofday(&ts, NULL);
 
        /* provide a default timeout for events */
        evutil_timerclear(&tv_timeout);
@@ -111,7 +116,7 @@ run_once(int num_pipes)
 
        event_dispatch();
 
-       gettimeofday(&te, NULL);
+       evutil_gettimeofday(&te, NULL);
        evutil_timersub(&te, &ts, &te);
 
        for (cp = pipes, i = 0; i < num_pipes; i++, cp += 2) {
index 19f025f1887244b125c295e82db4e874c856f2a4..25db4a7d8c4eeb6183532be0cd900bf1a91e5aa4 100644 (file)
 #else
 #include <sys/socket.h>
 #include <netinet/in.h>
+# ifdef _XOPEN_SOURCE_EXTENDED
+#  include <arpa/inet.h>
+# endif
 #endif
 #include <stdlib.h>
+#include <string.h>
 #include <errno.h>
 
 #include "event2/event.h"
@@ -84,7 +88,7 @@ errorcb(struct bufferevent *b, short what, void *arg)
        if (what & BEV_EVENT_EOF) {
                ++total_n_handled;
                total_n_bytes += ri->n_read;
-               gettimeofday(&now, NULL);
+               evutil_gettimeofday(&now, NULL);
                evutil_timersub(&now, &ri->started, &diff);
                evutil_timeradd(&diff, &total_time, &total_time);
 
@@ -127,6 +131,8 @@ launch_request(void)
 
        struct request_info *ri;
 
+       memset(&sin, 0, sizeof(sin));
+
        ++total_n_launched;
 
        sin.sin_family = AF_INET;
@@ -146,7 +152,7 @@ launch_request(void)
 
        ri = malloc(sizeof(*ri));
        ri->n_read = 0;
-       gettimeofday(&ri->started, NULL);
+       evutil_gettimeofday(&ri->started, NULL);
 
        b = bufferevent_socket_new(base, sock, BEV_OPT_CLOSE_ON_FREE);
 
@@ -178,11 +184,11 @@ main(int argc, char **argv)
                        perror("launch");
        }
 
-       gettimeofday(&start, NULL);
+       evutil_gettimeofday(&start, NULL);
 
        event_base_dispatch(base);
 
-       gettimeofday(&end, NULL);
+       evutil_gettimeofday(&end, NULL);
        evutil_timersub(&end, &start, &total);
        usec = total_time.tv_sec * 1000000 + total_time.tv_usec;
 
index ee6962fcca7ab27c30769e9721c3054afd9c8217..0987809a91c9847a2b5b273f274fb6d39b3196dd 100644 (file)
@@ -2204,7 +2204,7 @@ many_event_cb(evutil_socket_t fd, short event, void *arg)
 static void
 test_many_events(void *arg)
 {
-       /* Try 70 events that should all be aready at once.  This will
+       /* Try 70 events that should all be ready at once.  This will
         * exercise the "resize" code on most of the backends, and will make
         * sure that we can get past the 64-handle limit of some windows
         * functions. */
@@ -2212,14 +2212,25 @@ test_many_events(void *arg)
 
        struct basic_test_data *data = arg;
        struct event_base *base = data->base;
+       int one_at_a_time = data->setup_data != NULL;
        evutil_socket_t sock[MANY];
        struct event *ev[MANY];
        int called[MANY];
        int i;
+       int loopflags = EVLOOP_NONBLOCK, evflags=0;
+       const int is_evport = !strcmp(event_base_get_method(base),"evport");
+       if (one_at_a_time) {
+               loopflags |= EVLOOP_ONCE;
+               evflags = EV_PERSIST;
+       }
 
        memset(sock, 0xff, sizeof(sock));
        memset(ev, 0, sizeof(ev));
        memset(called, 0, sizeof(called));
+       if (is_evport && one_at_a_time) {
+               TT_DECLARE("NOTE", ("evport can't pass this in 2.0; skipping\n"));
+               tt_skip();
+       }
 
        for (i = 0; i < MANY; ++i) {
                /* We need an event that will hit the backend, and that will
@@ -2228,15 +2239,20 @@ test_many_events(void *arg)
                sock[i] = socket(AF_INET, SOCK_DGRAM, 0);
                tt_assert(sock[i] >= 0);
                called[i] = 0;
-               ev[i] = event_new(base, sock[i], EV_WRITE, many_event_cb,
-                   &called[i]);
+               ev[i] = event_new(base, sock[i], EV_WRITE|evflags,
+                   many_event_cb, &called[i]);
                event_add(ev[i], NULL);
+               if (one_at_a_time)
+                       event_base_loop(base, EVLOOP_NONBLOCK|EVLOOP_ONCE);
        }
 
-       event_base_loop(base, EVLOOP_NONBLOCK);
+       event_base_loop(base, loopflags);
 
        for (i = 0; i < MANY; ++i) {
-               tt_int_op(called[i], ==, 1);
+               if (one_at_a_time)
+                       tt_int_op(called[i], ==, MANY - i + 1);
+               else
+                       tt_int_op(called[i], ==, 1);
        }
 
 end:
@@ -2303,7 +2319,8 @@ struct testcase_t main_testcases[] = {
        { "dup_fd", test_dup_fd, TT_ISOLATED, &basic_setup, NULL },
 #endif
        { "mm_functions", test_mm_functions, TT_FORK, NULL, NULL },
-       BASIC(many_events, TT_ISOLATED),
+       { "many_events", test_many_events, TT_ISOLATED, &basic_setup, NULL },
+       { "many_events_slow_add", test_many_events, TT_ISOLATED, &basic_setup, (void*)1 },
 
        { "struct_event_size", test_struct_event_size, 0, NULL, NULL },
 
index 4f4a83036e5bf77b173fa8b77ccd1eec0dd9de51..327210b0e204518473e8e5522731bd67ce6b58d1 100644 (file)
@@ -1140,7 +1140,9 @@ test_evbuffer_callbacks(void *ptr)
        evbuffer_drain(buf_out2, evbuffer_get_length(buf_out2));
        /* Let's test the obsolete buffer_setcb function too. */
        cb1 = evbuffer_add_cb(buf, log_change_callback, buf_out1);
+       tt_assert(cb1 != NULL);
        cb2 = evbuffer_add_cb(buf, log_change_callback, buf_out2);
+       tt_assert(cb2 != NULL);
        evbuffer_setcb(buf, self_draining_callback, NULL);
        evbuffer_add_printf(buf, "This should get drained right away.");
        tt_uint_op(evbuffer_get_length(buf), ==, 0);
index a120e516ca88061d58e106c4fbff4a935b974d4c..d737b48d7827ef4ad2b0ddaa9e78ab6e26965614 100644 (file)
@@ -551,7 +551,7 @@ want_fail_eventcb(struct bufferevent *bev, short what, void *ctx)
        if (what & BEV_EVENT_ERROR) {
                s = bufferevent_getfd(bev);
                err = evutil_socket_error_to_string(evutil_socket_geterror(s));
-               TT_BLATHER(("connection failure %s", err));
+               TT_BLATHER(("connection failure on %d: %s", s, err));
                test_ok = 1;
        } else {
                TT_FAIL(("didn't fail? what %hd", what));
index 255f613a9b15e1ba91a120fb3312127d33a87499..7868bbb3d5950fdca8ad351e42c7f04595b04113 100644 (file)
@@ -71,6 +71,8 @@
 #include "regress.h"
 #include "regress_testutils.h"
 
+#include "../util-internal.h"
+
 static int dns_ok = 0;
 static int dns_got_cancel = 0;
 static int dns_err = 0;
@@ -1624,10 +1626,9 @@ gaic_launch(struct event_base *base, struct evdns_base *dns_base)
 }
 
 static void
-test_getaddrinfo_async_cancel_stress(void *arg)
+test_getaddrinfo_async_cancel_stress(void *ptr)
 {
-       struct basic_test_data *data = arg;
-       struct event_base *base = data->base;
+       struct event_base *base;
        struct evdns_base *dns_base = NULL;
        struct evdns_server_port *server = NULL;
        evutil_socket_t fd = -1;
@@ -1699,7 +1700,7 @@ struct testcase_t dns_testcases[] = {
        { "getaddrinfo_async", test_getaddrinfo_async,
          TT_FORK|TT_NEED_BASE, &basic_setup, (char*)"" },
        { "getaddrinfo_cancel_stress", test_getaddrinfo_async_cancel_stress,
-         TT_FORK|TT_NEED_BASE, &basic_setup, (char*)"" },
+         TT_FORK, NULL, NULL },
 
        END_OF_TESTCASES
 };
index 99e9f93896da1273d6952a3a3c1ad63db6757977..0aef4d7405401ce2bd82d28e8ea58fa945bafd0b 100644 (file)
@@ -27,6 +27,7 @@
 
 #ifdef WIN32
 #include <winsock2.h>
+#include <ws2tcpip.h>
 #include <windows.h>
 #endif
 
@@ -56,6 +57,7 @@
 #include "event2/http.h"
 #include "event2/buffer.h"
 #include "event2/bufferevent.h"
+#include "event2/util.h"
 #include "log-internal.h"
 #include "util-internal.h"
 #include "http-internal.h"
@@ -128,38 +130,23 @@ static evutil_socket_t
 http_connect(const char *address, u_short port)
 {
        /* Stupid code for connecting */
-#ifdef WIN32
-       struct hostent *he;
-       struct sockaddr_in sin;
-#else
-       struct addrinfo ai, *aitop;
+       struct evutil_addrinfo ai, *aitop;
        char strport[NI_MAXSERV];
-#endif
+
        struct sockaddr *sa;
        int slen;
        evutil_socket_t fd;
 
-#ifdef WIN32
-       if (!(he = gethostbyname(address))) {
-               event_warn("gethostbyname");
-       }
-       memcpy(&sin.sin_addr, he->h_addr_list[0], he->h_length);
-       sin.sin_family = AF_INET;
-       sin.sin_port = htons(port);
-       slen = sizeof(struct sockaddr_in);
-       sa = (struct sockaddr*)&sin;
-#else
        memset(&ai, 0, sizeof(ai));
        ai.ai_family = AF_INET;
        ai.ai_socktype = SOCK_STREAM;
        evutil_snprintf(strport, sizeof(strport), "%d", port);
-       if (getaddrinfo(address, strport, &ai, &aitop) != 0) {
+       if (evutil_getaddrinfo(address, strport, &ai, &aitop) != 0) {
                event_warn("getaddrinfo");
                return (-1);
        }
        sa = aitop->ai_addr;
        slen = aitop->ai_addrlen;
-#endif
 
        fd = socket(AF_INET, SOCK_STREAM, 0);
        if (fd == -1)
@@ -178,9 +165,7 @@ http_connect(const char *address, u_short port)
 #endif
        }
 
-#ifndef WIN32
-       freeaddrinfo(aitop);
-#endif
+       evutil_freeaddrinfo(aitop);
 
        return (fd);
 }
@@ -586,6 +571,8 @@ http_bad_request_test(void *arg)
        /* real NULL request */
        http_request = "";
 
+       bufferevent_write(bev, http_request, strlen(http_request));
+
        shutdown(fd, SHUT_WR);
        timerclear(&tv);
        tv.tv_usec = 10000;
@@ -2006,8 +1993,13 @@ end:
 static void
 http_parse_uri_test(void *ptr)
 {
+       const int nonconform = (ptr != NULL);
+       const unsigned parse_flags =
+           nonconform ? EVHTTP_URI_NONCONFORMANT : 0;
        struct evhttp_uri *uri = NULL;
        char url_tmp[4096];
+#define URI_PARSE(uri) \
+       evhttp_uri_parse_with_flags((uri), parse_flags)
 
 #define TT_URI(want) do {                                              \
        char *ret = evhttp_uri_join(uri, url_tmp, sizeof(url_tmp));     \
@@ -2023,21 +2015,37 @@ http_parse_uri_test(void *ptr)
 
        /* bad URIs: parsing */
 #define BAD(s) do {                                                    \
-               if (evhttp_uri_parse(s) != NULL)                        \
+               if (URI_PARSE(s) != NULL)                               \
                        TT_FAIL(("Expected error parsing \"%s\"",s));   \
        } while(0)
-       BAD("http://www.test.com/ why hello");
-       BAD("http://www.test.com/why-hello\x01");
-       BAD("http://www.test.com/why-hello?\x01");
-       BAD("http://www.test.com/why-hello#\x01");
+       /* Nonconformant URIs we can parse: parsing */
+#define NCF(s) do {                                                    \
+               uri = URI_PARSE(s);                                     \
+               if (uri != NULL && !nonconform) {                       \
+                       TT_FAIL(("Expected error parsing \"%s\"",s));   \
+               } else if (uri == NULL && nonconform) {                 \
+                       TT_FAIL(("Couldn't parse nonconformant URI \"%s\"", \
+                               s));                                    \
+               }                                                       \
+               if (uri) {                                              \
+                       tt_want(evhttp_uri_join(uri, url_tmp,           \
+                               sizeof(url_tmp)));                      \
+                       evhttp_uri_free(uri);                           \
+               }                                                       \
+       } while(0)
+
+       NCF("http://www.test.com/ why hello");
+       NCF("http://www.test.com/why-hello\x01");
+       NCF("http://www.test.com/why-hello?\x01");
+       NCF("http://www.test.com/why-hello#\x01");
        BAD("http://www.\x01.test.com/why-hello");
        BAD("http://www.%7test.com/why-hello");
-       BAD("http://www.test.com/why-hell%7o");
+       NCF("http://www.test.com/why-hell%7o");
        BAD("h%3ttp://www.test.com/why-hello");
-       BAD("http://www.test.com/why-hello%7");
-       BAD("http://www.test.com/why-hell%7o");
-       BAD("http://www.test.com/foo?ba%r");
-       BAD("http://www.test.com/foo#ba%r");
+       NCF("http://www.test.com/why-hello%7");
+       NCF("http://www.test.com/why-hell%7o");
+       NCF("http://www.test.com/foo?ba%r");
+       NCF("http://www.test.com/foo#ba%r");
        BAD("99:99/foo");
        BAD("http://www.test.com:999x/");
        BAD("http://www.test.com:x/");
@@ -2073,7 +2081,7 @@ http_parse_uri_test(void *ptr)
        tt_want(evhttp_uri_join(uri, NULL, sizeof(url_tmp))==NULL);
        tt_want(evhttp_uri_join(uri, url_tmp, 0)==NULL);
        evhttp_uri_free(uri);
-       uri = evhttp_uri_parse("mailto:foo@bar");
+       uri = URI_PARSE("mailto:foo@bar");
        tt_want(uri != NULL);
        tt_want(evhttp_uri_get_host(uri) == NULL);
        tt_want(evhttp_uri_get_userinfo(uri) == NULL);
@@ -2125,7 +2133,7 @@ http_parse_uri_test(void *ptr)
        evhttp_uri_free(uri);
 
        /* Valid parsing */
-       uri = evhttp_uri_parse("http://www.test.com/?q=t%33est");
+       uri = URI_PARSE("http://www.test.com/?q=t%33est");
        tt_want(strcmp(evhttp_uri_get_scheme(uri), "http") == 0);
        tt_want(strcmp(evhttp_uri_get_host(uri), "www.test.com") == 0);
        tt_want(strcmp(evhttp_uri_get_path(uri), "/") == 0);
@@ -2136,7 +2144,7 @@ http_parse_uri_test(void *ptr)
        TT_URI("http://www.test.com/?q=t%33est");
        evhttp_uri_free(uri);
 
-       uri = evhttp_uri_parse("http://%77ww.test.com");
+       uri = URI_PARSE("http://%77ww.test.com");
        tt_want(strcmp(evhttp_uri_get_scheme(uri), "http") == 0);
        tt_want(strcmp(evhttp_uri_get_host(uri), "%77ww.test.com") == 0);
        tt_want(strcmp(evhttp_uri_get_path(uri), "") == 0);
@@ -2147,7 +2155,7 @@ http_parse_uri_test(void *ptr)
        TT_URI("http://%77ww.test.com");
        evhttp_uri_free(uri);
 
-       uri = evhttp_uri_parse("http://www.test.com?q=test");
+       uri = URI_PARSE("http://www.test.com?q=test");
        tt_want(strcmp(evhttp_uri_get_scheme(uri), "http") == 0);
        tt_want(strcmp(evhttp_uri_get_host(uri), "www.test.com") == 0);
        tt_want(strcmp(evhttp_uri_get_path(uri), "") == 0);
@@ -2158,7 +2166,7 @@ http_parse_uri_test(void *ptr)
        TT_URI("http://www.test.com?q=test");
        evhttp_uri_free(uri);
 
-       uri = evhttp_uri_parse("http://www.test.com#fragment");
+       uri = URI_PARSE("http://www.test.com#fragment");
        tt_want(strcmp(evhttp_uri_get_scheme(uri), "http") == 0);
        tt_want(strcmp(evhttp_uri_get_host(uri), "www.test.com") == 0);
        tt_want(strcmp(evhttp_uri_get_path(uri), "") == 0);
@@ -2169,7 +2177,7 @@ http_parse_uri_test(void *ptr)
        TT_URI("http://www.test.com#fragment");
        evhttp_uri_free(uri);
 
-       uri = evhttp_uri_parse("http://8000/");
+       uri = URI_PARSE("http://8000/");
        tt_want(strcmp(evhttp_uri_get_scheme(uri), "http") == 0);
        tt_want(strcmp(evhttp_uri_get_host(uri), "8000") == 0);
        tt_want(strcmp(evhttp_uri_get_path(uri), "/") == 0);
@@ -2180,7 +2188,7 @@ http_parse_uri_test(void *ptr)
        TT_URI("http://8000/");
        evhttp_uri_free(uri);
 
-       uri = evhttp_uri_parse("http://:8000/");
+       uri = URI_PARSE("http://:8000/");
        tt_want(strcmp(evhttp_uri_get_scheme(uri), "http") == 0);
        tt_want(strcmp(evhttp_uri_get_host(uri), "") == 0);
        tt_want(strcmp(evhttp_uri_get_path(uri), "/") == 0);
@@ -2191,7 +2199,7 @@ http_parse_uri_test(void *ptr)
        TT_URI("http://:8000/");
        evhttp_uri_free(uri);
 
-       uri = evhttp_uri_parse("http://www.test.com:/"); /* empty port */
+       uri = URI_PARSE("http://www.test.com:/"); /* empty port */
        tt_want(strcmp(evhttp_uri_get_scheme(uri), "http") == 0);
        tt_want(strcmp(evhttp_uri_get_host(uri), "www.test.com") == 0);
        tt_want_str_op(evhttp_uri_get_path(uri), ==, "/");
@@ -2202,7 +2210,7 @@ http_parse_uri_test(void *ptr)
        TT_URI("http://www.test.com/");
        evhttp_uri_free(uri);
 
-       uri = evhttp_uri_parse("http://www.test.com:"); /* empty port 2 */
+       uri = URI_PARSE("http://www.test.com:"); /* empty port 2 */
        tt_want(strcmp(evhttp_uri_get_scheme(uri), "http") == 0);
        tt_want(strcmp(evhttp_uri_get_host(uri), "www.test.com") == 0);
        tt_want(strcmp(evhttp_uri_get_path(uri), "") == 0);
@@ -2213,7 +2221,7 @@ http_parse_uri_test(void *ptr)
        TT_URI("http://www.test.com");
        evhttp_uri_free(uri);
 
-       uri = evhttp_uri_parse("ftp://www.test.com/?q=test");
+       uri = URI_PARSE("ftp://www.test.com/?q=test");
        tt_want(strcmp(evhttp_uri_get_scheme(uri), "ftp") == 0);
        tt_want(strcmp(evhttp_uri_get_host(uri), "www.test.com") == 0);
        tt_want(strcmp(evhttp_uri_get_path(uri), "/") == 0);
@@ -2224,7 +2232,7 @@ http_parse_uri_test(void *ptr)
        TT_URI("ftp://www.test.com/?q=test");
        evhttp_uri_free(uri);
 
-       uri = evhttp_uri_parse("ftp://[::1]:999/?q=test");
+       uri = URI_PARSE("ftp://[::1]:999/?q=test");
        tt_want(strcmp(evhttp_uri_get_scheme(uri), "ftp") == 0);
        tt_want(strcmp(evhttp_uri_get_host(uri), "[::1]") == 0);
        tt_want(strcmp(evhttp_uri_get_path(uri), "/") == 0);
@@ -2235,7 +2243,7 @@ http_parse_uri_test(void *ptr)
        TT_URI("ftp://[::1]:999/?q=test");
        evhttp_uri_free(uri);
 
-       uri = evhttp_uri_parse("ftp://[ff00::127.0.0.1]/?q=test");
+       uri = URI_PARSE("ftp://[ff00::127.0.0.1]/?q=test");
        tt_want(strcmp(evhttp_uri_get_scheme(uri), "ftp") == 0);
        tt_want(strcmp(evhttp_uri_get_host(uri), "[ff00::127.0.0.1]") == 0);
        tt_want(strcmp(evhttp_uri_get_path(uri), "/") == 0);
@@ -2246,7 +2254,7 @@ http_parse_uri_test(void *ptr)
        TT_URI("ftp://[ff00::127.0.0.1]/?q=test");
        evhttp_uri_free(uri);
 
-       uri = evhttp_uri_parse("ftp://[v99.not_(any:time)_soon]/?q=test");
+       uri = URI_PARSE("ftp://[v99.not_(any:time)_soon]/?q=test");
        tt_want(strcmp(evhttp_uri_get_scheme(uri), "ftp") == 0);
        tt_want(strcmp(evhttp_uri_get_host(uri), "[v99.not_(any:time)_soon]") == 0);
        tt_want(strcmp(evhttp_uri_get_path(uri), "/") == 0);
@@ -2257,7 +2265,7 @@ http_parse_uri_test(void *ptr)
        TT_URI("ftp://[v99.not_(any:time)_soon]/?q=test");
        evhttp_uri_free(uri);
 
-       uri = evhttp_uri_parse("scheme://user:pass@foo.com:42/?q=test&s=some+thing#fragment");
+       uri = URI_PARSE("scheme://user:pass@foo.com:42/?q=test&s=some+thing#fragment");
        tt_want(strcmp(evhttp_uri_get_scheme(uri), "scheme") == 0);
        tt_want(strcmp(evhttp_uri_get_userinfo(uri), "user:pass") == 0);
        tt_want(strcmp(evhttp_uri_get_host(uri), "foo.com") == 0);
@@ -2268,7 +2276,7 @@ http_parse_uri_test(void *ptr)
        TT_URI("scheme://user:pass@foo.com:42/?q=test&s=some+thing#fragment");
        evhttp_uri_free(uri);
 
-       uri = evhttp_uri_parse("scheme://user@foo.com/#fragment");
+       uri = URI_PARSE("scheme://user@foo.com/#fragment");
        tt_want(strcmp(evhttp_uri_get_scheme(uri), "scheme") == 0);
        tt_want(strcmp(evhttp_uri_get_userinfo(uri), "user") == 0);
        tt_want(strcmp(evhttp_uri_get_host(uri), "foo.com") == 0);
@@ -2279,7 +2287,7 @@ http_parse_uri_test(void *ptr)
        TT_URI("scheme://user@foo.com/#fragment");
        evhttp_uri_free(uri);
 
-       uri = evhttp_uri_parse("scheme://%75ser@foo.com/#frag@ment");
+       uri = URI_PARSE("scheme://%75ser@foo.com/#frag@ment");
        tt_want(strcmp(evhttp_uri_get_scheme(uri), "scheme") == 0);
        tt_want(strcmp(evhttp_uri_get_userinfo(uri), "%75ser") == 0);
        tt_want(strcmp(evhttp_uri_get_host(uri), "foo.com") == 0);
@@ -2290,7 +2298,7 @@ http_parse_uri_test(void *ptr)
        TT_URI("scheme://%75ser@foo.com/#frag@ment");
        evhttp_uri_free(uri);
 
-       uri = evhttp_uri_parse("file:///some/path/to/the/file");
+       uri = URI_PARSE("file:///some/path/to/the/file");
        tt_want(strcmp(evhttp_uri_get_scheme(uri), "file") == 0);
        tt_want(evhttp_uri_get_userinfo(uri) == NULL);
        tt_want(strcmp(evhttp_uri_get_host(uri), "") == 0);
@@ -2301,7 +2309,7 @@ http_parse_uri_test(void *ptr)
        TT_URI("file:///some/path/to/the/file");
        evhttp_uri_free(uri);
 
-       uri = evhttp_uri_parse("///some/path/to/the-file");
+       uri = URI_PARSE("///some/path/to/the-file");
        tt_want(uri != NULL);
        tt_want(evhttp_uri_get_scheme(uri) == NULL);
        tt_want(evhttp_uri_get_userinfo(uri) == NULL);
@@ -2313,7 +2321,7 @@ http_parse_uri_test(void *ptr)
        TT_URI("///some/path/to/the-file");
        evhttp_uri_free(uri);
 
-       uri = evhttp_uri_parse("/s:ome/path/to/the-file?q=99#fred");
+       uri = URI_PARSE("/s:ome/path/to/the-file?q=99#fred");
        tt_want(uri != NULL);
        tt_want(evhttp_uri_get_scheme(uri) == NULL);
        tt_want(evhttp_uri_get_userinfo(uri) == NULL);
@@ -2325,7 +2333,7 @@ http_parse_uri_test(void *ptr)
        TT_URI("/s:ome/path/to/the-file?q=99#fred");
        evhttp_uri_free(uri);
 
-       uri = evhttp_uri_parse("relative/path/with/co:lon");
+       uri = URI_PARSE("relative/path/with/co:lon");
        tt_want(uri != NULL);
        tt_want(evhttp_uri_get_scheme(uri) == NULL);
        tt_want(evhttp_uri_get_userinfo(uri) == NULL);
@@ -2337,7 +2345,7 @@ http_parse_uri_test(void *ptr)
        TT_URI("relative/path/with/co:lon");
        evhttp_uri_free(uri);
 
-       uri = evhttp_uri_parse("bob?q=99&q2=q?33#fr?ed");
+       uri = URI_PARSE("bob?q=99&q2=q?33#fr?ed");
        tt_want(uri != NULL);
        tt_want(evhttp_uri_get_scheme(uri) == NULL);
        tt_want(evhttp_uri_get_userinfo(uri) == NULL);
@@ -2349,7 +2357,7 @@ http_parse_uri_test(void *ptr)
        TT_URI("bob?q=99&q2=q?33#fr?ed");
        evhttp_uri_free(uri);
 
-       uri = evhttp_uri_parse("#fr?ed");
+       uri = URI_PARSE("#fr?ed");
        tt_want(uri != NULL);
        tt_want(evhttp_uri_get_scheme(uri) == NULL);
        tt_want(evhttp_uri_get_userinfo(uri) == NULL);
@@ -2360,6 +2368,9 @@ http_parse_uri_test(void *ptr)
        tt_want(strcmp(evhttp_uri_get_fragment(uri), "fr?ed") == 0);
        TT_URI("#fr?ed");
        evhttp_uri_free(uri);
+#undef URI_PARSE
+#undef TT_URI
+#undef BAD
 }
 
 static void
@@ -2996,6 +3007,65 @@ http_stream_in_cancel_test(void *arg)
 
 }
 
+static void
+http_connection_fail_done(struct evhttp_request *req, void *arg)
+{
+       /* An ENETUNREACH error results in an unrecoverable
+        * evhttp_connection error (see evhttp_connection_fail()).  The
+        * connection will be reset, and the user will be notified with a NULL
+        * req parameter. */
+       tt_assert(!req);
+
+       test_ok = 1;
+
+ end:
+       event_base_loopexit(arg, NULL);
+}
+
+/* Test unrecoverable evhttp_connection errors by generating an ENETUNREACH
+ * error on connection. */
+static void
+http_connection_fail_test(void *arg)
+{
+       struct basic_test_data *data = arg;
+       ev_uint16_t port = 0;
+       struct evhttp_connection *evcon = NULL;
+       struct evhttp_request *req = NULL;
+
+       exit_base = data->base;
+       test_ok = 0;
+
+       /* auto detect a port */
+       http = http_setup(&port, data->base);
+       evhttp_free(http);
+       http = NULL;
+
+       /* Pick an unroutable address.  This administratively scoped multicast
+       * address should do when working with TCP. */
+       evcon = evhttp_connection_base_new(data->base, NULL, "239.10.20.30", 80);
+       tt_assert(evcon);
+
+       /*
+        * At this point, we want to schedule an HTTP GET request
+        * server using our make request method.
+        */
+
+       req = evhttp_request_new(http_connection_fail_done, data->base);
+       tt_assert(req);
+
+       if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/") == -1) {
+               tt_abort_msg("Couldn't make request");
+       }
+
+       event_base_dispatch(data->base);
+
+       tt_int_op(test_ok, ==, 1);
+
+ end:
+       if (evcon)
+               evhttp_connection_free(evcon);
+}
+
 static void
 http_connection_retry_done(struct evhttp_request *req, void *arg)
 {
@@ -3505,6 +3575,7 @@ struct testcase_t http_testcases[] = {
        { "bad_headers", http_bad_header_test, 0, NULL, NULL },
        { "parse_query", http_parse_query_test, 0, NULL, NULL },
        { "parse_uri", http_parse_uri_test, 0, NULL, NULL },
+       { "parse_uri_nc", http_parse_uri_test, 0, &basic_setup, (void*)"nc" },
        { "uriencode", http_uriencode_test, 0, NULL, NULL },
        HTTP(basic),
        HTTP(cancel),
@@ -3534,6 +3605,7 @@ struct testcase_t http_testcases[] = {
        HTTP(stream_in),
        HTTP(stream_in_cancel),
 
+       HTTP(connection_fail),
        HTTP(connection_retry),
        HTTP(data_length_constraints),
 
index 1438f3aa9f721258cc30cdfeef188cf989b73ad9..44fee7f4c5ead3e0d426e903adf5bc5123a1e3b7 100644 (file)
@@ -34,6 +34,9 @@
 #ifndef WIN32
 #include <sys/socket.h>
 #include <netinet/in.h>
+# ifdef _XOPEN_SOURCE_EXTENDED
+#  include <arpa/inet.h>
+# endif
 #include <unistd.h>
 #endif
 
index e16bf8b3160ec45652c978542c7309c606c48bb8..6bc5f320852c0012938a5c170871f70a7f10f976 100644 (file)
@@ -30,6 +30,7 @@
 #endif
 
 #ifndef WIN32
+#include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #endif
index b5bef1abd7816c1011b6b182c4b43b7e3c21c3f3..8902e63180529037dac742ee31f98bc628a76a45 100644 (file)
@@ -68,6 +68,8 @@
 #include "regress.h"
 #include "regress_testutils.h"
 
+#include "../util-internal.h"
+
 /* globals */
 static struct evdns_server_port *dns_port;
 evutil_socket_t dns_sock = -1;
index 158d0d611425ee4de230e8657b110a2376c120c9..6dd7bf8f611e0feb60e1142f39987b47cf78c73b 100644 (file)
@@ -46,7 +46,6 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include <zlib.h>
 #include <assert.h>
 #include <errno.h>
 
 
 #include "regress.h"
 
+/* zlib 1.2.4 and 1.2.5 do some "clever" things with macros.  Instead of
+   saying "(defined(FOO) ? FOO : 0)" they like to say "FOO-0", on the theory
+   that nobody will care if the compile outputs a no-such-identifier warning.
+
+   Sorry, but we like -Werror over here, so I guess we need to define these.
+   I hope that zlib 1.2.6 doesn't break these too.
+*/
+#ifndef _LARGEFILE64_SOURCE
+#define _LARGEFILE64_SOURCE 0
+#endif
+#ifndef _LFS64_LARGEFILE
+#define _LFS64_LARGEFILE 0
+#endif
+#ifndef _FILE_OFFSET_BITS
+#define _FILE_OFFSET_BITS 0
+#endif
+#ifndef off64_t
+#define off64_t ev_int64_t
+#endif
+
+#include <zlib.h>
+
 static int infilter_calls;
 static int outfilter_calls;
 static int readcb_finished;
@@ -276,6 +297,7 @@ test_bufferevent_zlib(void *arg)
        tt_int_op(r, ==, Z_OK);
        memset(&z_input, 0, sizeof(z_input));
        r = inflateInit(&z_input);
+       tt_int_op(r, ==, Z_OK);
 
        /* initialize filters */
        bev1 = bufferevent_filter_new(bev1, NULL, zlib_output_filter,
index 90b40938a62afbc875c695a37f168b6d6854fb37..417476e801d3b6c81557b7b97a13d6ddcc0bb003 100644 (file)
@@ -32,6 +32,7 @@
 
 int test_okay = 1;
 int called = 0;
+struct timeval timeout = {60, 0};
 
 static void
 read_cb(evutil_socket_t fd, short event, void *arg)
@@ -39,6 +40,11 @@ read_cb(evutil_socket_t fd, short event, void *arg)
        char buf[256];
        int len;
 
+       if (EV_TIMEOUT & event) {
+               printf("%s: Timeout!\n", __func__);
+               exit(1);
+       }
+
        len = recv(fd, buf, sizeof(buf), 0);
 
        printf("%s: read %d%s\n", __func__,
@@ -46,7 +52,7 @@ read_cb(evutil_socket_t fd, short event, void *arg)
 
        if (len) {
                if (!called)
-                       event_add(arg, NULL);
+                       event_add(arg, &timeout);
        } else if (called == 1)
                test_okay = 0;
 
@@ -85,9 +91,9 @@ main(int argc, char **argv)
        event_init();
 
        /* Initalize one event */
-       event_set(&ev, pair[1], EV_READ, read_cb, &ev);
+       event_set(&ev, pair[1], EV_READ | EV_TIMEOUT, read_cb, &ev);
 
-       event_add(&ev, NULL);
+       event_add(&ev, &timeout);
 
        event_dispatch();
 
index 824434e08959616a1de40b2a591799acfcbb910f..bbbd760809015c97f59fbc08ab30c48e052246c4 100644 (file)
@@ -36,6 +36,9 @@
 #else
 #include <sys/socket.h>
 #include <netinet/in.h>
+# ifdef _XOPEN_SOURCE_EXTENDED
+#  include <arpa/inet.h>
+# endif
 #endif
 #include <signal.h>
 
@@ -46,6 +49,8 @@
 #include "event2/listener.h"
 #include "event2/thread.h"
 
+#include "../util-internal.h"
+
 static int cfg_verbose = 0;
 static int cfg_help = 0;
 
index 48deb9b1f94f1c961728c20b92d389547ee6c31a..08a4cddb7a977096ce16d75a39017b842fd8a572 100755 (executable)
@@ -7,12 +7,18 @@ then
        TEST_OUTPUT_FILE=/dev/null
 fi
 
-# /bin/echo is a little more likely to support -n than sh's builtin echo.
-if test -x /bin/echo
+# /bin/echo is a little more likely to support -n than sh's builtin echo,
+# printf is even more likely
+if test "`printf %s hello 2>&1`" = "hello"
 then
-       ECHO=/bin/echo
+       ECHO_N="printf %s"
 else
-       ECHO=echo
+       if test -x /bin/echo
+       then
+               ECHO_N="/bin/echo -n"
+       else
+               ECHO_N="echo -n"
+       fi
 fi
 
 if test "$TEST_OUTPUT_FILE" != "/dev/null"
@@ -45,7 +51,7 @@ announce () {
 }
 
 announce_n () {
-       $ECHO -n "$@"
+       $ECHO_N "$@"
        echo "$@" >>"$TEST_OUTPUT_FILE"
 }
 
@@ -91,6 +97,7 @@ run_tests () {
                announce FAILED ;
                FAILED=yes
        fi
+       test -x $TEST_DIR/regress || return
        announce_n " regress: "
        if test "$TEST_OUTPUT_FILE" = "/dev/null" ;
        then
index 9f80fcd73158136a37c8a8bc635b569d5ad38281..1a7f75efc5aa47869ab0806f048322a398b59b9e 100644 (file)
@@ -6,4 +6,7 @@
 #include "event2/util.h"
 #include "util-internal.h"
 
+#ifdef snprintf
+#undef snprintf
+#endif
 #define snprintf evutil_snprintf
index cb76ee4fdd590bf76a3f2a33e30237d720ca4146..fe9ff3568efbc2631464ced206deff900f8095be 100644 (file)
@@ -38,6 +38,8 @@
 #endif
 #include "event2/util.h"
 
+#include "ipv6-internal.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -52,9 +54,13 @@ extern "C" {
 
 /* A good no-op to use in macro definitions. */
 #define _EVUTIL_NIL_STMT ((void)0)
-/* Suppresses the compiler's "unused variable" warnings for unused assert. */
+/* A no-op that tricks the compiler into thinking a condition is used while
+ * definitely not making any code for it.  Used to compile out asserts while
+ * avoiding "unused variable" warnings.  The "!" forces the compiler to
+ * do the sizeof() on an int, in case "condition" is a bitfield value.
+ */
 #define _EVUTIL_NIL_CONDITION(condition) do { \
-       (void)sizeof(condition); \
+       (void)sizeof(!(condition));  \
 } while(0)
 
 /* Internal use only: macros to match patterns of error codes in a
@@ -173,7 +179,7 @@ long _evutil_weakrand(void);
 
 /* Evaluates to the same boolean value as 'p', and hints to the compiler that
  * we expect this value to be false. */
-#ifdef __GNUC__
+#if defined(__GNUC__) && __GNUC__ >= 3         /* gcc 3.0 or later */
 #define EVUTIL_UNLIKELY(p) __builtin_expect(!!(p),0)
 #else
 #define EVUTIL_UNLIKELY(p) (p)
@@ -201,6 +207,21 @@ long _evutil_weakrand(void);
 #define EVUTIL_FAILURE_CHECK(cond) EVUTIL_UNLIKELY(cond)
 #endif
 
+#ifndef _EVENT_HAVE_STRUCT_SOCKADDR_STORAGE
+/* Replacement for sockaddr storage that we can use internally on platforms
+ * that lack it.  It is not space-efficient, but neither is sockaddr_storage.
+ */
+struct sockaddr_storage {
+       union {
+               struct sockaddr ss_sa;
+               struct sockaddr_in ss_sin;
+               struct sockaddr_in6 ss_sin6;
+               char ss_padding[128];
+       } ss_union;
+};
+#define ss_family ss_union.ss_sa.sa_family
+#endif
+
 /* Internal addrinfo error code.  This one is returned from only from
  * evutil_getaddrinfo_common, when we are sure that we'll have to hit a DNS
  * server. */
index 3b4cfbdb4cc1c95dca9aa10c70f0d016b952184d..5ad6b979bc5a16342006c062bf25dd0c816c66c7 100644 (file)
@@ -75,7 +75,7 @@ What's New In Libevent 2.0 so far:
   evutil.h) will continue to work by including the corresponding new
   headers.  Old code should not be broken by this change.
 
-2.2. New thread-safe, binary-compatibile, harder-to-mess-up APIs
+2.2. New thread-safe, binary-compatible, harder-to-mess-up APIs
 
   Some aspects of the historical Libevent API have encouraged
   non-threadsafe code, or forced code built against one version of Libevent