]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
[Bug 2747] Upgrade libevent to 2.1.5-beta
authorHarlan Stenn <stenn@ntp.org>
Wed, 11 Feb 2015 09:05:59 +0000 (09:05 +0000)
committerHarlan Stenn <stenn@ntp.org>
Wed, 11 Feb 2015 09:05:59 +0000 (09:05 +0000)
bk: 54db1b77dPyouexQ4D8Zp3XGGeDo6A

69 files changed:
sntp/libevent/ChangeLog
sntp/libevent/Makefile.am
sntp/libevent/README [deleted file]
sntp/libevent/README.md [new file with mode: 0644]
sntp/libevent/WIN32-Code/getopt.c [new file with mode: 0644]
sntp/libevent/WIN32-Code/getopt.h [new file with mode: 0644]
sntp/libevent/WIN32-Code/getopt_long.c [new file with mode: 0644]
sntp/libevent/WIN32-Code/nmake/event2/event-config.h
sntp/libevent/WIN32-Code/tree.h
sntp/libevent/buffer.c
sntp/libevent/bufferevent.c
sntp/libevent/bufferevent_async.c
sntp/libevent/bufferevent_filter.c
sntp/libevent/bufferevent_openssl.c
sntp/libevent/bufferevent_pair.c
sntp/libevent/configure.ac
sntp/libevent/evbuffer-internal.h
sntp/libevent/evdns.c
sntp/libevent/event.c
sntp/libevent/event_tagging.c
sntp/libevent/evrpc-internal.h
sntp/libevent/evthread-internal.h
sntp/libevent/evthread.c
sntp/libevent/evutil.c
sntp/libevent/evutil_time.c
sntp/libevent/ht-internal.h
sntp/libevent/http-internal.h
sntp/libevent/http.c
sntp/libevent/include/event2/buffer.h
sntp/libevent/include/event2/bufferevent.h
sntp/libevent/include/event2/dns.h
sntp/libevent/include/event2/event.h
sntp/libevent/include/event2/http.h
sntp/libevent/include/event2/listener.h
sntp/libevent/include/event2/util.h
sntp/libevent/kqueue.c
sntp/libevent/listener.c
sntp/libevent/sample/http-server.c
sntp/libevent/sample/https-client.c
sntp/libevent/sample/include.am
sntp/libevent/test/include.am
sntp/libevent/test/print-winsock-errors.c [new file with mode: 0644]
sntp/libevent/test/regress.c
sntp/libevent/test/regress.h
sntp/libevent/test/regress_buffer.c
sntp/libevent/test/regress_bufferevent.c
sntp/libevent/test/regress_dns.c
sntp/libevent/test/regress_finalize.c
sntp/libevent/test/regress_http.c
sntp/libevent/test/regress_main.c
sntp/libevent/test/regress_minheap.c
sntp/libevent/test/regress_ssl.c
sntp/libevent/test/regress_thread.c
sntp/libevent/test/regress_util.c
sntp/libevent/test/regress_zlib.c
sntp/libevent/test/test-fdleak.c
sntp/libevent/test/test-ratelim.c
sntp/libevent/test/test-ratelim.sh [new file with mode: 0755]
sntp/libevent/test/test-time.c
sntp/libevent/test/tinytest.c
sntp/libevent/test/tinytest.h
sntp/libevent/test/tinytest_demo.c [new file with mode: 0644]
sntp/libevent/test/tinytest_macros.h
sntp/libevent/time-internal.h
sntp/libevent/util-internal.h
sntp/libevent/whatsnew-2.1.txt
sntp/m4/LICENSE-OPENLDAP [moved from sntp/libevent/m4/LICENSE-OPENLDAP with 100% similarity]
sntp/m4/openldap-thread-check.m4 [moved from sntp/libevent/m4/openldap-thread-check.m4 with 100% similarity]
sntp/m4/openldap.m4 [moved from sntp/libevent/m4/openldap.m4 with 100% similarity]

index 8bb76cafff4e8053746240405952ade898cf6988..1499637504963a99a76fb9e2130c59dcaab2f349 100644 (file)
-Changes in version 2.1.4-beta (?? Dec 2013)
+Changes in version 2.1.5-beta (5 January 2015)
 
- (As of 735d838b0a537ae04f1e6a2e9cbc5f3f45ebb541)
+ Security Fixes (evbuffers)
+   o Avoid integer overflow bugs in evbuffer_add() and related functions.  See CVE-2014-6272 advisory for more information. (d49bc0e88b81a5812116074dc007f1db0ca1eecd)
 
+ New APIs (evconnlistener)
+   o Provide support for SO_REUSEPORT through LEV_OPT_REUSABLE_PORT (b625361 Maciej Soltysiak)
+
+ Bugfixes (core)
+    o Fix use-after-free error in EV_CLOSURE_EVENT callback (3cc0eac John Ohl)
+    o Fix race caused by event_active (3c7d6fc vjpai)
+
+ Bugfixes (evbuffer)
+   o Fix evbuffer_peek() with len==-1 and start_at non-NULL. (ba59923)
+   o Consistently check for failure from evbuffer_pullup() (60f8f72)
+   o Fix evbuffer_peek() with len==-1 and start_at non-NULL. (fb7e76a)
+
+ Bugfixes (windows, IOCP)
+   o be async: avoid double close() (f133b86 Azat Khuzhin)
+
+ Bugfixes (bufferevents)
+   o Fix issue #127, double free for filterevents that use BEV_OPT_CLOSE_ON_FREE (2c82aa0 John Ohl)
+   o make bufferevent_getwatermark api more robust (a21e510 ufo2243)
+   o [Bugfix] fix bufferevent setwatermark suspend_read (b34e4ac ufo2243)
+   o bufferevent_openssl: reset fd_is_set when setfd with -1 is called (3da84c2 Azat Khuzhin)
+   o Fix compilation for older OpenSSL versions. (5c7282f Joakim Soderberg)
+
+ New APIs (evhttp)
+   o Add evhttp_connection_set_family() to set addrinfo->family for DNS requests (12c29b0 Azat Khuzhin)
+   o Implement interface that provides the ability to have an outbound evhttp_connection free itself once all requests have completed (2b9ec4c,10fe4f John Ohl)
+
+ New APIs (core)
+   o Implement new/free for struct evutil_monotonic_timer and export monotonic time functions (f2645f8 Andrea Shepard)
+
+ Bugfixes (evdns)
+   o Load hosts file on Windows. (a0b247c Vilmos Nebehaj)
+   o Don't truncate hosts file path on Windows. (d0dc861 Vilmos Nebehaj)
+   o Fix a crash in evdns related to shutting down evdns (9f39c88,e8fe749)
+   o evdns: avoid read-after-free in evdns_request_timeout_callback() (61262a0 Azat Khuzhin)
+   o Correctly handle allocation failures in evdns_getaddrinfo (6a53d15)
+   o evdns: fix EVDNS_BASE_DISABLE_WHEN_INACTIVE in case retransmit/retry (74d0eee Azat Khuzhin)
+   o evdns: add retry/reissue tests for EVDNS_BASE_DISABLE_WHEN_INACTIVE (3ca9d43 Azat Khuzhin)
+   o evdns: fail ns after we are failing/retrasmitting request (97c750d Azat Khuzhin)
+
+ Bugfixes (evhttp)
+   o http: reset connection before installing retry timer (fix http retries handling) (bc79cc5 Azat Khuzhin)
+
+
+ Testing
+   o regress_dns: fix leaks in getaddrinfo_async{,_cancel_stress} tests (2fdc5f2 Azat Khuzhin)
+   o test: add family argument for http_connection_test_() (177b8a7 Azat Khuzhin)
+   o test: add regress for evhttp_connection_set_family() with AF_INET and AF_UNSPEC (42aefeb Azat Khuzhin)
+   o test/http: add regress test for set family to AF_INET6 (3fbf3cc Azat Khuzhin)
+   o Update to a more recent tinytest_macros. (8da5a18)
+   o test/regress: add simplestsignal: to track reorder bugs separately (b897bef Azat Khuzhin)
+   o test/evbuffer_peek: add regress in case we have first buffer greater (e2d139d Azat Khuzhin)
+   o More evbuffer_peek() test cases (154006a)
+   o use correct tt macro for pointer compare (08c88ea)
+   o regress_buffer: fix 'memcmp' compare size (79800df Maks Naumov)
+   o Fix a use-after-free in unit tests. CID 752027 (3739057)
+   o Fix a dead-code warning in unit tests. CID 1193548 (c119f24)
+   o Use evutil_weakrand() in unit tests. (a677b72, 364c110)
+   o Use a more precise calculation for max in time-ratelim.c (ca5b5c7)
+   o Make a buffer larger in the tests to avoid a scary evbuffer_copyout_from() (fb57b8b)
+   o Fix several memory leaks in the unit tests. (89c1a3b)
+   o Add test for evhttp_connection_free_on_completion (b0e9924 John Ohl)
+   o Fix annoying heisenbug in test-time.c (cb73704)
+
+ Sample code
+   o Make http-server.c output into good html5 (6d72bdc)
+   o Use FindClose for handle from FindFirstFile in http-server.c (6466e88)
+   o https-client: add -retries argument, for connection retries (d9da844 Azat Khuzhin)
+
+ Bugfixes (build)
+   o Add missing headerfile for cmake (15d90cc Trond Norbye)
+   o ignore one more test binary (b6593aa Michael Richardson)
+   o ignore config.cache/test-driver files (c83f333 Mike Frysinger)
+   o add a --disable-samples configure flag (0c492b3 Mike Frysinger)
+   o Add a few files created by "make verify" to .gitignore. (1a8295a Pierre Phaneuf)
+   o updates in cmake build (27bd9fa Sergey Nikulov)
+   o Fix cmake error when the Module path has more than one entry. (befbd13 Acer Yang)
+   o Fix CMake shared library build (e69d910 Nobuaki Sukegawa)
+   o Fix warnings when compiling with clang 3.5 (f5b4765 John Ohl)
+   o Fix mixed declarations and code (forbidden by ISO C90) (8afbdbc Thomas Bernard)
+
+ Bugfixes (miscellaneous)
+   o tree.h: drop duplicated content of tree.h (6193187 Azat Khuzhin)
+   o evdns: disable probing with EVDNS_BASE_DISABLE_WHEN_INACTIVE (610410b,ad0493e,fea86a6,d83b337,5ca9e97 Azat Khuzhin)
+   o [Bugfix] fix grammer error (3a4d249 ufo2243)
+   o Change return type of evutil_load_windows_system_library_ to HMODULE (f691389)
+   o Fix a c90 warning (76643dd)
+   o Fix a typo in a doxygen comment. Reported by äº¦å¾—. (be1aeff)
+   o remove trailing comma from enum (b361b8a Jean-Philippe Ouellet)
+
+ Bugfixes (FreeBSD)
+   o Handle ENOTCAPABLE from FreeBSD - this is returned if an event in the changelist is for an FD that has been closed. (6fd7394 Adrian Chadd)
+
+
+
+Changes in version 2.1.4-alpha (21 Mar 2014)
+
+ Libevent 2.1.4-alpha adds a number of new miscellaneous APIs to make
+ Libevent more useful, including support for early close detection with
+ epoll via EPOLLRDHUP, triggering bufferevent callbacks, adding more
+ evhttp callbacks, and more. There are also numerous bugfixes, including
+ a number for finalize-related issues from 2.1.3-alpha; and an
+ alternative (non-primary!) cmake-based build mechanism.
+
+ New APIs (core)
+   o Added event_base_get_num_events() (0fa107d Mobai Zhang)
+   o New event_base_active_by_fd API (865a142 Greg Hazel, 5c9da9a, 87fa2b0)
+   o Add event_base_active_by_signal by analogy (4865943)
+   o Add access to max event count stats (5173bef, efbd3dc, 26230a2
+     Andrew Sweeney)
+   o Implemented EV_CLOSED event for epoll backend
+     (EPOLLRDHUP). (b1b69ac Diego Giagio, 53d2793, 43ffcf6, dfe1e52
+     Marcin Juszkiewicz, ff26633 Joakim Soderberg, 3908a5e)
+
+ New APIs (evutil_secure_rng)
+   o Add evutil_secure_rng_set_urandom_device_file (2bbb5d7)
+
+ New APIs (bufferevents)
+   o Add function to fetch underlying ratelimit cfg (4b3d5af Mark Ellzey)
+   o Pass and return const for bufferevent_get_token_bucket_cfg (1c77fbb
+     Mark Ellzey)
+   o Add watermark introspection (4ce242b OndÅ™ej Kuzník)
+   o Add an option to trigger bufferevent I/O callbacks (61ee18b OndÅ™ej Kuzník)
+   o Add an option to trigger bufferevent event callbacks (a7384c7
+     OndÅ™ej Kuzník)
+   o Clarifications in response to merge req. comments (bd41947 OndÅ™ej
+     Kuzník)
+   o Minor optimizations on bufferevent_trigger options (a3172a4)
+
+ New APIs (evhttp)
+   o Add evhttp_connection_get_server(). (a7f82a3 Maxime Henrion)
+   o add a http default content type option (5a5acd9 Nicolas Martyanoff)
+   o http: implement new evhttp_connection_get_addr() api. (0c7f040 Azat
+     Khuzhin)
+   o Add a variant of evhttp_send_reply_chunk() with a callback on
+     evhttp_write_buffer() (8d8decf Julien BLACHE)
+   o Allow registering callback for parsing HTTP headers (b0bd7fe Balint Reczey)
+   o Provide on request complete callback facility (b083ca0 Andrew Sweeney)
+   o evhttp_request_set_on_complete_cb to be more specific about what
+     the function actually does and usage (da86dda Andrew Sweeney)
+   o Update unit test to make sure that the callback happens after the
+     output data is written (b85f398 Andrew Sweeney)
+
+ Features (evdns)
+   o bug fix for issues #293 evdns_base_load_hosts doesn't remove
+     outdated addresses (954d2f9, f03d353, 45eba6f Kuldeep Gupta)
+
+ Features: (cmake build support)
+   o Initial CMake commit. (e415196 Joakim Soderberg)
+   o Add all tests and benchmarks to CMake project. (e9fc014 Joakim Soderberg)
+   o More work on adding tests to CMake project (99c1dc3 Joakim Soderberg)
+   o Generate a dummy evconfig-private.h so things build
+     properly. (ce14def Joakim Soderberg)
+   o Link libm on unix platforms. (58fcd42 Joakim Soderberg)
+   o Added some GCC specific options. (19222e5 Joakim Soderberg)
+   o Use evutil_closesocket instead. (dbf2b51 Joakim Soderberg)
+   o Add copyright and licensing files for CMake modules. (c259d53
+     Joakim Soderberg)
+   o Only include WIN32 getopt where it is used. (9bbce0b Joakim Soderberg)
+   o Fix bench_cascade program on Windows. (78da644 Joakim Soderberg)
+   o Don't segfault on no found event backend. (8f2af50 Joakim Soderberg)
+   o Only test the event backends available on the system. (7ea4159
+     Joakim Soderberg)
+   o Added a "make verify" target. (e053c4f Joakim Soderberg)
+   o Fix the make "verify" target on Windows. (67e5d74 Joakim Soderberg)
+   o Get rid of deprecation warnings for OpenSSL on OSX 10.7+ (69c3516
+     Joakim Söderberg)
+   o Fix kqueue support. (a831f2f Joakim Söderberg)
+   o Added a test for testing if kqueue works with pipes. (2799b35
+     Joakim Söderberg)
+   o Change the BSD license from 4 to 3-clause. (86df3ed Joakim Soderberg)
+   o Minimum required python version is 2.4. (968e97b Joakim Soderberg)
+   o Get rid of unknown pragma warnings. (0ef1d04 Joakim Soderberg)
+   o Add a "make verify_coverage" target generation coverage
+     info. (f2483f8 Joakim Soderberg)
+   o Fix the "make verify" target on NetBSD (4ac086a Joakim Soderberg)
+   o Only look for ZLib when it is used (if tests are
+     included). (f780593 Joakim Soderberg)
+   o Added EVENT__ENABLE_GCC_WARNINGS, turns all warnings into
+     errors. (dd413bd Joakim Soderberg)
+   o Add CMake config and install targets. (f3446ed Joakim Soderberg)
+   o Fix typo (4b754df Joakim Soderberg)
+   o Some work on making it possible to simply do add_subdirectory() on
+     the project. (49ab363 Joakim Soderberg)
+   o Set USE_DEBUG=1 on EVENT__ENABLE_VERBOSE_DEBUG (fd42e70 Joakim Soderberg)
+   o Fix so that old nmake project still builds. (24d6466 Joakim
+     Soderberg)
+   o Rename README to README.md and use markdown to format. (d2bc39a
+     Joakim Soderberg)
+   o Update README with CMake build instructions. (604b8cc Joakim Soderberg)
+   o Clean up the README some. (8d4cb35 JoakimSoderberg)
+   o Forgotten headers for old nmake project compatability. (8697b99
+     Joakim Soderberg)
+   o Change all uses of WIN32 to _WIN32 (4e14395 Joakim Söderberg)
+   o Fix include bug. (2024467 Joakim Söderberg)
+   o Check if we're on OSX before disabling deprecation in le-proxy
+     (8b40a5b Joakim Söderberg)
+   o Fix broken autotools build. (ae1bd82 Joakim Söderberg)
+   o Disclaimerize cmake a little in the README (d03b5bf)
+   o Fix CMake compile when OpenSSL is disabled. (e423d42 Joakim
+     Söderberg)
+   o CMake: Get rid of python not found warning when regress tests
+     turned off. (d38d798 Joakim Söderberg)
+   o Fix https-client compilation on Windows. (d7be788 Joakim Soderberg)
+   o Guard against EVENT_NOWIN32 being set during testing. (f1715b4
+     Joakim Soderberg)
+   o Check for OSX when checking for clang. (e212c54 Joakim Soderberg)
+   o Added a Travis-CI configuration file. (8c0f0a9 Joakim Soderberg)
+   o Added -Qunused-arguments for clang on macosx (ed99d92 Trond Norbye)
+   o Rename event_extras to event_extra (a0dd5df Trond Norbye)
+   o Add option to build shared library (4545fa9 Trond Norbye)
+   o Add -Qunused-arguments for clang on macos (b56611d Trond Norbye)
+   o Add cmake-related files to .gitignore (e061321 Trond Norbye)
+   o Export event_extra not event_extras. (2b41bcf Joakim Söderberg)
+
+ Bugfixes (core)
+   o If evsel->del() fails, don't leave the evmap in an inconsistent
+     state (9b5a527 Maxime Henrion)
+   o Move event_debug_note_teardown_ before mm_free. (69b5c64)
+   o Check CLOCK_MONOTONIC_* at runtime if needed. (911abf3)
+   o Fix reinit of fds with EV_WRITE but not EV_READ. (ebfd8a8 maksqwe)
+   o Tweaked callbacks to prevent race condition
+     (https://github.com/libevent/libevent/issues/104) (40830f1, 2ea15ed
+     John Ohl)
+   o Move assert(ev) to before we use ev in EV_CLOSURE_EVENT_FINALIZE
+     case (9805972)
+
+ Bugfixes (evhttp)
+   o Fix a double close() bug in evhttp when the underlying bufferevent uses
+     BEV_OPT_CLOSE_ON_FREE. (31db8a0 Maxime Henrion)
+   o Fix an unlikely but possible error case for http connections (f22049e)
+   o Avoid racy bufferevent activation (5eb1788 Nate Rosenblum)
+
+ Bugfixes on 2.0 (Windows)
+   o Use windows vsnprintf fixup logic on all windows environments (e826f19)
+   o libevent/win32_dealloc() : fix sizeof(pointer) vs sizeof(*pointer)
+    (b8f5980 Frank Denis)
+
+ Bugfixes (evutil_secure_rng)
+   o When we seed from /proc/sys/kernel/random/uuid, count it as success
+     (e35b540)
+   o We should return after arc4random_buf() (1ea1f26 Makoto Kato)
+   o Avoid other RNG initialization FS reads when urandom file is
+     specified (9695e9c)
+   o Really remove RNG seeds from the stack (f5ced88)
+   o Fix another arc4random_buf-related warning (e64a2b0)
+
+ Bugfixes (bufferevents)
+   o Initialize async bufferevent timeout CBs unconditionally (af9b2a7)
 
  Bugfixes (evdns)
    o Checking request nameserver for NULL, before using it. (5c710c0
      Belobrov Andrey)
-   o Fix SEGFAULT after evdns_base_resume if no nameservers installed. (14971a8
-     Azat Khuzhin)
+   o Fix SEGFAULT after evdns_base_resume if no nameservers
+     installed. (14971a8 Azat Khuzhin)
    o Actually use the log facility for reporting evdns problems. (e1766a1)
-   o Fix SEGFAULT after evdns_base_resume if no nameservers installed. (f8d7df8 Azat Khuzhin)
+   o Fix SEGFAULT after evdns_base_resume if no nameservers
+     installed. (f8d7df8 Azat Khuzhin)
+   o fix for ServFail from RIPE Atlas release (62f596b Antony Antony)
 
- Bugfixes (compilatin)
+ Bugfixes (compilation)
    o Fix test compilation with nmake: add the gdi.lib dependency (5ba8ab7)
    o Whoops. It is gdi.lib, not gdi32.lib. (github issue #61) (8ab612e)
-   o Don't use return since return type is void and build error occurs using clang (838161d Makoto Kato)
+   o Don't use return since return type is void and build error occurs
+     using clang (838161d Makoto Kato)
    o Use void casts to suppress some "unchecked return value" warns (7080d55)
-   o rpcgen: Generate regress.gen.[c,h] in build rather than src dir (243386c Ross Lagerwall)
-   o Fix a compiler warning when checking for arc4random_buf linker breakage. (5cb3865)
+   o rpcgen: Generate regress.gen.[c,h] in build rather than src dir
+     (243386c Ross Lagerwall)
+   o Fix a compiler warning when checking for arc4random_buf linker
+     breakage. (5cb3865)
+   o Fix 'make distcheck' by adding regress.gen.[ch] to DISTCLEANFILES
+    (239d834)
+
+   o Fix a c90 warning (c207682)
+   o Fix consts in WIN32-Code/getopt*.[ch] (57abb35)
 
  Bugfixes (locks, synchronization)
    o Missed lock acquire/release in event_base_cancel_single_callback_()
@@ -30,7 +289,8 @@ Changes in version 2.1.4-beta (?? Dec 2013)
  Testing
    o Add tests for evdns_base_resume(). (1cd9ff5 Azat Khuzhin)
    o Fix dns/leak_resume_send_err test. (7e876df Azat Khuzhin)
-   o Add checks for evhttp_connection_get_server() in unit tests. (fbc323b Maxime Henrion)
+   o Add checks for evhttp_connection_get_server() in unit
+     tests. (fbc323b Maxime Henrion)
    o Fix a (failure-only) null dereference in the unit tests (1104d0b)
    o Fix a logic error in test_evbuffer_freeze (7765884)
    o Add missing check to test_evbuffer_file_segment_add_cleanup_cb (eba4506)
@@ -38,15 +298,12 @@ Changes in version 2.1.4-beta (?? Dec 2013)
    o DNS tests: add a missing check (f314900)
    o Finalize tests: add a missing check (82b6956)
    o test_evutil_rtrim: add another missing check. (e193c95)
-   o regress_main: logging all if env EVENT_DEBUG_LOGGING_ALL isset (611e28b Azat Khuzhin)
-   o regress_http: add tests for evhttp_connection_get_addr() (4dd500c Azat Khuzhin)
-
- Bugfixes (core)
-   o If evsel->del() fails, don't leave the evmap in an inconsistent state
-     (9b5a527 Maxime Henrion)
-   o Move event_debug_note_teardown_ before mm_free. (69b5c64)
-   o Check CLOCK_MONOTONIC_* at runtime if needed. (911abf3)
-   o Fix reinit of fds with EV_WRITE but not EV_READ. (ebfd8a8 maksqwe)
+   o regress_main: logging all if env EVENT_DEBUG_LOGGING_ALL isset
+     (611e28b Azat Khuzhin)
+   o regress_http: add tests for evhttp_connection_get_addr() (4dd500c
+     Azat Khuzhin)
+   o Update to the latest version of tinytest (7a80476)
+   o Heap-allocate zlib data structure in regress_zlib tests (4947c18)
 
  Performance tweaks (core)
    o Avoid redundant syscall to make a nonblocking socket nonblocking
@@ -54,56 +311,42 @@ Changes in version 2.1.4-beta (?? Dec 2013)
    o Avoid redundant syscall if making a socket cloexec twice (1f29b18)
    o Avoid redundant invocations of init_extension_functions for IOCP (3b77d62)
 
- Bugfixes (evhttp)
-   o Fix a double close() bug in evhttp when the underlying bufferevent uses
-     BEV_OPT_CLOSE_ON_FREE. (31db8a0 Maxime Henrion)
-   o Fix an unlikely but possible error case for http connections (f22049e)
-   o Avoid racy bufferevent activation (5eb1788 Nate Rosenblum)
-
- Bugfixes on 2.0 (Windows)
-   o Use windows vsnprintf fixup logic on all windows environments (e826f19)
-   o libevent/win32_dealloc() : fix sizeof(pointer) vs sizeof(*pointer) (b8f5980 Frank Denis)
-
- Bugfixes (evutil_secure_rng)
-   o When we seed from /proc/sys/kernel/random/uuid, count it as success (e35b540)
-   o We should return after arc4random_buf() (1ea1f26 Makoto Kato)
-   o Avoid other RNG initialization FS reads when urandom file is specified (9695e9c)
-   o Really remove RNG seeds from the stack (f5ced88)
-   o Fix another arc4random_buf-related warning (e64a2b0)
-
- New APIs (core)
-   o Added event_base_get_num_events() (0fa107d Mobai Zhang)
-   o Add function to fetch underlying ratelimit cfg (4b3d5af Mark Ellzey)
-   o Pass and return const for bufferevent_get_token_bucket_cfg (1c77fbb Mark Ellzey)
-
- New APIs (evhttp)
-   o Add evhttp_connection_get_server(). (a7f82a3 Maxime Henrion)
-   o add a http default content type option (5a5acd9 Nicolas Martyanoff)
-   o http: implement new evhttp_connection_get_addr() api. (0c7f040 Azat Khuzhin)
-
-
  Documentation
    o Document that arc4random is not a great cryptographic PRNG. (6e49696)
    o Small doxygen tweaks (6e67b51)
    o Try another doxygen tweak (ccf432b)
-
- New APIs (evutil_secure_rng)
-   o Add evutil_secure_rng_set_urandom_device_file (2bbb5d7)
+   o Clarify event_base_loop exit conditions (031a803)
+   o Fix a typo (be7bf2c OndÅ™ej Kuzník)
+   o Document deferred eventcb behaviour (13a9a02 OndÅ™ej Kuzník)
+   o Typo fixes from Linus Nordberg (cec62cb, 8cd695b)
+   o Fix duplicate paragraph in evbuffer_ptr documentation (58408ee)
+
+ Code Improvements (coverity)
+   o Fix a pile of coverity warnings in the unit tests (867f401)
+   o Fix coverity warnings in benchmark tools. (ff7f739)
+   o Whoops; fix compilation in bench.c (544cf88)
+   o Remove spurious checks in evrpc.c error cases (coverity) (991b362)
+   o Fix a couple of compilation warnings in regress_http.c (860767e)
+   o Fix even more coverity warnings. (d240328)
+   o Stop checking for inet_aton; we don't use it. (f665d5c)
+   o Add an include to evrpc-internal to fix openbsd compilation warning
+     (5e161c6)
 
  Cleanups
    o Remove an unreachable return statement in minheap-internal.h (e639a9e)
+   o Refactor evmap_{io,signal}_active_() to tolerate bad inputs (974c60e)
+   o Fix needless bufferevent includes in evdns.c (254c04e)
+   o Fix a couple of "#ifdef WIN32" instances (88ecda3)
+   o Remove unneeded declaration in bufferevent-internal.h (4c8ebcd)
 
  Sample code
-   o sample/le-proxy: Fail more gracefully if opening listener fails (44b2491)
-   o sample: drop uri_root from base_url in http-server. (6171e1c Azat Khuzhin)
-
-
-
-
-
-
-
-
+   o le-proxy: Fail more gracefully if opening listener fails (44b2491)
+   o http-server: drop uri_root from base_url in http-server. (6171e1c Azat Khuzhin)
+   o https-client: POST supported, args supported (c5887f7 Alexey Ozeritsky)
+   o https-client: code cleanup (29af65e Alexey Ozeritsky)
+   o https-client: Small tweaks to https-client.c (90786eb)
+   o https-client: Set hostname for SNI extension (by f69m) (d1976f8)
+   o https-client: add a cast to https-client.c (462e6b6)
 
 
 
@@ -377,6 +620,429 @@ INFRASTRUCTURE (Active-later events):
    o Refactor event_persist_closure: raise and extract some common logic
      (bec22b4)
    o Remove the unused bits from EVLIST_ALL (9889a3d)
+||||||| merged common ancestors
+Changes in version 2.0.22-stable (?? Dec 2013)
+
+ (As of 3b77d62829c4393bda6f9105a5d3b73b48a64b71.)
+
+BUGFIXES (evhttp)
+ o fix #73 and fix http_connection_fail_test to catch it (crash fix) (b618204 Greg Hazel)
+ o Avoid racy bufferevent activation (5eb1788 Nate Rosenblum)
+
+BUGFIXES (compilation and portability)
+ o Fix compilation with WIN32_HAVE_CONDITION_VARIABLES enabled (7e45739)
+ o Fix missing AC_PROG_SED on older Autoconfs (9ab2b3f Tay Ray Chuan)
+ o Backport libevent to vanilla Autoconf 2.59 (as used in RHEL5) (74d4c44 Kevin Bowling)
+ o Use AC_CONFIG_HEADERS in place of AM_CONFIG_HEADERS for autmake 1.13 compat (817ea36)
+ o Rename configure.in to configure.ac to appease newer autoconfs (0c79787)
+ o Avoid using top_srcdir in TESTS: new automakes do not like this (a55514e)
+ o Use windows vsnprintf fixup logic on all windows environments (e826f19)
+ o Fix a compiler warning when checking for arc4random_buf linker breakage. (5cb3865)
+ o Fix another arc4random_buf-related warning (e64a2b0)
+
+BUGFIXES (resource leaks/lock errors on error)
+ o Avoid leaking fds on evconnlistener with no callback set (69db261)
+ o Avoid double-close on getsockname error in evutil_ersatz_socketpair (0a822a6)
+ o Fix a locking error in bufferevent_socket_get_dns_error. (0a5eb2e)
+ o libevent/win32_dealloc() : fix sizeof(pointer) vs sizeof(*pointer) (b8f5980 Frank Denis)
+
+BUGFIXES (miscellaneous)
+ o Avoid other RNG initialization FS reads when urandom file is specified (9695e9c, bb52471)
+ o Avoid redundant invocations of init_extension_functions for IOCP (3b77d62)
+
+BUFGIXES (evdns)
+ o Checking request nameserver for NULL, before using it. (5c710c0 Belobrov Andrey)
+ o Fix SEGFAULT after evdns_base_resume if no nameservers installed. (f8d7df8 Azat Khuzhin)
+
+BUGFIXES (evutil_secure_random)
+ o When we seed from /proc/sys/kernel/random/uuid, count it as success (e35b540)
+ o Document that arc4random is not a great cryptographic PRNG. (6e49696)
+ o Add evutil_secure_rng_set_urandom_device_file (2bbb5d7)
+ o Really remove RNG seeds from the stack (f5ced88)
+
+
+DOCUMENTATION FIXES
+ o Fix a mistake in evbuffer_remove() arguments in example http server code (c322c20 Gyepi Sam)
+ o Fix a typo in a comment in buffer.h. Spotted by Alt_F4 (773b0a5)
+
+
+
+Changes in version 2.0.21-stable (18 Nov 2012)
+BUGFIXES:
+ o ssl: Don't discard SSL read event when timeout and read come close together (576b29f)
+ o ssl: Stop looping in "consider_reading" if reading is suspended. (f719b8a Joachim Bauch)
+ o ssl: No need to reserve space if reading is suspended. (1acf2eb Joachim Bauch)
+ o dns: Avoid a memory-leak on OOM in evdns. (73e85dd, f2bff75 George Danchev)
+ o build: Use python2 rather than python (0eb0109 Ross Lagerwall)
+ o build: Compile without warnings on mingw64 (94866c2)
+ o build: Fix compilation on mingw64 with -DUSE_DEBUG (62bd2c4)
+ o build: Make rpcgen_wrapper.sh work on systems without a "python2" binary (f3009e4)
+ o iocp: Close IOCP listener socket on free when LEV_OPT_CLOSE_ON_FREE is set (cb853ea Juan Pablo Fernandez)
+ o core: Avoid crash when event_pending() called with no event_base set on event (e3cccf3)
+ o misc: remove stray 'x' so print_err will compile when uncommented (ac35650 Patrick Pelletier)
+ o tests: Fix renegotiation test to work around openssl 1.0.1 bug (c2f3086)
+ o tests: Warn when openssl version in unit test mismatches compiled version. (ac009f9)
+
+
+Changes in version 2.0.20-stable (23 Aug 2012)
+BUGFIXES:
+ o core: Make event_pending() threadsafe. (be7a95c Simon Liu)
+ o win32: avoid crash when waiting forever on zero fds. (160e58b)
+ o evhttp: Fix a memory leak on error in evhttp_uriencode (11c8b31)
+ o evbuffer: Avoid possible needless call to writev. Found by coverity. (6a4ec5c)
+ o evdns: memset sockaddr_in before using it. Found by coverity. (a1a0e67)
+ o evhttp: Check more setsockopt return values when binding sockets. Found by coverity (a0912e3)
+ o evdns: Avoid segfault on weird timeout during name lookup. (dc32077 Greg Hazel)
+ o bufferevent_ssl: Correctly invoke callbacks when a SSL bufferevent reads some and then blocks. (606ac43)
+
+
+PORTABILITY FIXES:
+ o check for arc4random_buf at runtime, on OS X (bff5f94 Greg Hazel)
+ o Correctly check for arc4random_buf (fcec3e8 Sebastian Hahn)
+ o Add explicit AC_PROG_SED to configure.in so all autoconfs will expose $(SED) (ca80ea6)
+
+BUILD FIXES:
+ o Add GCC annotations so that the vsprintf functions get checked properly (117e327)
+ o Fix an unused variable warning on *BSD. (c0720c1)
+
+UNIT TEST FIXES:
+ o Fix a couple of memory leaks (found with Valgrind). (3b2529a Ross Lagerwall)
+ o Remove deadcode in http regression tests. Found by coverity. (5553346)
+ o Fix possible uninitialized read in dns regression tests. Found by coverity. (2259777)
+ o Set umask before calling mkstemp in unit tests. Found by coverity (f1ce15d)
+ o Fix various check-after-dereference issues in unit tests: found by coverity (4f3732d)
+ o Fix resource leaks in the unit tests; found by coverity (270f279)
+ o Add some missing null checks to unit tests; found by coverity (f021c3d)
+ o Avoid more crashes/bad calls in unit tests; found by coverity (3cde5bf)
+ o Remove unused variable; spotted by coverity (6355b2a)
+ o Add checks to various return values in unit tests. Found by coverity (b9e7329)
+ o Move assignment outside tt_assert in ssl unit tests. Appeases coverity. (a2006c0)
+
+
+
+Changes in version 2.0.19-stable (3 May 2012)
+BUGFIXES (CORE):
+ o Refactor event_persist_closure: raise and extract some common logic (bec22b4)
+ o If time has jumped so we'd reschedule a periodic event in the past, schedule it for the future instead (dfd808c)
+ o If a higher-priority event becomes active, don't continue running events of the current priority. (2bfda40)
+
+BUGFIXES (SSL):
+ o Fixed potential double-readcb execution with openssl bufferevents. (4e62cd1 Mark Ellzey)
+
+BUGFIXES (DNS):
+ o Cancel a probe request when the server is freed, and ignore cancelled probe callbacks (94d2336 Greg Hazel)
+ o Remove redundant DNS_ERR_CANCEL check, move comment (46b8060 Greg Hazel)
+ o When retransmitting a timed-out DNS request, pick a fresh nameserver. (3d9e52a)
+
+DOCUMENTATION FIXES:
+ o Fix a typo in the bufferevent documentation (98e9119)
+ o Add missing ) to changelog; spotted by rransom (4c7ee6b)
+ o Fix the website URL in the readme (f775521)
+
+COMPILATION FIXES:
+ o Fix a compilation error with MSVC 2005 due to use of mode_t (336dcae)
+ o Configure with gcc older than 2.95 (4a6fd43 Sebastian Hahn)
+ o Generate event-config.h with a single sed script (30b6f88 Zack Weinberg)
+
+FORWARD-COMPATIBILITY:
+ o Backport: provide EVENT_LOG_* names, and deprecate _EVENT_LOG_* (d1a03b2)
+
+TESTING/DEBUGGING SUPPORT:
+ o dns-example.c can now take a resolv.conf file on the commandline (6610fa5)
+ o Make some evdns.c debug logs more verbose (d873d67)
+ o Work-around a stupid gcov-breaking bug in OSX 10.6 (b3887cd)
+
+
+
+Changes in version 2.0.18-stable (22 Mar 2012)
+BUGFIXES (core):
+ o Make uses of open() close-on-exec safe by introducing an internal evutil_open_closeonexec. (d2b5f72 Ross Lagerwall, 03dce42)
+
+BUGFIXES (kqueue):
+ o Properly zero the kevent in kq_setup_kevent() (c2c7b39 Sebastian Hahn)
+
+BUILD FIXES:
+ o Added OPENSSL_LDFLAGS env variable which is appended to SSL checks. (9278196 Mark Ellzey)
+ o Changed OPENSSL_LDFLAGS to OPENSSL_LIBADD (2d67b63 Mark Ellzey)
+ o Don't do clang version detection when disabling some flags (083296b Sebastian Hahn)
+
+BUGFIXES (dns):
+ o Stop crashing in evdns when nameserver probes give a weird error (bec5068)
+
+
+Changes in version 2.0.17-stable (10 Feb 2012)
+
+BUGFIXES (core):
+ o Be absolutely sure to clear pncalls before leaving event_signal_closure (11f36a5)
+ o check for sysctl before we use it (358c745 Mike Frysinger)
+ o Remove bogus casts of socket to int before calling ev_callback (f032516)
+ o Make evconnlistener work around bug in older Linux when getting nmapped (ecfc720)
+ o Fix a list corruption bug when using event_reinit() with signals present (6e41cdc)
+ o Fix a fd leak in event_reinit() (3f18ad1)
+ o Do a memberwise comparison of threading function tables (c94a5f2 Nate R)
+ o Use C-style comments in C source files (for compatibility with compilers such as xlc on AIX). (d84d917 Greg Hewgill)
+ o Avoid crash when freeing event_iocp and using event_set_mem_functions (19715a6)
+ o In the kqueue backend, do not report EBADF as an EV_READ (5d7bfa1 Nicholas Marriott)
+
+BUGFIXES (evbuffer and bufferevents):
+ o Fix behavior of evbuffer_peek(buf,-1,NULL,NULL,0) (c986f23 Zack Weinberg)
+ o Loop on filtering SSL reads until we are blocked or exhausted. (5b4b812)
+
+BUGFIXES (evhttp):
+ o Force strict validation of HTTP version in response. (790f6b3 Catalin Patulea)
+
+BUGFIXES (evdns):
+ o evdns: fix a bug in circular-queue implementation (d6094b1)
+
+BUILD FIXES:
+ o Fix a silly compilation error with the sun compiler (1927776 Colin Watt)
+ o Suppress a gcc warning from ignoring fwrite return in http-sample.c (7206e8c)
+
+DOCUMENTATION FIXES:
+ o Slightly clarify evbuffer_peek documentation (7bbf6ca)
+ o Update copyright notices to 2012 (e49e289)
+
+NEW APIS:
+ o Backport evhttp_connection_get_bufferevent to Libevent 2.0 (da70fa7 Arno Bakker)
+
+TESTS AND TEST FIXES:
+ o Fix a race condition in the dns/bufferevent_connect_hostname test. (cba48c7)
+ o Add function to check referential integrity of an event_base (27737d5)
+ o Check event_base correctness at end of each unit test (3312b02)
+ o Workaround in the unit tests for an apparent epoll bug in Linux 3.2 (dab9187)
+ o Better workaround for Linux 3.2 edge-triggered epoll bug (9f9e259)
+
+Changes in version 2.0.16-stable (18 Nov 2011)
+BUGFIXES (core):
+ o More detailed message in case of libevent self-debugging failure. (9e6a4ef Leonid Evdokimov)
+ o epoll: close fd on alloc fail at initialization (1aee718 Jamie Iles)
+ o Fix compile warning from saying event2/*.h inside a comment (447b0ba)
+ o Warn when unable to construct base because of failing make_base_notifiable (4e797f3)
+ o Don't try to make notifiable event_base when no threading fns are configured (e787413)
+
+BUGFIXES (evbuffer):
+ o unit test for remove_buffer bug (90bd620 Greg Hazel)
+ o Fix an evbuffer crash in evbuffer_remove_buffer() (c37069c)
+
+BUGFIXES (bufferevent_openssl):
+ o Refactor amount-to-read calculations in buffervent_ssl consider_reading() (a186e73 Mark Ellzey)
+ o Move SSL rate-limit enforcement into bytes_to_read() (96c562f)
+ o Avoid spinning on OpenSSL reads (2aa036f Mark Ellzey)
+
+BUGFIXES (dns)
+ o Empty DNS reply with OK status is another way to say NODATA. (21a08d6 Leonid Evdokimov)
+
+TESTING:
+ o Tests for 94fba5b and f72e8f6 (d58c15e Leonid Evdokimov)
+ o Test for commit aff6ba1 (f7841bf Leonid Evdokimov)
+ o Style and comment tweaks for dns/leak* tests (5e42202)
+ o improve test to remove at least one buffer from src (7eb52eb Greg Hazel)
+
+DOCUMENTATION:
+ o Add note about evhttp_send_reply_end to its doxygen (724bfb5)
+ o Update copyright dates to 2011. (3c824bd)
+ o Fix typo in whatsnew-2.0.txt (674bc6a Mansour Moufid)
+ o Improve win32 behavior of dns-sample.c code (a3f320e Gisle Vanem)
+
+
+
+Changes in version 2.0.15-stable (12 Oct 2011)
+BUGFIXES (DNS):
+ o DNS: add ttl for negative answers using RFC 2308 idea. (f72e8f6 Leonid Evdokimov)
+ o Add DNS_ERR_NODATA error code to handle empty replies. (94fba5b Leonid Evdokimov)
+
+BUFGIXES (bufferevents and evbuffers):
+ o Make evbuffer callbacks get the right n_added value after evbuffer_add (1ef1f68 Alex)
+ o Prefer mmap to sendfile unless a DRAINS_TO_FD flag is set. Allows add_file to work with SSL. (0ba0af9)
+
+BUGFIXES (event loop):
+ o When a signal callback is activated to run multiple times, allow event_base_loopbreak to work even before they all have run. (4e8eb6a)
+
+DOCUMENTATION FIXES:
+ o Fix docstring in dns.h (2b6eae5 Leonid Evdokimov)
+ o refer to non-deprecated evdns functions in comments (ba5c27d Greg Hazel)
+
+BUILD AND TESTING FIXES:
+ o le-proxy and regress depend on openssl directly (9ae061a Sergey Avseyev)
+ o Use _SOURCES, not _sources, in sample/Makefile.am (7f82382)
+ o Fixed compiler warnings for unchecked read/write calls. (c3b62fd Mark Ellzey)
+ o Make write-checking fixes use tt_fail_perror (2b76847)
+ o Fix some "value never used" warnings with gcc 4.6.1 (39c0cf7)
+
+
+
+Changes in version 2.0.14-stable (31 Aug 2011)
+BUGFIXES (bufferevents and evbuffers):
+ o Propagate errors on the underlying bufferevent to the user. (4a34394 Joachim Bauch)
+ o Ignore OpenSSL deprecation warnings on OS X (5d1b255 Sebastian Hahn)
+ o Fix handling of group rate limits under 64 bytes of burst (6d5440e)
+ o Solaris sendfile: correctly detect amount of data sent (643922e Michael Herf)
+ o Make rate limiting work with common_timeout logic (5b18f13)
+ o clear read watermark on underlying bufferevent when creating filtering bev to fix potentially failing fragmented ssl handshakes (54f7e61 Joachim Bauch)
+
+BUGFIXES (IOCP):
+ o IOCP: don't launch reads or writes on an unconnected socket (495c227)
+ o Make IOCP rate-limiting group support stricter and less surprising. (a98da7b)
+ o Have test-ratelim.c support IOCP (0ff2c5a)
+ o Make overlapped reads result in evbuffer callbacks getting invoked (6acfbdd)
+ o Correctly terminate IO on an async bufferevent on bufferevent_free (e6af35d)
+
+BUGFIXES (other):
+ o Fix evsig_dealloc memory leak with debugging turned on. (9b724b2 Leonid Evdokimov)
+ o Fix request_finished memory leak with debugging turned on. (aff6ba1 Leonid Evdokimov)
+
+BUILD AND TESTING FIXES:
+ o Allow OS-neutral builds for platforms where some versions have arc4random_buf (b442302 Mitchell Livingston)
+ o Try to fix 'make distcheck' errors when building out-of-tree (04656ea Dave Hart)
+ o Clean up some problems identified by Coverity. (7c11e51 Harlan Stenn)
+
+
+Changes in version 2.0.13-stable (18 Jul 2011)
+BUGFIXES
+ o Avoid race-condition when initializing global locks (b683cae)
+ o Fix bug in SSL bufferevents backed by a bev with a write high-watermarks (e050703 Joachim Bauch)
+ o Speed up invoke_callbacks on evbuffers when there are no callbacks (f87f568 Mark Ellzey)
+ o Avoid a segfault when all methods are disabled or broken (27ce38b)
+ o Fix incorrect results from evbuffer_search_eol(EOL_LF) (4461f1a)
+ o Add some missing checks for mm_calloc failures (89d5e09)
+ o Replace an assertion for event_base_free(NULL) with a check-and-warn (09fe97d)
+ o Report kqueue ebadf, epipe, and eperm as EV_READ events (1fd34ab)
+ o Check if the `evhttp_new_object' function in `http.c' returns NULL. (446cc7a Mansour Moufid)
+ o Use the correct printf args when formatting size_t (3203f88)
+ o Complain if the caller tries to change threading cbs after setting them (cb6ecee)
+
+DOCUMENTATION FIXES AND IMPROVEMENTS
+ o Revise the event/evbuffer/bufferevent doxygen for clarity and accuracy (2888fac)
+ o Update Doxyfile to produce more useful output (aea0555)
+
+TEST FIXES
+ o Fix up test_evutil_snprintf (caf695a)
+ o Fix tinytest invocation from windows shell (57def34 Ed Day)
+
+BUILD FIXES
+ o Use AM_CPPFLAGS in sample/Makefile.am, not AM_CFLAGS (4a5c82d)
+ o Fix select.c compilation on systems with no NFDBITS (49d1136)
+ o Fix a few warnings on OpenBSD (8ee9f9c Nicholas Marriott)
+ o Don't break when building tests from git without python installed (b031adf)
+ o Don't install event_rpcgen.py when --disable-libevent-install is used (e23cda3 Harlan Stenn)
+ o Fix AIX build issue with TAILQ_FOREACH definition (e934096)
+
+
+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:
  Libevent 2.1.2-alpha modernizes Libevent's use of autotools, and makes
index 58f1f016a81d25c675139bdcf1fa7640b872b17c..3053cc016a524faeca645c70591eb2c43d5d6c3d 100644 (file)
@@ -38,7 +38,7 @@ RELEASE = -release 2.1
 #
 # Once an RC is out, DO NOT MAKE ANY ABI-BREAKING CHANGES IN THAT SERIES
 # UNLESS YOU REALLY REALLY HAVE TO.
-VERSION_INFO = 3:0:0
+VERSION_INFO = 5:0:0
 
 # History:          RELEASE    VERSION_INFO
 #  2.0.1-alpha --     2.0        1:0:0
@@ -67,6 +67,8 @@ VERSION_INFO = 3:0:0
 #  2.1.1-alpha --     2.1        1:0:0
 #  2.1.2-alpha --     2.1        1:0:0 (should have been 2:0:1)
 #  2.1.3-alpha --     2.1        3:0:0 (ABI changed slightly)
+#  2.1.4-alpha --     2.1        4:0:0 (ABI changed slightly)
+#  2.1.5-beta  --     2.1        5:0:0 (ABI changed slightly)
 
 # ABI version history for this package effectively restarts every time
 # we change RELEASE.  Version 1.4.x had RELEASE of 1.4.
diff --git a/sntp/libevent/README b/sntp/libevent/README
deleted file mode 100644 (file)
index 2723a2c..0000000
+++ /dev/null
@@ -1,218 +0,0 @@
-0. BUILDING AND INSTALLATION (Briefly)
-
-$ ./configure
-$ make
-$ make verify   # (optional)
-$ sudo make install
-
-1. BUILDING AND INSTALLATION (In Depth)
-
-To build libevent, type
-
-$ ./configure && make
-
-     (If you got libevent from the git repository, you will
-      first need to run the included "autogen.sh" script in order to
-      generate the configure script.)
-
-You can run the regression tests by running
-
-$ make verify
-
-Install as root via
-
-# make install
-
-Before reporting any problems, please run the regression tests.
-
-To enable the low-level tracing build the library as:
-
-   CFLAGS=-DUSE_DEBUG ./configure [...]
-
-Standard configure flags should work.  In particular, see:
-
-   --disable-shared          Only build static libraries
-   --prefix                  Install all files relative to this directory.
-
-
-The configure script also supports the following flags:
-
-   --enable-gcc-warnings     Enable extra compiler checking with GCC.
-   --disable-malloc-replacement
-                             Don't let applications replace our memory
-                             management functions
-   --disable-openssl         Disable support for OpenSSL encryption.
-   --disable-thread-support  Don't support multithreaded environments.
-
-2. USEFUL LINKS:
-
-For the latest released version of Libevent, see the official website at
-http://libevent.org/ .
-
-There's a pretty good work-in-progress manual up at
-   http://www.wangafu.net/~nickm/libevent-book/ .
-
-For the latest development versions of Libevent, access our Git repository
-via
-   "git clone git://levent.git.sourceforge.net/gitroot/levent/libevent"
-
-You can browse the git repository online at
-http://levent.git.sourceforge.net/git/gitweb-index.cgi .
-
-To report bugs, request features, or submit patches to Libevent,
-use the Sourceforge trackers at
-https://sourceforge.net/tracker/?group_id=50884 .
-
-There's also a libevent-users mailing list for talking about Libevent
-use and development: http://archives.seul.org/libevent/users/
-
-3. ACKNOWLEDGMENTS
-
-The following people have helped with suggestions, ideas, code or
-fixing bugs:
-
-  Samy Al Bahra
-  Jacob Appelbaum
-  Arno Bakker
-  Weston Andros Adamson
-  William Ahern
-  Ivan Andropov
-  Sergey Avseyev
-  Avi Bab
-  Joachim Bauch
-  Gilad Benjamini
-  Stas Bekman
-  Denis Bilenko
-  Julien Blache
-  Kevin Bowling
-  Tomash Brechko
-  Kelly Brock
-  Ralph Castain
-  Adrian Chadd
-  Lawnstein Chan
-  Shuo Chen
-  Ka-Hing Cheung
-  Andrew Cox
-  Paul Croome
-  George Danchev
-  Andrew Danforth
-  Ed Day
-  Christopher Davis
-  Mike Davis
-  Antony Dovgal
-  Mihai Draghicioiu
-  Alexander Drozdov
-  Mark Ellzey
-  Shie Erlich
-  Leonid Evdokimov
-  Juan Pablo Fernandez
-  Christophe Fillot
-  Mike Frysinger
-  Remi Gacogne
-  Artem Germanov
-  Alexander von Gernler
-  Artur Grabowski
-  Diwaker Gupta
-  Sebastian Hahn
-  Dave Hart
-  Greg Hazel
-  Michael Herf
-  Sebastian Hahn
-  Savg He
-  Mark Heily
-  Michael Herf
-  Greg Hewgill
-  Andrew Hochhaus
-  Aaron Hopkins
-  Tani Hosokawa
-  Jamie Iles
-  Claudio Jeker
-  Evan Jones
-  George Kadianakis
-  Phua Keat
-  Azat Khuzhin
-  Alexander Klauer
-  Kevin Ko
-  Brian Koehmstedt
-  Marko Kreen
-  Valery Kyholodov
-  Ross Lagerwall
-  Scott Lamb
-  Christopher Layne
-  Adam Langley
-  Graham Leggett
-  Philip Lewis
-  Zhou Li
-  David Libenzi
-  Yan Lin
-  Moshe Litvin
-  Simon Liu
-  Mitchell Livingston
-  Hagne Mahre
-  Lubomir Marinov
-  Abilio Marques
-  Abel Mathew
-  Nick Mathewson
-  James Mansion
-  Nicholas Marriott
-  Andrey Matveev
-  Caitlin Mercer
-  Dagobert Michelsen
-  Andrea Montefusco
-  Mansour Moufid
-  Mina Naguib
-  Felix Nawothnig
-  Trond Norbye
-  Linus Nordberg
-  Richard Nyberg
-  Jon Oberheide
-  Phil Oleson
-  Dave Pacheco
-  Derrick Pallas
-  Tassilo von Parseval
-  Catalin Patulea
-  Patrick Pelletier
-  Simon Perreault
-  Pierre Phaneuf
-  Amarin Phaosawasdi
-  Ryan Phillips
-  Dimitre Piskyulev
-  Pavel Plesov
-  Jon Poland
-  Roman Puls
-  Nate R
-  Robert Ransom
-  Bert JW Regeer
-  Peter Rosin
-  Maseeb Abdul Qadir
-  Wang Qin
-  Alex S
-  Hanna Schroeter
-  Ralf Schmitt
-  Mike Smellie
-  Kevin Springborn
-  Nir Soffer
-  Harlan Stenn
-  Steve Snyder
-  Dug Song
-  Dongsheng Song
-  Hannes Sowa
-  Ferenc Szalai
-  Brodie Thiesfield
-  Jason Toffaletti
-  Gisle Vanem
-  Bas Verhoeven
-  Constantine Verutin
-  Colin Watt
-  Zack Weinberg
-  Jardel Weyrich
-  Jay R. Wren
-  Zack Weinberg
-  Alejo
-  Alex
-  Taral
-  propanbutan
-  mmadia
-  yangacer
-
-If we have forgotten your name, please contact us.
diff --git a/sntp/libevent/README.md b/sntp/libevent/README.md
new file mode 100644 (file)
index 0000000..a7c82b0
--- /dev/null
@@ -0,0 +1,318 @@
+# 0. BUILDING AND INSTALLATION (Briefly)
+
+## Autoconf
+
+     $ ./configure
+     $ make
+     $ make verify   # (optional)
+     $ sudo make install
+
+## CMake (Windows)
+
+Install CMake: <http://www.cmake.org>
+
+
+     $ md build && cd build
+     $ cmake -G "Visual Studio 10" ..   # Or whatever generator you want to use cmake --help for a list.
+     $ start libevent.sln
+
+## CMake (Unix)
+
+     $ mkdir build && cd build
+     $ cmake ..     # Default to Unix Makefiles.
+     $ make
+     $ make verify  # (optional)
+
+
+# 1. BUILDING AND INSTALLATION (In Depth)
+
+## Autoconf
+
+To build libevent, type
+
+     $ ./configure && make
+
+
+ (If you got libevent from the git repository, you will
+  first need to run the included "autogen.sh" script in order to
+  generate the configure script.)
+
+You can run the regression tests by running
+
+     $ make verify
+
+Install as root via
+
+     $ make install
+
+Before reporting any problems, please run the regression tests.
+
+To enable the low-level tracing build the library as:
+
+     $ CFLAGS=-DUSE_DEBUG ./configure [...]
+
+Standard configure flags should work.  In particular, see:
+
+   --disable-shared          Only build static libraries
+   --prefix                  Install all files relative to this directory.
+
+
+The configure script also supports the following flags:
+
+   --enable-gcc-warnings     Enable extra compiler checking with GCC.
+   --disable-malloc-replacement
+                             Don't let applications replace our memory
+                             management functions
+   --disable-openssl         Disable support for OpenSSL encryption.
+   --disable-thread-support  Don't support multithreaded environments.
+
+## CMake (Windows)
+
+(Note that autoconf is currently the most mature and supported build
+enviroment for libevent; the cmake instructions here are new and
+experimental, though they _should_ be solid.  We hope that cmake will
+still be supported in future versions of Libevent, and will try to
+make sure that happens.)
+
+First of all install <http://www.cmake.org>.
+
+To build libevent using Microsoft Visual studio open the "Visual Studio Command prompt" and type:
+
+```
+$ cd <libevent source dir>
+$ mkdir build && cd build
+$ cmake -G "Visual Studio 10" ..   # Or whatever generator you want to use cmake --help for a list.
+$ start libevent.sln
+```
+
+In the above, the ".." refers to the dir containing the Libevent source code. 
+You can build multiple versions (with different compile time settings) from the same source tree
+by creating other build directories. 
+
+It is highly recommended to build "out of source" when using
+CMake instead of "in source" like the normal behaviour of autoconf for this reason.
+
+The "NMake Makefiles" CMake generator can be used to build entirely via the command line.
+
+To get a list of settings available for the project you can type:
+
+```
+$ cmake -LH ..
+```
+
+### GUI
+
+CMake also provides a GUI that lets you specify the source directory and output (binary) directory
+that the build should be placed in.
+
+### OpenSSL support
+
+To build Libevent with OpenSSL support you will need to have OpenSSL binaries available when building,
+these can be found here: <http://www.openssl.org/related/binaries.html>
+
+# 2. USEFUL LINKS:
+
+For the latest released version of Libevent, see the official website at
+<http://libevent.org/> .
+
+There's a pretty good work-in-progress manual up at
+   <http://www.wangafu.net/~nickm/libevent-book/> .
+
+For the latest development versions of Libevent, access our Git repository
+via
+
+```
+$ git clone git://levent.git.sourceforge.net/gitroot/levent/libevent
+```
+
+You can browse the git repository online at:
+
+<http://levent.git.sourceforge.net/git/gitweb-index.cgi> 
+
+<https://github.com/libevent/Libevent>
+
+To report bugs, request features, or submit patches to Libevent,
+use the Sourceforge trackers at
+
+<https://sourceforge.net/tracker/?group_id=50884> 
+
+There's also a libevent-users mailing list for talking about Libevent
+use and development: 
+
+<http://archives.seul.org/libevent/users/>
+
+# 3. ACKNOWLEDGMENTS
+
+The following people have helped with suggestions, ideas, code or
+fixing bugs:
+
+ * Samy Al Bahra
+ * Antony Antony
+ * Jacob Appelbaum
+ * Arno Bakker
+ * Weston Andros Adamson
+ * William Ahern
+ * Ivan Andropov
+ * Sergey Avseyev
+ * Avi Bab
+ * Joachim Bauch
+ * Andrey Belobrov
+ * Gilad Benjamini
+ * Stas Bekman
+ * Denis Bilenko
+ * Julien Blache
+ * Kevin Bowling
+ * Tomash Brechko
+ * Kelly Brock
+ * Ralph Castain
+ * Adrian Chadd
+ * Lawnstein Chan
+ * Shuo Chen
+ * Ka-Hing Cheung
+ * Andrew Cox
+ * Paul Croome
+ * George Danchev
+ * Andrew Danforth
+ * Ed Day
+ * Christopher Davis
+ * Mike Davis
+ * Frank Denis
+ * Antony Dovgal
+ * Mihai Draghicioiu
+ * Alexander Drozdov
+ * Mark Ellzey
+ * Shie Erlich
+ * Leonid Evdokimov
+ * Juan Pablo Fernandez
+ * Christophe Fillot
+ * Mike Frysinger
+ * Remi Gacogne
+ * Artem Germanov
+ * Alexander von Gernler
+ * Diego Giagio
+ * Artur Grabowski
+ * Diwaker Gupta
+ * Kuldeep Gupta
+ * Sebastian Hahn
+ * Dave Hart
+ * Greg Hazel
+ * Nicholas Heath
+ * Michael Herf
+ * Sebastian Hahn
+ * Savg He
+ * Mark Heily
+ * Maxime Henrion
+ * Michael Herf
+ * Greg Hewgill
+ * Andrew Hochhaus
+ * Aaron Hopkins
+ * Tani Hosokawa
+ * Jamie Iles
+ * Xiuqiang Jiang
+ * Claudio Jeker
+ * Evan Jones
+ * Marcin Juszkiewicz
+ * George Kadianakis
+ * Makoto Kato
+ * Phua Keat
+ * Azat Khuzhin
+ * Alexander Klauer
+ * Kevin Ko
+ * Brian Koehmstedt
+ * Marko Kreen
+ * OndÅ™ej Kuzník
+ * Valery Kyholodov
+ * Ross Lagerwall
+ * Scott Lamb
+ * Christopher Layne
+ * Adam Langley
+ * Graham Leggett
+ * Volker Lendecke
+ * Philip Lewis
+ * Zhou Li
+ * David Libenzi
+ * Yan Lin
+ * Moshe Litvin
+ * Simon Liu
+ * Mitchell Livingston
+ * Hagne Mahre
+ * Lubomir Marinov
+ * Abilio Marques
+ * Nicolas Martyanoff
+ * Abel Mathew
+ * Nick Mathewson
+ * James Mansion
+ * Nicholas Marriott
+ * Andrey Matveev
+ * Caitlin Mercer
+ * Dagobert Michelsen
+ * Andrea Montefusco
+ * Mansour Moufid
+ * Mina Naguib
+ * Felix Nawothnig
+ * Trond Norbye
+ * Linus Nordberg
+ * Richard Nyberg
+ * Jon Oberheide
+ * John Ohl
+ * Phil Oleson
+ * Alexey Ozeritsky
+ * Dave Pacheco
+ * Derrick Pallas
+ * Tassilo von Parseval
+ * Catalin Patulea
+ * Patrick Pelletier
+ * Simon Perreault
+ * Dan Petro
+ * Pierre Phaneuf
+ * Amarin Phaosawasdi
+ * Ryan Phillips
+ * Dimitre Piskyulev
+ * Pavel Plesov
+ * Jon Poland
+ * Roman Puls
+ * Nate R
+ * Robert Ransom
+ * Balint Reczey
+ * Bert JW Regeer
+ * Nate Rosenblum
+ * Peter Rosin
+ * Maseeb Abdul Qadir
+ * Wang Qin
+ * Alex S
+ * Gyepi Sam
+ * Hanna Schroeter
+ * Ralf Schmitt
+ * Mike Smellie
+ * Steve Snyder
+ * Nir Soffer
+ * Dug Song
+ * Dongsheng Song
+ * Hannes Sowa
+ * Joakim Soderberg
+ * Joseph Spadavecchia
+ * Kevin Springborn
+ * Harlan Stenn
+ * Andrew Sweeney
+ * Ferenc Szalai
+ * Brodie Thiesfield
+ * Jason Toffaletti
+ * Brian Utterback
+ * Gisle Vanem
+ * Bas Verhoeven
+ * Constantine Verutin
+ * Colin Watt
+ * Zack Weinberg
+ * Jardel Weyrich
+ * Jay R. Wren
+ * Zack Weinberg
+ * Mobai Zhang
+ * Alejo
+ * Alex
+ * Taral
+ * propanbutan
+ * masksqwe
+ * mmadia
+ * yangacer
+
+If we have forgotten your name, please contact us.
diff --git a/sntp/libevent/WIN32-Code/getopt.c b/sntp/libevent/WIN32-Code/getopt.c
new file mode 100644 (file)
index 0000000..0fcba5d
--- /dev/null
@@ -0,0 +1,149 @@
+/*     $NetBSD: getopt.c,v 1.16 1999/12/02 13:15:56 kleink Exp $       */
+
+/*
+ * Copyright (c) 1987, 1993, 1994, 1995
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS 
+ * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if 0
+static char sccsid[] = "@(#)getopt.c   8.3 (Berkeley) 4/27/95";
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#define __P(x) x
+#define _DIAGASSERT(x) assert(x)
+
+#ifdef __weak_alias
+__weak_alias(getopt,_getopt);
+#endif
+
+
+int    opterr = 1,             /* if error message should be printed */
+       optind = 1,             /* index into parent argv vector */
+       optopt,                 /* character checked for validity */
+       optreset;               /* reset getopt */
+char   *optarg;                /* argument associated with option */
+
+static char * _progname __P((char *));
+int getopt_internal __P((int, char * const *, const char *));
+
+static char *
+_progname(nargv0)
+       char * nargv0;
+{
+       char * tmp;
+
+       _DIAGASSERT(nargv0 != NULL);
+
+       tmp = strrchr(nargv0, '/');
+       if (tmp)
+               tmp++;
+       else
+               tmp = nargv0;
+       return(tmp);
+}
+
+#define        BADCH   (int)'?'
+#define        BADARG  (int)':'
+#define        EMSG    ""
+
+/*
+ * getopt --
+ *     Parse argc/argv argument vector.
+ */
+int
+getopt(nargc, nargv, ostr)
+       int nargc;
+       char * const nargv[];
+       const char *ostr;
+{
+       static char *__progname = 0;
+       static char *place = EMSG;              /* option letter processing */
+       char *oli;                              /* option letter list index */
+        __progname = __progname?__progname:_progname(*nargv);
+
+       _DIAGASSERT(nargv != NULL);
+       _DIAGASSERT(ostr != NULL);
+
+       if (optreset || !*place) {              /* update scanning pointer */
+               optreset = 0;
+               if (optind >= nargc || *(place = nargv[optind]) != '-') {
+                       place = EMSG;
+                       return (-1);
+               }
+               if (place[1] && *++place == '-' /* found "--" */
+                   && place[1] == '\0') {
+                       ++optind;
+                       place = EMSG;
+                       return (-1);
+               }
+       }                                       /* option letter okay? */
+       if ((optopt = (int)*place++) == (int)':' ||
+           !(oli = strchr(ostr, optopt))) {
+               /*
+                * if the user didn't specify '-' as an option,
+                * assume it means -1.
+                */
+               if (optopt == (int)'-')
+                       return (-1);
+               if (!*place)
+                       ++optind;
+               if (opterr && *ostr != ':')
+                       (void)fprintf(stderr,
+                           "%s: illegal option -- %c\n", __progname, optopt);
+               return (BADCH);
+       }
+       if (*++oli != ':') {                    /* don't need argument */
+               optarg = NULL;
+               if (!*place)
+                       ++optind;
+       }
+       else {                                  /* need an argument */
+               if (*place)                     /* no white space */
+                       optarg = place;
+               else if (nargc <= ++optind) {   /* no arg */
+                       place = EMSG;
+                       if (*ostr == ':')
+                               return (BADARG);
+                       if (opterr)
+                               (void)fprintf(stderr,
+                                   "%s: option requires an argument -- %c\n",
+                                   __progname, optopt);
+                       return (BADCH);
+               }
+               else                            /* white space */
+                       optarg = nargv[optind];
+               place = EMSG;
+               ++optind;
+       }
+       return (optopt);                        /* dump back option letter */
+}
+
diff --git a/sntp/libevent/WIN32-Code/getopt.h b/sntp/libevent/WIN32-Code/getopt.h
new file mode 100644 (file)
index 0000000..796f455
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef __GETOPT_H__
+#define __GETOPT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int opterr;             /* if error message should be printed */
+extern int optind;             /* index into parent argv vector */
+extern int optopt;             /* character checked for validity */
+extern int optreset;           /* reset getopt */
+extern char *optarg;           /* argument associated with option */
+
+struct option
+{
+  const char *name;
+  int has_arg;
+  int *flag;
+  int val;
+};
+
+#define no_argument       0
+#define required_argument 1
+#define optional_argument 2
+
+int getopt(int, char**, const char*);
+int getopt_long(int, char**, const char*, const struct option*, int*);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GETOPT_H__ */
diff --git a/sntp/libevent/WIN32-Code/getopt_long.c b/sntp/libevent/WIN32-Code/getopt_long.c
new file mode 100644 (file)
index 0000000..03f0c01
--- /dev/null
@@ -0,0 +1,233 @@
+
+/*
+ * Copyright (c) 1987, 1993, 1994, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS 
+ * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "getopt.h"
+
+extern int       opterr;       /* if error message should be printed */
+extern int       optind;       /* index into parent argv vector */
+extern int       optopt;       /* character checked for validity */
+extern int       optreset;     /* reset getopt */
+extern char *optarg;   /* argument associated with option */
+
+#define __P(x) x
+#define _DIAGASSERT(x) assert(x)
+
+static char * __progname __P((char *));
+int getopt_internal __P((int, char * const *, const char *));
+
+static char *
+__progname(nargv0)
+       char * nargv0;
+{
+       char * tmp;
+
+       _DIAGASSERT(nargv0 != NULL);
+
+       tmp = strrchr(nargv0, '/');
+       if (tmp)
+               tmp++;
+       else
+               tmp = nargv0;
+       return(tmp);
+}
+
+#define        BADCH   (int)'?'
+#define        BADARG  (int)':'
+#define        EMSG    ""
+
+/*
+ * getopt --
+ *     Parse argc/argv argument vector.
+ */
+int
+getopt_internal(nargc, nargv, ostr)
+       int nargc;
+       char * const *nargv;
+       const char *ostr;
+{
+       static char *place = EMSG;              /* option letter processing */
+       char *oli;                              /* option letter list index */
+
+       _DIAGASSERT(nargv != NULL);
+       _DIAGASSERT(ostr != NULL);
+
+       if (optreset || !*place) {              /* update scanning pointer */
+               optreset = 0;
+               if (optind >= nargc || *(place = nargv[optind]) != '-') {
+                       place = EMSG;
+                       return (-1);
+               }
+               if (place[1] && *++place == '-') {      /* found "--" */
+                       /* ++optind; */
+                       place = EMSG;
+                       return (-2);
+               }
+       }                                       /* option letter okay? */
+       if ((optopt = (int)*place++) == (int)':' ||
+           !(oli = strchr(ostr, optopt))) {
+               /*
+                * if the user didn't specify '-' as an option,
+                * assume it means -1.
+                */
+               if (optopt == (int)'-')
+                       return (-1);
+               if (!*place)
+                       ++optind;
+               if (opterr && *ostr != ':')
+                       (void)fprintf(stderr,
+                           "%s: illegal option -- %c\n", __progname(nargv[0]), optopt);
+               return (BADCH);
+       }
+       if (*++oli != ':') {                    /* don't need argument */
+               optarg = NULL;
+               if (!*place)
+                       ++optind;
+       } else {                                /* need an argument */
+               if (*place)                     /* no white space */
+                       optarg = place;
+               else if (nargc <= ++optind) {   /* no arg */
+                       place = EMSG;
+                       if ((opterr) && (*ostr != ':'))
+                               (void)fprintf(stderr,
+                                   "%s: option requires an argument -- %c\n",
+                                   __progname(nargv[0]), optopt);
+                       return (BADARG);
+               } else                          /* white space */
+                       optarg = nargv[optind];
+               place = EMSG;
+               ++optind;
+       }
+       return (optopt);                        /* dump back option letter */
+}
+
+#if 0
+/*
+ * getopt --
+ *     Parse argc/argv argument vector.
+ */
+int
+getopt2(nargc, nargv, ostr)
+       int nargc;
+       char * const *nargv;
+       const char *ostr;
+{
+       int retval;
+
+       if ((retval = getopt_internal(nargc, nargv, ostr)) == -2) {
+               retval = -1;
+               ++optind; 
+       }
+       return(retval);
+}
+#endif
+
+/*
+ * getopt_long --
+ *     Parse argc/argv argument vector.
+ */
+int
+getopt_long(nargc, nargv, options, long_options, index)
+       int nargc;
+       char ** nargv;
+       const char * options;
+       const struct option * long_options;
+       int * index;
+{
+       int retval;
+
+       _DIAGASSERT(nargv != NULL);
+       _DIAGASSERT(options != NULL);
+       _DIAGASSERT(long_options != NULL);
+       /* index may be NULL */
+
+       if ((retval = getopt_internal(nargc, nargv, options)) == -2) {
+               char *current_argv = nargv[optind++] + 2, *has_equal;
+               int i, current_argv_len, match = -1;
+
+               if (*current_argv == '\0') {
+                       return(-1);
+               }
+               if ((has_equal = strchr(current_argv, '=')) != NULL) {
+                       current_argv_len = has_equal - current_argv;
+                       has_equal++;
+               } else
+                       current_argv_len = strlen(current_argv);
+
+               for (i = 0; long_options[i].name; i++) { 
+                       if (strncmp(current_argv, long_options[i].name, current_argv_len))
+                               continue;
+
+                       if (strlen(long_options[i].name) == (unsigned)current_argv_len) { 
+                               match = i;
+                               break;
+                       }
+                       if (match == -1)
+                               match = i;
+               }
+               if (match != -1) {
+                       if (long_options[match].has_arg == required_argument ||
+                           long_options[match].has_arg == optional_argument) {
+                               if (has_equal)
+                                       optarg = has_equal;
+                               else
+                                       optarg = nargv[optind++];
+                       }
+                       if ((long_options[match].has_arg == required_argument)
+                           && (optarg == NULL)) {
+                               /*
+                                * Missing argument, leading :
+                                * indicates no error should be generated
+                                */
+                               if ((opterr) && (*options != ':'))
+                                       (void)fprintf(stderr,
+                                     "%s: option requires an argument -- %s\n",
+                                     __progname(nargv[0]), current_argv);
+                               return (BADARG);
+                       }
+               } else { /* No matching argument */
+                       if ((opterr) && (*options != ':'))
+                               (void)fprintf(stderr,
+                                   "%s: illegal option -- %s\n", __progname(nargv[0]), current_argv);
+                       return (BADCH);
+               }
+               if (long_options[match].flag) {
+                       *long_options[match].flag = long_options[match].val;
+                       retval = 0;
+               } else 
+                       retval = long_options[match].val;
+               if (index)
+                       *index = match;
+       }
+       return(retval);
+}
index da550283adf403eadfbeaf6d8bfe7d7bf3910364..8cbf1902891f4d8c18e4fa0078a7b436a3dda093 100644 (file)
 /* #undef EVENT__HAVE_WORKING_KQUEUE */
 
 /* Numeric representation of the version */
-#define EVENT__NUMERIC_VERSION 0x02010301
+#define EVENT__NUMERIC_VERSION 0x02010500
 
 /* Name of package */
 #define EVENT__PACKAGE "libevent"
 #define EVENT__TIME_WITH_SYS_TIME 1
 
 /* Version number of package */
-#define EVENT__VERSION "2.1.3-alpha-dev"
+#define EVENT__VERSION "2.1.5-beta"
 
 /* Define to appropriate substitue if compiler doesnt have __func__ */
 #define EVENT____func__ __FUNCTION__
index 585618dde0c0035e54f7a31f116d19204329b083..2ccfbf20ac91102285de698306f04dd9224c4fea 100644 (file)
@@ -675,680 +675,3 @@ name##_RB_MINMAX(struct name *head, int val)                              \
             (x) = name##_RB_NEXT(x))
 
 #endif /* _SYS_TREE_H_ */
-/*     $OpenBSD: tree.h,v 1.7 2002/10/17 21:51:54 art Exp $    */
-/*
- * Copyright 2002 Niels Provos <provos@citi.umich.edu>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef        _SYS_TREE_H_
-#define        _SYS_TREE_H_
-
-/*
- * This file defines data structures for different types of trees:
- * splay trees and red-black trees.
- *
- * A splay tree is a self-organizing data structure.  Every operation
- * on the tree causes a splay to happen.  The splay moves the requested
- * node to the root of the tree and partly rebalances it.
- *
- * This has the benefit that request locality causes faster lookups as
- * the requested nodes move to the top of the tree.  On the other hand,
- * every lookup causes memory writes.
- *
- * The Balance Theorem bounds the total access time for m operations
- * and n inserts on an initially empty tree as O((m + n)lg n).  The
- * amortized cost for a sequence of m accesses to a splay tree is O(lg n);
- *
- * A red-black tree is a binary search tree with the node color as an
- * extra attribute.  It fulfills a set of conditions:
- *     - every search path from the root to a leaf consists of the
- *       same number of black nodes,
- *     - each red node (except for the root) has a black parent,
- *     - each leaf node is black.
- *
- * Every operation on a red-black tree is bounded as O(lg n).
- * The maximum height of a red-black tree is 2lg (n+1).
- */
-
-#define SPLAY_HEAD(name, type)                                         \
-struct name {                                                          \
-       struct type *sph_root; /* root of the tree */                   \
-}
-
-#define SPLAY_INITIALIZER(root)                                                \
-       { NULL }
-
-#define SPLAY_INIT(root) do {                                          \
-       (root)->sph_root = NULL;                                        \
-} while (0)
-
-#define SPLAY_ENTRY(type)                                              \
-struct {                                                               \
-       struct type *spe_left; /* left element */                       \
-       struct type *spe_right; /* right element */                     \
-}
-
-#define SPLAY_LEFT(elm, field)         (elm)->field.spe_left
-#define SPLAY_RIGHT(elm, field)                (elm)->field.spe_right
-#define SPLAY_ROOT(head)               (head)->sph_root
-#define SPLAY_EMPTY(head)              (SPLAY_ROOT(head) == NULL)
-
-/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */
-#define SPLAY_ROTATE_RIGHT(head, tmp, field) do {                      \
-       SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field);  \
-       SPLAY_RIGHT(tmp, field) = (head)->sph_root;                     \
-       (head)->sph_root = tmp;                                         \
-} while (0)
-
-#define SPLAY_ROTATE_LEFT(head, tmp, field) do {                       \
-       SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field);  \
-       SPLAY_LEFT(tmp, field) = (head)->sph_root;                      \
-       (head)->sph_root = tmp;                                         \
-} while (0)
-
-#define SPLAY_LINKLEFT(head, tmp, field) do {                          \
-       SPLAY_LEFT(tmp, field) = (head)->sph_root;                      \
-       tmp = (head)->sph_root;                                         \
-       (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);         \
-} while (0)
-
-#define SPLAY_LINKRIGHT(head, tmp, field) do {                         \
-       SPLAY_RIGHT(tmp, field) = (head)->sph_root;                     \
-       tmp = (head)->sph_root;                                         \
-       (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);        \
-} while (0)
-
-#define SPLAY_ASSEMBLE(head, node, left, right, field) do {            \
-       SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \
-       SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\
-       SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \
-       SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \
-} while (0)
-
-/* Generates prototypes and inline functions */
-
-#define SPLAY_PROTOTYPE(name, type, field, cmp)                                \
-void name##_SPLAY(struct name *, struct type *);                       \
-void name##_SPLAY_MINMAX(struct name *, int);                          \
-struct type *name##_SPLAY_INSERT(struct name *, struct type *);                \
-struct type *name##_SPLAY_REMOVE(struct name *, struct type *);                \
-                                                                       \
-/* Finds the node with the same key as elm */                          \
-static __inline struct type *                                          \
-name##_SPLAY_FIND(struct name *head, struct type *elm)                 \
-{                                                                      \
-       if (SPLAY_EMPTY(head))                                          \
-               return(NULL);                                           \
-       name##_SPLAY(head, elm);                                        \
-       if ((cmp)(elm, (head)->sph_root) == 0)                          \
-               return (head->sph_root);                                \
-       return (NULL);                                                  \
-}                                                                      \
-                                                                       \
-static __inline struct type *                                          \
-name##_SPLAY_NEXT(struct name *head, struct type *elm)                 \
-{                                                                      \
-       name##_SPLAY(head, elm);                                        \
-       if (SPLAY_RIGHT(elm, field) != NULL) {                          \
-               elm = SPLAY_RIGHT(elm, field);                          \
-               while (SPLAY_LEFT(elm, field) != NULL) {                \
-                       elm = SPLAY_LEFT(elm, field);                   \
-               }                                                       \
-       } else                                                          \
-               elm = NULL;                                             \
-       return (elm);                                                   \
-}                                                                      \
-                                                                       \
-static __inline struct type *                                          \
-name##_SPLAY_MIN_MAX(struct name *head, int val)                       \
-{                                                                      \
-       name##_SPLAY_MINMAX(head, val);                                 \
-       return (SPLAY_ROOT(head));                                      \
-}
-
-/* Main splay operation.
- * Moves node close to the key of elm to top
- */
-#define SPLAY_GENERATE(name, type, field, cmp)                         \
-struct type *                                                          \
-name##_SPLAY_INSERT(struct name *head, struct type *elm)               \
-{                                                                      \
-    if (SPLAY_EMPTY(head)) {                                           \
-           SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL;    \
-    } else {                                                           \
-           int __comp;                                                 \
-           name##_SPLAY(head, elm);                                    \
-           __comp = (cmp)(elm, (head)->sph_root);                      \
-           if(__comp < 0) {                                            \
-                   SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\
-                   SPLAY_RIGHT(elm, field) = (head)->sph_root;         \
-                   SPLAY_LEFT((head)->sph_root, field) = NULL;         \
-           } else if (__comp > 0) {                                    \
-                   SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\
-                   SPLAY_LEFT(elm, field) = (head)->sph_root;          \
-                   SPLAY_RIGHT((head)->sph_root, field) = NULL;        \
-           } else                                                      \
-                   return ((head)->sph_root);                          \
-    }                                                                  \
-    (head)->sph_root = (elm);                                          \
-    return (NULL);                                                     \
-}                                                                      \
-                                                                       \
-struct type *                                                          \
-name##_SPLAY_REMOVE(struct name *head, struct type *elm)               \
-{                                                                      \
-       struct type *__tmp;                                             \
-       if (SPLAY_EMPTY(head))                                          \
-               return (NULL);                                          \
-       name##_SPLAY(head, elm);                                        \
-       if ((cmp)(elm, (head)->sph_root) == 0) {                        \
-               if (SPLAY_LEFT((head)->sph_root, field) == NULL) {      \
-                       (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\
-               } else {                                                \
-                       __tmp = SPLAY_RIGHT((head)->sph_root, field);   \
-                       (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\
-                       name##_SPLAY(head, elm);                        \
-                       SPLAY_RIGHT((head)->sph_root, field) = __tmp;   \
-               }                                                       \
-               return (elm);                                           \
-       }                                                               \
-       return (NULL);                                                  \
-}                                                                      \
-                                                                       \
-void                                                                   \
-name##_SPLAY(struct name *head, struct type *elm)                      \
-{                                                                      \
-       struct type __node, *__left, *__right, *__tmp;                  \
-       int __comp;                                                     \
-\
-       SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
-       __left = __right = &__node;                                     \
-\
-       while ((__comp = (cmp)(elm, (head)->sph_root))) {               \
-               if (__comp < 0) {                                       \
-                       __tmp = SPLAY_LEFT((head)->sph_root, field);    \
-                       if (__tmp == NULL)                              \
-                               break;                                  \
-                       if ((cmp)(elm, __tmp) < 0){                     \
-                               SPLAY_ROTATE_RIGHT(head, __tmp, field); \
-                               if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
-                                       break;                          \
-                       }                                               \
-                       SPLAY_LINKLEFT(head, __right, field);           \
-               } else if (__comp > 0) {                                \
-                       __tmp = SPLAY_RIGHT((head)->sph_root, field);   \
-                       if (__tmp == NULL)                              \
-                               break;                                  \
-                       if ((cmp)(elm, __tmp) > 0){                     \
-                               SPLAY_ROTATE_LEFT(head, __tmp, field);  \
-                               if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
-                                       break;                          \
-                       }                                               \
-                       SPLAY_LINKRIGHT(head, __left, field);           \
-               }                                                       \
-       }                                                               \
-       SPLAY_ASSEMBLE(head, &__node, __left, __right, field);          \
-}                                                                      \
-                                                                       \
-/* Splay with either the minimum or the maximum element                        \
- * Used to find minimum or maximum element in tree.                    \
- */                                                                    \
-void name##_SPLAY_MINMAX(struct name *head, int __comp) \
-{                                                                      \
-       struct type __node, *__left, *__right, *__tmp;                  \
-\
-       SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
-       __left = __right = &__node;                                     \
-\
-       while (1) {                                                     \
-               if (__comp < 0) {                                       \
-                       __tmp = SPLAY_LEFT((head)->sph_root, field);    \
-                       if (__tmp == NULL)                              \
-                               break;                                  \
-                       if (__comp < 0){                                \
-                               SPLAY_ROTATE_RIGHT(head, __tmp, field); \
-                               if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
-                                       break;                          \
-                       }                                               \
-                       SPLAY_LINKLEFT(head, __right, field);           \
-               } else if (__comp > 0) {                                \
-                       __tmp = SPLAY_RIGHT((head)->sph_root, field);   \
-                       if (__tmp == NULL)                              \
-                               break;                                  \
-                       if (__comp > 0) {                               \
-                               SPLAY_ROTATE_LEFT(head, __tmp, field);  \
-                               if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
-                                       break;                          \
-                       }                                               \
-                       SPLAY_LINKRIGHT(head, __left, field);           \
-               }                                                       \
-       }                                                               \
-       SPLAY_ASSEMBLE(head, &__node, __left, __right, field);          \
-}
-
-#define SPLAY_NEGINF   -1
-#define SPLAY_INF      1
-
-#define SPLAY_INSERT(name, x, y)       name##_SPLAY_INSERT(x, y)
-#define SPLAY_REMOVE(name, x, y)       name##_SPLAY_REMOVE(x, y)
-#define SPLAY_FIND(name, x, y)         name##_SPLAY_FIND(x, y)
-#define SPLAY_NEXT(name, x, y)         name##_SPLAY_NEXT(x, y)
-#define SPLAY_MIN(name, x)             (SPLAY_EMPTY(x) ? NULL  \
-                                       : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF))
-#define SPLAY_MAX(name, x)             (SPLAY_EMPTY(x) ? NULL  \
-                                       : name##_SPLAY_MIN_MAX(x, SPLAY_INF))
-
-#define SPLAY_FOREACH(x, name, head)                                   \
-       for ((x) = SPLAY_MIN(name, head);                               \
-            (x) != NULL;                                               \
-            (x) = SPLAY_NEXT(name, head, x))
-
-/* Macros that define a red-back tree */
-#define RB_HEAD(name, type)                                            \
-struct name {                                                          \
-       struct type *rbh_root; /* root of the tree */                   \
-}
-
-#define RB_INITIALIZER(root)                                           \
-       { NULL }
-
-#define RB_INIT(root) do {                                             \
-       (root)->rbh_root = NULL;                                        \
-} while (0)
-
-#define RB_BLACK       0
-#define RB_RED         1
-#define RB_ENTRY(type)                                                 \
-struct {                                                               \
-       struct type *rbe_left;          /* left element */              \
-       struct type *rbe_right;         /* right element */             \
-       struct type *rbe_parent;        /* parent element */            \
-       int rbe_color;                  /* node color */                \
-}
-
-#define RB_LEFT(elm, field)            (elm)->field.rbe_left
-#define RB_RIGHT(elm, field)           (elm)->field.rbe_right
-#define RB_PARENT(elm, field)          (elm)->field.rbe_parent
-#define RB_COLOR(elm, field)           (elm)->field.rbe_color
-#define RB_ROOT(head)                  (head)->rbh_root
-#define RB_EMPTY(head)                 (RB_ROOT(head) == NULL)
-
-#define RB_SET(elm, parent, field) do {                                        \
-       RB_PARENT(elm, field) = parent;                                 \
-       RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL;              \
-       RB_COLOR(elm, field) = RB_RED;                                  \
-} while (0)
-
-#define RB_SET_BLACKRED(black, red, field) do {                                \
-       RB_COLOR(black, field) = RB_BLACK;                              \
-       RB_COLOR(red, field) = RB_RED;                                  \
-} while (0)
-
-#ifndef RB_AUGMENT
-#define RB_AUGMENT(x)
-#endif
-
-#define RB_ROTATE_LEFT(head, elm, tmp, field) do {                     \
-       (tmp) = RB_RIGHT(elm, field);                                   \
-       if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field))) {             \
-               RB_PARENT(RB_LEFT(tmp, field), field) = (elm);          \
-       }                                                               \
-       RB_AUGMENT(elm);                                                \
-       if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) {          \
-               if ((elm) == RB_LEFT(RB_PARENT(elm, field), field))     \
-                       RB_LEFT(RB_PARENT(elm, field), field) = (tmp);  \
-               else                                                    \
-                       RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
-       } else                                                          \
-               (head)->rbh_root = (tmp);                               \
-       RB_LEFT(tmp, field) = (elm);                                    \
-       RB_PARENT(elm, field) = (tmp);                                  \
-       RB_AUGMENT(tmp);                                                \
-       if ((RB_PARENT(tmp, field)))                                    \
-               RB_AUGMENT(RB_PARENT(tmp, field));                      \
-} while (0)
-
-#define RB_ROTATE_RIGHT(head, elm, tmp, field) do {                    \
-       (tmp) = RB_LEFT(elm, field);                                    \
-       if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field))) {             \
-               RB_PARENT(RB_RIGHT(tmp, field), field) = (elm);         \
-       }                                                               \
-       RB_AUGMENT(elm);                                                \
-       if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) {          \
-               if ((elm) == RB_LEFT(RB_PARENT(elm, field), field))     \
-                       RB_LEFT(RB_PARENT(elm, field), field) = (tmp);  \
-               else                                                    \
-                       RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
-       } else                                                          \
-               (head)->rbh_root = (tmp);                               \
-       RB_RIGHT(tmp, field) = (elm);                                   \
-       RB_PARENT(elm, field) = (tmp);                                  \
-       RB_AUGMENT(tmp);                                                \
-       if ((RB_PARENT(tmp, field)))                                    \
-               RB_AUGMENT(RB_PARENT(tmp, field));                      \
-} while (0)
-
-/* Generates prototypes and inline functions */
-#define RB_PROTOTYPE(name, type, field, cmp)                           \
-void name##_RB_INSERT_COLOR(struct name *, struct type *);     \
-void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\
-struct type *name##_RB_REMOVE(struct name *, struct type *);           \
-struct type *name##_RB_INSERT(struct name *, struct type *);           \
-struct type *name##_RB_FIND(struct name *, struct type *);             \
-struct type *name##_RB_NEXT(struct type *);                            \
-struct type *name##_RB_MINMAX(struct name *, int);                     \
-                                                                       \
-
-/* Main rb operation.
- * Moves node close to the key of elm to top
- */
-#define RB_GENERATE(name, type, field, cmp)                            \
-void                                                                   \
-name##_RB_INSERT_COLOR(struct name *head, struct type *elm)            \
-{                                                                      \
-       struct type *parent, *gparent, *tmp;                            \
-       while ((parent = RB_PARENT(elm, field)) &&                      \
-           RB_COLOR(parent, field) == RB_RED) {                        \
-               gparent = RB_PARENT(parent, field);                     \
-               if (parent == RB_LEFT(gparent, field)) {                \
-                       tmp = RB_RIGHT(gparent, field);                 \
-                       if (tmp && RB_COLOR(tmp, field) == RB_RED) {    \
-                               RB_COLOR(tmp, field) = RB_BLACK;        \
-                               RB_SET_BLACKRED(parent, gparent, field);\
-                               elm = gparent;                          \
-                               continue;                               \
-                       }                                               \
-                       if (RB_RIGHT(parent, field) == elm) {           \
-                               RB_ROTATE_LEFT(head, parent, tmp, field);\
-                               tmp = parent;                           \
-                               parent = elm;                           \
-                               elm = tmp;                              \
-                       }                                               \
-                       RB_SET_BLACKRED(parent, gparent, field);        \
-                       RB_ROTATE_RIGHT(head, gparent, tmp, field);     \
-               } else {                                                \
-                       tmp = RB_LEFT(gparent, field);                  \
-                       if (tmp && RB_COLOR(tmp, field) == RB_RED) {    \
-                               RB_COLOR(tmp, field) = RB_BLACK;        \
-                               RB_SET_BLACKRED(parent, gparent, field);\
-                               elm = gparent;                          \
-                               continue;                               \
-                       }                                               \
-                       if (RB_LEFT(parent, field) == elm) {            \
-                               RB_ROTATE_RIGHT(head, parent, tmp, field);\
-                               tmp = parent;                           \
-                               parent = elm;                           \
-                               elm = tmp;                              \
-                       }                                               \
-                       RB_SET_BLACKRED(parent, gparent, field);        \
-                       RB_ROTATE_LEFT(head, gparent, tmp, field);      \
-               }                                                       \
-       }                                                               \
-       RB_COLOR(head->rbh_root, field) = RB_BLACK;                     \
-}                                                                      \
-                                                                       \
-void                                                                   \
-name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \
-{                                                                      \
-       struct type *tmp;                                               \
-       while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) &&     \
-           elm != RB_ROOT(head)) {                                     \
-               if (RB_LEFT(parent, field) == elm) {                    \
-                       tmp = RB_RIGHT(parent, field);                  \
-                       if (RB_COLOR(tmp, field) == RB_RED) {           \
-                               RB_SET_BLACKRED(tmp, parent, field);    \
-                               RB_ROTATE_LEFT(head, parent, tmp, field);\
-                               tmp = RB_RIGHT(parent, field);          \
-                       }                                               \
-                       if ((RB_LEFT(tmp, field) == NULL ||             \
-                           RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
-                           (RB_RIGHT(tmp, field) == NULL ||            \
-                           RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
-                               RB_COLOR(tmp, field) = RB_RED;          \
-                               elm = parent;                           \
-                               parent = RB_PARENT(elm, field);         \
-                       } else {                                        \
-                               if (RB_RIGHT(tmp, field) == NULL ||     \
-                                   RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\
-                                       struct type *oleft;             \
-                                       if ((oleft = RB_LEFT(tmp, field)))\
-                                               RB_COLOR(oleft, field) = RB_BLACK;\
-                                       RB_COLOR(tmp, field) = RB_RED;  \
-                                       RB_ROTATE_RIGHT(head, tmp, oleft, field);\
-                                       tmp = RB_RIGHT(parent, field);  \
-                               }                                       \
-                               RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
-                               RB_COLOR(parent, field) = RB_BLACK;     \
-                               if (RB_RIGHT(tmp, field))               \
-                                       RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\
-                               RB_ROTATE_LEFT(head, parent, tmp, field);\
-                               elm = RB_ROOT(head);                    \
-                               break;                                  \
-                       }                                               \
-               } else {                                                \
-                       tmp = RB_LEFT(parent, field);                   \
-                       if (RB_COLOR(tmp, field) == RB_RED) {           \
-                               RB_SET_BLACKRED(tmp, parent, field);    \
-                               RB_ROTATE_RIGHT(head, parent, tmp, field);\
-                               tmp = RB_LEFT(parent, field);           \
-                       }                                               \
-                       if ((RB_LEFT(tmp, field) == NULL ||             \
-                           RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
-                           (RB_RIGHT(tmp, field) == NULL ||            \
-                           RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
-                               RB_COLOR(tmp, field) = RB_RED;          \
-                               elm = parent;                           \
-                               parent = RB_PARENT(elm, field);         \
-                       } else {                                        \
-                               if (RB_LEFT(tmp, field) == NULL ||      \
-                                   RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\
-                                       struct type *oright;            \
-                                       if ((oright = RB_RIGHT(tmp, field)))\
-                                               RB_COLOR(oright, field) = RB_BLACK;\
-                                       RB_COLOR(tmp, field) = RB_RED;  \
-                                       RB_ROTATE_LEFT(head, tmp, oright, field);\
-                                       tmp = RB_LEFT(parent, field);   \
-                               }                                       \
-                               RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
-                               RB_COLOR(parent, field) = RB_BLACK;     \
-                               if (RB_LEFT(tmp, field))                \
-                                       RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\
-                               RB_ROTATE_RIGHT(head, parent, tmp, field);\
-                               elm = RB_ROOT(head);                    \
-                               break;                                  \
-                       }                                               \
-               }                                                       \
-       }                                                               \
-       if (elm)                                                        \
-               RB_COLOR(elm, field) = RB_BLACK;                        \
-}                                                                      \
-                                                                       \
-struct type *                                                          \
-name##_RB_REMOVE(struct name *head, struct type *elm)                  \
-{                                                                      \
-       struct type *child, *parent, *old = elm;                        \
-       int color;                                                      \
-       if (RB_LEFT(elm, field) == NULL)                                \
-               child = RB_RIGHT(elm, field);                           \
-       else if (RB_RIGHT(elm, field) == NULL)                          \
-               child = RB_LEFT(elm, field);                            \
-       else {                                                          \
-               struct type *left;                                      \
-               elm = RB_RIGHT(elm, field);                             \
-               while ((left = RB_LEFT(elm, field)))                    \
-                       elm = left;                                     \
-               child = RB_RIGHT(elm, field);                           \
-               parent = RB_PARENT(elm, field);                         \
-               color = RB_COLOR(elm, field);                           \
-               if (child)                                              \
-                       RB_PARENT(child, field) = parent;               \
-               if (parent) {                                           \
-                       if (RB_LEFT(parent, field) == elm)              \
-                               RB_LEFT(parent, field) = child;         \
-                       else                                            \
-                               RB_RIGHT(parent, field) = child;        \
-                       RB_AUGMENT(parent);                             \
-               } else                                                  \
-                       RB_ROOT(head) = child;                          \
-               if (RB_PARENT(elm, field) == old)                       \
-                       parent = elm;                                   \
-               (elm)->field = (old)->field;                            \
-               if (RB_PARENT(old, field)) {                            \
-                       if (RB_LEFT(RB_PARENT(old, field), field) == old)\
-                               RB_LEFT(RB_PARENT(old, field), field) = elm;\
-                       else                                            \
-                               RB_RIGHT(RB_PARENT(old, field), field) = elm;\
-                       RB_AUGMENT(RB_PARENT(old, field));              \
-               } else                                                  \
-                       RB_ROOT(head) = elm;                            \
-               RB_PARENT(RB_LEFT(old, field), field) = elm;            \
-               if (RB_RIGHT(old, field))                               \
-                       RB_PARENT(RB_RIGHT(old, field), field) = elm;   \
-               if (parent) {                                           \
-                       left = parent;                                  \
-                       do {                                            \
-                               RB_AUGMENT(left);                       \
-                       } while ((left = RB_PARENT(left, field)));      \
-               }                                                       \
-               goto color;                                             \
-       }                                                               \
-       parent = RB_PARENT(elm, field);                                 \
-       color = RB_COLOR(elm, field);                                   \
-       if (child)                                                      \
-               RB_PARENT(child, field) = parent;                       \
-       if (parent) {                                                   \
-               if (RB_LEFT(parent, field) == elm)                      \
-                       RB_LEFT(parent, field) = child;                 \
-               else                                                    \
-                       RB_RIGHT(parent, field) = child;                \
-               RB_AUGMENT(parent);                                     \
-       } else                                                          \
-               RB_ROOT(head) = child;                                  \
-color:                                                                 \
-       if (color == RB_BLACK)                                          \
-               name##_RB_REMOVE_COLOR(head, parent, child);            \
-       return (old);                                                   \
-}                                                                      \
-                                                                       \
-/* Inserts a node into the RB tree */                                  \
-struct type *                                                          \
-name##_RB_INSERT(struct name *head, struct type *elm)                  \
-{                                                                      \
-       struct type *tmp;                                               \
-       struct type *parent = NULL;                                     \
-       int comp = 0;                                                   \
-       tmp = RB_ROOT(head);                                            \
-       while (tmp) {                                                   \
-               parent = tmp;                                           \
-               comp = (cmp)(elm, parent);                              \
-               if (comp < 0)                                           \
-                       tmp = RB_LEFT(tmp, field);                      \
-               else if (comp > 0)                                      \
-                       tmp = RB_RIGHT(tmp, field);                     \
-               else                                                    \
-                       return (tmp);                                   \
-       }                                                               \
-       RB_SET(elm, parent, field);                                     \
-       if (parent != NULL) {                                           \
-               if (comp < 0)                                           \
-                       RB_LEFT(parent, field) = elm;                   \
-               else                                                    \
-                       RB_RIGHT(parent, field) = elm;                  \
-               RB_AUGMENT(parent);                                     \
-       } else                                                          \
-               RB_ROOT(head) = elm;                                    \
-       name##_RB_INSERT_COLOR(head, elm);                              \
-       return (NULL);                                                  \
-}                                                                      \
-                                                                       \
-/* Finds the node with the same key as elm */                          \
-struct type *                                                          \
-name##_RB_FIND(struct name *head, struct type *elm)                    \
-{                                                                      \
-       struct type *tmp = RB_ROOT(head);                               \
-       int comp;                                                       \
-       while (tmp) {                                                   \
-               comp = cmp(elm, tmp);                                   \
-               if (comp < 0)                                           \
-                       tmp = RB_LEFT(tmp, field);                      \
-               else if (comp > 0)                                      \
-                       tmp = RB_RIGHT(tmp, field);                     \
-               else                                                    \
-                       return (tmp);                                   \
-       }                                                               \
-       return (NULL);                                                  \
-}                                                                      \
-                                                                       \
-struct type *                                                          \
-name##_RB_NEXT(struct type *elm)                                       \
-{                                                                      \
-       if (RB_RIGHT(elm, field)) {                                     \
-               elm = RB_RIGHT(elm, field);                             \
-               while (RB_LEFT(elm, field))                             \
-                       elm = RB_LEFT(elm, field);                      \
-       } else {                                                        \
-               if (RB_PARENT(elm, field) &&                            \
-                   (elm == RB_LEFT(RB_PARENT(elm, field), field)))     \
-                       elm = RB_PARENT(elm, field);                    \
-               else {                                                  \
-                       while (RB_PARENT(elm, field) &&                 \
-                           (elm == RB_RIGHT(RB_PARENT(elm, field), field)))\
-                               elm = RB_PARENT(elm, field);            \
-                       elm = RB_PARENT(elm, field);                    \
-               }                                                       \
-       }                                                               \
-       return (elm);                                                   \
-}                                                                      \
-                                                                       \
-struct type *                                                          \
-name##_RB_MINMAX(struct name *head, int val)                           \
-{                                                                      \
-       struct type *tmp = RB_ROOT(head);                               \
-       struct type *parent = NULL;                                     \
-       while (tmp) {                                                   \
-               parent = tmp;                                           \
-               if (val < 0)                                            \
-                       tmp = RB_LEFT(tmp, field);                      \
-               else                                                    \
-                       tmp = RB_RIGHT(tmp, field);                     \
-       }                                                               \
-       return (parent);                                                \
-}
-
-#define RB_NEGINF      -1
-#define RB_INF 1
-
-#define RB_INSERT(name, x, y)  name##_RB_INSERT(x, y)
-#define RB_REMOVE(name, x, y)  name##_RB_REMOVE(x, y)
-#define RB_FIND(name, x, y)    name##_RB_FIND(x, y)
-#define RB_NEXT(name, x, y)    name##_RB_NEXT(y)
-#define RB_MIN(name, x)                name##_RB_MINMAX(x, RB_NEGINF)
-#define RB_MAX(name, x)                name##_RB_MINMAX(x, RB_INF)
-
-#define RB_FOREACH(x, name, head)                                      \
-       for ((x) = RB_MIN(name, head);                                  \
-            (x) != NULL;                                               \
-            (x) = name##_RB_NEXT(x))
-
-#endif /* _SYS_TREE_H_ */
index e603be863f01f70441081cf0f930e13462af2edf..a1a2b988c13a38346cbc80333af9dd097fa2bdd9 100644 (file)
@@ -158,12 +158,20 @@ evbuffer_chain_new(size_t size)
        struct evbuffer_chain *chain;
        size_t to_alloc;
 
+       if (size > EVBUFFER_CHAIN_MAX - EVBUFFER_CHAIN_SIZE)
+               return (NULL);
+
        size += EVBUFFER_CHAIN_SIZE;
 
        /* get the next largest memory that can hold the buffer */
-       to_alloc = MIN_BUFFER_SIZE;
-       while (to_alloc < size)
-               to_alloc <<= 1;
+       if (size < EVBUFFER_CHAIN_MAX / 2) {
+               to_alloc = MIN_BUFFER_SIZE;
+               while (to_alloc < size) {
+                       to_alloc <<= 1;
+               }
+       } else {
+               to_alloc = size;
+       }
 
        /* we get everything in one chunk */
        if ((chain = mm_malloc(to_alloc)) == NULL)
@@ -1133,6 +1141,7 @@ evbuffer_drain(struct evbuffer *buf, size_t len)
                }
 
                buf->first = chain;
+               EVUTIL_ASSERT(chain && remaining <= chain->off);
                chain->misalign += remaining;
                chain->off -= remaining;
        }
@@ -1181,6 +1190,10 @@ evbuffer_copyout_from(struct evbuffer *buf, const struct evbuffer_ptr *pos,
        EVBUFFER_LOCK(buf);
 
        if (pos) {
+               if (datlen > (size_t)(EV_SSIZE_MAX - pos->pos)) {
+                       result = -1;
+                       goto done;
+               }
                chain = pos->internal_.chain;
                pos_in_chain = pos->internal_.pos_in_chain;
                if (datlen + pos->pos > buf->total_len)
@@ -1218,6 +1231,8 @@ evbuffer_copyout_from(struct evbuffer *buf, const struct evbuffer_ptr *pos,
 
        if (datlen) {
                EVUTIL_ASSERT(chain);
+               EVUTIL_ASSERT(datlen+pos_in_chain <= chain->off);
+
                memcpy(data, chain->buffer + chain->misalign + pos_in_chain,
                    datlen);
        }
@@ -1712,6 +1727,10 @@ evbuffer_add(struct evbuffer *buf, const void *data_in, size_t datlen)
        if (buf->freeze_end) {
                goto done;
        }
+       /* Prevent buf->total_len overflow */
+       if (datlen > EV_SIZE_MAX - buf->total_len) {
+               goto done;
+       }
 
        chain = buf->last;
 
@@ -1725,7 +1744,10 @@ evbuffer_add(struct evbuffer *buf, const void *data_in, size_t datlen)
        }
 
        if ((chain->flags & EVBUFFER_IMMUTABLE) == 0) {
-               remain = (size_t)(chain->buffer_len - chain->misalign - chain->off);
+               /* Always true for mutable buffers */
+               EVUTIL_ASSERT(chain->misalign >= 0 &&
+                   (ev_uint64_t)chain->misalign <= EVBUFFER_CHAIN_MAX);
+               remain = chain->buffer_len - (size_t)chain->misalign - chain->off;
                if (remain >= datlen) {
                        /* there's enough space to hold all the data in the
                         * current last chain */
@@ -1796,6 +1818,9 @@ evbuffer_prepend(struct evbuffer *buf, const void *data, size_t datlen)
        if (buf->freeze_start) {
                goto done;
        }
+       if (datlen > EV_SIZE_MAX - buf->total_len) {
+               goto done;
+       }
 
        chain = buf->first;
 
@@ -1808,6 +1833,10 @@ evbuffer_prepend(struct evbuffer *buf, const void *data, size_t datlen)
 
        /* we cannot touch immutable buffers */
        if ((chain->flags & EVBUFFER_IMMUTABLE) == 0) {
+               /* Always true for mutable buffers */
+               EVUTIL_ASSERT(chain->misalign >= 0 &&
+                   (ev_uint64_t)chain->misalign <= EVBUFFER_CHAIN_MAX);
+
                /* If this chain is empty, we can treat it as
                 * 'empty at the beginning' rather than 'empty at the end' */
                if (chain->off == 0)
@@ -1845,6 +1874,7 @@ evbuffer_prepend(struct evbuffer *buf, const void *data, size_t datlen)
        tmp->next = chain;
 
        tmp->off = datlen;
+       EVUTIL_ASSERT(datlen <= tmp->buffer_len);
        tmp->misalign = tmp->buffer_len - datlen;
 
        memcpy(tmp->buffer + tmp->misalign, data, datlen);
@@ -1943,7 +1973,9 @@ evbuffer_expand_singlechain(struct evbuffer *buf, size_t datlen)
 
        /* Would expanding this chunk be affordable and worthwhile? */
        if (CHAIN_SPACE_LEN(chain) < chain->buffer_len / 8 ||
-           chain->off > MAX_TO_COPY_IN_EXPAND) {
+           chain->off > MAX_TO_COPY_IN_EXPAND ||
+           (datlen < EVBUFFER_CHAIN_MAX &&
+               EVBUFFER_CHAIN_MAX - datlen >= chain->off)) {
                /* It's not worth resizing this chain. Can the next one be
                 * used? */
                if (chain->next && CHAIN_SPACE_LEN(chain->next) >= datlen) {
@@ -2071,6 +2103,8 @@ evbuffer_expand_fast_(struct evbuffer *buf, size_t datlen, int n)
                        rmv_all = 1;
                        avail = 0;
                } else {
+                       /* can't overflow, since only mutable chains have
+                        * huge misaligns. */
                        avail = (size_t) CHAIN_SPACE_LEN(chain);
                        chain = chain->next;
                }
@@ -2081,6 +2115,7 @@ evbuffer_expand_fast_(struct evbuffer *buf, size_t datlen, int n)
                        EVUTIL_ASSERT(chain->off == 0);
                        evbuffer_chain_free(chain);
                }
+               EVUTIL_ASSERT(datlen >= avail);
                tmp = evbuffer_chain_new(datlen - avail);
                if (tmp == NULL) {
                        if (rmv_all) {
@@ -2210,6 +2245,7 @@ get_n_bytes_readable_on_socket(evutil_socket_t fd)
        unsigned long lng = EVBUFFER_MAX_READ;
        if (ioctlsocket(fd, FIONREAD, &lng) < 0)
                return -1;
+       /* Can overflow, but mostly harmlessly. XXXX */
        return (int)lng;
 #elif defined(FIONREAD)
        int n = EVBUFFER_MAX_READ;
@@ -2322,8 +2358,14 @@ evbuffer_read(struct evbuffer *buf, evutil_socket_t fd, int howmuch)
 #ifdef USE_IOVEC_IMPL
        remaining = n;
        for (i=0; i < nvecs; ++i) {
-               ev_ssize_t space = (ev_ssize_t) CHAIN_SPACE_LEN(*chainp);
-               if (space < remaining) {
+               /* can't overflow, since only mutable chains have
+                * huge misaligns. */
+               size_t space = (size_t) CHAIN_SPACE_LEN(*chainp);
+               /* XXXX This is a kludge that can waste space in perverse
+                * situations. */
+               if (space > EVBUFFER_CHAIN_MAX)
+                       space = EVBUFFER_CHAIN_MAX;
+               if ((ev_ssize_t)space < remaining) {
                        (*chainp)->off += space;
                        remaining -= (int)space;
                } else {
@@ -2485,9 +2527,11 @@ evbuffer_write_atmost(struct evbuffer *buffer, evutil_socket_t fd,
                /* XXX(nickm) Don't disable this code until we know if
                 * the WSARecv code above works. */
                void *p = evbuffer_pullup(buffer, howmuch);
+               EVUTIL_ASSERT(p || !howmuch);
                n = send(fd, p, howmuch, 0);
 #else
                void *p = evbuffer_pullup(buffer, howmuch);
+               EVUTIL_ASSERT(p || !howmuch);
                n = write(fd, p, howmuch);
 #endif
 #ifdef USE_SENDFILE
@@ -2538,6 +2582,8 @@ static int
 evbuffer_ptr_subtract(struct evbuffer *buf, struct evbuffer_ptr *pos,
     size_t howfar)
 {
+       if (pos->pos < 0)
+               return -1;
        if (howfar > (size_t)pos->pos)
                return -1;
        if (pos->internal_.chain && howfar <= pos->internal_.pos_in_chain) {
@@ -2571,12 +2617,17 @@ evbuffer_ptr_set(struct evbuffer *buf, struct evbuffer_ptr *pos,
        case EVBUFFER_PTR_ADD:
                /* this avoids iterating over all previous chains if
                   we just want to advance the position */
+               if (pos->pos < 0 || EV_SIZE_MAX - position < (size_t)pos->pos) {
+                       EVBUFFER_UNLOCK(buf);
+                       return -1;
+               }
                chain = pos->internal_.chain;
                pos->pos += position;
                position = pos->internal_.pos_in_chain;
                break;
        }
 
+       EVUTIL_ASSERT(EV_SIZE_MAX - left >= position);
        while (chain && position + left >= chain->off) {
                left -= chain->off - position;
                chain = chain->next;
@@ -2613,7 +2664,9 @@ evbuffer_ptr_memcmp(const struct evbuffer *buf, const struct evbuffer_ptr *pos,
 
        ASSERT_EVBUFFER_LOCKED(buf);
 
-       if (pos->pos + len > buf->total_len)
+       if (pos->pos < 0 ||
+           EV_SIZE_MAX - len < (size_t)pos->pos ||
+           pos->pos + len > buf->total_len)
                return -1;
 
        chain = pos->internal_.chain;
@@ -2740,7 +2793,10 @@ evbuffer_peek(struct evbuffer *buffer, ev_ssize_t len,
        if (n_vec == 0 && len < 0) {
                /* If no vectors are provided and they asked for "everything",
                 * pretend they asked for the actual available amount. */
-               len = buffer->total_len - len_so_far;
+               len = buffer->total_len;
+               if (start_at) {
+                       len -= start_at->pos;
+               }
        }
 
        while (chain) {
@@ -2804,6 +2860,9 @@ evbuffer_add_vprintf(struct evbuffer *buf, const char *fmt, va_list ap)
 
                if (sz < 0)
                        goto done;
+               if (INT_MAX >= EVBUFFER_CHAIN_MAX &&
+                   (size_t)sz >= EVBUFFER_CHAIN_MAX)
+                       goto done;
                if ((size_t)sz < space) {
                        chain->off += sz;
                        buf->total_len += sz;
@@ -2913,6 +2972,11 @@ evbuffer_file_segment_new(
        }
        seg->length = length;
 
+       if (offset < 0 || length < 0 ||
+           ((ev_uint64_t)length > EVBUFFER_CHAIN_MAX) ||
+           (ev_uint64_t)offset > (ev_uint64_t)(EVBUFFER_CHAIN_MAX - length))
+               goto err;
+
 #if defined(USE_SENDFILE)
        if (!(flags & EVBUF_FS_DISABLE_SENDFILE)) {
                seg->can_sendfile = 1;
@@ -3201,7 +3265,7 @@ evbuffer_add_file_segment(struct evbuffer *buf,
        return 0;
 err:
        EVBUFFER_UNLOCK(buf);
-       evbuffer_file_segment_free(seg);
+       evbuffer_file_segment_free(seg); /* Lowers the refcount */
        return -1;
 }
 
index 588461a33e1ac63117583ffdd0f8ccfddedbe120..d298d0b3f01387aae7a453ecff9b9193e2b94d76 100644 (file)
@@ -599,7 +599,7 @@ bufferevent_setwatermark(struct bufferevent *bufev, short events,
                                      bufev_private->read_watermarks_cb,
                                      EVBUFFER_CB_ENABLED|EVBUFFER_CB_NODEFER);
 
-                       if (evbuffer_get_length(bufev->input) > highmark)
+                       if (evbuffer_get_length(bufev->input) >= highmark)
                                bufferevent_wm_suspend_read(bufev);
                        else if (evbuffer_get_length(bufev->input) < highmark)
                                bufferevent_wm_unsuspend_read(bufev);
@@ -615,25 +615,30 @@ bufferevent_setwatermark(struct bufferevent *bufev, short events,
        BEV_UNLOCK(bufev);
 }
 
-void
+int
 bufferevent_getwatermark(struct bufferevent *bufev, short events,
     size_t *lowmark, size_t *highmark)
 {
-       BEV_LOCK(bufev);
        if (events == EV_WRITE) {
+               BEV_LOCK(bufev);
                if (lowmark)
                        *lowmark = bufev->wm_write.low;
                if (highmark)
                        *highmark = bufev->wm_write.high;
+               BEV_UNLOCK(bufev);
+               return 0;
        }
 
        if (events == EV_READ) {
+               BEV_LOCK(bufev);
                if (lowmark)
                        *lowmark = bufev->wm_read.low;
                if (highmark)
                        *highmark = bufev->wm_read.high;
+               BEV_UNLOCK(bufev);
+               return 0;
        }
-       BEV_UNLOCK(bufev);
+       return -1;
 }
 
 int
index 137ad24797feda682f293f3f516bf0963e686c6a..6395e57a9f0c67faac04cc619dbafc7379b9aad5 100644 (file)
@@ -381,9 +381,10 @@ be_async_destruct(struct bufferevent *bev)
        bev_async_del_write(bev_async);
 
        fd = evbuffer_overlapped_get_fd_(bev->input);
-       if (bev_p->options & BEV_OPT_CLOSE_ON_FREE) {
-               /* XXXX possible double-close */
+       if (fd != (evutil_socket_t)INVALID_SOCKET &&
+               (bev_p->options & BEV_OPT_CLOSE_ON_FREE)) {
                evutil_closesocket(fd);
+               evbuffer_overlapped_set_fd_(bev->input, INVALID_SOCKET);
        }
 }
 
@@ -564,9 +565,9 @@ bufferevent_async_new_(struct event_base *base,
        event_overlapped_init_(&bev_a->read_overlapped, read_complete);
        event_overlapped_init_(&bev_a->write_overlapped, write_complete);
 
+       bufferevent_init_generic_timeout_cbs_(bev);
+
        bev_a->ok = fd >= 0;
-       if (bev_a->ok)
-               bufferevent_init_generic_timeout_cbs_(bev);
 
        return bev;
 err:
@@ -671,6 +672,7 @@ be_async_ctrl(struct bufferevent *bev, enum bufferevent_ctrl_op op,
                if (fd != (evutil_socket_t)INVALID_SOCKET &&
                    (bev_a->bev.options & BEV_OPT_CLOSE_ON_FREE)) {
                        closesocket(fd);
+                       evbuffer_overlapped_set_fd_(bev->input, INVALID_SOCKET);
                }
                bev_a->ok = 0;
                return 0;
index af71ebeeae912095e9acdfbcbab55f533dea8365..4d9be43e25db8c69743f712b5cbdc6afcec48e5b 100644 (file)
@@ -425,26 +425,34 @@ be_filter_readcb(struct bufferevent *underlying, void *me_)
        enum bufferevent_filter_result res;
        enum bufferevent_flush_mode state;
        struct bufferevent *bufev = downcast(bevf);
+       struct bufferevent_private *bufev_private = BEV_UPCAST(bufev);
        int processed_any = 0;
 
-       bufferevent_incref_and_lock_(bufev);
+       BEV_LOCK(bufev);
 
-       if (bevf->got_eof)
-               state = BEV_FINISHED;
-       else
-               state = BEV_NORMAL;
+       // It's possible our refcount is 0 at this point if another thread free'd our filterevent
+       EVUTIL_ASSERT(bufev_private->refcnt >= 0);
 
-       /* XXXX use return value */
-       res = be_filter_process_input(bevf, state, &processed_any);
-       (void)res;
+       // If our refcount is > 0
+       if (bufev_private->refcnt > 0) {
 
-       /* XXX This should be in process_input, not here.  There are
-        * other places that can call process-input, and they should
-        * force readcb calls as needed. */
-       if (processed_any)
-               bufferevent_trigger_nolock_(bufev, EV_READ, 0);
+               if (bevf->got_eof)
+                       state = BEV_FINISHED;
+               else
+                       state = BEV_NORMAL;
 
-       bufferevent_decref_and_unlock_(bufev);
+               /* 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
+                * force readcb calls as needed. */
+               if (processed_any)
+                       bufferevent_trigger_nolock_(bufev, EV_READ, 0);
+       }
+
+       BEV_UNLOCK(bufev);
 }
 
 /* Called when the underlying socket has drained enough that we can write to
@@ -454,11 +462,20 @@ be_filter_writecb(struct bufferevent *underlying, void *me_)
 {
        struct bufferevent_filtered *bevf = me_;
        struct bufferevent *bev = downcast(bevf);
+       struct bufferevent_private *bufev_private = BEV_UPCAST(bev);
        int processed_any = 0;
 
-       bufferevent_incref_and_lock_(bev);
-       be_filter_process_output(bevf, BEV_NORMAL, &processed_any);
-       bufferevent_decref_and_unlock_(bev);
+       BEV_LOCK(bev);
+
+       // It's possible our refcount is 0 at this point if another thread free'd our filterevent
+       EVUTIL_ASSERT(bufev_private->refcnt >= 0);
+
+       // If our refcount is > 0
+       if (bufev_private->refcnt > 0) {
+               be_filter_process_output(bevf, BEV_NORMAL, &processed_any);
+       }
+
+       BEV_UNLOCK(bev);
 }
 
 /* Called when the underlying socket has given us an error */
@@ -467,11 +484,21 @@ be_filter_eventcb(struct bufferevent *underlying, short what, void *me_)
 {
        struct bufferevent_filtered *bevf = me_;
        struct bufferevent *bev = downcast(bevf);
+       struct bufferevent_private *bufev_private = BEV_UPCAST(bev);
+
+       BEV_LOCK(bev);
+
+       // It's possible our refcount is 0 at this point if another thread free'd our filterevent
+       EVUTIL_ASSERT(bufev_private->refcnt >= 0);
+
+       // If our refcount is > 0
+       if (bufev_private->refcnt > 0) {
+
+               /* All we can really to is tell our own eventcb. */
+               bufferevent_run_eventcb_(bev, what, 0);
+       }
 
-       bufferevent_incref_and_lock_(bev);
-       /* All we can really to is tell our own eventcb. */
-       bufferevent_run_eventcb_(bev, what, 0);
-       bufferevent_decref_and_unlock_(bev);
+       BEV_UNLOCK(bev);
 }
 
 static int
index 423b34f10097e80552485717ce7c499f474d648a..b30f90ff2e946ff71dd7d1e89068ab731e294b83 100644 (file)
@@ -1276,6 +1276,8 @@ be_openssl_ctrl(struct bufferevent *bev,
                        SSL_set_bio(bev_ssl->ssl, bio, bio);
                        bev_ssl->fd_is_set = 1;
                }
+               if (data->fd == -1)
+                       bev_ssl->fd_is_set = 0;
                if (bev_ssl->state == BUFFEREVENT_SSL_OPEN)
                        return set_open_callbacks(bev_ssl, data->fd);
                else {
index 4340f23723c0bf8dc63d6b3e5e1d741edfd99111..8154e17be732dcb7a67f8efa3e51a2ac4d1e4440 100644 (file)
@@ -45,6 +45,8 @@
 struct bufferevent_pair {
        struct bufferevent_private bev;
        struct bufferevent_pair *partner;
+       /* For ->destruct() lock checking */
+       struct bufferevent_pair *unlinked_partner;
 };
 
 
@@ -265,11 +267,40 @@ be_pair_unlink(struct bufferevent *bev)
        struct bufferevent_pair *bev_p = upcast(bev);
 
        if (bev_p->partner) {
+               bev_p->unlinked_partner = bev_p->partner;
                bev_p->partner->partner = NULL;
                bev_p->partner = NULL;
        }
 }
 
+/* Free *shared* lock in the latest be (since we share it between two of them). */
+static void
+be_pair_destruct(struct bufferevent *bev)
+{
+       struct bufferevent_pair *bev_p = upcast(bev);
+
+       /* Transfer ownership of the lock into partner, otherwise we will use
+        * already free'd lock during freeing second bev, see next example:
+        *
+        * bev1->own_lock = 1
+        * bev2->own_lock = 0
+        * bev2->lock = bev1->lock
+        *
+        * bufferevent_free(bev1) # refcnt == 0 -> unlink
+        * bufferevent_free(bev2) # refcnt == 0 -> unlink
+        *
+        * event_base_free() -> finilizers -> EVTHREAD_FREE_LOCK(bev1->lock)
+        *                                 -> BEV_LOCK(bev2->lock) <-- already freed
+        *
+        * Where bev1 == pair[0], bev2 == pair[1].
+        */
+       if (bev_p->unlinked_partner && bev_p->bev.own_lock) {
+               bev_p->unlinked_partner->bev.own_lock = 1;
+               bev_p->bev.own_lock = 0;
+       }
+       bev_p->unlinked_partner = NULL;
+}
+
 static int
 be_pair_flush(struct bufferevent *bev, short iotype,
     enum bufferevent_flush_mode mode)
@@ -320,7 +351,7 @@ const struct bufferevent_ops bufferevent_ops_pair = {
        be_pair_enable,
        be_pair_disable,
        be_pair_unlink,
-       NULL, /* be_pair_destruct, */
+       be_pair_destruct,
        bufferevent_generic_adj_timeouts_,
        be_pair_flush,
        NULL, /* ctrl */
index c60c7ace87f6e3245cdf3f4a7272bbe095a2d381..2cdc74f16d8238912621a92e53f5e98499d32213 100644 (file)
@@ -5,18 +5,17 @@ dnl See LICENSE for copying information.
 dnl
 dnl Original version Dug Song <dugsong@monkey.org>
 
-AC_INIT(libevent,2.1.3-alpha-dev)
+AC_INIT(libevent,2.1.5-beta)
 AC_PREREQ(2.59)
 AC_CONFIG_SRCDIR(event.c)
 
 AC_CONFIG_MACRO_DIR([m4])
 AC_CONFIG_AUX_DIR([build-aux])
-
 AM_INIT_AUTOMAKE
 dnl AM_SILENT_RULES req. automake 1.11.  [no] defaults V=1
 m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
 AC_CONFIG_HEADERS(config.h  evconfig-private.h:evconfig-private.h.in)
-AC_DEFINE(NUMERIC_VERSION, 0x02010301, [Numeric representation of the version])
+AC_DEFINE(NUMERIC_VERSION, 0x02010500, [Numeric representation of the version])
 
 dnl Initialize prefix.
 if test "$prefix" = "NONE"; then
@@ -113,6 +112,9 @@ AC_ARG_ENABLE([libevent-install],
 AC_ARG_ENABLE([libevent-regress],
      AS_HELP_STRING([--disable-libevent-regress, skip regress in make check]),
        [], [enable_libevent_regress=yes])
+AC_ARG_ENABLE([samples],
+     AS_HELP_STRING([--disable-samples, skip building of sample programs]),
+       [], [enable_samples=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])
@@ -129,6 +131,7 @@ dnl   the command line with --enable-shared and --disable-shared.
 dnl AC_DISABLE_SHARED
 AC_SUBST(LIBTOOL_DEPS)
 
+AM_CONDITIONAL([BUILD_SAMPLES], [test "$enable_samples" = "yes"])
 AM_CONDITIONAL([BUILD_REGRESS], [test "$enable_libevent_regress" = "yes"])
 
 dnl Checks for libraries.
@@ -724,22 +727,16 @@ AC_TRY_COMPILE([],
 # check if we can compile with pthreads
 have_pthreads=no
 if test x$bwin32 != xtrue && test "$enable_thread_support" != "no"; then
-    OL_THREAD_CHECK([
-       have_pthreads=yes
-       PTHREAD_LIBS="$LTHREAD_LIBS"
-       CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
-       AC_CHECK_SIZEOF(
-           [pthread_t],
-           [],
-           [
-               AC_INCLUDES_DEFAULT()
-               #include <pthread.h>
-           ]
-       )
-    ])
+  ACX_PTHREAD([
+       AC_DEFINE(HAVE_PTHREADS, 1,
+               [Define if we have pthreads on this system])
+       have_pthreads=yes])
+  CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+  AC_CHECK_SIZEOF(pthread_t, ,
+     [AC_INCLUDES_DEFAULT()
+      #include <pthread.h> ]
+  )
 fi
-AC_SUBST([PTHREAD_LIBS])
-AC_SUBST([PTHREAD_CFLAGS])
 AM_CONDITIONAL([PTHREADS], [test "$have_pthreads" != "no" && test "$enable_thread_support" != "no"])
 
 # check if we should compile locking into the library
index fb67ec0957257603433b9418d3f971f0ab3ed41c..cf4bddc80ea86c0ebbe42e98c82ae78cf1934b25 100644 (file)
@@ -155,6 +155,18 @@ struct evbuffer {
        struct bufferevent *parent;
 };
 
+#if EVENT__SIZEOF_OFF_T < EVENT__SIZEOF_SIZE_T
+typedef ev_ssize_t ev_misalign_t;
+#define EVBUFFER_CHAIN_MAX ((size_t)EV_SSIZE_MAX)
+#else
+typedef ev_off_t ev_misalign_t;
+#if EVENT__SIZEOF_OFF_T > EVENT__SIZEOF_SIZE_T
+#define EVBUFFER_CHAIN_MAX EV_SIZE_MAX
+#else
+#define EVBUFFER_CHAIN_MAX ((size_t)EV_SSIZE_MAX)
+#endif
+#endif
+
 /** A single item in an evbuffer. */
 struct evbuffer_chain {
        /** points to next buffer in the chain */
@@ -165,7 +177,7 @@ struct evbuffer_chain {
 
        /** unused space at the beginning of buffer or an offset into a
         * file for sendfile buffers. */
-       ev_off_t misalign;
+       ev_misalign_t misalign;
 
        /** Offset into buffer + misalign at which to start writing.
         * In other words, the total number of bytes actually stored
index 59c3abe18655ddd367d3421999e8a8b2e8264823..60f4db5c5fba1b0fc1b0e5849f1d473ae1c4dc50 100644 (file)
@@ -541,6 +541,17 @@ nameserver_probe_failed(struct nameserver *const ns) {
        }
 }
 
+static void
+request_swap_ns(struct request *req, struct nameserver *ns) {
+       if (ns && req->ns != ns) {
+               EVUTIL_ASSERT(req->ns->requests_inflight > 0);
+               req->ns->requests_inflight--;
+               ns->requests_inflight++;
+
+               req->ns = ns;
+       }
+}
+
 /* called when a nameserver has been deemed to have failed. For example, too */
 /* many packets have timed out etc */
 static void
@@ -595,7 +606,7 @@ nameserver_failed(struct nameserver *const ns, const char *msg) {
                                if (req->tx_count == 0 && req->ns == ns) {
                                        /* still waiting to go out, can be moved */
                                        /* to another server */
-                                       req->ns = nameserver_pick(base);
+                                       request_swap_ns(req, nameserver_pick(base));
                                }
                                req = req->next;
                        } while (req != started_at);
@@ -659,6 +670,7 @@ request_finished(struct request *const req, struct request **head, int free_hand
            req->ns->requests_inflight == 0 &&
            req->base->disable_when_inactive) {
                event_del(&req->ns->event);
+               evtimer_del(&req->ns->timeout_event);
        }
 
        if (!req->request_appended) {
@@ -707,7 +719,7 @@ request_reissue(struct request *req) {
        /* the last nameserver should have been marked as failing */
        /* by the caller of this function, therefore pick will try */
        /* not to return it */
-       req->ns = nameserver_pick(req->base);
+       request_swap_ns(req, nameserver_pick(req->base));
        if (req->ns == last_ns) {
                /* ... but pick did return it */
                /* not a lot of point in trying again with the */
@@ -2158,29 +2170,30 @@ evdns_request_timeout_callback(evutil_socket_t fd, short events, void *arg) {
        log(EVDNS_LOG_DEBUG, "Request %p timed out", arg);
        EVDNS_LOCK(base);
 
-       req->ns->timedout++;
-       if (req->ns->timedout > req->base->global_max_nameserver_timeout) {
-               req->ns->timedout = 0;
-               nameserver_failed(req->ns, "request timed out.");
-       }
-
        if (req->tx_count >= req->base->global_max_retransmits) {
+               struct nameserver *ns = req->ns;
                /* this request has failed */
                log(EVDNS_LOG_DEBUG, "Giving up on request %p; tx_count==%d",
                    arg, req->tx_count);
                reply_schedule_callback(req, 0, DNS_ERR_TIMEOUT, NULL);
+
                request_finished(req, &REQ_HEAD(req->base, req->trans_id), 1);
+               nameserver_failed(ns, "request timed out.");
        } else {
                /* retransmit it */
-               struct nameserver *new_ns;
                log(EVDNS_LOG_DEBUG, "Retransmitting request %p; tx_count==%d",
                    arg, req->tx_count);
                (void) evtimer_del(&req->timeout_event);
-               new_ns = nameserver_pick(base);
-               if (new_ns)
-                       req->ns = new_ns;
+               request_swap_ns(req, nameserver_pick(base));
                evdns_request_transmit(req);
+
+               req->ns->timedout++;
+               if (req->ns->timedout > req->base->global_max_nameserver_timeout) {
+                       req->ns->timedout = 0;
+                       nameserver_failed(req->ns, "request timed out.");
+               }
        }
+
        EVDNS_UNLOCK(base);
 }
 
@@ -2639,6 +2652,34 @@ evdns_base_nameserver_sockaddr_add(struct evdns_base *base,
        return res;
 }
 
+int
+evdns_base_get_nameserver_addr(struct evdns_base *base, int idx,
+    struct sockaddr *sa, ev_socklen_t len)
+{
+       int result = -1;
+       int i;
+       struct nameserver *server;
+       EVDNS_LOCK(base);
+       server = base->server_head;
+       for (i = 0; i < idx && server; ++i, server = server->next) {
+               if (server->next == base->server_head)
+                       goto done;
+       }
+       if (! server)
+               goto done;
+
+       if (server->addrlen > len) {
+               result = (int) server->addrlen;
+               goto done;
+       }
+
+       memcpy(sa, &server->address, server->addrlen);
+       result = (int) server->addrlen;
+done:
+       EVDNS_UNLOCK(base);
+       return result;
+}
+
 /* remove from the queue */
 static void
 evdns_request_remove(struct request *req, struct request **head)
@@ -3311,7 +3352,7 @@ strtoint(const char *const str)
 
 /* Parse a number of seconds into a timeval; return -1 on error. */
 static int
-strtotimeval(const char *const str, struct timeval *out)
+evdns_strtotimeval(const char *const str, struct timeval *out)
 {
        double d;
        char *endptr;
@@ -3414,13 +3455,13 @@ evdns_base_set_option_impl(struct evdns_base *base,
                base->global_search_state->ndots = ndots;
        } else if (str_matches_option(option, "timeout:")) {
                struct timeval tv;
-               if (strtotimeval(val, &tv) == -1) return -1;
+               if (evdns_strtotimeval(val, &tv) == -1) return -1;
                if (!(flags & DNS_OPTION_MISC)) return 0;
                log(EVDNS_LOG_DEBUG, "Setting timeout to %s", val);
                memcpy(&base->global_timeout, &tv, sizeof(struct timeval));
        } else if (str_matches_option(option, "getaddrinfo-allow-skew:")) {
                struct timeval tv;
-               if (strtotimeval(val, &tv) == -1) return -1;
+               if (evdns_strtotimeval(val, &tv) == -1) return -1;
                if (!(flags & DNS_OPTION_MISC)) return 0;
                log(EVDNS_LOG_DEBUG, "Setting getaddrinfo-allow-skew to %s",
                    val);
@@ -3462,7 +3503,7 @@ evdns_base_set_option_impl(struct evdns_base *base,
                base->global_outgoing_addrlen = len;
        } else if (str_matches_option(option, "initial-probe-timeout:")) {
                struct timeval tv;
-               if (strtotimeval(val, &tv) == -1) return -1;
+               if (evdns_strtotimeval(val, &tv) == -1) return -1;
                if (tv.tv_sec > 3600)
                        tv.tv_sec = 3600;
                if (!(flags & DNS_OPTION_MISC)) return 0;
@@ -3555,8 +3596,8 @@ evdns_get_default_hosts_filename(void)
 
        if (! SHGetSpecialFolderPathA(NULL, path, CSIDL_SYSTEM, 0))
                return NULL;
-       len_out = strlen(path)+strlen(hostfile);
-       path_out = mm_malloc(len_out+1);
+       len_out = strlen(path)+strlen(hostfile)+1;
+       path_out = mm_malloc(len_out);
        evutil_snprintf(path_out, len_out, "%s%s", path, hostfile);
        return path_out;
 #else
@@ -3826,17 +3867,18 @@ evdns_base_config_windows_nameservers(struct evdns_base *base)
        if (base == NULL)
                return -1;
        EVDNS_LOCK(base);
+       fname = evdns_get_default_hosts_filename();
+       log(EVDNS_LOG_DEBUG, "Loading hosts entries from %s", fname);
+       evdns_base_load_hosts(base, fname);
+       if (fname)
+               mm_free(fname);
+
        if (load_nameservers_with_getnetworkparams(base) == 0) {
                EVDNS_UNLOCK(base);
                return 0;
        }
        r = load_nameservers_from_registry(base);
 
-       fname = evdns_get_default_hosts_filename();
-       evdns_base_load_hosts(base, fname);
-       if (fname)
-               mm_free(fname);
-
        EVDNS_UNLOCK(base);
        return r;
 }
@@ -3973,6 +4015,10 @@ evdns_nameserver_free(struct nameserver *server)
        event_debug_unassign(&server->event);
        if (server->state == 0)
                (void) event_del(&server->timeout_event);
+       if (server->probe_request) {
+               evdns_cancel_request(server->base, server->probe_request);
+               server->probe_request = NULL;
+       }
        event_debug_unassign(&server->timeout_event);
        mm_free(server);
 }
@@ -3988,6 +4034,15 @@ evdns_base_free_and_unlock(struct evdns_base *base, int fail_requests)
 
        /* TODO(nickm) we might need to refcount here. */
 
+       for (server = base->server_head; server; server = server_next) {
+               server_next = server->next;
+               evdns_nameserver_free(server);
+               if (server_next == base->server_head)
+                       break;
+       }
+       base->server_head = NULL;
+       base->global_good_nameservers = 0;
+
        for (i = 0; i < base->n_req_heads; ++i) {
                while (base->req_heads[i]) {
                        if (fail_requests)
@@ -4002,14 +4057,6 @@ evdns_base_free_and_unlock(struct evdns_base *base, int fail_requests)
        }
        base->global_requests_inflight = base->global_requests_waiting = 0;
 
-       for (server = base->server_head; server; server = server_next) {
-               server_next = server->next;
-               evdns_nameserver_free(server);
-               if (server_next == base->server_head)
-                       break;
-       }
-       base->server_head = NULL;
-       base->global_good_nameservers = 0;
 
        if (base->global_search_state) {
                for (dom = base->global_search_state->head; dom; dom = dom_next) {
@@ -4663,7 +4710,7 @@ evdns_getaddrinfo(struct evdns_base *dns_base,
                data->ipv4_request.r = evdns_base_resolve_ipv4(dns_base,
                    nodename, 0, evdns_getaddrinfo_gotresolve,
                    &data->ipv4_request);
-               if (want_cname)
+               if (want_cname && data->ipv4_request.r)
                        data->ipv4_request.r->current_req->put_cname_in_ptr =
                            &data->cname_result;
        }
@@ -4674,7 +4721,7 @@ evdns_getaddrinfo(struct evdns_base *dns_base,
                data->ipv6_request.r = evdns_base_resolve_ipv6(dns_base,
                    nodename, 0, evdns_getaddrinfo_gotresolve,
                    &data->ipv6_request);
-               if (want_cname)
+               if (want_cname && data->ipv6_request.r)
                        data->ipv6_request.r->current_req->put_cname_in_ptr =
                            &data->cname_result;
        }
index 01f0e14226c9e28e49a6f9ca3d13df03dc7f10e1..af4a6e05e677491bbb0421f4a19b766562d36b5d 100644 (file)
@@ -526,22 +526,24 @@ event_enable_debug_mode(void)
 #endif
 }
 
-#if 0
 void
 event_disable_debug_mode(void)
 {
+#ifndef EVENT__DISABLE_DEBUG_MODE
        struct event_debug_entry **ent, *victim;
 
        EVLOCK_LOCK(event_debug_map_lock_, 0);
        for (ent = HT_START(event_debug_map, &global_debug_map); ent; ) {
                victim = *ent;
-               ent = HT_NEXT_RMV(event_debug_map,&global_debug_map, ent);
+               ent = HT_NEXT_RMV(event_debug_map, &global_debug_map, ent);
                mm_free(victim);
        }
        HT_CLEAR(event_debug_map, &global_debug_map);
        EVLOCK_UNLOCK(event_debug_map_lock_ , 0);
-}
+
+       event_debug_mode_on_  = 0;
 #endif
+}
 
 struct event_base *
 event_base_new_with_config(const struct event_config *cfg)
@@ -993,6 +995,21 @@ done:
        return (res);
 }
 
+/* Get the monotonic time for this event_base' timer */
+int
+event_gettime_monotonic(struct event_base *base, struct timeval *tv)
+{
+  int rv = -1;
+
+  if (base && tv) {
+    EVBASE_ACQUIRE_LOCK(base, th_base_lock);
+    rv = evutil_gettime_monotonic_(&(base->monotonic_timer), tv);
+    EVBASE_RELEASE_LOCK(base, th_base_lock);
+  }
+
+  return rv;
+}
+
 const char **
 event_get_supported_methods(void)
 {
@@ -1454,10 +1471,13 @@ done:
 static inline void
 event_persist_closure(struct event_base *base, struct event *ev)
 {
-
-       // Define our callback, we use this to store our callback before it's executed
        void (*evcb_callback)(evutil_socket_t, short, void *);
 
+        // Other fields of *ev that must be stored before executing
+        evutil_socket_t evcb_fd;
+        short evcb_res;
+        void *evcb_arg;
+
        /* reschedule the persistent event if we have a timeout. */
        if (ev->ev_io_timeout.tv_sec || ev->ev_io_timeout.tv_usec) {
                /* If there was a timeout, we want it to run at an interval of
@@ -1501,13 +1521,16 @@ event_persist_closure(struct event_base *base, struct event *ev)
        }
 
        // Save our callback before we release the lock
-       evcb_callback = *ev->ev_callback;
+       evcb_callback = ev->ev_callback;
+        evcb_fd = ev->ev_fd;
+        evcb_res = ev->ev_res;
+        evcb_arg = ev->ev_arg;
 
        // Release the lock
        EVBASE_RELEASE_LOCK(base, th_base_lock);
 
        // Execute the callback
-       (evcb_callback)(ev->ev_fd, ev->ev_res, ev->ev_arg);
+        (evcb_callback)(evcb_fd, evcb_res, evcb_arg);
 }
 
 /*
@@ -1569,8 +1592,9 @@ event_process_active_single_queue(struct event_base *base,
                        event_persist_closure(base, ev);
                        break;
                case EV_CLOSURE_EVENT: {
+                       void (*evcb_callback)(evutil_socket_t, short, void *);
                        EVUTIL_ASSERT(ev != NULL);
-                       void (*evcb_callback)(evutil_socket_t, short, void *) = *ev->ev_callback;
+                       evcb_callback = *ev->ev_callback;
                        EVBASE_RELEASE_LOCK(base, th_base_lock);
                        evcb_callback(ev->ev_fd, ev->ev_res, ev->ev_arg);
                }
@@ -1583,14 +1607,16 @@ event_process_active_single_queue(struct event_base *base,
                break;
                case EV_CLOSURE_EVENT_FINALIZE:
                case EV_CLOSURE_EVENT_FINALIZE_FREE: {
+                       void (*evcb_evfinalize)(struct event *, void *);
+                       int evcb_closure = evcb->evcb_closure;
                        EVUTIL_ASSERT(ev != NULL);
-                       void (*evcb_evfinalize)(struct event *, void *) = ev->ev_evcallback.evcb_cb_union.evcb_evfinalize;
                        base->current_event = NULL;
+                       evcb_evfinalize = ev->ev_evcallback.evcb_cb_union.evcb_evfinalize;
                        EVUTIL_ASSERT((evcb->evcb_flags & EVLIST_FINALIZING));
                        EVBASE_RELEASE_LOCK(base, th_base_lock);
                        evcb_evfinalize(ev, ev->ev_arg);
                        event_debug_note_teardown_(ev);
-                       if (evcb->evcb_closure == EV_CLOSURE_EVENT_FINALIZE_FREE)
+                       if (evcb_closure == EV_CLOSURE_EVENT_FINALIZE_FREE)
                                mm_free(ev);
                }
                break;
@@ -3739,6 +3765,7 @@ event_free_debug_globals_locks(void)
        if (event_debug_map_lock_ != NULL) {
                EVTHREAD_FREE_LOCK(event_debug_map_lock_, 0);
                event_debug_map_lock_ = NULL;
+               evthreadimpl_disable_lock_debugging_();
        }
 #endif /* EVENT__DISABLE_DEBUG_MODE */
 #endif /* EVENT__DISABLE_THREAD_SUPPORT */
@@ -3774,6 +3801,7 @@ event_free_globals(void)
 void
 libevent_global_shutdown(void)
 {
+       event_disable_debug_mode();
        event_free_globals();
 }
 
index 7edd3da5d956122e669232d1c0a26195be8d5d1d..64b100b82510aca72901afae7b78e6f0a61f239f 100644 (file)
@@ -207,10 +207,19 @@ decode_tag_internal(ev_uint32_t *ptag, struct evbuffer *evbuf, int dodrain)
         */
        data = evbuffer_pullup(
                evbuf, len < sizeof(number) + 1 ? len : sizeof(number) + 1);
+       if (!data)
+               return (-1);
 
        while (count++ < len) {
                ev_uint8_t lower = *data++;
-               number |= (lower & 0x7f) << shift;
+               if (shift >= 28) {
+                       /* Make sure it fits into 32 bits */
+                       if (shift > 28)
+                               return (-1);
+                       if ((lower & 0x7f) > 15)
+                               return (-1);
+               }
+               number |= (lower & (unsigned)0x7f) << shift;
                shift += 7;
 
                if (!(lower & 0x80)) {
@@ -313,6 +322,8 @@ do {                                                                        \
                                                                        \
        /* XXX(niels): faster? */                                       \
        data = evbuffer_pullup(evbuf, offset + 1) + offset;             \
+       if (!data)                                                      \
+               return (-1);                                            \
                                                                        \
        nibbles = ((data[0] & 0xf0) >> 4) + 1;                          \
        if (nibbles > maxnibbles || (nibbles >> 1) + 1 > len)           \
@@ -320,6 +331,8 @@ do {                                                                        \
        len = (nibbles >> 1) + 1;                                       \
                                                                        \
        data = evbuffer_pullup(evbuf, offset + len) + offset;           \
+       if (!data)                                                      \
+               return (-1);                                            \
                                                                        \
        while (nibbles > 0) {                                           \
                number <<= 4;                                           \
index e53d06e0f40cc6454829efe0fadd1165f67493ee..9eb376386de4daf471bb7464f08d826916846d72 100644 (file)
@@ -27,6 +27,7 @@
 #ifndef EVRPC_INTERNAL_H_INCLUDED_
 #define EVRPC_INTERNAL_H_INCLUDED_
 
+#include "event2/http.h"
 #include "http-internal.h"
 
 struct evrpc;
index 346b2bb9277470878915ecfc4f148411760d569c..16adf167d2e5bf7e40012aa9a1dc8a76b970d15e 100644 (file)
@@ -376,6 +376,13 @@ int evsig_global_setup_locks_(const int enable_locks);
 int evutil_global_setup_locks_(const int enable_locks);
 int evutil_secure_rng_global_setup_locks_(const int enable_locks);
 
+/** Return current evthread_lock_callbacks */
+struct evthread_lock_callbacks *evthread_get_lock_callbacks();
+/** Return current evthread_condition_callbacks */
+struct evthread_condition_callbacks *evthread_get_condition_callbacks();
+/** Disable locking for internal usage (like global shutdown) */
+void evthreadimpl_disable_lock_debugging_(void);
+
 #endif
 
 #ifdef __cplusplus
index 4da5d24e80408d683c5d10408de81b179d7a4c9f..02dab7a8057e58f0fe64b0175ed016635d442eec 100644 (file)
@@ -69,12 +69,25 @@ evthread_set_id_callback(unsigned long (*id_fn)(void))
        evthread_id_fn_ = id_fn;
 }
 
+struct evthread_lock_callbacks *evthread_get_lock_callbacks()
+{
+       return evthread_lock_debugging_enabled_
+           ? &original_lock_fns_ : &evthread_lock_fns_;
+}
+struct evthread_condition_callbacks *evthread_get_condition_callbacks()
+{
+       return evthread_lock_debugging_enabled_
+           ? &original_cond_fns_ : &evthread_cond_fns_;
+}
+void evthreadimpl_disable_lock_debugging_(void)
+{
+       evthread_lock_debugging_enabled_ = 0;
+}
+
 int
 evthread_set_lock_callbacks(const struct evthread_lock_callbacks *cbs)
 {
-       struct evthread_lock_callbacks *target =
-           evthread_lock_debugging_enabled_
-           ? &original_lock_fns_ : &evthread_lock_fns_;
+       struct evthread_lock_callbacks *target = evthread_get_lock_callbacks();
 
        if (!cbs) {
                if (target->alloc)
@@ -109,9 +122,7 @@ evthread_set_lock_callbacks(const struct evthread_lock_callbacks *cbs)
 int
 evthread_set_condition_callbacks(const struct evthread_condition_callbacks *cbs)
 {
-       struct evthread_condition_callbacks *target =
-           evthread_lock_debugging_enabled_
-           ? &original_cond_fns_ : &evthread_cond_fns_;
+       struct evthread_condition_callbacks *target = evthread_get_condition_callbacks();
 
        if (!cbs) {
                if (target->alloc_condition)
index c28caded59cad6704b076940c732d229e1b25476..3d72e4032450d89498ad84467aaa8df4ec848abc 100644 (file)
@@ -367,6 +367,20 @@ evutil_make_listen_socket_reuseable(evutil_socket_t sock)
 #endif
 }
 
+int
+evutil_make_listen_socket_reuseable_port(evutil_socket_t sock)
+{
+#if defined __linux__ && defined(SO_REUSEPORT)
+       int one = 1;
+       /* REUSEPORT on Linux 3.9+ means, "Multiple servers (processes or
+        * threads) can bind to the same port if they each set the option. */
+       return setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (void*) &one,
+           (ev_socklen_t)sizeof(one));
+#else
+       return 0;
+#endif
+}
+
 int
 evutil_make_tcp_listen_socket_deferred(evutil_socket_t sock)
 {
@@ -652,7 +666,7 @@ evutil_check_ifaddrs(void)
           "GetAdaptersInfo", but that's deprecated; let's just try
           GetAdaptersAddresses and fall back to connect+getsockname.
        */
-       HANDLE lib = evutil_load_windows_system_library_(TEXT("ihplapi.dll"));
+       HMODULE lib = evutil_load_windows_system_library_(TEXT("ihplapi.dll"));
        GetAdaptersAddresses_fn_t fn;
        ULONG size, res;
        IP_ADAPTER_ADDRESSES *addresses = NULL, *address;
@@ -1918,15 +1932,15 @@ evutil_inet_pton(int af, const char *src, void *dst)
        return inet_pton(af, src, dst);
 #else
        if (af == AF_INET) {
-               int a,b,c,d;
+               unsigned a,b,c,d;
                char more;
                struct in_addr *addr = dst;
-               if (sscanf(src, "%d.%d.%d.%d%c", &a,&b,&c,&d,&more) != 4)
+               if (sscanf(src, "%u.%u.%u.%u%c", &a,&b,&c,&d,&more) != 4)
                        return 0;
-               if (a < 0 || a > 255) return 0;
-               if (b < 0 || b > 255) return 0;
-               if (c < 0 || c > 255) return 0;
-               if (d < 0 || d > 255) return 0;
+               if (a > 255) return 0;
+               if (b > 255) return 0;
+               if (c > 255) return 0;
+               if (d > 255) return 0;
                addr->s_addr = htonl((a<<24) | (b<<16) | (c<<8) | d);
                return 1;
 #ifdef AF_INET6
@@ -1941,7 +1955,7 @@ evutil_inet_pton(int af, const char *src, void *dst)
                else if (!dot)
                        eow = src+strlen(src);
                else {
-                       int byte1,byte2,byte3,byte4;
+                       unsigned byte1,byte2,byte3,byte4;
                        char more;
                        for (eow = dot-1; eow >= src && EVUTIL_ISDIGIT_(*eow); --eow)
                                ;
@@ -1949,14 +1963,14 @@ evutil_inet_pton(int af, const char *src, void *dst)
 
                        /* We use "scanf" because some platform inet_aton()s are too lax
                         * about IPv4 addresses of the form "1.2.3" */
-                       if (sscanf(eow, "%d.%d.%d.%d%c",
+                       if (sscanf(eow, "%u.%u.%u.%u%c",
                                           &byte1,&byte2,&byte3,&byte4,&more) != 4)
                                return 0;
 
-                       if (byte1 > 255 || byte1 < 0 ||
-                               byte2 > 255 || byte2 < 0 ||
-                               byte3 > 255 || byte3 < 0 ||
-                               byte4 > 255 || byte4 < 0)
+                       if (byte1 > 255 ||
+                           byte2 > 255 ||
+                           byte3 > 255 ||
+                           byte4 > 255)
                                return 0;
 
                        words[6] = (byte1<<8) | byte2;
@@ -2453,7 +2467,7 @@ evutil_hex_char_to_int_(char c)
 }
 
 #ifdef _WIN32
-HANDLE
+HMODULE
 evutil_load_windows_system_library_(const TCHAR *library_name)
 {
   TCHAR path[MAX_PATH];
index e433043e4d2bd008c2f1aa87f37bffa3bf8d5f19..8f53c66b68c0e403fd8f4d53cb73117dd75d03bb 100644 (file)
@@ -54,6 +54,7 @@
 #include "event2/util.h"
 #include "util-internal.h"
 #include "log-internal.h"
+#include "mm-internal.h"
 
 #ifndef EVENT__HAVE_GETTIMEOFDAY
 /* No gettimeofday; this must be windows. */
@@ -160,6 +161,55 @@ adjust_monotonic_time(struct evutil_monotonic_timer *base,
        base->last_time = *tv;
 }
 
+/*
+   Allocate a new struct evutil_monotonic_timer
+ */
+struct evutil_monotonic_timer *
+evutil_monotonic_timer_new(void)
+{
+  struct evutil_monotonic_timer *p = NULL;
+
+  p = mm_malloc(sizeof(*p));
+  if (!p) goto done;
+
+  memset(p, 0, sizeof(*p));
+
+ done:
+  return p;
+}
+
+/*
+   Free a struct evutil_monotonic_timer
+ */
+void
+evutil_monotonic_timer_free(struct evutil_monotonic_timer *timer)
+{
+  if (timer) {
+    mm_free(timer);
+  }
+}
+
+/*
+   Set up a struct evutil_monotonic_timer for initial use
+ */
+int
+evutil_configure_monotonic_time(struct evutil_monotonic_timer *timer,
+                                int flags)
+{
+  return evutil_configure_monotonic_time_(timer, flags);
+}
+
+/*
+   Query the current monotonic time
+ */
+int
+evutil_gettime_monotonic(struct evutil_monotonic_timer *timer,
+                         struct timeval *tp)
+{
+  return evutil_gettime_monotonic_(timer, tp);
+}
+
+
 #if defined(HAVE_POSIX_MONOTONIC)
 /* =====
    The POSIX clock_gettime() interface provides a few ways to get at a
index 8842f4cd75b24706ca4293384710e332f202bba2..50375bbaa94c0b3ae2610cfafc64a283550c46dc 100644 (file)
@@ -380,7 +380,6 @@ ht_string_hash_(const char *s)
   {                                                                     \
     if (head->hth_table)                                                \
       freefn(head->hth_table);                                          \
-    head->hth_table_length = 0;                                         \
     name##_HT_INIT(head);                                               \
   }                                                                     \
   /* Debugging helper: return false iff the representation of 'head' is \
index 82dd402a06264fba874bcc0a1e171a8efa0f2508..a83160c8341b8ae9e348f15526c13356c2581b7a 100644 (file)
@@ -74,6 +74,7 @@ struct evhttp_connection {
 #define EVHTTP_CON_INCOMING    0x0001  /* only one request on it ever */
 #define EVHTTP_CON_OUTGOING    0x0002  /* multiple requests possible */
 #define EVHTTP_CON_CLOSEDETECT  0x0004  /* detecting if persistent close */
+#define EVHTTP_CON_AUTOFREE 0x0008  /* set when we want to auto free the connection */
 
        struct timeval timeout;         /* timeout for events */
        int retry_cnt;                  /* retry count */
@@ -99,6 +100,7 @@ struct evhttp_connection {
 
        struct event_base *base;
        struct evdns_base *dns_base;
+       int ai_family;
 
        /* Saved conn_addr, to extract IP address from it.
         *
index 51470225e9bb53960e473c6f60e125d749ee41a0..dd8c9cffddfc77905f56038ee0cf50d0879d8089 100644 (file)
@@ -769,6 +769,7 @@ evhttp_connection_done(struct evhttp_connection *evcon)
 {
        struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
        int con_outgoing = evcon->flags & EVHTTP_CON_OUTGOING;
+       int free_evcon = 0;
 
        if (con_outgoing) {
                /* idle or close the connection */
@@ -801,6 +802,12 @@ evhttp_connection_done(struct evhttp_connection *evcon)
                         * need to detect if the other side closes it.
                         */
                        evhttp_connection_start_detectclose(evcon);
+               } else if ((evcon->flags & EVHTTP_CON_AUTOFREE)) {
+                       /*
+                        * If we have no more requests that need completion
+                        * and we're not waiting for the connection to close
+                        */
+                        free_evcon = 1;
                }
        } else {
                /*
@@ -819,6 +826,16 @@ evhttp_connection_done(struct evhttp_connection *evcon)
        if (con_outgoing && ((req->flags & EVHTTP_USER_OWNED) == 0)) {
                evhttp_request_free(req);
        }
+
+       /* If this was the last request of an outgoing connection and we're
+        * not waiting to receive a connection close event and we want to
+        * automatically free the connection. We check to ensure our request
+        * list is empty one last time just in case our callback added a
+        * new request.
+        */
+       if (free_evcon && TAILQ_FIRST(&evcon->requests) == NULL) {
+               evhttp_connection_free(evcon);
+       }
 }
 
 /*
@@ -1174,6 +1191,11 @@ evhttp_connection_free(struct evhttp_connection *evcon)
        mm_free(evcon);
 }
 
+void
+evhttp_connection_free_on_completion(struct evhttp_connection *evcon) {
+       evcon->flags |= EVHTTP_CON_AUTOFREE;
+}
+
 void
 evhttp_connection_set_local_address(struct evhttp_connection *evcon,
     const char *address)
@@ -1243,6 +1265,7 @@ evhttp_connection_reset_(struct evhttp_connection *evcon)
 
                shutdown(evcon->fd, EVUTIL_SHUT_WR);
                evutil_closesocket(evcon->fd);
+               bufferevent_setfd(evcon->bufev, -1);
                evcon->fd = -1;
        }
 
@@ -1285,6 +1308,7 @@ evhttp_connection_cb_cleanup(struct evhttp_connection *evcon)
 {
        struct evcon_requestq requests;
 
+       evhttp_connection_reset_(evcon);
        if (evcon->retry_max < 0 || evcon->retry_cnt < evcon->retry_max) {
                struct timeval tv_retry = evcon->initial_retry_timeout;
                int i;
@@ -1306,7 +1330,6 @@ evhttp_connection_cb_cleanup(struct evhttp_connection *evcon)
                evcon->retry_cnt++;
                return;
        }
-       evhttp_connection_reset_(evcon);
 
        /*
         * User callback can do evhttp_make_request() on the same
@@ -1385,6 +1408,17 @@ evhttp_error_cb(struct bufferevent *bufev, short what, void *arg)
                 */
                EVUTIL_ASSERT(evcon->state == EVCON_IDLE);
                evhttp_connection_reset_(evcon);
+
+               /*
+                * If we have no more requests that need completion
+                * and we want to auto-free the connection when all
+                * requests have been completed.
+                */
+               if (TAILQ_FIRST(&evcon->requests) == NULL
+                 && (evcon->flags & EVHTTP_CON_OUTGOING)
+                 && (evcon->flags & EVHTTP_CON_AUTOFREE)) {
+                       evhttp_connection_free(evcon);
+               }
                return;
        }
 
@@ -2267,6 +2301,7 @@ evhttp_connection_base_bufferevent_new(struct event_base *base, struct evdns_bas
            evhttp_deferred_read_cb, evcon);
 
        evcon->dns_base = dnsbase;
+       evcon->ai_family = AF_UNSPEC;
 
        return (evcon);
 
@@ -2294,6 +2329,12 @@ evhttp_connection_base_new(struct event_base *base, struct evdns_base *dnsbase,
        return evhttp_connection_base_bufferevent_new(base, dnsbase, NULL, address, port);
 }
 
+void evhttp_connection_set_family(struct evhttp_connection *evcon,
+       int family)
+{
+       evcon->ai_family = family;
+}
+
 void
 evhttp_connection_set_base(struct evhttp_connection *evcon,
     struct event_base *base)
@@ -2419,7 +2460,7 @@ evhttp_connection_connect_(struct evhttp_connection *evcon)
        evcon->state = EVCON_CONNECTING;
 
        if (bufferevent_socket_connect_hostname(evcon->bufev, evcon->dns_base,
-               AF_UNSPEC, evcon->address, evcon->port) < 0) {
+               evcon->ai_family, evcon->address, evcon->port) < 0) {
                evcon->state = old_state;
                event_sock_warn(evcon->fd, "%s: connection to \"%s\" failed",
                    __func__, evcon->address);
@@ -4289,6 +4330,8 @@ parse_port(const char *s, const char *eos)
                portnum = (portnum * 10) + (*s - '0');
                if (portnum < 0)
                        return -1;
+               if (portnum > 65535)
+                       return -1;
                ++s;
        }
        return portnum;
index 839d6e7ca4c5402017a0679601e97c7a74b48613..468588b9f141c200c2ab310afd1e448dd643e70f 100644 (file)
@@ -105,13 +105,8 @@ struct evbuffer
 
     Used when repeatedly searching through a buffer.  Calling any function
     that modifies or re-packs the buffer contents may invalidate all
-    evbuffer_ptrs for that buffer.  Do not modify these values except with
-    evbuffer_ptr_set.
-
-    Used when repeatedly searching through a buffer.  Calls to any function
-    that modifies or re-packs the buffer contents may invalidate all
-    evbuffer_ptrs for that buffer.  Do not modify these values except with
-    evbuffer_ptr_set.
+    evbuffer_ptrs for that buffer.  Do not modify or contruct these values
+    except with evbuffer_ptr_set.
 
     An evbuffer_ptr can represent any position from the start of a buffer up
     to a position immediately after the end of a buffer.
@@ -787,7 +782,7 @@ enum evbuffer_ptr_how {
    There are two ways to use this function: you can call
       evbuffer_ptr_set(buf, &pos, N, EVBUFFER_PTR_SET)
    to move 'pos' to a position 'N' bytes after the start of the buffer, or
-      evbuffer_ptr_set(buf, &pos, N, EVBUFFER_PTR_SET)
+      evbuffer_ptr_set(buf, &pos, N, EVBUFFER_PTR_ADD)
    to move 'pos' forward by 'N' bytes.
 
    If evbuffer_ptr is not initialized, this function can only be called
index 46203b04f59601961268edd9799e36b11f86f251..fe8a74d348c635f04faed31032d4d9903b809f0e 100644 (file)
@@ -535,8 +535,9 @@ void bufferevent_setwatermark(struct bufferevent *bufev, short events,
     size_t lowmark, size_t highmark);
 
 /**
-  Retrieves the watermarks for read or write events. Result is undefined if
-  events contains both EV_READ and EV_WRITE.
+  Retrieves the watermarks for read or write events.
+  Returns non-zero if events contains not only EV_READ or EV_WRITE.
+  Returns zero if events equal EV_READ or EV_WRITE
 
   @param bufev the bufferevent to be examined
   @param events EV_READ or EV_WRITE
@@ -544,7 +545,7 @@ void bufferevent_setwatermark(struct bufferevent *bufev, short events,
   @param highmark receives the high watermark if not NULL
 */
 EVENT2_EXPORT_SYMBOL
-void bufferevent_getwatermark(struct bufferevent *bufev, short events,
+int bufferevent_getwatermark(struct bufferevent *bufev, short events,
     size_t *lowmark, size_t *highmark);
 
 /**
@@ -598,7 +599,7 @@ enum bufferevent_trigger_options {
        BEV_TRIG_IGNORE_WATERMARKS = (1<<16),
 
        /** defer even if the callbacks are not */
-       BEV_TRIG_DEFER_CALLBACKS = BEV_OPT_DEFER_CALLBACKS,
+       BEV_TRIG_DEFER_CALLBACKS = BEV_OPT_DEFER_CALLBACKS
 
        /* (Note: for internal reasons, these need to be disjoint from
         * bufferevent_options, except when they mean the same thing. */
index a00c83e6a37313172b911e6ff4438e58b7a2bff2..17cd86a2ec2df91f515b056619e67a1ca2fca700 100644 (file)
@@ -453,7 +453,7 @@ int evdns_base_set_option(struct evdns_base *base, const char *option, const cha
 
   @param base the evdns_base to which to apply this operation
   @param flags any of DNS_OPTION_NAMESERVERS|DNS_OPTION_SEARCH|DNS_OPTION_MISC|
-    DNS_OPTIONS_HOSTSFILE|DNS_OPTIONS_ALL
+    DNS_OPTION_HOSTSFILE|DNS_OPTIONS_ALL
   @param filename the path to the resolv.conf file
   @return 0 if successful, or various positive error codes if an error
     occurred (see above)
@@ -694,6 +694,22 @@ struct evdns_getaddrinfo_request *evdns_getaddrinfo(
 EVENT2_EXPORT_SYMBOL
 void evdns_getaddrinfo_cancel(struct evdns_getaddrinfo_request *req);
 
+/**
+   Retrieve the address of the 'idx'th configured nameserver.
+
+   @param base The evdns_base to examine.
+   @param idx The index of the nameserver to get the address of.
+   @param sa A location to receive the server's address.
+   @param len The number of bytes available at sa.
+
+   @return the number of bytes written into sa on success.  On failure, returns
+     -1 if idx is greater than the number of configured nameservers, or a
+     value greater than 'len' if len was not high enough.
+ */
+EVENT2_EXPORT_SYMBOL
+int evdns_base_get_nameserver_addr(struct evdns_base *base, int idx,
+    struct sockaddr *sa, ev_socklen_t len);
+
 #ifdef __cplusplus
 }
 #endif
index 6e2b884d440d5004a6a5e9fd431abadf67da8c52..6e0a4f04c739649fd205406ffc6bf0589b243600 100644 (file)
@@ -396,6 +396,12 @@ const char *event_base_get_method(const struct event_base *);
 EVENT2_EXPORT_SYMBOL
 const char **event_get_supported_methods(void);
 
+/** Query the current monotonic time from a the timer for a struct
+ * event_base.
+ */
+EVENT2_EXPORT_SYMBOL
+int event_gettime_monotonic(struct event_base *base, struct timeval *tp);
+
 /**
    @name event type flag
 
index 81f44b85523156c2760c32cca45868bf20d92c54..4284d5fc32bc21bffb8cde93c4422930616d0a67 100644 (file)
@@ -630,6 +630,12 @@ struct evhttp_connection *evhttp_connection_base_new(
        struct event_base *base, struct evdns_base *dnsbase,
        const char *address, unsigned short port);
 
+/**
+ * Set family hint for DNS requests.
+ */
+void evhttp_connection_set_family(struct evhttp_connection *evcon,
+       int family);
+
 /** Takes ownership of the request object
  *
  * Can be used in a request callback to keep onto the request until
@@ -669,6 +675,14 @@ void evhttp_connection_set_max_body_size(struct evhttp_connection* evcon,
 EVENT2_EXPORT_SYMBOL
 void evhttp_connection_free(struct evhttp_connection *evcon);
 
+/** Disowns a given connection object
+ *
+ * Can be used to tell libevent to free the connection object after
+ * the last request has completed or failed.
+ */
+EVENT2_EXPORT_SYMBOL
+void evhttp_connection_free_on_completion(struct evhttp_connection *evcon);
+
 /** sets the ip address from which http connections are made */
 EVENT2_EXPORT_SYMBOL
 void evhttp_connection_set_local_address(struct evhttp_connection *evcon,
index 8c77803d6d84ce19dcdfb15518a06413ca541ad1..84b4da055d8d24fa3edd1e4b1fa3f40f769991de 100644 (file)
@@ -88,6 +88,15 @@ typedef void (*evconnlistener_errorcb)(struct evconnlistener *, void *);
  * to use the option before it is actually bound.
  */
 #define LEV_OPT_DEFERRED_ACCEPT                (1u<<6)
+/** Flag: Indicates that we ask to allow multiple servers (processes or
+ * threads) to bind to the same port if they each set the option. 
+ * 
+ * SO_REUSEPORT is what most people would expect SO_REUSEADDR to be, however
+ * SO_REUSEPORT does not imply SO_REUSEADDR.
+ *
+ * This is only available on Linux and kernel 3.9+
+ */
+#define LEV_OPT_REUSEABLE_PORT         (1u<<7)
 
 /**
    Allocate a new evconnlistener object to listen for incoming TCP connections
index 14c6a25d7a86d1bb24578cd2579105fb05a9d5e2..b152a4b40b5142f090212b7c091a3e8e700dbc0a 100644 (file)
@@ -292,6 +292,62 @@ extern "C" {
 #define evutil_socket_t int
 #endif
 
+/**
+ * Structure to hold information about a monotonic timer
+ *
+ * Use this with evutil_configure_monotonic_time() and
+ * evutil_gettime_monotonic().
+ *
+ * This is an opaque structure; you can allocate one using
+ * evutil_monotonic_timer_new().
+ *
+ * @see evutil_monotonic_timer_new(), evutil_monotonic_timer_free(),
+ * evutil_configure_monotonic_time(), evutil_gettime_monotonic()
+ */
+struct evutil_monotonic_timer
+#ifdef EVENT_IN_DOXYGEN_
+{/*Empty body so that doxygen will generate documentation here.*/}
+#endif
+;
+
+#define EV_MONOT_PRECISE  1
+#define EV_MONOT_FALLBACK 2
+
+/** Allocate a new struct evutil_monotonic_timer for use with the
+ * evutil_configure_monotonic_time() and evutil_gettime_monotonic()
+ * functions.  You must configure the timer with
+ * evutil_configure_monotonic_time() before using it.
+ */
+EVENT2_EXPORT_SYMBOL
+struct evutil_monotonic_timer * evutil_monotonic_timer_new(void);
+
+/** Free a struct evutil_monotonic_timer that was allocated using
+ * evutil_monotonic_timer_new().
+ */
+EVENT2_EXPORT_SYMBOL
+void evutil_monotonic_timer_free(struct evutil_monotonic_timer *timer);
+
+/** Set up a struct evutil_monotonic_timer; flags can include
+ * EV_MONOT_PRECISE and EV_MONOT_FALLBACK.
+ */
+EVENT2_EXPORT_SYMBOL
+int evutil_configure_monotonic_time(struct evutil_monotonic_timer *timer,
+                                    int flags);
+
+/** Query the current monotonic time from a struct evutil_monotonic_timer
+ * previously configured with evutil_configure_monotonic_time().  Monotonic
+ * time is guaranteed never to run in reverse, but is not necessarily epoch-
+ * based, or relative to any other definite point.  Use it to make reliable
+ * measurements of elapsed time between events even when the system time
+ * may be changed.
+ *
+ * It is not safe to use this funtion on the same timer from multiple
+ * threads.
+ */
+EVENT2_EXPORT_SYMBOL
+int evutil_gettime_monotonic(struct evutil_monotonic_timer *timer,
+                             struct timeval *tp);
+
 /** Create two new sockets that are connected to each other.
 
     On Unix, this simply calls socketpair().  On Windows, it uses the
@@ -327,6 +383,19 @@ int evutil_make_socket_nonblocking(evutil_socket_t sock);
 EVENT2_EXPORT_SYMBOL
 int evutil_make_listen_socket_reuseable(evutil_socket_t sock);
 
+/** Do platform-specific operations to make a listener port reusable.
+
+    Specifically, we want to make sure that multiple programs which also
+    set the same socket option will be able to bind, listen at the same time.
+
+    This is a feature available only to Linux 3.9+
+
+    @param sock The socket to make reusable
+    @return 0 on success, -1 on failure
+ */
+EVENT2_EXPORT_SYMBOL
+int evutil_make_listen_socket_reuseable_port(evutil_socket_t sock);
+
 /** Do platform-specific operations as needed to close a socket upon a
     successful execution of one of the exec*() functions.
 
index 39334674244bb0828d2244d5d0479a2f34120936..a6578dfe1a57eb7e70777f4cc2797a70246168e7 100644 (file)
@@ -332,6 +332,23 @@ kq_dispatch(struct event_base *base, struct timeval *tv)
                         * on FreeBSD. */
                        case EINVAL:
                                continue;
+#if defined(__FreeBSD__) && defined(ENOTCAPABLE)
+                       /*
+                        * This currently occurs if an FD is closed
+                        * before the EV_DELETE makes it out via kevent().
+                        * The FreeBSD capabilities code sees the blank
+                        * capability set and rejects the request to
+                        * modify an event.
+                        *
+                        * To be strictly correct - when an FD is closed,
+                        * all the registered events are also removed.
+                        * Queuing EV_DELETE to a closed FD is wrong.
+                        * The event(s) should just be deleted from
+                        * the pending changelist.
+                        */
+                       case ENOTCAPABLE:
+                               continue;
+#endif
 
                        /* Can occur on a delete if the fd is closed. */
                        case EBADF:
index 3272c405ce6eeea844ccbde42c0632d32d7b49d1..172d2927c0c3c70198538b2711fe9100be968d6f 100644 (file)
@@ -235,6 +235,11 @@ evconnlistener_new_bind(struct event_base *base, evconnlistener_cb cb,
                        goto err;
        }
 
+       if (flags & LEV_OPT_REUSEABLE_PORT) {
+               if (evutil_make_listen_socket_reuseable_port(fd) < 0)
+                       goto err;
+       }
+
        if (flags & LEV_OPT_DEFERRED_ACCEPT) {
                if (evutil_make_tcp_listen_socket_deferred(fd) < 0)
                        goto err;
index 1cb89bc91b04ed7a3ec4a84d1889ce712411cf7e..cbb9c914dd8fd9e758419d6a5a43c5674cfe640e 100644 (file)
@@ -246,7 +246,10 @@ send_document_cb(struct evhttp_request *req, void *arg)
                        goto err;
 #endif
 
-               evbuffer_add_printf(evb, "<html>\n <head>\n"
+               evbuffer_add_printf(evb,
+                    "<!DOCTYPE html>\n"
+                    "<html>\n <head>\n"
+                    "  <meta charset='utf-8'>\n"
                    "  <title>%s</title>\n"
                    "  <base href='%s%s'>\n"
                    " </head>\n"
@@ -274,7 +277,7 @@ send_document_cb(struct evhttp_request *req, void *arg)
 #endif
                evbuffer_add_printf(evb, "</ul></body></html>\n");
 #ifdef _WIN32
-               CloseHandle(d);
+               FindClose(d);
 #else
                closedir(d);
 #endif
index e13ac4bd342f51cfc2369f2437cdade828a8933d..fbd5de8c59c2a8be4382a15a4182796d9919a3ca 100644 (file)
@@ -96,7 +96,7 @@ static void
 syntax(void)
 {
        fputs("Syntax:\n", stderr);
-       fputs("   https-client -url <https-url> [-data data-file.bin] [-ignore-cert]\n", stderr);
+       fputs("   https-client -url <https-url> [-data data-file.bin] [-ignore-cert] [-retries num]\n", stderr);
        fputs("Example:\n", stderr);
        fputs("   https-client -url https://ip.appspot.com/\n", stderr);
 
@@ -195,6 +195,7 @@ main(int argc, char **argv)
        const char *scheme, *host, *path, *query;
        char uri[256];
        int port;
+       int retries = 0;
 
        SSL_CTX *ssl_ctx;
        SSL *ssl;
@@ -221,6 +222,12 @@ main(int argc, char **argv)
                        } else {
                                syntax();
                        }
+               } else if (!strcmp("-retries", argv[i])) {
+                       if (i < argc - 1) {
+                               retries = atoi(argv[i + 1]);
+                       } else {
+                               syntax();
+                       }
                } else if (!strcmp("-help", argv[i])) {
                        syntax();
                }
@@ -346,8 +353,10 @@ main(int argc, char **argv)
                die_openssl("SSL_new()");
        }
 
+       #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
        // Set hostname for SNI extension
        SSL_set_tlsext_host_name(ssl, host);
+       #endif
 
        if (strcasecmp(scheme, "http") == 0) {
                bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE);
@@ -373,6 +382,10 @@ main(int argc, char **argv)
                return 1;
        }
 
+       if (retries > 0) {
+               evhttp_connection_set_retries(evcon, retries);
+       }
+
        // Fire off the request
        req = evhttp_request_new(http_request_done, bev);
        if (req == NULL) {
@@ -402,7 +415,7 @@ main(int argc, char **argv)
                        evbuffer_add(output_buffer, buf, s);
                        bytes += s;
                }
-               evutil_snprintf(buf, sizeof(buf)-1, "%lu", bytes);
+               evutil_snprintf(buf, sizeof(buf)-1, "%lu", (unsigned long)bytes);
                evhttp_add_header(output_headers, "Content-Length", buf);
                fclose(f);
        }
index 81980ac51e1d8e94d7cba862738846c7d3105a2a..75f87c70d961c112dea44caeefa2e687b60b60f9 100644 (file)
@@ -30,7 +30,9 @@ noinst_HEADERS += \
        sample/openssl_hostname_validation.h
 endif
 
+if BUILD_SAMPLES
 noinst_PROGRAMS += $(SAMPLES)
+endif
 
 $(SAMPLES) : libevent.la
 
index ca36da46e271ab1a8aa846781976249dabdbe1fe..4cd49ef6306f8dc0877e050021cfbf8065af1f51 100644 (file)
@@ -49,7 +49,8 @@ TESTS = test/test-script.sh
 test/test-script.sh: test/test.sh
        cp $(top_srcdir)/test/test.sh $@
 
-DISTCLEANFILES += test/test-script.sh test/regress.gen.c test/regress.gen.h
+DISTCLEANFILES += test/test-script.sh
+DISTCLEANFILES += test/regress.gen.c test/regress.gen.h
 
 if BUILD_REGRESS
 BUILT_SOURCES += test/regress.gen.c test/regress.gen.h
diff --git a/sntp/libevent/test/print-winsock-errors.c b/sntp/libevent/test/print-winsock-errors.c
new file mode 100644 (file)
index 0000000..ab6e610
--- /dev/null
@@ -0,0 +1,84 @@
+#include <winsock2.h>
+#include <windows.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "event2/event.h"
+#include "event2/util.h"
+#include "event2/thread.h"
+
+#define E(x) printf (#x " -> \"%s\"\n", evutil_socket_error_to_string (x));
+
+int main (int argc, char **argv)
+{
+  int i, j;
+  const char *s1, *s2;
+
+  evthread_use_windows_threads ();
+
+  s1 = evutil_socket_error_to_string (WSAEINTR);
+
+  for (i = 0; i < 3; i++) {
+    printf ("\niteration %d:\n\n", i);
+    E(WSAEINTR);
+    E(WSAEACCES);
+    E(WSAEFAULT);
+    E(WSAEINVAL);
+    E(WSAEMFILE);
+    E(WSAEWOULDBLOCK);
+    E(WSAEINPROGRESS);
+    E(WSAEALREADY);
+    E(WSAENOTSOCK);
+    E(WSAEDESTADDRREQ);
+    E(WSAEMSGSIZE);
+    E(WSAEPROTOTYPE);
+    E(WSAENOPROTOOPT);
+    E(WSAEPROTONOSUPPORT);
+    E(WSAESOCKTNOSUPPORT);
+    E(WSAEOPNOTSUPP);
+    E(WSAEPFNOSUPPORT);
+    E(WSAEAFNOSUPPORT);
+    E(WSAEADDRINUSE);
+    E(WSAEADDRNOTAVAIL);
+    E(WSAENETDOWN);
+    E(WSAENETUNREACH);
+    E(WSAENETRESET);
+    E(WSAECONNABORTED);
+    E(WSAECONNRESET);
+    E(WSAENOBUFS);
+    E(WSAEISCONN);
+    E(WSAENOTCONN);
+    E(WSAESHUTDOWN);
+    E(WSAETIMEDOUT);
+    E(WSAECONNREFUSED);
+    E(WSAEHOSTDOWN);
+    E(WSAEHOSTUNREACH);
+    E(WSAEPROCLIM);
+    E(WSASYSNOTREADY);
+    E(WSAVERNOTSUPPORTED);
+    E(WSANOTINITIALISED);
+    E(WSAEDISCON);
+    E(WSATYPE_NOT_FOUND);
+    E(WSAHOST_NOT_FOUND);
+    E(WSATRY_AGAIN);
+    E(WSANO_RECOVERY);
+    E(WSANO_DATA);
+    E(0xdeadbeef); /* test the case where no message is available */
+
+    /* fill up the hash table a bit to make sure it grows properly */
+    for (j = 0; j < 50; j++) {
+      int err;
+      evutil_secure_rng_get_bytes(&err, sizeof(err));
+      evutil_socket_error_to_string(err);
+    }
+  }
+
+  s2 = evutil_socket_error_to_string (WSAEINTR);
+  if (s1 != s2)
+    printf ("caching failed!\n");
+
+  libevent_global_shutdown ();
+
+  return EXIT_SUCCESS;
+}
index 4d17b6780b0437c13b9efa225d583d13aeefc322..399ba2fbd8d7953025882865d744f1b8d479715e 100644 (file)
@@ -944,17 +944,18 @@ signal_cb(evutil_socket_t fd, short event, void *arg)
 }
 
 static void
-test_simplesignal(void)
+test_simplesignal_impl(int find_reorder)
 {
        struct event ev;
        struct itimerval itv;
 
-       setup_test("Simple signal: ");
        evsignal_set(&ev, SIGALRM, signal_cb, &ev);
        evsignal_add(&ev, NULL);
        /* find bugs in which operations are re-ordered */
-       evsignal_del(&ev);
-       evsignal_add(&ev, NULL);
+       if (find_reorder) {
+               evsignal_del(&ev);
+               evsignal_add(&ev, NULL);
+       }
 
        memset(&itv, 0, sizeof(itv));
        itv.it_value.tv_sec = 0;
@@ -970,6 +971,20 @@ test_simplesignal(void)
        cleanup_test();
 }
 
+static void
+test_simplestsignal(void)
+{
+       setup_test("Simplest one signal: ");
+       test_simplesignal_impl(0);
+}
+
+static void
+test_simplesignal(void)
+{
+       setup_test("Simple signal: ");
+       test_simplesignal_impl(1);
+}
+
 static void
 test_multiplesignal(void)
 {
@@ -1658,7 +1673,7 @@ static void
 test_active_later(void *ptr)
 {
        struct basic_test_data *data = ptr;
-       struct event *ev1, *ev2;
+       struct event *ev1 = NULL, *ev2 = NULL;
        struct event ev3, ev4;
        struct timeval qsec = {0, 100000};
        ev1 = event_new(data->base, data->pair[0], EV_READ|EV_PERSIST, read_and_drain_cb, NULL);
@@ -1693,10 +1708,15 @@ test_active_later(void *ptr)
         * it. */
        event_active_later_(&ev3, EV_READ);
        event_base_assert_ok_(data->base);
+
+end:
+       if (ev1)
+               event_free(ev1);
+       if (ev2)
+               event_free(ev2);
+
        event_base_free(data->base);
        data->base = NULL;
-end:
-       ;
 }
 
 
@@ -2281,7 +2301,7 @@ evtag_fuzz(void *ptr)
 
        for (j = 0; j < 100; j++) {
                for (i = 0; i < (int)sizeof(buffer); i++)
-                       buffer[i] = rand();
+                       buffer[i] = test_weakrand();
                evbuffer_drain(tmp, -1);
                evbuffer_add(tmp, buffer, sizeof(buffer));
 
@@ -3294,6 +3314,7 @@ struct testcase_t evtag_testcases[] = {
 
 struct testcase_t signal_testcases[] = {
 #ifndef _WIN32
+       LEGACY(simplestsignal, TT_ISOLATED),
        LEGACY(simplesignal, TT_ISOLATED),
        LEGACY(multiplesignal, TT_ISOLATED),
        LEGACY(immediatesignal, TT_ISOLATED),
index a9892b0ef7c8b3b3ef5414b551e7138d4dd648fd..bbfefe6739e449ae5ea2fd4b8a2f4bc2cf1fb400 100644 (file)
@@ -53,6 +53,10 @@ extern struct testcase_t listener_testcases[];
 extern struct testcase_t listener_iocp_testcases[];
 extern struct testcase_t thread_testcases[];
 
+extern struct evutil_weakrand_state test_weakrand_state;
+
+#define test_weakrand() (evutil_weakrand_(&test_weakrand_state))
+
 void regress_threads(void *);
 void test_bufferevent_zlib(void *);
 
@@ -114,7 +118,7 @@ int test_ai_eq_(const struct evutil_addrinfo *ai, const char *sockaddr_port,
        } while (0)
 
 #define test_timeval_diff_leq(tv1, tv2, diff, tolerance)               \
-       tt_int_op(abs(timeval_msec_diff((tv1), (tv2)) - diff), <=, tolerance)
+       tt_int_op(labs(timeval_msec_diff((tv1), (tv2)) - diff), <=, tolerance)
 
 #define test_timeval_diff_eq(tv1, tv2, diff)                           \
        test_timeval_diff_leq((tv1), (tv2), (diff), 50)
index ccb14870a5be8c6e2f7e8c0c2726321ab8e4e243..4d6a5de20b33a376386b39c897c8c84f6708a7f1 100644 (file)
@@ -246,7 +246,7 @@ test_evbuffer(void *ptr)
        if (memcmp(evbuffer_pullup(
                           evb, -1), buffer, sizeof(buffer) / 2) != 0 ||
            memcmp(evbuffer_pullup(
-                          evb_two, -1), buffer, sizeof(buffer) != 0))
+                          evb_two, -1), buffer, sizeof(buffer)) != 0)
                tt_abort_msg("Pullup did not preserve content");
 
        evbuffer_validate(evb);
@@ -863,6 +863,10 @@ test_evbuffer_add_file(void *ptr)
                evutil_closesocket(pair[0]);
        if (pair[1] >= 0)
                evutil_closesocket(pair[1]);
+       if (wev)
+               event_free(wev);
+       if (rev)
+               event_free(rev);
        if (tmpfilename) {
                unlink(tmpfilename);
                free(tmpfilename);
@@ -1534,9 +1538,9 @@ test_evbuffer_callbacks(void *ptr)
        tt_assert(!evbuffer_remove_cb(buf, log_change_callback, buf_out2));
        evbuffer_validate(buf);
 
-       tt_str_op(evbuffer_pullup(buf_out1, -1), ==,
+       tt_str_op((const char *) evbuffer_pullup(buf_out1, -1), ==,
                  "0->36; 36->26; 26->31; 31->38; ");
-       tt_str_op(evbuffer_pullup(buf_out2, -1), ==,
+       tt_str_op((const char *) evbuffer_pullup(buf_out2, -1), ==,
                  "0->36; 31->38; 38->0; 0->1; ");
        evbuffer_drain(buf_out1, evbuffer_get_length(buf_out1));
        evbuffer_drain(buf_out2, evbuffer_get_length(buf_out2));
@@ -1552,7 +1556,7 @@ test_evbuffer_callbacks(void *ptr)
        tt_uint_op(evbuffer_get_length(buf_out2), ==, 0);
        evbuffer_setcb(buf, NULL, NULL);
        evbuffer_add_printf(buf, "This will not.");
-       tt_str_op(evbuffer_pullup(buf, -1), ==, "This will not.");
+       tt_str_op((const char *) evbuffer_pullup(buf, -1), ==, "This will not.");
        evbuffer_validate(buf);
        evbuffer_drain(buf, evbuffer_get_length(buf));
        evbuffer_validate(buf);
@@ -1660,7 +1664,7 @@ test_evbuffer_add_reference(void *ptr)
        evbuffer_add(buf1, "You shake and shake the ", 24);
        evbuffer_add_reference(buf1, "ketchup bottle", 14, ref_done_cb,
            (void*)3333);
-       evbuffer_add(buf1, ". Nothing comes and then a lot'll.", 42);
+       evbuffer_add(buf1, ". Nothing comes and then a lot'll.", 35);
        evbuffer_free(buf1);
        buf1 = NULL;
        tt_int_op(ref_done_cb_called_count, ==, 3);
@@ -1839,6 +1843,42 @@ end:
 
 }
 
+static void
+test_evbuffer_peek_first_gt(void *info)
+{
+       struct evbuffer *buf = NULL, *tmp_buf = NULL;
+       struct evbuffer_ptr ptr;
+       struct evbuffer_iovec v[2];
+
+       buf = evbuffer_new();
+       tmp_buf = evbuffer_new();
+       evbuffer_add_printf(tmp_buf, "Contents of chunk 100\n");
+       evbuffer_add_buffer(buf, tmp_buf);
+       evbuffer_add_printf(tmp_buf, "Contents of chunk 1\n");
+       evbuffer_add_buffer(buf, tmp_buf);
+
+       evbuffer_ptr_set(buf, &ptr, 0, EVBUFFER_PTR_SET);
+
+       /** The only case that matters*/
+       tt_int_op(evbuffer_peek(buf, -1, &ptr, NULL, 0), ==, 2);
+       /** Just in case */
+       tt_int_op(evbuffer_peek(buf, -1, &ptr, v, 2), ==, 2);
+
+       evbuffer_ptr_set(buf, &ptr, 20, EVBUFFER_PTR_ADD);
+       tt_int_op(evbuffer_peek(buf, -1, &ptr, NULL, 0), ==, 2);
+       tt_int_op(evbuffer_peek(buf, -1, &ptr, v, 2), ==, 2);
+       tt_int_op(evbuffer_peek(buf, 2, &ptr, NULL, 0), ==, 1);
+       tt_int_op(evbuffer_peek(buf, 2, &ptr, v, 2), ==, 1);
+       tt_int_op(evbuffer_peek(buf, 3, &ptr, NULL, 0), ==, 2);
+       tt_int_op(evbuffer_peek(buf, 3, &ptr, v, 2), ==, 2);
+
+end:
+       if (buf)
+               evbuffer_free(buf);
+       if (tmp_buf)
+               evbuffer_free(tmp_buf);
+}
+
 static void
 test_evbuffer_peek(void *info)
 {
@@ -2096,7 +2136,7 @@ test_evbuffer_copyout(void *dummy)
            "When the rich Allobrogenses never kept amanuenses, "
            "And our only plots were piled in lakes at Berne.";
        /* -- Kipling, "In The Neolithic Age" */
-       char tmp[256];
+       char tmp[1024];
        struct evbuffer_ptr ptr;
        struct evbuffer *buf;
 
@@ -2206,6 +2246,7 @@ struct testcase_t evbuffer_testcases[] = {
        { "multicast_drain", test_evbuffer_multicast_drain, 0, NULL, NULL },
        { "prepend", test_evbuffer_prepend, TT_FORK, NULL, NULL },
        { "peek", test_evbuffer_peek, 0, NULL, NULL },
+       { "peek_first_gt", test_evbuffer_peek_first_gt, 0, NULL, NULL },
        { "freeze_start", test_evbuffer_freeze, 0, &nil_setup, (void*)"start" },
        { "freeze_end", test_evbuffer_freeze, 0, &nil_setup, (void*)"end" },
        { "add_iovec", test_evbuffer_add_iovec, 0, NULL, NULL},
index 4ec2dccf43e9c1ac32ad62b684050524943b7aad..a1998ba62cd1de161c2598584651b52b3caa4fd4 100644 (file)
@@ -75,6 +75,7 @@
 #include "event2/util.h"
 
 #include "bufferevent-internal.h"
+#include "evthread-internal.h"
 #include "util-internal.h"
 #ifdef _WIN32
 #include "iocp-internal.h"
@@ -173,9 +174,9 @@ test_bufferevent_impl(int use_pair)
 
        event_dispatch();
 
-       bufferevent_free(bev1);
-       tt_ptr_op(bufferevent_pair_get_partner(bev2), ==, NULL);
        bufferevent_free(bev2);
+       tt_ptr_op(bufferevent_pair_get_partner(bev1), ==, NULL);
+       bufferevent_free(bev1);
 
        if (test_ok != 2)
                test_ok = 0;
@@ -195,6 +196,143 @@ test_bufferevent_pair(void)
        test_bufferevent_impl(1);
 }
 
+#if defined(EVTHREAD_USE_PTHREADS_IMPLEMENTED)
+/**
+ * Trace lock/unlock/alloc/free for locks.
+ * (More heavier then evthread_debug*)
+ */
+typedef struct
+{
+       void *lock;
+       enum {
+               ALLOC, FREE,
+       } status;
+       size_t locked /** allow recursive locking */;
+} lock_wrapper;
+struct lock_unlock_base
+{
+       /* Original callbacks */
+       struct evthread_lock_callbacks cbs;
+       /* Map of locks */
+       lock_wrapper *locks;
+       size_t nr_locks;
+} lu_base = {
+       .locks = NULL,
+};
+
+static lock_wrapper *lu_find(void *lock_)
+{
+       size_t i;
+       for (i = 0; i < lu_base.nr_locks; ++i) {
+               lock_wrapper *lock = &lu_base.locks[i];
+               if (lock->lock == lock_)
+                       return lock;
+       }
+       return NULL;
+}
+
+static void *trace_lock_alloc(unsigned locktype)
+{
+       ++lu_base.nr_locks;
+       lu_base.locks = realloc(lu_base.locks,
+               sizeof(lock_wrapper) * lu_base.nr_locks);
+       void *lock = lu_base.cbs.alloc(locktype);
+       lu_base.locks[lu_base.nr_locks - 1] = (lock_wrapper){ lock, ALLOC, 0 };
+       return lock;
+}
+static void trace_lock_free(void *lock_, unsigned locktype)
+{
+       lock_wrapper *lock = lu_find(lock_);
+       if (!lock || lock->status == FREE || lock->locked) {
+               __asm__("int3");
+               TT_FAIL(("lock: free error"));
+       } else {
+               lock->status = FREE;
+               lu_base.cbs.free(lock_, locktype);
+       }
+}
+static int trace_lock_lock(unsigned mode, void *lock_)
+{
+       lock_wrapper *lock = lu_find(lock_);
+       if (!lock || lock->status == FREE) {
+               TT_FAIL(("lock: lock error"));
+               return -1;
+       } else {
+               ++lock->locked;
+               return lu_base.cbs.lock(mode, lock_);
+       }
+}
+static int trace_lock_unlock(unsigned mode, void *lock_)
+{
+       lock_wrapper *lock = lu_find(lock_);
+       if (!lock || lock->status == FREE || !lock->locked) {
+               TT_FAIL(("lock: unlock error"));
+               return -1;
+       } else {
+               --lock->locked;
+               return lu_base.cbs.unlock(mode, lock_);
+       }
+}
+static void lock_unlock_free_thread_cbs()
+{
+       event_base_free(NULL);
+
+       /** drop immutable flag */
+       evthread_set_lock_callbacks(NULL);
+       /** avoid calling of event_global_setup_locks_() for new cbs */
+       libevent_global_shutdown();
+       /** drop immutable flag for non-debug ops (since called after shutdown) */
+       evthread_set_lock_callbacks(NULL);
+}
+
+static int use_lock_unlock_profiler(void)
+{
+       struct evthread_lock_callbacks cbs = {
+               EVTHREAD_LOCK_API_VERSION,
+               EVTHREAD_LOCKTYPE_RECURSIVE,
+               trace_lock_alloc,
+               trace_lock_free,
+               trace_lock_lock,
+               trace_lock_unlock,
+       };
+       memcpy(&lu_base.cbs, evthread_get_lock_callbacks(),
+               sizeof(lu_base.cbs));
+       {
+               lock_unlock_free_thread_cbs();
+
+               evthread_set_lock_callbacks(&cbs);
+               /** re-create debug locks correctly */
+               evthread_enable_lock_debugging();
+
+               event_init();
+       }
+       return 0;
+}
+static void free_lock_unlock_profiler(struct basic_test_data *data)
+{
+       lock_unlock_free_thread_cbs();
+       free(lu_base.locks);
+       data->base = NULL;
+}
+
+static void test_bufferevent_pair_release_lock(void *arg)
+{
+       struct basic_test_data *data = arg;
+       use_lock_unlock_profiler();
+       {
+               struct bufferevent *pair[2];
+               if (!bufferevent_pair_new(NULL, BEV_OPT_THREADSAFE, pair)) {
+                       bufferevent_free(pair[0]);
+                       bufferevent_free(pair[1]);
+               } else
+                       tt_abort_perror("bufferevent_pair_new");
+       }
+       free_lock_unlock_profiler(data);
+end:
+       ;
+}
+#endif
+
 /*
  * test watermarks and bufferevent
  */
@@ -287,6 +425,11 @@ test_bufferevent_watermarks_impl(int use_pair)
        tt_int_op(low, ==, 100);
        tt_int_op(high, ==, 2000);
 
+       {
+       int r = bufferevent_getwatermark(bev1, EV_WRITE | EV_READ, &low, &high);
+       tt_int_op(r, !=, 0);
+       }
+
        bufferevent_write(bev1, buffer, sizeof(buffer));
 
        event_dispatch();
@@ -944,6 +1087,11 @@ struct testcase_t bufferevent_testcases[] = {
 
        LEGACY(bufferevent, TT_ISOLATED),
        LEGACY(bufferevent_pair, TT_ISOLATED),
+#if defined(EVTHREAD_USE_PTHREADS_IMPLEMENTED)
+       { "bufferevent_pair_release_lock", test_bufferevent_pair_release_lock,
+         TT_FORK|TT_ISOLATED|TT_NEED_THREADS|TT_NEED_BASE|TT_LEGACY,
+         &basic_setup, NULL },
+#endif
        LEGACY(bufferevent_watermarks, TT_ISOLATED),
        LEGACY(bufferevent_pair_watermarks, TT_ISOLATED),
        LEGACY(bufferevent_filters, TT_ISOLATED),
index 338c4ee8fd548c427944db724f18fdf66e4a218f..6d6b48443df591ba1414c0dd4a4c93a695994911 100644 (file)
@@ -406,6 +406,22 @@ dns_server(void)
         * the only nameserver. */
        evdns_base_nameserver_sockaddr_add(base, (struct sockaddr*)&ss, slen, 0);
        tt_int_op(evdns_base_count_nameservers(base), ==, 1);
+       {
+               struct sockaddr_storage ss2;
+               int slen2;
+
+               memset(&ss2, 0, sizeof(ss2));
+
+               slen2 = evdns_base_get_nameserver_addr(base, 0, (struct sockaddr *)&ss2, 3);
+               tt_int_op(slen2, ==, slen);
+               tt_int_op(ss2.ss_family, ==, 0);
+               slen2 = evdns_base_get_nameserver_addr(base, 0, (struct sockaddr *)&ss2, sizeof(ss2));
+               tt_int_op(slen2, ==, slen);
+               tt_mem_op(&ss2, ==, &ss, slen);
+
+               slen2 = evdns_base_get_nameserver_addr(base, 1, (struct sockaddr *)&ss2, sizeof(ss2));
+               tt_int_op(-1, ==, slen2);
+       }
 
        /* Send some queries. */
        evdns_base_resolve_ipv4(base, "zz.example.com", DNS_QUERY_NO_SEARCH,
@@ -443,6 +459,7 @@ end:
 
 static int n_replies_left;
 static struct event_base *exit_base;
+static struct evdns_server_port *exit_port;
 
 struct generic_dns_callback_result {
        int result;
@@ -483,8 +500,14 @@ generic_dns_callback(int result, char type, int count, int ttl, void *addresses,
                res->addrs = res->addrs_buf;
        }
 
-       if (--n_replies_left == 0)
-               event_base_loopexit(exit_base, NULL);
+       --n_replies_left;
+       if (n_replies_left == 0) {
+               if (exit_port) {
+                       evdns_close_server_port(exit_port);
+                       exit_port = NULL;
+               } else
+                       event_base_loopexit(exit_base, NULL);
+       }
 }
 
 static struct regress_dns_server_table search_table[] = {
@@ -664,7 +687,7 @@ end:
 }
 
 static void
-dns_retry_test(void *arg)
+dns_retry_test_impl(void *arg, int flags)
 {
        struct basic_test_data *data = arg;
        struct event_base *base = data->base;
@@ -681,7 +704,7 @@ dns_retry_test(void *arg)
        tt_assert(port);
        evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum);
 
-       dns = evdns_base_new(base, 0);
+       dns = evdns_base_new(base, flags);
        tt_assert(!evdns_base_nameserver_ip_add(dns, buf));
        tt_assert(! evdns_base_set_option(dns, "timeout", "0.2"));
        tt_assert(! evdns_base_set_option(dns, "max-timeouts:", "10"));
@@ -736,6 +759,16 @@ end:
        if (port)
                evdns_close_server_port(port);
 }
+static void
+dns_retry_test(void *arg)
+{
+       dns_retry_test_impl(arg, 0);
+}
+static void
+dns_retry_disable_when_inactive_test(void *arg)
+{
+       dns_retry_test_impl(arg, EVDNS_BASE_DISABLE_WHEN_INACTIVE);
+}
 
 static struct regress_dns_server_table internal_error_table[] = {
        /* Error 4 (NOTIMPL) makes us reissue the request to another server
@@ -753,7 +786,7 @@ static struct regress_dns_server_table reissue_table[] = {
 };
 
 static void
-dns_reissue_test(void *arg)
+dns_reissue_test_impl(void *arg, int flags)
 {
        struct basic_test_data *data = arg;
        struct event_base *base = data->base;
@@ -772,7 +805,7 @@ dns_reissue_test(void *arg)
        evutil_snprintf(buf1, sizeof(buf1), "127.0.0.1:%d", (int)portnum1);
        evutil_snprintf(buf2, sizeof(buf2), "127.0.0.1:%d", (int)portnum2);
 
-       dns = evdns_base_new(base, 0);
+       dns = evdns_base_new(base, flags);
        tt_assert(!evdns_base_nameserver_ip_add(dns, buf1));
        tt_assert(! evdns_base_set_option(dns, "timeout:", "0.3"));
        tt_assert(! evdns_base_set_option(dns, "max-timeouts:", "2"));
@@ -805,6 +838,16 @@ end:
        if (port2)
                evdns_close_server_port(port2);
 }
+static void
+dns_reissue_test(void *arg)
+{
+       dns_reissue_test_impl(arg, 0);
+}
+static void
+dns_reissue_disable_when_inactive_test(void *arg)
+{
+       dns_reissue_test_impl(arg, EVDNS_BASE_DISABLE_WHEN_INACTIVE);
+}
 
 #if 0
 static void
@@ -819,21 +862,29 @@ dumb_bytes_fn(char *p, size_t n)
 #endif
 
 static void
-dns_inflight_test(void *arg)
+dns_inflight_test_impl(void *arg, int flags)
 {
        struct basic_test_data *data = arg;
        struct event_base *base = data->base;
        struct evdns_base *dns = NULL;
+       struct evdns_server_port *dns_port = NULL;
        ev_uint16_t portnum = 0;
        char buf[64];
+       int disable_when_inactive = flags & EVDNS_BASE_DISABLE_WHEN_INACTIVE;
 
        struct generic_dns_callback_result r[20];
        int i;
 
-       tt_assert(regress_dnsserver(base, &portnum, reissue_table));
+       dns_port = regress_get_dnsserver(base, &portnum, NULL,
+               regress_dns_server_cb, reissue_table);
+       tt_assert(dns_port);
+       if (disable_when_inactive) {
+               exit_port = dns_port;
+       }
+
        evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum);
 
-       dns = evdns_base_new(base, 0);
+       dns = evdns_base_new(base, flags);
        tt_assert(!evdns_base_nameserver_ip_add(dns, buf));
        tt_assert(! evdns_base_set_option(dns, "max-inflight:", "3"));
        tt_assert(! evdns_base_set_option(dns, "randomize-case:", "0"));
@@ -852,10 +903,68 @@ dns_inflight_test(void *arg)
                tt_int_op(((ev_uint32_t*)r[i].addrs)[0], ==, htonl(0xf00ff00f));
        }
 
+end:
+       if (dns)
+               evdns_base_free(dns, 0);
+       if (exit_port) {
+               evdns_close_server_port(exit_port);
+               exit_port = NULL;
+       } else if (! disable_when_inactive) {
+               evdns_close_server_port(dns_port);
+       }
+}
+
+static void
+dns_inflight_test(void *arg)
+{
+       dns_inflight_test_impl(arg, 0);
+}
+
+static void
+dns_disable_when_inactive_test(void *arg)
+{
+       dns_inflight_test_impl(arg, EVDNS_BASE_DISABLE_WHEN_INACTIVE);
+}
+
+static void
+dns_disable_when_inactive_no_ns_test(void *arg)
+{
+       struct basic_test_data *data = arg;
+       struct event_base *base = data->base, *inactive_base;
+       struct evdns_base *dns = NULL;
+       ev_uint16_t portnum = 0;
+       char buf[64];
+       struct generic_dns_callback_result r;
+
+       inactive_base = event_base_new();
+       tt_assert(inactive_base);
+
+       /** Create dns server with inactive base, to avoid replying to clients */
+       tt_assert(regress_dnsserver(inactive_base, &portnum, search_table));
+       evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum);
+
+       dns = evdns_base_new(base, EVDNS_BASE_DISABLE_WHEN_INACTIVE);
+       tt_assert(!evdns_base_nameserver_ip_add(dns, buf));
+       tt_assert(! evdns_base_set_option(dns, "timeout:", "0.1"));
+
+       evdns_base_resolve_ipv4(dns, "foof.example.com", 0, generic_dns_callback, &r);
+       n_replies_left = 1;
+       exit_base = base;
+
+       event_base_dispatch(base);
+
+       tt_int_op(n_replies_left, ==, 0);
+
+       tt_int_op(r.result, ==, DNS_ERR_TIMEOUT);
+       tt_int_op(r.count, ==, 0);
+       tt_ptr_op(r.addrs, ==, NULL);
+
 end:
        if (dns)
                evdns_base_free(dns, 0);
        regress_clean_dnsserver();
+       if (inactive_base)
+               event_base_free(inactive_base);
 }
 
 /* === Test for bufferevent_socket_connect_hostname */
@@ -1563,7 +1672,8 @@ test_getaddrinfo_async(void *arg)
 end:
        if (local_outcome.ai)
                evutil_freeaddrinfo(local_outcome.ai);
-       for (i=0;i<10;++i) {
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+       for (i=0;i<(int)ARRAY_SIZE(a_out);++i) {
                if (a_out[i].ai)
                        evutil_freeaddrinfo(a_out[i].ai);
        }
@@ -1694,9 +1804,15 @@ testleak_setup(const struct testcase_t *testcase)
        struct testleak_env_t *env;
 
        allocated_chunks = 0;
+
+       /* Reset allocation counter, to start allocations from the very beginning.
+        * (this will avoid false-positive negative numbers for allocated_chunks)
+        */
+       libevent_global_shutdown();
+
        event_set_mem_functions(cnt_malloc, cnt_realloc, cnt_free);
-       if (!libevent_tests_running_in_debug_mode)
-               event_enable_debug_mode();
+
+       event_enable_debug_mode();
 
        /* not mm_calloc: we don't want to mess with the count. */
        env = calloc(1, sizeof(struct testleak_env_t));
@@ -1717,8 +1833,8 @@ testleak_cleanup(const struct testcase_t *testcase, void *env_)
 #ifdef EVENT__DISABLE_DEBUG_MODE
        tt_int_op(allocated_chunks, ==, 0);
 #else
-       /* FIXME: that's `1' because of event_debug_map_HT_GROW */
-       tt_int_op(allocated_chunks, ==, 1);
+       libevent_global_shutdown();
+       tt_int_op(allocated_chunks, ==, 0);
 #endif
        ok = 1;
 end:
@@ -1791,6 +1907,7 @@ dbg_leak_resume(void *env_, int cancel, int send_err_shutdown)
 end:
        evdns_base_free(env->dns_base, send_err_shutdown);
        env->dns_base = 0;
+
        event_base_free(env->base);
        env->base = 0;
 }
@@ -1875,6 +1992,8 @@ end:
                evdns_base_free(dns_base, 1);
        if (server)
                evdns_close_server_port(server);
+       if (base)
+               event_base_free(base);
        if (fd >= 0)
                evutil_closesocket(fd);
 }
@@ -1894,10 +2013,18 @@ struct testcase_t dns_testcases[] = {
        { "search_cancel", dns_search_cancel_test,
          TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
        { "retry", dns_retry_test, TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL },
+       { "retry_disable_when_inactive", dns_retry_disable_when_inactive_test,
+         TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL },
        { "reissue", dns_reissue_test, TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL },
+       { "reissue_disable_when_inactive", dns_reissue_disable_when_inactive_test,
+         TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL },
        { "inflight", dns_inflight_test, TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
        { "bufferevent_connect_hostname", test_bufferevent_connect_hostname,
          TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
+       { "disable_when_inactive", dns_disable_when_inactive_test,
+         TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
+       { "disable_when_inactive_no_ns", dns_disable_when_inactive_no_ns_test,
+         TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
 
        { "getaddrinfo_async", test_getaddrinfo_async,
          TT_FORK|TT_NEED_BASE, &basic_setup, (char*)"" },
index 61a6313f1b3bf182a3931af270ea749af3e60e74..552210fe9d01c2539d5590da2862e56c543461e5 100644 (file)
@@ -25,6 +25,7 @@
  */
 
 #include "event2/event-config.h"
+#include "evconfig-private.h"
 #include "tinytest.h"
 #include "tinytest_macros.h"
 #include <stdlib.h>
index ca7d5155bf140db381bd422b9b67b22c6cc096c0..35f6dd768961c3bb3ea1c8a7ab01b336c35c26b7 100644 (file)
@@ -105,8 +105,12 @@ http_bind(struct evhttp *myhttp, ev_uint16_t *pport, int ipv6)
        else
                sock = evhttp_bind_socket_with_handle(myhttp, "127.0.0.1", *pport);
 
-       if (sock == NULL)
-               event_errx(1, "Could not start web server");
+       if (sock == NULL) {
+               if (ipv6)
+                       return -1;
+               else
+                       event_errx(1, "Could not start web server");
+       }
 
        port = regress_get_socket_port(evhttp_bound_socket_get_fd(sock));
        if (port < 0)
@@ -395,7 +399,7 @@ http_basic_test(void *arg)
 {
        struct basic_test_data *data = arg;
        struct timeval tv;
-       struct bufferevent *bev;
+       struct bufferevent *bev = NULL;
        evutil_socket_t fd;
        const char *http_request;
        ev_uint16_t port = 0, port2 = 0;
@@ -480,7 +484,8 @@ http_basic_test(void *arg)
 
        evhttp_free(http);
  end:
-       ;
+       if (bev)
+               bufferevent_free(bev);
 }
 
 
@@ -714,6 +719,7 @@ http_delete_test(void *arg)
 
        http = http_setup(&port, data->base, 0);
 
+       tt_assert(http);
        fd = http_connect("127.0.0.1", port);
        tt_int_op(fd, >=, 0);
 
@@ -734,6 +740,7 @@ http_delete_test(void *arg)
 
        bufferevent_free(bev);
        evutil_closesocket(fd);
+       fd = -1;
 
        evhttp_free(http);
 
@@ -953,7 +960,8 @@ static void http_request_done(struct evhttp_request *, void *);
 static void http_request_empty_done(struct evhttp_request *, void *);
 
 static void
-http_connection_test_(struct basic_test_data *data, int persistent, const char *address, struct evdns_base *dnsbase, int ipv6)
+http_connection_test_(struct basic_test_data *data, int persistent,
+       const char *address, struct evdns_base *dnsbase, int ipv6, int family)
 {
        ev_uint16_t port = 0;
        struct evhttp_connection *evcon = NULL;
@@ -962,9 +970,14 @@ http_connection_test_(struct basic_test_data *data, int persistent, const char *
        test_ok = 0;
 
        http = http_setup(&port, data->base, ipv6);
+       if (!http && ipv6) {
+               tt_skip();
+       }
+       tt_assert(http);
 
        evcon = evhttp_connection_base_new(data->base, dnsbase, address, port);
        tt_assert(evcon);
+       evhttp_connection_set_family(evcon, family);
 
        tt_assert(evhttp_connection_get_base(evcon) == data->base);
 
@@ -1038,12 +1051,12 @@ http_connection_test_(struct basic_test_data *data, int persistent, const char *
 static void
 http_connection_test(void *arg)
 {
-       http_connection_test_(arg, 0, "127.0.0.1", NULL, 0);
+       http_connection_test_(arg, 0, "127.0.0.1", NULL, 0, AF_UNSPEC);
 }
 static void
 http_persist_connection_test(void *arg)
 {
-       http_connection_test_(arg, 1, "127.0.0.1", NULL, 0);
+       http_connection_test_(arg, 1, "127.0.0.1", NULL, 0, AF_UNSPEC);
 }
 
 static struct regress_dns_server_table search_table[] = {
@@ -1146,6 +1159,63 @@ http_connection_async_test(void *arg)
        regress_clean_dnsserver();
 }
 
+static void
+http_autofree_connection_test(void *arg)
+{
+       struct basic_test_data *data = arg;
+       ev_uint16_t port = 0;
+       struct evhttp_connection *evcon = NULL;
+       struct evhttp_request *req[2] = { NULL };
+
+       test_ok = 0;
+       http = http_setup(&port, data->base, 0);
+
+       evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port);
+       tt_assert(evcon);
+
+       /*
+        * At this point, we want to schedule two request to the HTTP
+        * server using our make request method.
+        */
+       req[0] = evhttp_request_new(http_request_empty_done, data->base);
+       req[1] = evhttp_request_new(http_request_empty_done, data->base);
+
+       /* Add the information that we care about */
+       evhttp_add_header(evhttp_request_get_output_headers(req[0]), "Host", "somehost");
+       evhttp_add_header(evhttp_request_get_output_headers(req[0]), "Connection", "close");
+       evhttp_add_header(evhttp_request_get_output_headers(req[0]), "Empty", "itis");
+       evhttp_add_header(evhttp_request_get_output_headers(req[1]), "Host", "somehost");
+       evhttp_add_header(evhttp_request_get_output_headers(req[1]), "Connection", "close");
+       evhttp_add_header(evhttp_request_get_output_headers(req[1]), "Empty", "itis");
+
+       /* We give ownership of the request to the connection */
+       if (evhttp_make_request(evcon, req[0], EVHTTP_REQ_GET, "/test") == -1) {
+               tt_abort_msg("couldn't make request");
+       }
+       if (evhttp_make_request(evcon, req[1], EVHTTP_REQ_GET, "/test") == -1) {
+               tt_abort_msg("couldn't make request");
+       }
+
+       /*
+        * Tell libevent to free the connection when the request completes
+        *      We then set the evcon pointer to NULL since we don't want to free it
+        *      when this function ends.
+        */
+       evhttp_connection_free_on_completion(evcon);
+       evcon = NULL;
+
+       event_base_dispatch(data->base);
+
+       /* at this point, the http server should have no connection */
+       tt_assert(TAILQ_FIRST(&http->connections) == NULL);
+
+ end:
+       if (evcon)
+               evhttp_connection_free(evcon);
+       if (http)
+               evhttp_free(http);
+}
+
 static void
 http_request_never_call(struct evhttp_request *req, void *arg)
 {
@@ -2743,6 +2813,7 @@ http_incomplete_test_(struct basic_test_data *data, int use_timeout)
        bufferevent_free(bev);
        if (use_timeout) {
                evutil_closesocket(fd);
+               fd = -1;
        }
 
        evhttp_free(http);
@@ -3748,7 +3819,7 @@ static struct regress_dns_server_table ipv6_search_table[] = {
 };
 
 static void
-http_ipv6_for_domain_test(void *arg)
+http_ipv6_for_domain_test_impl(void *arg, int family)
 {
        struct basic_test_data *data = arg;
        struct evdns_base *dns_base = NULL;
@@ -3765,13 +3836,19 @@ http_ipv6_for_domain_test(void *arg)
        evutil_snprintf(address, sizeof(address), "127.0.0.1:%d", portnum);
        evdns_base_nameserver_ip_add(dns_base, address);
 
-       http_connection_test_(arg, 0 /* not persistent */, "localhost", dns_base, 1 /* ipv6 */);
+       http_connection_test_(arg, 0 /* not persistent */, "localhost", dns_base,
+               1 /* ipv6 */, family);
 
  end:
        if (dns_base)
                evdns_base_free(dns_base, 0);
        regress_clean_dnsserver();
 }
+static void
+http_ipv6_for_domain_test(void *arg)
+{
+       http_ipv6_for_domain_test_impl(arg, AF_UNSPEC);
+}
 
 static void
 http_request_get_addr_on_close(struct evhttp_connection *evcon, void *arg)
@@ -3836,6 +3913,22 @@ http_get_addr_test(void *arg)
                evhttp_free(http);
 }
 
+static void
+http_set_family_test(void *arg)
+{
+       http_connection_test_(arg, 0, "127.0.0.1", NULL, 0, AF_UNSPEC);
+}
+static void
+http_set_family_ipv4_test(void *arg)
+{
+       http_connection_test_(arg, 0, "127.0.0.1", NULL, 0, AF_INET);
+}
+static void
+http_set_family_ipv6_test(void *arg)
+{
+       http_ipv6_for_domain_test_impl(arg, AF_INET6);
+}
+
 #define HTTP_LEGACY(name)                                              \
        { #name, run_legacy_test_fn, TT_ISOLATED|TT_LEGACY, &legacy_setup, \
                    http_##name##_test }
@@ -3861,6 +3954,7 @@ struct testcase_t http_testcases[] = {
        HTTP(failure),
        HTTP(connection),
        HTTP(persist_connection),
+       HTTP(autofree_connection),
        HTTP(connection_async),
        HTTP(close_detection),
        HTTP(close_detection_delay),
@@ -3888,6 +3982,10 @@ struct testcase_t http_testcases[] = {
        HTTP(ipv6_for_domain),
        HTTP(get_addr),
 
+       HTTP(set_family),
+       HTTP(set_family_ipv4),
+       HTTP(set_family_ipv6),
+
        END_OF_TESTCASES
 };
 
index 58cbe5fe2741f858b9cf5ea0d4498029cdaf3ef8..3198ced1da3559bb53832f55ebe91b247ec93238 100644 (file)
@@ -90,6 +90,8 @@
 #include "../iocp-internal.h"
 #include "../event-internal.h"
 
+struct evutil_weakrand_state test_weakrand_state;
+
 long
 timeval_msec_diff(const struct timeval *start, const struct timeval *end)
 {
@@ -452,6 +454,8 @@ main(int argc, const char **argv)
 
        tinytest_set_aliases(testaliases);
 
+       evutil_weakrand_seed_(&test_weakrand_state, 0);
+
        if (tinytest_main(argc,argv,testgroups))
                return 1;
 
index a1f554ebbe8ff0f800fd3a8c90350ce698840c4b..05db32e26f4de7420ea8d9dd60392e2acc224279 100644 (file)
 
 #include "tinytest.h"
 #include "tinytest_macros.h"
+#include "regress.h"
 
 static void
 set_random_timeout(struct event *ev)
 {
-       ev->ev_timeout.tv_sec = rand();
-       ev->ev_timeout.tv_usec = rand() & 0xfffff;
+       ev->ev_timeout.tv_sec = test_weakrand();
+       ev->ev_timeout.tv_usec = test_weakrand() & 0xfffff;
        ev->ev_timeout_pos.min_heap_idx = -1;
 }
 
index c2113414cc63957ba2d4278069cd4c5118d33ffb..bf9b46b1ef88ee3cb0917f1bec1571837821fe3b 100644 (file)
@@ -194,6 +194,7 @@ respond_to_number(struct bufferevent *bev, void *ctx)
        n = atoi(line);
        if (n <= 0)
                TT_FAIL(("Bad number: %s", line));
+       free(line);
        TT_BLATHER(("The number was %d", n));
        if (n == 1001) {
                ++test_is_done;
index 612bf1d6111fafdeb0be04597e7f5890a833f8e4..c42668ea8839c150c3d0253e07ab02625c64b802 100644 (file)
@@ -361,7 +361,7 @@ thread_conditions_simple(void *arg)
                            &tv_signal);
                        diff2 = timeval_msec_diff(&actual_delay,
                            &tv_broadcast);
-                       if (abs(diff1) < abs(diff2)) {
+                       if (labs(diff1) < labs(diff2)) {
                                TT_BLATHER(("%d looks like a signal\n", i));
                                target_delay = &tv_signal;
                                ++n_signal;
@@ -382,7 +382,8 @@ thread_conditions_simple(void *arg)
        tt_int_op(n_signal, ==, 1);
 
 end:
-       ;
+       EVTHREAD_FREE_LOCK(cond.lock, EVTHREAD_LOCKTYPE_RECURSIVE);
+       EVTHREAD_FREE_COND(cond.cond);
 }
 
 #define CB_COUNT 128
index d64d002495ab4c0cf24c2c96ef8816dbd3b5aad0..60f085bf1db3f85d3cf0738f00e146cc3d7418b7 100644 (file)
@@ -179,10 +179,10 @@ regress_ipv6_parse(void *ptr)
                for (j = 0; j < 4; ++j) {
                        /* Can't use s6_addr32 here; some don't have it. */
                        ev_uint32_t u =
-                               (in6.s6_addr[j*4  ] << 24) |
-                               (in6.s6_addr[j*4+1] << 16) |
-                               (in6.s6_addr[j*4+2] << 8) |
-                               (in6.s6_addr[j*4+3]);
+                           ((ev_uint32_t)in6.s6_addr[j*4  ] << 24) |
+                           ((ev_uint32_t)in6.s6_addr[j*4+1] << 16) |
+                           ((ev_uint32_t)in6.s6_addr[j*4+2] << 8) |
+                           ((ev_uint32_t)in6.s6_addr[j*4+3]);
                        if (u != ent->res[j]) {
                                TT_FAIL(("%s did not parse as expected.", ent->addr));
                                continue;
@@ -726,46 +726,48 @@ test_evutil_integers(void *arg)
        tt_assert(u64 > 0);
        tt_assert(i64 > 0);
        u64++;
-       i64++;
+/*     i64++; */
        tt_assert(u64 == 0);
-       tt_assert(i64 == EV_INT64_MIN);
-       tt_assert(i64 < 0);
+/*     tt_assert(i64 == EV_INT64_MIN); */
+/*     tt_assert(i64 < 0); */
 
        u32 = EV_UINT32_MAX;
        i32 = EV_INT32_MAX;
        tt_assert(u32 > 0);
        tt_assert(i32 > 0);
        u32++;
-       i32++;
+/*     i32++; */
        tt_assert(u32 == 0);
-       tt_assert(i32 == EV_INT32_MIN);
-       tt_assert(i32 < 0);
+/*     tt_assert(i32 == EV_INT32_MIN); */
+/*     tt_assert(i32 < 0); */
 
        u16 = EV_UINT16_MAX;
        i16 = EV_INT16_MAX;
        tt_assert(u16 > 0);
        tt_assert(i16 > 0);
        u16++;
-       i16++;
+/*     i16++; */
        tt_assert(u16 == 0);
-       tt_assert(i16 == EV_INT16_MIN);
-       tt_assert(i16 < 0);
+/*     tt_assert(i16 == EV_INT16_MIN); */
+/*     tt_assert(i16 < 0); */
 
        u8 = EV_UINT8_MAX;
        i8 = EV_INT8_MAX;
        tt_assert(u8 > 0);
        tt_assert(i8 > 0);
        u8++;
-       i8++;
+/*     i8++;*/
        tt_assert(u8 == 0);
-       tt_assert(i8 == EV_INT8_MIN);
-       tt_assert(i8 < 0);
+/*     tt_assert(i8 == EV_INT8_MIN); */
+/*     tt_assert(i8 < 0); */
 
+/*
        ssize = EV_SSIZE_MAX;
        tt_assert(ssize > 0);
        ssize++;
        tt_assert(ssize < 0);
        tt_assert(ssize == EV_SSIZE_MIN);
+*/
 
        ptr = &ssize;
        iptr = (ev_intptr_t)ptr;
@@ -1119,7 +1121,7 @@ end:
 static void
 test_evutil_loadsyslib(void *arg)
 {
-       HANDLE h=NULL;
+       HMODULE h=NULL;
 
        h = evutil_load_windows_system_library_(TEXT("kernel32.dll"));
        tt_assert(h);
index 9339397c93b6b2bd6f72e9c24f97535b581a9478..8406676932ed337f6b3c55b7f94fc3e4065658ad 100644 (file)
@@ -56,6 +56,7 @@
 #include "event2/bufferevent.h"
 
 #include "regress.h"
+#include "mm-internal.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
@@ -95,6 +96,7 @@ zlib_deflate_free(void *ctx)
        z_streamp p = ctx;
 
        assert(deflateEnd(p) == Z_OK);
+       mm_free(p);
 }
 
 static void
@@ -103,6 +105,7 @@ zlib_inflate_free(void *ctx)
        z_streamp p = ctx;
 
        assert(inflateEnd(p) == Z_OK);
+       mm_free(p);
 }
 
 static int
@@ -275,7 +278,7 @@ test_bufferevent_zlib(void *arg)
 {
        struct bufferevent *bev1=NULL, *bev2=NULL;
        char buffer[8333];
-       z_stream z_input, z_output;
+       z_stream *z_input, *z_output;
        int i, r;
        evutil_socket_t pair[2] = {-1, -1};
        (void)arg;
@@ -293,18 +296,18 @@ test_bufferevent_zlib(void *arg)
        bev1 = bufferevent_socket_new(NULL, pair[0], 0);
        bev2 = bufferevent_socket_new(NULL, pair[1], 0);
 
-       memset(&z_output, 0, sizeof(z_output));
-       r = deflateInit(&z_output, Z_DEFAULT_COMPRESSION);
+       z_output = mm_calloc(sizeof(*z_output), 1);
+       r = deflateInit(z_output, Z_DEFAULT_COMPRESSION);
        tt_int_op(r, ==, Z_OK);
-       memset(&z_input, 0, sizeof(z_input));
-       r = inflateInit(&z_input);
+       z_input = mm_calloc(sizeof(*z_input), 1);
+       r = inflateInit(z_input);
        tt_int_op(r, ==, Z_OK);
 
        /* initialize filters */
        bev1 = bufferevent_filter_new(bev1, NULL, zlib_output_filter,
-           BEV_OPT_CLOSE_ON_FREE, zlib_deflate_free, &z_output);
+           BEV_OPT_CLOSE_ON_FREE, zlib_deflate_free, z_output);
        bev2 = bufferevent_filter_new(bev2, zlib_input_filter,
-           NULL, BEV_OPT_CLOSE_ON_FREE, zlib_inflate_free, &z_input);
+           NULL, BEV_OPT_CLOSE_ON_FREE, zlib_inflate_free, z_input);
        bufferevent_setcb(bev1, readcb, writecb, errorcb, NULL);
        bufferevent_setcb(bev2, readcb, writecb, errorcb, NULL);
 
index ee2432b713176d3f20aaa2f1cdab61591a61bd0e..4c4eba25e70e5b60afddf3234538cf056c49ec2e 100644 (file)
@@ -57,7 +57,7 @@
 #endif
 
 /* Provide storage for the address, both for the server & the clients */
-static struct sockaddr_in sin;
+static struct sockaddr_in saddr;
 
 /* Number of sucessful requests so far */
 static int num_requests;
@@ -131,7 +131,7 @@ start_loop(void)
 
        listener = evconnlistener_new_bind(base, listener_accept_cb, NULL,
            LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE,
-           -1, (struct sockaddr *)&sin, sizeof(sin));
+           -1, (struct sockaddr *)&saddr, sizeof(saddr));
        if (listener == NULL) {
                my_perror("Could not create listener!");
                exit(1);
@@ -145,8 +145,8 @@ start_loop(void)
                my_perror("getsockname()");
                exit(1);
        }
-       memcpy(&sin, &ss, sizeof(sin));
-       if (sin.sin_family != AF_INET) {
+       memcpy(&saddr, &ss, sizeof(saddr));
+       if (saddr.sin_family != AF_INET) {
                puts("AF mismatch from getsockname().");
                exit(1);
        }
@@ -208,8 +208,8 @@ start_client(struct event_base *base)
                                                          BEV_OPT_CLOSE_ON_FREE);
        bufferevent_setcb(bev, client_read_cb, NULL, client_event_cb, NULL);
 
-       if (bufferevent_socket_connect(bev, (struct sockaddr *)&sin,
-                                       sizeof(sin)) < 0) {
+       if (bufferevent_socket_connect(bev, (struct sockaddr *)&saddr,
+                                       sizeof(saddr)) < 0) {
                my_perror("Could not connect!");
                bufferevent_free(bev);
                exit(2);
@@ -236,10 +236,10 @@ main(int argc, char **argv)
 #endif
 
        /* Set up an address, used by both client & server. */
-       memset(&sin, 0, sizeof(sin));
-       sin.sin_family = AF_INET;
-       sin.sin_addr.s_addr = htonl(0x7f000001);
-       sin.sin_port = 0; /* Tell the implementation to pick a port. */
+       memset(&saddr, 0, sizeof(saddr));
+       saddr.sin_family = AF_INET;
+       saddr.sin_addr.s_addr = htonl(0x7f000001);
+       saddr.sin_port = 0; /* Tell the implementation to pick a port. */
 
        start_loop();
 
index 27649b8490e0b45a10b2820aabbd20d1d09087ab..17babfdcbcf5804af022805849a2b395f78aa0c8 100644 (file)
@@ -50,6 +50,7 @@
 #include "event2/listener.h"
 #include "event2/thread.h"
 
+static struct evutil_weakrand_state weakrand_state;
 
 static int cfg_verbose = 0;
 static int cfg_help = 0;
@@ -113,11 +114,7 @@ loud_writecb(struct bufferevent *bev, void *ctx)
        struct client_state *cs = ctx;
        struct evbuffer *output = bufferevent_get_output(bev);
        char buf[1024];
-#ifdef _WIN32
-       int r = rand() % 256;
-#else
-       int r = random() % 256;
-#endif
+       int r = evutil_weakrand_(&weakrand_state);
        memset(buf, r, sizeof(buf));
        while (evbuffer_get_length(output) < 8192) {
                evbuffer_add(output, buf, sizeof(buf));
@@ -223,7 +220,7 @@ check_bucket_levels_cb(evutil_socket_t fd, short events, void *arg)
 #undef B
 
        total_n_bev_checks++;
-       if (total_n_bev_checks >= .8 * (cfg_duration / cfg_tick_msec) * cfg_n_connections) {
+       if (total_n_bev_checks >= .8 * ((double)cfg_duration / cfg_tick_msec) * cfg_n_connections) {
                event_free(event_base_get_running_event(bufferevent_get_base(bev)));
        }
 }
@@ -553,6 +550,8 @@ main(int argc, char **argv)
        (void) WSAStartup(wVersionRequested, &wsaData);
 #endif
 
+       evutil_weakrand_seed_(&weakrand_state, 0);
+
 #ifndef _WIN32
        if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
                return 1;
diff --git a/sntp/libevent/test/test-ratelim.sh b/sntp/libevent/test/test-ratelim.sh
new file mode 100755 (executable)
index 0000000..b5e0ca6
--- /dev/null
@@ -0,0 +1,88 @@
+#!/bin/sh
+
+FAILED=no
+
+if test "x$TEST_OUTPUT_FILE" = "x"
+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
+then
+       ECHO=/bin/echo
+else
+       ECHO=echo
+fi
+
+if test "$TEST_OUTPUT_FILE" != "/dev/null"
+then
+       touch "$TEST_OUTPUT_FILE" || exit 1
+fi
+
+TEST_DIR=.
+
+T=`echo "$0" | sed -e 's/test-ratelim.sh$//'`
+if test -x "$T/test-ratelim"
+then
+       TEST_DIR="$T"
+fi
+
+announce () {
+       echo $@
+       echo $@ >>"$TEST_OUTPUT_FILE"
+}
+
+announce_n () {
+       $ECHO -n $@
+       echo $@ >>"$TEST_OUTPUT_FILE"
+}
+
+
+run_tests () {
+       announce_n "  Group limits, no connection limit:"
+       if $TEST_DIR/test-ratelim -g 30000 -n 30 -t 100 --check-grouplimit 1000 --check-stddev 100 >>"$TEST_OUTPUT_FILE"
+       then
+               announce OKAY
+       else
+               announce FAILED
+               FAILED=yes
+       fi
+
+       announce_n "  Connection limit, no group limit:"
+       if $TEST_DIR/test-ratelim -c 1000 -n 30 -t 100 --check-connlimit 50 --check-stddev 50 >>"$TEST_OUTPUT_FILE"
+       then
+               announce OKAY ;
+       else
+               announce FAILED ;
+               FAILED=yes
+       fi
+
+       announce_n "  Connection limit and group limit:"
+       if $TEST_DIR/test-ratelim -c 1000 -g 30000 -n 30 -t 100 --check-grouplimit 1000 --check-connlimit 50 --check-stddev 50 >>"$TEST_OUTPUT_FILE"
+       then
+               announce OKAY ;
+       else
+               announce FAILED ;
+               FAILED=yes
+       fi
+
+       announce_n "  Connection limit and group limit with independent drain:"
+       if $TEST_DIR/test-ratelim -c 1000 -g 35000 -n 30 -t 100 -G 500 --check-grouplimit 1000 --check-connlimit 50 --check-stddev 50 >>"$TEST_OUTPUT_FILE"
+       then
+               announce OKAY ;
+       else
+               announce FAILED ;
+               FAILED=yes
+       fi
+
+
+}
+
+announce "Running rate-limiting tests:"
+
+run_tests
+
+if test "$FAILED" = "yes"; then
+       exit 1
+fi
index dcd6639a56fb88fe0f0a6f95c8be064c4987aca7..bcc7086df7eda470b47d641715926416bf46576d 100644 (file)
@@ -41,6 +41,7 @@
 #include "event2/event.h"
 #include "event2/event_compat.h"
 #include "event2/event_struct.h"
+#include "util-internal.h"
 
 int called = 0;
 
@@ -48,14 +49,12 @@ int called = 0;
 
 struct event *ev[NEVENT];
 
+struct evutil_weakrand_state weakrand_state;
+
 static int
 rand_int(int n)
 {
-#ifdef _WIN32
-       return (int)(rand() % n);
-#else
-       return (int)(random() % n);
-#endif
+       return evutil_weakrand_(&weakrand_state) % n;
 }
 
 static void
@@ -71,7 +70,7 @@ time_cb(evutil_socket_t fd, short event, void *arg)
                        j = rand_int(NEVENT);
                        tv.tv_sec = 0;
                        tv.tv_usec = rand_int(50000);
-                       if (tv.tv_usec % 2)
+                       if (tv.tv_usec % 2 || called < NEVENT)
                                evtimer_add(ev[j], &tv);
                        else
                                evtimer_del(ev[j]);
@@ -93,6 +92,8 @@ main(int argc, char **argv)
        (void) WSAStartup(wVersionRequested, &wsaData);
 #endif
 
+       evutil_weakrand_seed_(&weakrand_state, 0);
+
        /* Initalize the event library */
        event_init();
 
@@ -108,6 +109,8 @@ main(int argc, char **argv)
 
        event_dispatch();
 
+
+       printf("%d, %d\n", called, NEVENT);
        return (called < NEVENT);
 }
 
index 36b3a627c48bf1f00cb7e3a4763b3891c40914aa..3a8e331055015365f72c861157becfc6ae5ceb47 100644 (file)
@@ -31,6 +31,8 @@
 #include <string.h>
 #include <assert.h>
 
+#ifndef NO_FORKING
+
 #ifdef _WIN32
 #include <windows.h>
 #else
@@ -48,6 +50,8 @@
 #endif
 #endif
 
+#endif /* !NO_FORKING */
+
 #ifndef __GNUC__
 #define __attribute__(x)
 #endif
@@ -111,6 +115,8 @@ testcase_run_bare_(const struct testcase_t *testcase)
 
 #define MAGIC_EXITCODE 42
 
+#ifndef NO_FORKING
+
 static enum outcome
 testcase_run_forked_(const struct testgroup_t *group,
                     const struct testcase_t *testcase)
@@ -211,6 +217,8 @@ testcase_run_forked_(const struct testgroup_t *group,
 #endif
 }
 
+#endif /* !NO_FORKING */
+
 int
 testcase_run_one(const struct testgroup_t *group,
                 const struct testcase_t *testcase)
@@ -234,9 +242,13 @@ testcase_run_one(const struct testgroup_t *group,
                cur_test_name = testcase->name;
        }
 
+#ifndef NO_FORKING
        if ((testcase->flags & TT_FORK) && !(opt_forked||opt_nofork)) {
                outcome = testcase_run_forked_(group, testcase);
        } else {
+#else
+       {
+#endif
                outcome = testcase_run_bare_(testcase);
        }
 
@@ -411,7 +423,9 @@ tinytest_main(int c, const char **v, struct testgroup_t *groups)
        if (!n)
                tinytest_set_flag_(groups, "..", 1, TT_ENABLED_);
 
+#ifdef _IONBF
        setvbuf(stdout, NULL, _IONBF, 0);
+#endif
 
        ++in_tinytest_main;
        for (i=0; groups[i].prefix; ++i)
@@ -458,3 +472,22 @@ tinytest_set_test_skipped_(void)
                cur_test_outcome = SKIP;
 }
 
+char *
+tinytest_format_hex_(const void *val_, unsigned long len)
+{
+       const unsigned char *val = val_;
+       char *result, *cp;
+       size_t i;
+
+       if (!val)
+               return strdup("null");
+       if (!(result = malloc(len*2+1)))
+               return strdup("<allocation failure>");
+       cp = result;
+       for (i=0;i<len;++i) {
+               *cp++ = "0123456789ABCDEF"[val[i] >> 4];
+               *cp++ = "0123456789ABCDEF"[val[i] & 0x0f];
+       }
+       *cp = 0;
+       return result;
+}
index dff440e3190ed250e52bb9a54d786f46a7523322..ed07b26bc006bd6f3c00ced89c0ba90198203466 100644 (file)
@@ -81,6 +81,8 @@ int tinytest_get_verbosity_(void);
 /** Implementation: Set a flag on tests matching a name; returns number
  * of tests that matched. */
 int tinytest_set_flag_(struct testgroup_t *, const char *, int set, unsigned long);
+/** Implementation: Put a chunk of memory into hex. */
+char *tinytest_format_hex_(const void *, unsigned long);
 
 /** Set all tests in 'groups' matching the name 'named' to be skipped. */
 #define tinytest_skip(groups, named) \
diff --git a/sntp/libevent/test/tinytest_demo.c b/sntp/libevent/test/tinytest_demo.c
new file mode 100644 (file)
index 0000000..bdd0e60
--- /dev/null
@@ -0,0 +1,260 @@
+/* tinytest_demo.c -- Copyright 2009-2012 Nick Mathewson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/* Welcome to the example file for tinytest!  I'll show you how to set up
+ * some simple and not-so-simple testcases. */
+
+/* Make sure you include these headers. */
+#include "tinytest.h"
+#include "tinytest_macros.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+
+/* ============================================================ */
+
+/* First, let's see if strcmp is working.  (All your test cases should be
+ * functions declared to take a single void * as an argument.) */
+void
+test_strcmp(void *data)
+{
+       (void)data; /* This testcase takes no data. */
+
+       /* Let's make sure the empty string is equal to itself */
+       if (strcmp("","")) {
+               /* This macro tells tinytest to stop the current test
+                * and go straight to the "end" label. */
+               tt_abort_msg("The empty string was not equal to itself");
+       }
+
+       /* Pretty often, calling tt_abort_msg to indicate failure is more
+          heavy-weight than you want.  Instead, just say: */
+       tt_assert(strcmp("testcase", "testcase") == 0);
+
+       /* Occasionally, you don't want to stop the current testcase just
+          because a single assertion has failed.  In that case, use
+          tt_want: */
+       tt_want(strcmp("tinytest", "testcase") > 0);
+
+       /* You can use the tt_*_op family of macros to compare values and to
+          fail unless they have the relationship you want.  They produce
+          more useful output than tt_assert, since they display the actual
+          values of the failing things.
+
+          Fail unless strcmp("abc, "abc") == 0 */
+       tt_int_op(strcmp("abc", "abc"), ==, 0);
+
+       /* Fail unless strcmp("abc, "abcd") is less than 0 */
+       tt_int_op(strcmp("abc", "abcd"), < , 0);
+
+       /* Incidentally, there's a test_str_op that uses strcmp internally. */
+       tt_str_op("abc", <, "abcd");
+
+
+       /* Every test-case function needs to finish with an "end:"
+          label and (optionally) code to clean up local variables. */
+ end:
+       ;
+}
+
+/* ============================================================ */
+
+/* Now let's mess with setup and teardown functions!  These are handy if
+   you have a bunch of tests that all need a similar environment, and you
+   want to reconstruct that environment freshly for each one. */
+
+/* First you declare a type to hold the environment info, and functions to
+   set it up and tear it down. */
+struct data_buffer {
+       /* We're just going to have couple of character buffer.  Using
+          setup/teardown functions is probably overkill for this case.
+
+          You could also do file descriptors, complicated handles, temporary
+          files, etc. */
+       char buffer1[512];
+       char buffer2[512];
+};
+/* The setup function needs to take a const struct testcase_t and return
+   void* */
+void *
+setup_data_buffer(const struct testcase_t *testcase)
+{
+       struct data_buffer *db = malloc(sizeof(struct data_buffer));
+
+       /* If you had a complicated set of setup rules, you might behave
+          differently here depending on testcase->flags or
+          testcase->setup_data or even or testcase->name. */
+
+       /* Returning a NULL here would mean that we couldn't set up for this
+          test, so we don't need to test db for null. */
+       return db;
+}
+/* The clean function deallocates storage carefully and returns true on
+   success. */
+int
+clean_data_buffer(const struct testcase_t *testcase, void *ptr)
+{
+       struct data_buffer *db = ptr;
+
+       if (db) {
+               free(db);
+               return 1;
+       }
+       return 0;
+}
+/* Finally, declare a testcase_setup_t with these functions. */
+struct testcase_setup_t data_buffer_setup = {
+       setup_data_buffer, clean_data_buffer
+};
+
+
+/* Now let's write our test. */
+void
+test_memcpy(void *ptr)
+{
+       /* This time, we use the argument. */
+       struct data_buffer *db = ptr;
+
+       /* We'll also introduce a local variable that might need cleaning up. */
+       char *mem = NULL;
+
+       /* Let's make sure that memcpy does what we'd like. */
+       strcpy(db->buffer1, "String 0");
+       memcpy(db->buffer2, db->buffer1, sizeof(db->buffer1));
+       tt_str_op(db->buffer1, ==, db->buffer2);
+
+        /* This one works if there's an internal NUL. */
+        tt_mem_op(db->buffer1, <, db->buffer2, sizeof(db->buffer1));
+
+       /* Now we've allocated memory that's referenced by a local variable.
+          The end block of the function will clean it up. */
+       mem = strdup("Hello world.");
+       tt_assert(mem);
+
+       /* Another rather trivial test. */
+       tt_str_op(db->buffer1, !=, mem);
+
+ end:
+       /* This time our end block has something to do. */
+       if (mem)
+               free(mem);
+}
+
+void
+test_timeout(void *ptr)
+{
+       time_t t1, t2;
+       (void)ptr;
+       t1 = time(NULL);
+#ifdef _WIN32
+       Sleep(5000);
+#else
+       sleep(5);
+#endif
+       t2 = time(NULL);
+
+       tt_int_op(t2-t1, >=, 4);
+
+       tt_int_op(t2-t1, <=, 6);
+
+ end:
+       ;
+}
+
+/* ============================================================ */
+
+/* Now we need to make sure that our tests get invoked.          First, you take
+   a bunch of related tests and put them into an array of struct testcase_t.
+*/
+
+struct testcase_t demo_tests[] = {
+       /* Here's a really simple test: it has a name you can refer to it
+          with, and a function to invoke it. */
+       { "strcmp", test_strcmp, },
+
+       /* The second test has a flag, "TT_FORK", to make it run in a
+          subprocess, and a pointer to the testcase_setup_t that configures
+          its environment. */
+       { "memcpy", test_memcpy, TT_FORK, &data_buffer_setup },
+
+       /* This flag is off-by-default, since it takes a while to run.  You
+        * can enable it manually by passing +demo/timeout at the command line.*/
+       { "timeout", test_timeout, TT_OFF_BY_DEFAULT },
+
+       /* The array has to end with END_OF_TESTCASES. */
+       END_OF_TESTCASES
+};
+
+/* Next, we make an array of testgroups.  This is mandatory.  Unlike more
+   heavy-duty testing frameworks, groups can't nest. */
+struct testgroup_t groups[] = {
+
+       /* Every group has a 'prefix', and an array of tests.  That's it. */
+       { "demo/", demo_tests },
+
+       END_OF_GROUPS
+};
+
+/* We can also define test aliases. These can be used for types of tests that
+ * cut across groups. */
+const char *alltests[] = { "+..", NULL };
+const char *slowtests[] = { "+demo/timeout", NULL };
+struct testlist_alias_t aliases[] = {
+
+       { "ALL", alltests },
+       { "SLOW", slowtests },
+
+       END_OF_ALIASES
+};
+
+
+int
+main(int c, const char **v)
+{
+       /* Finally, just call tinytest_main().  It lets you specify verbose
+          or quiet output with --verbose and --quiet.  You can list
+          specific tests:
+
+              tinytest-demo demo/memcpy
+
+          or use a ..-wildcard to select multiple tests with a common
+          prefix:
+
+              tinytest-demo demo/..
+
+          If you list no tests, you get them all by default, so that
+          "tinytest-demo" and "tinytest-demo .." mean the same thing.
+
+       */
+       tinytest_set_aliases(aliases);
+       return tinytest_main(c, v, groups);
+}
index 9ff69b1d506dab1f8d1ecc92517f8a4734754bd3..c3728d1fdd61daeb016970abb45c5b0b056c0e7c 100644 (file)
 #define tt_assert_test_fmt_type(a,b,str_test,type,test,printf_type,printf_fmt, \
     setup_block,cleanup_block,die_on_fail)                             \
        TT_STMT_BEGIN                                                   \
-       type val1_ = (type)(a);                                         \
-       type val2_ = (type)(b);                                         \
+       type val1_ = (a);                                               \
+       type val2_ = (b);                                               \
        int tt_status_ = (test);                                        \
        if (!tt_status_ || tinytest_get_verbosity_()>1) {               \
                printf_type print_;                                     \
        tt_assert_test_fmt_type(a,b,str_test,type,test,type,fmt,        \
            {print_=value_;},{},die_on_fail)
 
+#define tt_assert_test_type_opt(a,b,str_test,type,test,fmt,die_on_fail)        \
+       tt_assert_test_fmt_type(a,b,str_test,type,test,type,fmt,        \
+            {print_=value_?value_:"<NULL>";},{},die_on_fail)
+
 /* Helper: assert that a op b, when cast to type.  Format the values with
  * printf format fmt on failure. */
 #define tt_assert_op_type(a,op,b,type,fmt)                             \
            (val1_ op val2_),"%lu",TT_EXIT_TEST_FUNCTION)
 
 #define tt_ptr_op(a,op,b)                                              \
-       tt_assert_test_type(a,b,#a" "#op" "#b,void*,                    \
+       tt_assert_test_type(a,b,#a" "#op" "#b,const void*,              \
            (val1_ op val2_),"%p",TT_EXIT_TEST_FUNCTION)
 
 #define tt_str_op(a,op,b)                                              \
-       tt_assert_test_type(a,b,#a" "#op" "#b,const char *,             \
-           (strcmp(val1_,val2_) op 0),"<%s>",TT_EXIT_TEST_FUNCTION)
+       tt_assert_test_type_opt(a,b,#a" "#op" "#b,const char *,         \
+           (val1_ && val2_ && strcmp(val1_,val2_) op 0),"<%s>",        \
+           TT_EXIT_TEST_FUNCTION)
+
+#define tt_mem_op(expr1, op, expr2, len)                                \
+  tt_assert_test_fmt_type(expr1,expr2,#expr1" "#op" "#expr2,            \
+                         const void *,                                 \
+                         (val1_ && val2_ && memcmp(val1_, val2_, len) op 0), \
+                         char *, "%s",                                 \
+                         { print_ = tinytest_format_hex_(value_, (len)); }, \
+                         { if (print_) free(print_); },                \
+                         TT_EXIT_TEST_FUNCTION                         \
+                          );
 
 #define tt_want_int_op(a,op,b)                                         \
        tt_assert_test_type(a,b,#a" "#op" "#b,long,(val1_ op val2_),"%ld",(void)0)
            (val1_ op val2_),"%lu",(void)0)
 
 #define tt_want_ptr_op(a,op,b)                                         \
-       tt_assert_test_type(a,b,#a" "#op" "#b,void*,                    \
+  tt_assert_test_type(a,b,#a" "#op" "#b,const void*,                   \
            (val1_ op val2_),"%p",(void)0)
 
 #define tt_want_str_op(a,op,b)                                         \
index daf20f47a30ebf7f5e2aad5bc7a2efb00b969f27..2c584fa75263641057a92a659ff305941ca70c57 100644 (file)
@@ -86,9 +86,6 @@ struct evutil_monotonic_timer {
        struct timeval last_time;
 };
 
-#define EV_MONOT_PRECISE  1
-#define EV_MONOT_FALLBACK 2
-
 int evutil_configure_monotonic_time_(struct evutil_monotonic_timer *mt,
     int flags);
 int evutil_gettime_monotonic_(struct evutil_monotonic_timer *mt, struct timeval *tv);
index 5866dbc518bdf3ddf48f8dce276ae8990aa48d65..4fdedeaf93c575ac4dae47f4ba34775314513261 100644 (file)
@@ -392,7 +392,7 @@ void evutil_free_secure_rng_globals_(void);
 void evutil_free_globals_(void);
 
 #ifdef _WIN32
-HANDLE evutil_load_windows_system_library_(const TCHAR *library_name);
+HMODULE evutil_load_windows_system_library_(const TCHAR *library_name);
 #endif
 
 #ifndef EV_SIZE_FMT
index c0ee7cf7dc028e573d49119bdba47585b5a60e85..0be54ae11b50d3d3af99f6d7090bf167949adfe9 100644 (file)
@@ -41,7 +41,7 @@
 
   We don't try to do binary compatibility except within stable release
   series, so binaries linked against any version of Libevent 2.0 will
-  probably need to be recompiled against Libevent 2.1.3-alpha if you
+  probably need to be recompiled against Libevent 2.1.4-alpha if you
   want to use it.  It is probable that we'll break binary compatibility
   again before Libevent 2.1 is stable.
 
@@ -63,6 +63,9 @@
   surrounded with appropriate #ifdef lines to keep your IDE from getting
   upset.
 
+  There is now an alternative cmake-based build process; cmake users
+  should see the relevant sections in the README.
+
 
 1.2. New functions for events and the event loop
 
   that's a no-op in past versions of Libevent, and we don't want to
   break compatibility.)
 
+  You can use the new event_base_get_num_events() function to find the
+  number of events active or pending on an event_base. To find the
+  largest number of events that there have been since the last call, use
+  event_base_get_max_events().
+
+  You can now activate all the events waiting for a given fd or signal
+  using the event_base_active_by_fd() and event_base_active_by_signal()
+  APIs.
+
+  On backends that support it (currently epoll), there is now an
+  EV_CLOSED flag that programs can use to detect when a socket has
+  closed without having to read all the bytes until receiving an EOF.
+
 1.3. Event finalization
 
   [NOTE: This is an experimental feature in Libevent 2.1.3-alpha. Though
   You can find the priority at which a bufferevent runs with
   bufferevent_get_priority().
 
+  The function bufferevent_get_token_bucket_cfg() can retrieve the
+  rate-limit settings for a bufferevent; bufferevent_getwatermark() can
+  return a bufferevent's current watermark settings.
+
+  You can manually trigger a bufferevent's callbacks via
+  bufferevent_trigger() and bufferevent_trigger_event().
+
 1.7. New functions and features: evdns
 
   The previous evdns interface used an "open a test UDP socket" trick in
   flag, which tells the evdns_base that it should not prevent Libevent from
   exiting while it has no DNS requests in progress.
 
+  There is a new evdns_base_clear_host_addresses() function to remove
+  all the /etc/hosts addresses registered with an evdns instance.
+
 1.8. New functions and features: evconnlistener
 
   Libevent 2.1 adds the following evconnlistener flags:
   and actually reports the error code and lets you figure out which request
   failed.
 
+  You can navigate from an evhttp_connection back to its evhttp with the
+  new evhttp_connection_get_server() function.
+
+  You can override the default HTTP Content-Type with the new
+  evhttp_set_default_content_type() function
+
+  There's a new evhttp_connection_get_addr() API to return the peer
+  address of an evhttp_connection.
+
+  The new evhttp_send_reply_chunk_with_cb() is a variant of
+  evhttp_send_reply_chunk() with a callback to be invoked when the
+  chunk is sent.
+
+  The evhttp_request_set_header_cb() facility adds a callback to be
+  invoked while parsing headers.
+
+  The evhttp_request_set_on_complete_cb() facility adds a callback to be
+  invoked on request completion.
+
+1.10. New functions and features: evutil
+
+  There's a function "evutil_secure_rng_set_urandom_device_file()" that
+  you can use to override the default file that Libevent uses to seed
+  its (sort-of) secure RNG.
+
 2. Cross-platform performance improvements
 
 2.1. Better data structures