From: Harlan Stenn Date: Wed, 11 Feb 2015 09:05:59 +0000 (+0000) Subject: [Bug 2747] Upgrade libevent to 2.1.5-beta X-Git-Tag: NTP_4_3_0~3^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9e596893e3243830244043b7309fd387f411f7f3;p=thirdparty%2Fntp.git [Bug 2747] Upgrade libevent to 2.1.5-beta bk: 54db1b77dPyouexQ4D8Zp3XGGeDo6A --- diff --git a/sntp/libevent/ChangeLog b/sntp/libevent/ChangeLog index 8bb76caff..149963750 100644 --- a/sntp/libevent/ChangeLog +++ b/sntp/libevent/ChangeLog @@ -1,23 +1,282 @@ -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 diff --git a/sntp/libevent/Makefile.am b/sntp/libevent/Makefile.am index 58f1f016a..3053cc016 100644 --- a/sntp/libevent/Makefile.am +++ b/sntp/libevent/Makefile.am @@ -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 index 2723a2cac..000000000 --- a/sntp/libevent/README +++ /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 index 000000000..a7c82b016 --- /dev/null +++ b/sntp/libevent/README.md @@ -0,0 +1,318 @@ +# 0. BUILDING AND INSTALLATION (Briefly) + +## Autoconf + + $ ./configure + $ make + $ make verify # (optional) + $ sudo make install + +## CMake (Windows) + +Install CMake: + + + $ 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 . + +To build libevent using Microsoft Visual studio open the "Visual Studio Command prompt" and type: + +``` +$ cd +$ 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: + +# 2. USEFUL LINKS: + +For the latest released version of Libevent, see the official website at + . + +There's a pretty good work-in-progress manual up at + . + +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: + + + + + +To report bugs, request features, or submit patches to Libevent, +use the Sourceforge trackers at + + + +There's also a libevent-users mailing list for talking about Libevent +use and development: + + + +# 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 index 000000000..0fcba5d91 --- /dev/null +++ b/sntp/libevent/WIN32-Code/getopt.c @@ -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 +#include +#include +#include + +#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 index 000000000..796f45505 --- /dev/null +++ b/sntp/libevent/WIN32-Code/getopt.h @@ -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 index 000000000..03f0c01a1 --- /dev/null +++ b/sntp/libevent/WIN32-Code/getopt_long.c @@ -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 +#include +#include +#include +#include +#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); +} diff --git a/sntp/libevent/WIN32-Code/nmake/event2/event-config.h b/sntp/libevent/WIN32-Code/nmake/event2/event-config.h index da550283a..8cbf19028 100644 --- a/sntp/libevent/WIN32-Code/nmake/event2/event-config.h +++ b/sntp/libevent/WIN32-Code/nmake/event2/event-config.h @@ -274,7 +274,7 @@ /* #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" @@ -331,7 +331,7 @@ #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__ diff --git a/sntp/libevent/WIN32-Code/tree.h b/sntp/libevent/WIN32-Code/tree.h index 585618dde..2ccfbf20a 100644 --- a/sntp/libevent/WIN32-Code/tree.h +++ b/sntp/libevent/WIN32-Code/tree.h @@ -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 - * 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_ */ diff --git a/sntp/libevent/buffer.c b/sntp/libevent/buffer.c index e603be863..a1a2b988c 100644 --- a/sntp/libevent/buffer.c +++ b/sntp/libevent/buffer.c @@ -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; } diff --git a/sntp/libevent/bufferevent.c b/sntp/libevent/bufferevent.c index 588461a33..d298d0b3f 100644 --- a/sntp/libevent/bufferevent.c +++ b/sntp/libevent/bufferevent.c @@ -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 diff --git a/sntp/libevent/bufferevent_async.c b/sntp/libevent/bufferevent_async.c index 137ad2479..6395e57a9 100644 --- a/sntp/libevent/bufferevent_async.c +++ b/sntp/libevent/bufferevent_async.c @@ -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; diff --git a/sntp/libevent/bufferevent_filter.c b/sntp/libevent/bufferevent_filter.c index af71ebeea..4d9be43e2 100644 --- a/sntp/libevent/bufferevent_filter.c +++ b/sntp/libevent/bufferevent_filter.c @@ -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 diff --git a/sntp/libevent/bufferevent_openssl.c b/sntp/libevent/bufferevent_openssl.c index 423b34f10..b30f90ff2 100644 --- a/sntp/libevent/bufferevent_openssl.c +++ b/sntp/libevent/bufferevent_openssl.c @@ -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 { diff --git a/sntp/libevent/bufferevent_pair.c b/sntp/libevent/bufferevent_pair.c index 4340f2372..8154e17be 100644 --- a/sntp/libevent/bufferevent_pair.c +++ b/sntp/libevent/bufferevent_pair.c @@ -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 */ diff --git a/sntp/libevent/configure.ac b/sntp/libevent/configure.ac index c60c7ace8..2cdc74f16 100644 --- a/sntp/libevent/configure.ac +++ b/sntp/libevent/configure.ac @@ -5,18 +5,17 @@ dnl See LICENSE for copying information. dnl dnl Original version Dug Song -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 - ] - ) - ]) + 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 ] + ) 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 diff --git a/sntp/libevent/evbuffer-internal.h b/sntp/libevent/evbuffer-internal.h index fb67ec095..cf4bddc80 100644 --- a/sntp/libevent/evbuffer-internal.h +++ b/sntp/libevent/evbuffer-internal.h @@ -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 diff --git a/sntp/libevent/evdns.c b/sntp/libevent/evdns.c index 59c3abe18..60f4db5c5 100644 --- a/sntp/libevent/evdns.c +++ b/sntp/libevent/evdns.c @@ -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; } diff --git a/sntp/libevent/event.c b/sntp/libevent/event.c index 01f0e1422..af4a6e05e 100644 --- a/sntp/libevent/event.c +++ b/sntp/libevent/event.c @@ -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(); } diff --git a/sntp/libevent/event_tagging.c b/sntp/libevent/event_tagging.c index 7edd3da5d..64b100b82 100644 --- a/sntp/libevent/event_tagging.c +++ b/sntp/libevent/event_tagging.c @@ -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; \ diff --git a/sntp/libevent/evrpc-internal.h b/sntp/libevent/evrpc-internal.h index e53d06e0f..9eb376386 100644 --- a/sntp/libevent/evrpc-internal.h +++ b/sntp/libevent/evrpc-internal.h @@ -27,6 +27,7 @@ #ifndef EVRPC_INTERNAL_H_INCLUDED_ #define EVRPC_INTERNAL_H_INCLUDED_ +#include "event2/http.h" #include "http-internal.h" struct evrpc; diff --git a/sntp/libevent/evthread-internal.h b/sntp/libevent/evthread-internal.h index 346b2bb92..16adf167d 100644 --- a/sntp/libevent/evthread-internal.h +++ b/sntp/libevent/evthread-internal.h @@ -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 diff --git a/sntp/libevent/evthread.c b/sntp/libevent/evthread.c index 4da5d24e8..02dab7a80 100644 --- a/sntp/libevent/evthread.c +++ b/sntp/libevent/evthread.c @@ -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) diff --git a/sntp/libevent/evutil.c b/sntp/libevent/evutil.c index c28caded5..3d72e4032 100644 --- a/sntp/libevent/evutil.c +++ b/sntp/libevent/evutil.c @@ -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]; diff --git a/sntp/libevent/evutil_time.c b/sntp/libevent/evutil_time.c index e433043e4..8f53c66b6 100644 --- a/sntp/libevent/evutil_time.c +++ b/sntp/libevent/evutil_time.c @@ -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 diff --git a/sntp/libevent/ht-internal.h b/sntp/libevent/ht-internal.h index 8842f4cd7..50375bbaa 100644 --- a/sntp/libevent/ht-internal.h +++ b/sntp/libevent/ht-internal.h @@ -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 \ diff --git a/sntp/libevent/http-internal.h b/sntp/libevent/http-internal.h index 82dd402a0..a83160c83 100644 --- a/sntp/libevent/http-internal.h +++ b/sntp/libevent/http-internal.h @@ -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. * diff --git a/sntp/libevent/http.c b/sntp/libevent/http.c index 51470225e..dd8c9cffd 100644 --- a/sntp/libevent/http.c +++ b/sntp/libevent/http.c @@ -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; diff --git a/sntp/libevent/include/event2/buffer.h b/sntp/libevent/include/event2/buffer.h index 839d6e7ca..468588b9f 100644 --- a/sntp/libevent/include/event2/buffer.h +++ b/sntp/libevent/include/event2/buffer.h @@ -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 diff --git a/sntp/libevent/include/event2/bufferevent.h b/sntp/libevent/include/event2/bufferevent.h index 46203b04f..fe8a74d34 100644 --- a/sntp/libevent/include/event2/bufferevent.h +++ b/sntp/libevent/include/event2/bufferevent.h @@ -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. */ diff --git a/sntp/libevent/include/event2/dns.h b/sntp/libevent/include/event2/dns.h index a00c83e6a..17cd86a2e 100644 --- a/sntp/libevent/include/event2/dns.h +++ b/sntp/libevent/include/event2/dns.h @@ -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 diff --git a/sntp/libevent/include/event2/event.h b/sntp/libevent/include/event2/event.h index 6e2b884d4..6e0a4f04c 100644 --- a/sntp/libevent/include/event2/event.h +++ b/sntp/libevent/include/event2/event.h @@ -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 diff --git a/sntp/libevent/include/event2/http.h b/sntp/libevent/include/event2/http.h index 81f44b855..4284d5fc3 100644 --- a/sntp/libevent/include/event2/http.h +++ b/sntp/libevent/include/event2/http.h @@ -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, diff --git a/sntp/libevent/include/event2/listener.h b/sntp/libevent/include/event2/listener.h index 8c77803d6..84b4da055 100644 --- a/sntp/libevent/include/event2/listener.h +++ b/sntp/libevent/include/event2/listener.h @@ -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 diff --git a/sntp/libevent/include/event2/util.h b/sntp/libevent/include/event2/util.h index 14c6a25d7..b152a4b40 100644 --- a/sntp/libevent/include/event2/util.h +++ b/sntp/libevent/include/event2/util.h @@ -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. diff --git a/sntp/libevent/kqueue.c b/sntp/libevent/kqueue.c index 393346742..a6578dfe1 100644 --- a/sntp/libevent/kqueue.c +++ b/sntp/libevent/kqueue.c @@ -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: diff --git a/sntp/libevent/listener.c b/sntp/libevent/listener.c index 3272c405c..172d2927c 100644 --- a/sntp/libevent/listener.c +++ b/sntp/libevent/listener.c @@ -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; diff --git a/sntp/libevent/sample/http-server.c b/sntp/libevent/sample/http-server.c index 1cb89bc91..cbb9c914d 100644 --- a/sntp/libevent/sample/http-server.c +++ b/sntp/libevent/sample/http-server.c @@ -246,7 +246,10 @@ send_document_cb(struct evhttp_request *req, void *arg) goto err; #endif - evbuffer_add_printf(evb, "\n \n" + evbuffer_add_printf(evb, + "\n" + "\n \n" + " \n" " %s\n" " \n" " \n" @@ -274,7 +277,7 @@ send_document_cb(struct evhttp_request *req, void *arg) #endif evbuffer_add_printf(evb, "\n"); #ifdef _WIN32 - CloseHandle(d); + FindClose(d); #else closedir(d); #endif diff --git a/sntp/libevent/sample/https-client.c b/sntp/libevent/sample/https-client.c index e13ac4bd3..fbd5de8c5 100644 --- a/sntp/libevent/sample/https-client.c +++ b/sntp/libevent/sample/https-client.c @@ -96,7 +96,7 @@ static void syntax(void) { fputs("Syntax:\n", stderr); - fputs(" https-client -url [-data data-file.bin] [-ignore-cert]\n", stderr); + fputs(" https-client -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); } diff --git a/sntp/libevent/sample/include.am b/sntp/libevent/sample/include.am index 81980ac51..75f87c70d 100644 --- a/sntp/libevent/sample/include.am +++ b/sntp/libevent/sample/include.am @@ -30,7 +30,9 @@ noinst_HEADERS += \ sample/openssl_hostname_validation.h endif +if BUILD_SAMPLES noinst_PROGRAMS += $(SAMPLES) +endif $(SAMPLES) : libevent.la diff --git a/sntp/libevent/test/include.am b/sntp/libevent/test/include.am index ca36da46e..4cd49ef63 100644 --- a/sntp/libevent/test/include.am +++ b/sntp/libevent/test/include.am @@ -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 index 000000000..ab6e610e8 --- /dev/null +++ b/sntp/libevent/test/print-winsock-errors.c @@ -0,0 +1,84 @@ +#include +#include + +#include +#include + +#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; +} diff --git a/sntp/libevent/test/regress.c b/sntp/libevent/test/regress.c index 4d17b6780..399ba2fbd 100644 --- a/sntp/libevent/test/regress.c +++ b/sntp/libevent/test/regress.c @@ -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), diff --git a/sntp/libevent/test/regress.h b/sntp/libevent/test/regress.h index a9892b0ef..bbfefe673 100644 --- a/sntp/libevent/test/regress.h +++ b/sntp/libevent/test/regress.h @@ -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) diff --git a/sntp/libevent/test/regress_buffer.c b/sntp/libevent/test/regress_buffer.c index ccb14870a..4d6a5de20 100644 --- a/sntp/libevent/test/regress_buffer.c +++ b/sntp/libevent/test/regress_buffer.c @@ -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}, diff --git a/sntp/libevent/test/regress_bufferevent.c b/sntp/libevent/test/regress_bufferevent.c index 4ec2dccf4..a1998ba62 100644 --- a/sntp/libevent/test/regress_bufferevent.c +++ b/sntp/libevent/test/regress_bufferevent.c @@ -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), diff --git a/sntp/libevent/test/regress_dns.c b/sntp/libevent/test/regress_dns.c index 338c4ee8f..6d6b48443 100644 --- a/sntp/libevent/test/regress_dns.c +++ b/sntp/libevent/test/regress_dns.c @@ -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*)"" }, diff --git a/sntp/libevent/test/regress_finalize.c b/sntp/libevent/test/regress_finalize.c index 61a6313f1..552210fe9 100644 --- a/sntp/libevent/test/regress_finalize.c +++ b/sntp/libevent/test/regress_finalize.c @@ -25,6 +25,7 @@ */ #include "event2/event-config.h" +#include "evconfig-private.h" #include "tinytest.h" #include "tinytest_macros.h" #include diff --git a/sntp/libevent/test/regress_http.c b/sntp/libevent/test/regress_http.c index ca7d5155b..35f6dd768 100644 --- a/sntp/libevent/test/regress_http.c +++ b/sntp/libevent/test/regress_http.c @@ -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 }; diff --git a/sntp/libevent/test/regress_main.c b/sntp/libevent/test/regress_main.c index 58cbe5fe2..3198ced1d 100644 --- a/sntp/libevent/test/regress_main.c +++ b/sntp/libevent/test/regress_main.c @@ -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; diff --git a/sntp/libevent/test/regress_minheap.c b/sntp/libevent/test/regress_minheap.c index a1f554ebb..05db32e26 100644 --- a/sntp/libevent/test/regress_minheap.c +++ b/sntp/libevent/test/regress_minheap.c @@ -30,12 +30,13 @@ #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; } diff --git a/sntp/libevent/test/regress_ssl.c b/sntp/libevent/test/regress_ssl.c index c2113414c..bf9b46b1e 100644 --- a/sntp/libevent/test/regress_ssl.c +++ b/sntp/libevent/test/regress_ssl.c @@ -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; diff --git a/sntp/libevent/test/regress_thread.c b/sntp/libevent/test/regress_thread.c index 612bf1d61..c42668ea8 100644 --- a/sntp/libevent/test/regress_thread.c +++ b/sntp/libevent/test/regress_thread.c @@ -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 diff --git a/sntp/libevent/test/regress_util.c b/sntp/libevent/test/regress_util.c index d64d00249..60f085bf1 100644 --- a/sntp/libevent/test/regress_util.c +++ b/sntp/libevent/test/regress_util.c @@ -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); diff --git a/sntp/libevent/test/regress_zlib.c b/sntp/libevent/test/regress_zlib.c index 9339397c9..840667693 100644 --- a/sntp/libevent/test/regress_zlib.c +++ b/sntp/libevent/test/regress_zlib.c @@ -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); diff --git a/sntp/libevent/test/test-fdleak.c b/sntp/libevent/test/test-fdleak.c index ee2432b71..4c4eba25e 100644 --- a/sntp/libevent/test/test-fdleak.c +++ b/sntp/libevent/test/test-fdleak.c @@ -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(); diff --git a/sntp/libevent/test/test-ratelim.c b/sntp/libevent/test/test-ratelim.c index 27649b849..17babfdcb 100644 --- a/sntp/libevent/test/test-ratelim.c +++ b/sntp/libevent/test/test-ratelim.c @@ -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 index 000000000..b5e0ca62a --- /dev/null +++ b/sntp/libevent/test/test-ratelim.sh @@ -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 diff --git a/sntp/libevent/test/test-time.c b/sntp/libevent/test/test-time.c index dcd6639a5..bcc7086df 100644 --- a/sntp/libevent/test/test-time.c +++ b/sntp/libevent/test/test-time.c @@ -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); } diff --git a/sntp/libevent/test/tinytest.c b/sntp/libevent/test/tinytest.c index 36b3a627c..3a8e33105 100644 --- a/sntp/libevent/test/tinytest.c +++ b/sntp/libevent/test/tinytest.c @@ -31,6 +31,8 @@ #include #include +#ifndef NO_FORKING + #ifdef _WIN32 #include #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(""); + cp = result; + for (i=0;i> 4]; + *cp++ = "0123456789ABCDEF"[val[i] & 0x0f]; + } + *cp = 0; + return result; +} diff --git a/sntp/libevent/test/tinytest.h b/sntp/libevent/test/tinytest.h index dff440e31..ed07b26bc 100644 --- a/sntp/libevent/test/tinytest.h +++ b/sntp/libevent/test/tinytest.h @@ -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 index 000000000..bdd0e6008 --- /dev/null +++ b/sntp/libevent/test/tinytest_demo.c @@ -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 +#include +#include +#include +#include +#ifndef _WIN32 +#include +#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); +} diff --git a/sntp/libevent/test/tinytest_macros.h b/sntp/libevent/test/tinytest_macros.h index 9ff69b1d5..c3728d1fd 100644 --- a/sntp/libevent/test/tinytest_macros.h +++ b/sntp/libevent/test/tinytest_macros.h @@ -113,8 +113,8 @@ #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_; \ @@ -144,6 +144,10 @@ 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_:"";},{},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) \ @@ -159,12 +163,23 @@ (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) @@ -174,7 +189,7 @@ (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) \ diff --git a/sntp/libevent/time-internal.h b/sntp/libevent/time-internal.h index daf20f47a..2c584fa75 100644 --- a/sntp/libevent/time-internal.h +++ b/sntp/libevent/time-internal.h @@ -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); diff --git a/sntp/libevent/util-internal.h b/sntp/libevent/util-internal.h index 5866dbc51..4fdedeaf9 100644 --- a/sntp/libevent/util-internal.h +++ b/sntp/libevent/util-internal.h @@ -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 diff --git a/sntp/libevent/whatsnew-2.1.txt b/sntp/libevent/whatsnew-2.1.txt index c0ee7cf7d..0be54ae11 100644 --- a/sntp/libevent/whatsnew-2.1.txt +++ b/sntp/libevent/whatsnew-2.1.txt @@ -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 @@ -146,6 +149,19 @@ 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 @@ -325,6 +341,13 @@ 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 @@ -340,6 +363,9 @@ 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: @@ -392,6 +418,31 @@ 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 diff --git a/sntp/libevent/m4/LICENSE-OPENLDAP b/sntp/m4/LICENSE-OPENLDAP similarity index 100% rename from sntp/libevent/m4/LICENSE-OPENLDAP rename to sntp/m4/LICENSE-OPENLDAP diff --git a/sntp/libevent/m4/openldap-thread-check.m4 b/sntp/m4/openldap-thread-check.m4 similarity index 100% rename from sntp/libevent/m4/openldap-thread-check.m4 rename to sntp/m4/openldap-thread-check.m4 diff --git a/sntp/libevent/m4/openldap.m4 b/sntp/m4/openldap.m4 similarity index 100% rename from sntp/libevent/m4/openldap.m4 rename to sntp/m4/openldap.m4