+Changes in version 2.0.11-stable (27 Apr 2011)
+ [Autogenerated from the Git log, sorted and cleaned by hand.]
+BUGFIXES:
+ o Fix evport handling of POLLHUP and POLLERR (b42ce4b)
+ o Fix compilation on Windows with NDEBUG (cb8059d)
+ o Check for POLLERR, POLLHUP and POLLNVAL for Solaris event ports (0144886 Trond Norbye)
+ o Detect and handle more allocation failures. (666b096 Jardel Weyrich)
+ o Use event_err() only if the failure is truly unrecoverable. (3f8d22a Jardel Weyrich)
+ o Handle resize failures in the select backend better. (83e805a)
+ o Correctly free selectop fields when select_resize fails in select_init (0c0ec0b)
+ o Make --enable-gcc-warnings a no-op if not using gcc (3267703)
+ o Fix a type error in our (unused) arc4random_stir() (f736198)
+ o Correctly detect and stop non-chunked http requests when the body is too long (63a715e)
+ o Have event_base_gettimeofday_cached() always return wall-clock time (a459ef7)
+ o Workaround for http crash bug 3078187 (5dc5662 Tomash Brechko)
+ o Fix incorrect assertions and possible use-after-free in evrpc_free() (4b8f02f Christophe Fillot)
+ o Reset outgoing http connection when read data in idle state. (272823f Tomash Brechko)
+ o Fix subtle recursion in evhttp_connection_cb_cleanup(). (218cf19 Tomash Brechko)
+ o Fix the case when failed evhttp_make_request() leaved request in the queue. (0d6622e Tomash Brechko)
+ o Fix a crash bug in evdns server circular list code (00e91b3)
+ o Handle calloc failure in evdns. (Found by Dave Hart) (364291e)
+ o Fix a memory leak on win32 socket->event map. (b4f89f0)
+ o Add a forgotten NULL check to evhttp_parse_headers (12311ff Sebastian Hahn)
+ o Fix possible NULL-deref in evdns_cancel_request (5208544 Sebastian Hahn)
+
+PORTABILITY:
+ o Fall back to sscanf if we have no other way to implement strtoll (453317b)
+ o Build correctly on platforms without sockaddr_storage (9184563)
+ o Try to build correctly on platforms with no IPv6 support (713c254)
+ o Build on systems without AI_PASSIVE (cb92113)
+ o Fix http unit test on non-windows platforms without getaddrinfo (6092f12)
+ o Do not check for gethostbyname_r versions if we have getaddrinfo (c1260b0)
+ o Include arpa/inet.h as needed on HPUX (10c834c Harlan Stenn)
+ o Include util-internal.h as needed to build on platforms with no sockaddr_storage (bbf5515 Harlan Stenn)
+ o Check for getservbyname even if not on win32. (af08a94 Harlan Stenn)
+ o Add -D_OSF_SOURCE to fix hpux builds (0b33479 Harlan Stenn)
+ o Check for allocation failures in apply_socktype_protocol_hack (637d17a)
+ o Fix the check for multicast or broadcast addresses in evutil_check_interfaces (1a21d7b)
+ o Avoid a free(NULL) if out-of-memory in evdns_getaddrinfo. Found by Dave Hart (3417f68)
+
+DEFENSIVE PROGRAMMING:
+ o Add compile-time check for AF_UNSPEC==PF_UNSPEC (3c8f4e7)
+
+BUGS IN TESTS:
+ o Fix test.sh output on solaris (b4f89b6 Dave Hart)
+ o Make test-eof fail with a timeout if we never get an eof. (05a2c22 Harlan Stenn)
+ o Use %s with printf in test.sh (039b9bd)
+ o Add an assert to appease clang's static analyzer (b0ff7eb Sebastian Hahn)
+ o Add a forgotten return value check in the unit tests (3819b62 Sebastian Hahn)
+ o Actually send NULL request in http_bad_request_test (b693c32 Sebastian Hahn)
+ o add some (void) casts for unused variables (65707d7 Sebastian Hahn)
+ o Refactor test_getaddrinfo_async_cancel_stress() (48c44a6 Sebastian Hahn)
+ o Be nice and "handle" error return values in sample code (4bac793 Sebastian Hahn)
+ o Check return value of evbuffer_add_cb in tests (93a1abb Sebastian Hahn)
+ o Remote some dead code from dns-example.c (744c745 Sebastian Hahn)
+ o Zero a struct sockaddr_in before using it (646f9fe Sebastian Hahn)
+
+BUILD FIXES:
+ o Fix warnings about AC_LANG_PROGRAM usage (f663112 Sebastian Hahn)
+ o Skip check for zlib if we have no zlib.h (a317c06 Harlan Stenn)
+ o Fix autoconf bracket issues; make check for getaddrinfo include netdb.h (833e5e9 Harlan Stenn)
+ o Correct an AM_CFLAGS to an AM_CPPFLAGS in test/Makefile.am (9c469db Dave Hart)
+ o Fix make distcheck & installation of libevent 1 headers (b5a1f9f Dave Hart)
+ o Fix compilation under LLVM/clang with --enable-gcc-warnings (ad9ff58 Sebastian Hahn)
+
+FEATURES:
+ o Make URI parser able to tolerate nonconformant URIs. (95060b5)
+
+DOCUMENTATION:
+ o Clarify event_set_mem_functions doc (926f816)
+ o Correct evhttp_del_accept_socket documentation on whether socket is closed (f665924)
+ o fix spelling mistake in whatsnew-2.0.txt (deb2f73)
+ o Fix sample/http-server ipv6 fixes (eb692be)
+ o Comment internal headers used in sample code. (4eb281c)
+ o Be explicit about how long event loops run in event.h documentation (f95bafb)
+ o Add comment to configure.in to explain gc-sections test logic (c621359)
+ o Fix a couple of memory leaks in samples/http-server.c. Found by Dave Hart. (2e9f665)
+
+BUILD IMPROVEMENTS:
+ o Use the gcc -ffunction-segments feature to allow gc when linking with static libevent (0965c56 Dave Hart)
+ o Add configure options to disable installation, regression tests (49e9bb7 Dave Hart)
+
+
+
Changes in version 2.0.10-stable (16 Dec 2010)
[Autogenerated from the Git log, sorted and cleaned by hand.]
BUGFIXES
if BUILD_WIN32
-SYS_LIBS = -lws2_32
+SYS_LIBS = -lws2_32 -lshell32 -ladvapi32
SYS_SRC = win32select.c evthread_win32.c buffer_iocp.c event_iocp.c \
bufferevent_async.c
SYS_INCLUDES = -IWIN32-Code
if OPENSSL
libevent_openssl_la_SOURCES = bufferevent_openssl.c
-libevent_openssl_la_LIBADD = $(MAYBE_CORE) -lcrypto -lssl
+libevent_openssl_la_LIBADD = $(MAYBE_CORE) $(OPENSSL_LIBS)
libevent_openssl_la_LDFLAGS = $(GENERIC_LDFLAGS)
endif
# tons of important things. DO NOT RELY ON IT TO BUILD A GOOD LIBEVENT.
# Needed for correctness
-CFLAGS=/IWIN32-Code /Iinclude /Icompat /DWIN32 /DHAVE_CONFIG_H /I.
+CFLAGS=/IWIN32-Code /Iinclude /Icompat /DHAVE_CONFIG_H /I.
# For optimization and warnings
CFLAGS=$(CFLAGS) /Ox /W3 /wd4996 /nologo
Denis Bilenko
Julien Blache
Kevin Bowling
+ Tomash Brechko
Kelly Brock
Ralph Castain
Shuo Chen
Mihai Draghicioiu
Mark Ellzey
Shie Erlich
+ Christophe Fillot
Alexander von Gernler
Artur Grabowski
+ Dave Hart
Michael Herf
Sebastian Hahn
Aaron Hopkins
Tani Hosokawa
Claudio Jeker
Evan Jones
- Valery Kyholodov
+ Phua Keat
Marko Kreen
+ Valery Kyholodov
Scott Lamb
Christopher Layne
Adam Langley
- Christopher Layne
Philip Lewis
Zhou Li
David Libenzi
Ralf Schmitt
Mike Smellie
Kevin Springborn
+ Harlan Stenn
Ferenc Szalai
Dug Song
+ Dongsheng Song
Brodie Thiesfield
Jason Toffaletti
Bas Verhoeven
Constantine Verutin
Zack Weinberg
+ Jardel Weyrich
Taral
propanbutan
mmadia
/* Define to 1 if `sin_len' is member of `struct sockaddr_in'. */
/* #undef _EVENT_HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
+/* Define to 1 if the system has the type `struct sockaddr_storage'. */
+#define _EVENT_HAVE_STRUCT_SOCKADDR_STORAGE 1
+
/* Define to 1 if you have the <sys/devpoll.h> header file. */
/* #undef _EVENT_HAVE_SYS_DEVPOLL_H */
#ifndef ARC4RANDOM_NO_INCLUDES
#include "evconfig-private.h"
-#ifdef WIN32
+#ifdef _WIN32
#include <wincrypt.h>
#include <process.h>
#else
unsigned char s[256];
};
-#ifdef WIN32
+#ifdef _WIN32
#define getpid _getpid
#define pid_t int
#endif
rs.j = rs.i;
}
-#ifndef WIN32
+#ifndef _WIN32
static ssize_t
read_all(int fd, unsigned char *buf, size_t count)
{
}
#endif
-#ifdef WIN32
+#ifdef _WIN32
#define TRY_SEED_WIN32
static int
arc4_seed_win32(void)
}
#endif
-#ifndef WIN32
+#ifndef _WIN32
#define TRY_SEED_URANDOM
static int
arc4_seed_urandom(void)
#include "event2/event-config.h"
#include "evconfig-private.h"
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#include <windows.h>
#include <io.h>
struct evbuffer_chain_file_segment,
chain);
if (info->segment) {
-#ifdef WIN32
+#ifdef _WIN32
if (info->segment->type == EVBUF_FS_MMAP)
UnmapViewOfFile(chain->buffer);
#endif
* Reads data from a file descriptor into a buffer.
*/
-#if defined(_EVENT_HAVE_SYS_UIO_H) || defined(WIN32)
+#if defined(_EVENT_HAVE_SYS_UIO_H) || defined(_WIN32)
#define USE_IOVEC_IMPL
#endif
static int
get_n_bytes_readable_on_socket(evutil_socket_t fd)
{
-#if defined(FIONREAD) && defined(WIN32)
+#if defined(FIONREAD) && defined(_WIN32)
unsigned long lng = EVBUFFER_MAX_READ;
if (ioctlsocket(fd, FIONREAD, &lng) < 0)
return -1;
WSABUF_FROM_EVBUFFER_IOV(&vecs[i], &ev_vecs[i]);
#endif
-#ifdef WIN32
+#ifdef _WIN32
{
DWORD bytesRead;
DWORD flags=0;
/* We can append new data at this point */
p = chain->buffer + chain->misalign + chain->off;
-#ifndef WIN32
+#ifndef _WIN32
n = read(fd, p, howmuch);
#else
n = recv(fd, p, howmuch, 0);
}
chain = chain->next;
}
-#ifdef WIN32
+#ifdef _WIN32
{
DWORD bytesSent;
if (WSASend(fd, iov, i, &bytesSent, 0, NULL, NULL))
#endif
#ifdef USE_IOVEC_IMPL
n = evbuffer_write_iovec(buffer, fd, howmuch);
-#elif defined(WIN32)
+#elif defined(_WIN32)
/* XXX(nickm) Don't disable this code until we know if
* the WSARecv code above works. */
void *p = evbuffer_pullup(buffer, howmuch);
seg->fd = fd;
seg->flags = flags;
-#ifdef WIN32
+#ifdef _WIN32
#define lseek _lseeki64
#define fstat _fstat
#define stat _stat
}
}
#endif
-#ifdef WIN32
+#ifdef _WIN32
if (!(flags & EVBUF_FS_DISABLE_MMAP)) {
long h = (long)_get_osfhandle(fd);
HANDLE m;
if (seg->type == EVBUF_FS_SENDFILE) {
;
} else if (seg->type == EVBUF_FS_MMAP) {
-#ifdef WIN32
+#ifdef _WIN32
CloseHandle(seg->mapping_handle);
#elif defined (_EVENT_HAVE_MMAP)
if (munmap(seg->mapping, seg->length) == -1)
chain->off = length;
chain->buffer_len = chain->misalign + length;
} else if (seg->type == EVBUF_FS_MMAP) {
-#ifdef WIN32
+#ifdef _WIN32
ev_uint64_t total_offset = seg->offset+offset;
ev_uint64_t offset_rounded=0, offset_remaining=0;
LPVOID data;
#define BEV_IS_FILTER(bevp) ((bevp)->be_ops == &bufferevent_ops_filter)
#define BEV_IS_PAIR(bevp) ((bevp)->be_ops == &bufferevent_ops_pair)
-#ifdef WIN32
+#ifdef _WIN32
extern const struct bufferevent_ops bufferevent_ops_async;
#define BEV_IS_ASYNC(bevp) ((bevp)->be_ops == &bufferevent_ops_async)
#else
#include <stdarg.h>
#endif
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#endif
#include <errno.h>
#include <unistd.h>
#endif
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#endif
#include "util-internal.h"
#include "iocp-internal.h"
+#ifndef SO_UPDATE_CONNECT_CONTEXT
+/* Mingw is sometimes missing this */
+#define SO_UPDATE_CONNECT_CONTEXT 0x7010
+#endif
+
/* prototypes */
static int be_async_enable(struct bufferevent *, short);
static int be_async_disable(struct bufferevent *, short);
{
struct bufferevent_async *bev_a = upcast_connect(eo);
struct bufferevent *bev = &bev_a->bev.bev;
+ evutil_socket_t sock;
BEV_LOCK(bev);
EVUTIL_ASSERT(bev_a->bev.connecting);
bev_a->bev.connecting = 0;
+ sock = _evbuffer_overlapped_get_fd(bev_a->bev.bev.input);
+ /* XXXX Handle error? */
+ setsockopt(sock, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0);
if (ok)
bufferevent_async_set_connected(bev);
#include <stdarg.h>
#endif
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#endif
/* 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
#include <unistd.h>
#endif
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#endif
consider_writing(bev_ssl);
}
/* XXX Handle r < 0 */
+ (void)r;
}
#include <sys/types.h>
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#endif
#include <unistd.h>
#endif
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#endif
#include "mm-internal.h"
#include "bufferevent-internal.h"
#include "util-internal.h"
-#ifdef WIN32
+#ifdef _WIN32
#include "iocp-internal.h"
#endif
goto done;
} else {
connected = 1;
-#ifdef WIN32
+#ifdef _WIN32
if (BEV_IS_ASYNC(bufev)) {
event_del(&bufev->ev_write);
bufferevent_async_set_connected(bufev);
struct bufferevent_private *bufev_p;
struct bufferevent *bufev;
-#ifdef WIN32
+#ifdef _WIN32
if (base && event_base_get_iocp(base))
return bufferevent_async_new(base, fd, options);
#endif
ownfd = 1;
}
if (sa) {
-#ifdef WIN32
+#ifdef _WIN32
if (bufferevent_async_can_connect(bev)) {
bufferevent_setfd(bev, fd);
r = bufferevent_async_connect(bev, fd, sa, socklen);
if (r < 0)
goto freesock;
}
-#ifdef WIN32
+#ifdef _WIN32
/* ConnectEx() isn't always around, even when IOCP is enabled.
* Here, we borrow the socket object's write handler to fall back
* on a non-blocking connect() when ConnectEx() is unavailable. */
/* XXX use the other addrinfos? */
/* XXX use this return value */
r = bufferevent_socket_connect(bev, ai->ai_addr, (int)ai->ai_addrlen);
+ (void)r;
_bufferevent_decref_and_unlock(bev);
evutil_freeaddrinfo(ai);
}
#define SLIST_HEAD_INITIALIZER(head) \
{ NULL }
-#ifndef WIN32
+#ifndef _WIN32
#define SLIST_ENTRY(type) \
struct { \
struct type *sle_next; /* next element */ \
dnl Checks for programs.
AC_PROG_CC
+AM_PROG_CC_C_O
AC_PROG_INSTALL
AC_PROG_LN_S
# AC_PROG_MKDIR_P - $(MKDIR_P) should be defined by AM_INIT_AUTOMAKE
AC_SUBST(LIBTOOL_DEPS)
AM_CONDITIONAL([BUILD_REGRESS], [test "$enable_libevent_regress" = "yes"])
-if test "$enable_libevent_regress" = "yes" ; then
- CHECK_REGRESS=regress
-else
- CHECK_REGRESS=
-fi
-AC_SUBST([CHECK_REGRESS])
dnl Checks for libraries.
AC_SEARCH_LIBS([inet_ntoa], [nsl])
AC_SEARCH_LIBS([clock_gettime], [rt])
AC_SEARCH_LIBS([sendfile], [sendfile])
+dnl - check if the macro _WIN32 is defined on this compiler.
+dnl - (this is how we check for a windows compiler)
+AC_MSG_CHECKING(for WIN32)
+AC_TRY_COMPILE(,
+ [
+#ifndef _WIN32
+die horribly
+#endif
+ ],
+ bwin32=true; AC_MSG_RESULT(yes),
+ bwin32=false; AC_MSG_RESULT(no),
+)
+
AC_CHECK_HEADERS([zlib.h])
if test "x$ac_cv_header_zlib_h" = "xyes"; then
AM_CONDITIONAL(ZLIB_REGRESS, [test "$have_zlib" = "yes"])
dnl See if we have openssl. This doesn't go in LIBS either.
+if test "$bwin32" = true; then
+ EV_LIB_WS32=-lws2_32
+ EV_LIB_GDI=-lgdi32
+else
+ EV_LIB_WS32=
+ EV_LIB_GDI=
+fi
+AC_SUBST(EV_LIB_WS32)
+AC_SUBST(EV_LIB_GDI)
+
+AC_CHECK_HEADERS([openssl/bio.h])
+
if test "$enable_openssl" = "yes"; then
save_LIBS="$LIBS"
LIBS=""
OPENSSL_LIBS=""
have_openssl=no
AC_SEARCH_LIBS([SSL_new], [ssl],
- [have_openssl=yes
- OPENSSL_LIBS="$LIBS"
- AC_DEFINE(HAVE_OPENSSL, 1, [Define if the system has openssl])])
+ [have_openssl=yes
+ OPENSSL_LIBS="$LIBS -lcrypto $EV_LIB_GDI $EV_LIB_WS32"
+ AC_DEFINE(HAVE_OPENSSL, 1, [Define if the system has openssl])],
+ [have_openssl=no],
+ [-lcrypto $EV_LIB_GDI $EV_LIB_WS32])
LIBS="$save_LIBS"
AC_SUBST(OPENSSL_LIBS)
fi
)
fi
-dnl - check if the macro WIN32 is defined on this compiler.
-dnl - (this is how we check for a windows version of GCC)
-AC_MSG_CHECKING(for WIN32)
-AC_TRY_COMPILE(,
- [
-#ifndef WIN32
-die horribly
-#endif
- ],
- bwin32=true; AC_MSG_RESULT(yes),
- bwin32=false; AC_MSG_RESULT(no),
-)
-
AM_CONDITIONAL(BUILD_WIN32, test x$bwin32 = xtrue)
if test x$bwin32 = xtrue; then
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
-#ifdef WIN32
+#ifdef _WIN32
#define WIN32_WINNT 0x400
#define _WIN32_WINNT 0x400
#define WIN32_LEAN_AND_MEAN
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
-#ifdef WIN32
+#ifdef _WIN32
#define WIN32_WINNT 0x400
#define _WIN32_WINNT 0x400
#define WIN32_LEAN_AND_MEAN
#error
#endif])], have_gcc45=yes, have_gcc45=no)
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [
+#if !defined(__clang__)
+#error
+#endif])], have_clang=yes, have_clang=no)
+
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [
+#if !defined(__clang__) || (__clang_major__ > 2) || (__clang_major__ == 2 && __clang_minor__ > 9)
+#error
+#endif])], have_clang29orlower=yes, have_clang29orlower=no)
+
CFLAGS="$CFLAGS -W -Wfloat-equal -Wundef -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes -Wwrite-strings -Wredundant-decls -Wchar-subscripts -Wcomment -Wformat -Wwrite-strings -Wmissing-declarations -Wredundant-decls -Wnested-externs -Wbad-function-cast -Wswitch-enum -Werror"
CFLAGS="$CFLAGS -Wno-unused-parameter -Wstrict-aliasing"
if test x$have_gcc42 = xyes ; then
# These warnings break gcc 4.0.2 and work on gcc 4.2
- CFLAGS="$CFLAGS -Waddress -Wnormalized=id -Woverride-init"
+ CFLAGS="$CFLAGS -Waddress"
+ fi
+
+ if test x$have_gcc42 = xyes && test x$have_clang29orlower = xno; then
+ # These warnings break gcc 4.0.2 and clang, but work on gcc 4.2
+ # We only disable these for clang 2.9 and lower, in case they are
+ # supported in later versions.
+ CFLAGS="$CFLAGS -Wnormalized=id -Woverride-init"
fi
if test x$have_gcc45 = xyes ; then
# These warnings work on gcc 4.5
CFLAGS="$CFLAGS -Wlogical-op"
fi
+
+ if test x$have_clang = xyes; then
+ # Disable the unused-function warnings, because these trigger
+ # for minheap-internal.h related code.
+ CFLAGS="$CFLAGS -Wno-unused-function"
+ fi
+
##This will break the world on some 64-bit architectures
# CFLAGS="$CFLAGS -Winline"
* arguments. */
#define EVBUFFER_CB_NODEFER 2
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#endif
#include <sys/queue.h>
* overflows when we have mutually recursive callbacks, and for
* serializing callbacks in a single thread. */
unsigned deferred_cbs : 1;
-#ifdef WIN32
+#ifdef _WIN32
/** True iff this buffer is set up for overlapped IO. */
unsigned is_overlapped : 1;
#endif
* evbuffer_chain with the EVBUFFER_FILESEGMENT flag set. */
struct evbuffer_chain_file_segment {
struct evbuffer_file_segment *segment;
-#ifdef WIN32
+#ifdef _WIN32
/** If we're using CreateFileMapping, this is the handle to the view. */
HANDLE view_handle;
#endif
int fd;
/** If we're using mmap, this is the raw mapped memory. */
void *mapping;
-#ifdef WIN32
+#ifdef _WIN32
/** If we're using CreateFileMapping, this is the mapping */
HANDLE mapping_handle;
#endif
--- /dev/null
+.\"
+.\" Copyright (c) 2006 Niels Provos <provos@citi.umich.edu>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\"
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 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 ``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.
+.\"
+.Dd October 7, 2006
+.Dt EVDNS 3
+.Os
+.Sh NAME
+.Nm evdns_init
+.Nm evdns_shutdown
+.Nm evdns_err_to_string
+.Nm evdns_nameserver_add
+.Nm evdns_count_nameservers
+.Nm evdns_clear_nameservers_and_suspend
+.Nm evdns_resume
+.Nm evdns_nameserver_ip_add
+.Nm evdns_resolve_ipv4
+.Nm evdns_resolve_reverse
+.Nm evdns_resolv_conf_parse
+.Nm evdns_config_windows_nameservers
+.Nm evdns_search_clear
+.Nm evdns_search_add
+.Nm evdns_search_ndots_set
+.Nm evdns_set_log_fn
+.Nd asynchronous functions for DNS resolution.
+.Sh SYNOPSIS
+.Fd #include <sys/time.h>
+.Fd #include <event.h>
+.Fd #include <evdns.h>
+.Ft int
+.Fn evdns_init
+.Ft void
+.Fn evdns_shutdown "int fail_requests"
+.Ft "const char *"
+.Fn evdns_err_to_string "int err"
+.Ft int
+.Fn evdns_nameserver_add "unsigned long int address"
+.Ft int
+.Fn evdns_count_nameservers
+.Ft int
+.Fn evdns_clear_nameservers_and_suspend
+.Ft int
+.Fn evdns_resume
+.Ft int
+.Fn evdns_nameserver_ip_add(const char *ip_as_string);
+.Ft int
+.Fn evdns_resolve_ipv4 "const char *name" "int flags" "evdns_callback_type callback" "void *ptr"
+.Ft int
+.Fn evdns_resolve_reverse "struct in_addr *in" "int flags" "evdns_callback_type callback" "void *ptr"
+.Ft int
+.Fn evdns_resolv_conf_parse "int flags" "const char *"
+.Ft void
+.Fn evdns_search_clear
+.Ft void
+.Fn evdns_search_add "const char *domain"
+.Ft void
+.Fn evdns_search_ndots_set "const int ndots"
+.Ft void
+.Fn evdns_set_log_fn "evdns_debug_log_fn_type fn"
+.Ft int
+.Fn evdns_config_windows_nameservers
+.Sh DESCRIPTION
+Welcome, gentle reader
+.Pp
+Async DNS lookups are really a whole lot harder than they should be,
+mostly stemming from the fact that the libc resolver has never been
+very good at them. Before you use this library you should see if libc
+can do the job for you with the modern async call getaddrinfo_a
+(see http://www.imperialviolet.org/page25.html#e498). Otherwise,
+please continue.
+.Pp
+This code is based on libevent and you must call event_init before
+any of the APIs in this file. You must also seed the OpenSSL random
+source if you are using OpenSSL for ids (see below).
+.Pp
+This library is designed to be included and shipped with your source
+code. You statically link with it. You should also test for the
+existence of strtok_r and define HAVE_STRTOK_R if you have it.
+.Pp
+The DNS protocol requires a good source of id numbers and these
+numbers should be unpredictable for spoofing reasons. There are
+three methods for generating them here and you must define exactly
+one of them. In increasing order of preference:
+.Pp
+.Bl -tag -width "DNS_USE_GETTIMEOFDAY_FOR_ID" -compact -offset indent
+.It DNS_USE_GETTIMEOFDAY_FOR_ID
+Using the bottom 16 bits of the usec result from gettimeofday. This
+is a pretty poor solution but should work anywhere.
+.It DNS_USE_CPU_CLOCK_FOR_ID
+Using the bottom 16 bits of the nsec result from the CPU's time
+counter. This is better, but may not work everywhere. Requires
+POSIX realtime support and you'll need to link against -lrt on
+glibc systems at least.
+.It DNS_USE_OPENSSL_FOR_ID
+Uses the OpenSSL RAND_bytes call to generate the data. You must
+have seeded the pool before making any calls to this library.
+.El
+.Pp
+The library keeps track of the state of nameservers and will avoid
+them when they go down. Otherwise it will round robin between them.
+.Pp
+Quick start guide:
+ #include "evdns.h"
+ void callback(int result, char type, int count, int ttl,
+ void *addresses, void *arg);
+ evdns_resolv_conf_parse(DNS_OPTIONS_ALL, "/etc/resolv.conf");
+ evdns_resolve("www.hostname.com", 0, callback, NULL);
+.Pp
+When the lookup is complete the callback function is called. The
+first argument will be one of the DNS_ERR_* defines in evdns.h.
+Hopefully it will be DNS_ERR_NONE, in which case type will be
+DNS_IPv4_A, count will be the number of IP addresses, ttl is the time
+which the data can be cached for (in seconds), addresses will point
+to an array of uint32_t's and arg will be whatever you passed to
+evdns_resolve.
+.Pp
+Searching:
+.Pp
+In order for this library to be a good replacement for glibc's resolver it
+supports searching. This involves setting a list of default domains, in
+which names will be queried for. The number of dots in the query name
+determines the order in which this list is used.
+.Pp
+Searching appears to be a single lookup from the point of view of the API,
+although many DNS queries may be generated from a single call to
+evdns_resolve. Searching can also drastically slow down the resolution
+of names.
+.Pp
+To disable searching:
+.Bl -enum -compact -offset indent
+.It
+Never set it up. If you never call
+.Fn evdns_resolv_conf_parse,
+.Fn evdns_init,
+or
+.Fn evdns_search_add
+then no searching will occur.
+.It
+If you do call
+.Fn evdns_resolv_conf_parse
+then don't pass
+.Va DNS_OPTION_SEARCH
+(or
+.Va DNS_OPTIONS_ALL,
+which implies it).
+.It
+When calling
+.Fn evdns_resolve,
+pass the
+.Va DNS_QUERY_NO_SEARCH
+flag.
+.El
+.Pp
+The order of searches depends on the number of dots in the name. If the
+number is greater than the ndots setting then the names is first tried
+globally. Otherwise each search domain is appended in turn.
+.Pp
+The ndots setting can either be set from a resolv.conf, or by calling
+evdns_search_ndots_set.
+.Pp
+For example, with ndots set to 1 (the default) and a search domain list of
+["myhome.net"]:
+ Query: www
+ Order: www.myhome.net, www.
+.Pp
+ Query: www.abc
+ Order: www.abc., www.abc.myhome.net
+.Pp
+.Sh API reference
+.Pp
+.Bl -tag -width 0123456
+.It Ft int Fn evdns_init
+Initializes support for non-blocking name resolution by calling
+.Fn evdns_resolv_conf_parse
+on UNIX and
+.Fn evdns_config_windows_nameservers
+on Windows.
+.It Ft int Fn evdns_nameserver_add "unsigned long int address"
+Add a nameserver. The address should be an IP address in
+network byte order. The type of address is chosen so that
+it matches in_addr.s_addr.
+Returns non-zero on error.
+.It Ft int Fn evdns_nameserver_ip_add "const char *ip_as_string"
+This wraps the above function by parsing a string as an IP
+address and adds it as a nameserver.
+Returns non-zero on error
+.It Ft int Fn evdns_resolve "const char *name" "int flags" "evdns_callback_type callback" "void *ptr"
+Resolve a name. The name parameter should be a DNS name.
+The flags parameter should be 0, or DNS_QUERY_NO_SEARCH
+which disables searching for this query. (see defn of
+searching above).
+.Pp
+The callback argument is a function which is called when
+this query completes and ptr is an argument which is passed
+to that callback function.
+.Pp
+Returns non-zero on error
+.It Ft void Fn evdns_search_clear
+Clears the list of search domains
+.It Ft void Fn evdns_search_add "const char *domain"
+Add a domain to the list of search domains
+.It Ft void Fn evdns_search_ndots_set "int ndots"
+Set the number of dots which, when found in a name, causes
+the first query to be without any search domain.
+.It Ft int Fn evdns_count_nameservers "void"
+Return the number of configured nameservers (not necessarily the
+number of running nameservers). This is useful for double-checking
+whether our calls to the various nameserver configuration functions
+have been successful.
+.It Ft int Fn evdns_clear_nameservers_and_suspend "void"
+Remove all currently configured nameservers, and suspend all pending
+resolves. Resolves will not necessarily be re-attempted until
+evdns_resume() is called.
+.It Ft int Fn evdns_resume "void"
+Re-attempt resolves left in limbo after an earlier call to
+evdns_clear_nameservers_and_suspend().
+.It Ft int Fn evdns_config_windows_nameservers "void"
+Attempt to configure a set of nameservers based on platform settings on
+a win32 host. Preferentially tries to use GetNetworkParams; if that fails,
+looks in the registry. Returns 0 on success, nonzero on failure.
+.It Ft int Fn evdns_resolv_conf_parse "int flags" "const char *filename"
+Parse a resolv.conf like file from the given filename.
+.Pp
+See the man page for resolv.conf for the format of this file.
+The flags argument determines what information is parsed from
+this file:
+.Bl -tag -width "DNS_OPTION_NAMESERVERS" -offset indent -compact -nested
+.It DNS_OPTION_SEARCH
+domain, search and ndots options
+.It DNS_OPTION_NAMESERVERS
+nameserver lines
+.It DNS_OPTION_MISC
+timeout and attempts options
+.It DNS_OPTIONS_ALL
+all of the above
+.El
+.Pp
+The following directives are not parsed from the file:
+ sortlist, rotate, no-check-names, inet6, debug
+.Pp
+Returns non-zero on error:
+.Bl -tag -width "0" -offset indent -compact -nested
+.It 0
+no errors
+.It 1
+failed to open file
+.It 2
+failed to stat file
+.It 3
+file too large
+.It 4
+out of memory
+.It 5
+short read from file
+.El
+.El
+.Sh Internals:
+Requests are kept in two queues. The first is the inflight queue. In
+this queue requests have an allocated transaction id and nameserver.
+They will soon be transmitted if they haven't already been.
+.Pp
+The second is the waiting queue. The size of the inflight ring is
+limited and all other requests wait in waiting queue for space. This
+bounds the number of concurrent requests so that we don't flood the
+nameserver. Several algorithms require a full walk of the inflight
+queue and so bounding its size keeps thing going nicely under huge
+(many thousands of requests) loads.
+.Pp
+If a nameserver loses too many requests it is considered down and we
+try not to use it. After a while we send a probe to that nameserver
+(a lookup for google.com) and, if it replies, we consider it working
+again. If the nameserver fails a probe we wait longer to try again
+with the next probe.
+.Sh SEE ALSO
+.Xr event 3 ,
+.Xr gethostbyname 3 ,
+.Xr resolv.conf 5
+.Sh HISTORY
+The
+.Nm evdns
+API was developed by Adam Langley on top of the
+.Nm libevent
+API.
+The code was integrate into
+.Nm Tor
+by Nick Mathewson and finally put into
+.Nm libevent
+itself by Niels Provos.
+.Sh AUTHORS
+The
+.Nm evdns
+API and code was written by Adam Langley with significant
+contributions by Nick Mathewson.
+.Sh BUGS
+This documentation is neither complete nor authoritative.
+If you are in doubt about the usage of this API then
+check the source code to find out how it works, write
+up the missing piece of documentation and send it to
+me for inclusion in this man page.
#include <sys/stat.h>
#include <stdio.h>
#include <stdarg.h>
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#ifndef _WIN32_IE
#include "ipv6-internal.h"
#include "util-internal.h"
#include "evthread-internal.h"
-#ifdef WIN32
+#ifdef _WIN32
#include <ctype.h>
#include <winsock2.h>
#include <windows.h>
{
struct deferred_reply_callback *d = mm_calloc(1, sizeof(*d));
+ if (!d) {
+ event_warn("%s: Couldn't allocate space for deferred callback.",
+ __func__);
+ return;
+ }
+
ASSERT_LOCKED(req->base);
d->request_type = req->request_type;
GET16(answers);
GET16(authority);
GET16(additional);
+ (void)answers;
+ (void)additional;
+ (void)authority;
if (flags & 0x8000) return -1; /* Must not be an answer. */
flags &= 0x0110; /* Only RD and CD get preserved. */
EVDNS_LOCK(req->port);
lock=1;
if (req->port->pending_replies == req) {
- if (req->next_pending)
+ if (req->next_pending && req->next_pending != req)
req->port->pending_replies = req->next_pending;
else
req->port->pending_replies = NULL;
evtimer_assign(&ns->timeout_event, ns->base->event_base, nameserver_prod_callback, ns);
- ns->socket = socket(PF_INET, SOCK_DGRAM, 0);
+ ns->socket = socket(address->sa_family, SOCK_DGRAM, 0);
if (ns->socket < 0) { err = 1; goto out1; }
evutil_make_socket_closeonexec(ns->socket);
evutil_make_socket_nonblocking(ns->socket);
{
struct request *req;
+ if (!handle->current_req)
+ return;
+
if (!base) {
/* This redundancy is silly; can we fix it? (Not for 2.0) XXXX */
base = handle->base;
- if (!base && handle->current_req)
+ if (!base)
base = handle->current_req->base;
}
static char *
evdns_get_default_hosts_filename(void)
{
-#ifdef WIN32
+#ifdef _WIN32
/* Windows is a little coy about where it puts its configuration
* files. Sure, they're _usually_ in C:\windows\system32, but
* there's no reason in principle they couldn't be in
}
-#ifdef WIN32
+#ifdef _WIN32
/* Add multiple nameservers from a space-or-comma-separated list. */
static int
evdns_nameserver_ip_add_line(struct evdns_base *base, const char *ips) {
if (initialize_nameservers) {
int r;
-#ifdef WIN32
+#ifdef _WIN32
r = evdns_base_config_windows_nameservers(base);
#else
r = evdns_base_resolv_conf_parse(base, DNS_OPTIONS_ALL, "/etc/resolv.conf");
size_t fdinfo_len;
};
-#ifdef WIN32
+#ifdef _WIN32
/* If we're on win32, then file descriptors are not nice low densely packed
integers. Instead, they are pointer-like windows handles, and we want to
use a hashtable instead of an array to map fds to events.
int current_event_waiters;
#endif
-#ifdef WIN32
+#ifdef _WIN32
/** IOCP support structure, if IOCP is enabled. */
struct event_iocp_port *iocp;
#endif
--- /dev/null
+.\" $OpenBSD: event.3,v 1.4 2002/07/12 18:50:48 provos Exp $
+.\"
+.\" Copyright (c) 2000 Artur Grabowski <art@openbsd.org>
+.\" 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. 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 ``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.
+.\"
+.Dd August 8, 2000
+.Dt EVENT 3
+.Os
+.Sh NAME
+.Nm event_init ,
+.Nm event_dispatch ,
+.Nm event_loop ,
+.Nm event_loopexit ,
+.Nm event_loopbreak ,
+.Nm event_set ,
+.Nm event_base_dispatch ,
+.Nm event_base_loop ,
+.Nm event_base_loopexit ,
+.Nm event_base_loopbreak ,
+.Nm event_base_set ,
+.Nm event_base_free ,
+.Nm event_add ,
+.Nm event_del ,
+.Nm event_once ,
+.Nm event_base_once ,
+.Nm event_pending ,
+.Nm event_initialized ,
+.Nm event_priority_init ,
+.Nm event_priority_set ,
+.Nm evtimer_set ,
+.Nm evtimer_add ,
+.Nm evtimer_del ,
+.Nm evtimer_pending ,
+.Nm evtimer_initialized ,
+.Nm signal_set ,
+.Nm signal_add ,
+.Nm signal_del ,
+.Nm signal_pending ,
+.Nm signal_initialized ,
+.Nm bufferevent_new ,
+.Nm bufferevent_free ,
+.Nm bufferevent_write ,
+.Nm bufferevent_write_buffer ,
+.Nm bufferevent_read ,
+.Nm bufferevent_enable ,
+.Nm bufferevent_disable ,
+.Nm bufferevent_settimeout ,
+.Nm bufferevent_base_set ,
+.Nm evbuffer_new ,
+.Nm evbuffer_free ,
+.Nm evbuffer_add ,
+.Nm evbuffer_add_buffer ,
+.Nm evbuffer_add_printf ,
+.Nm evbuffer_add_vprintf ,
+.Nm evbuffer_drain ,
+.Nm evbuffer_write ,
+.Nm evbuffer_read ,
+.Nm evbuffer_find ,
+.Nm evbuffer_readline ,
+.Nm evhttp_new ,
+.Nm evhttp_bind_socket ,
+.Nm evhttp_free
+.Nd execute a function when a specific event occurs
+.Sh SYNOPSIS
+.Fd #include <sys/time.h>
+.Fd #include <event.h>
+.Ft "struct event_base *"
+.Fn "event_init" "void"
+.Ft int
+.Fn "event_dispatch" "void"
+.Ft int
+.Fn "event_loop" "int flags"
+.Ft int
+.Fn "event_loopexit" "struct timeval *tv"
+.Ft int
+.Fn "event_loopbreak" "void"
+.Ft void
+.Fn "event_set" "struct event *ev" "int fd" "short event" "void (*fn)(int, short, void *)" "void *arg"
+.Ft int
+.Fn "event_base_dispatch" "struct event_base *base"
+.Ft int
+.Fn "event_base_loop" "struct event_base *base" "int flags"
+.Ft int
+.Fn "event_base_loopexit" "struct event_base *base" "struct timeval *tv"
+.Ft int
+.Fn "event_base_loopbreak" "struct event_base *base"
+.Ft int
+.Fn "event_base_set" "struct event_base *base" "struct event *"
+.Ft void
+.Fn "event_base_free" "struct event_base *base"
+.Ft int
+.Fn "event_add" "struct event *ev" "struct timeval *tv"
+.Ft int
+.Fn "event_del" "struct event *ev"
+.Ft int
+.Fn "event_once" "int fd" "short event" "void (*fn)(int, short, void *)" "void *arg" "struct timeval *tv"
+.Ft int
+.Fn "event_base_once" "struct event_base *base" "int fd" "short event" "void (*fn)(int, short, void *)" "void *arg" "struct timeval *tv"
+.Ft int
+.Fn "event_pending" "struct event *ev" "short event" "struct timeval *tv"
+.Ft int
+.Fn "event_initialized" "struct event *ev"
+.Ft int
+.Fn "event_priority_init" "int npriorities"
+.Ft int
+.Fn "event_priority_set" "struct event *ev" "int priority"
+.Ft void
+.Fn "evtimer_set" "struct event *ev" "void (*fn)(int, short, void *)" "void *arg"
+.Ft void
+.Fn "evtimer_add" "struct event *ev" "struct timeval *"
+.Ft void
+.Fn "evtimer_del" "struct event *ev"
+.Ft int
+.Fn "evtimer_pending" "struct event *ev" "struct timeval *tv"
+.Ft int
+.Fn "evtimer_initialized" "struct event *ev"
+.Ft void
+.Fn "signal_set" "struct event *ev" "int signal" "void (*fn)(int, short, void *)" "void *arg"
+.Ft void
+.Fn "signal_add" "struct event *ev" "struct timeval *"
+.Ft void
+.Fn "signal_del" "struct event *ev"
+.Ft int
+.Fn "signal_pending" "struct event *ev" "struct timeval *tv"
+.Ft int
+.Fn "signal_initialized" "struct event *ev"
+.Ft "struct bufferevent *"
+.Fn "bufferevent_new" "int fd" "evbuffercb readcb" "evbuffercb writecb" "everrorcb" "void *cbarg"
+.Ft void
+.Fn "bufferevent_free" "struct bufferevent *bufev"
+.Ft int
+.Fn "bufferevent_write" "struct bufferevent *bufev" "void *data" "size_t size"
+.Ft int
+.Fn "bufferevent_write_buffer" "struct bufferevent *bufev" "struct evbuffer *buf"
+.Ft size_t
+.Fn "bufferevent_read" "struct bufferevent *bufev" "void *data" "size_t size"
+.Ft int
+.Fn "bufferevent_enable" "struct bufferevent *bufev" "short event"
+.Ft int
+.Fn "bufferevent_disable" "struct bufferevent *bufev" "short event"
+.Ft void
+.Fn "bufferevent_settimeout" "struct bufferevent *bufev" "int timeout_read" "int timeout_write"
+.Ft int
+.Fn "bufferevent_base_set" "struct event_base *base" "struct bufferevent *bufev"
+.Ft "struct evbuffer *"
+.Fn "evbuffer_new" "void"
+.Ft void
+.Fn "evbuffer_free" "struct evbuffer *buf"
+.Ft int
+.Fn "evbuffer_add" "struct evbuffer *buf" "const void *data" "size_t size"
+.Ft int
+.Fn "evbuffer_add_buffer" "struct evbuffer *dst" "struct evbuffer *src"
+.Ft int
+.Fn "evbuffer_add_printf" "struct evbuffer *buf" "const char *fmt" "..."
+.Ft int
+.Fn "evbuffer_add_vprintf" "struct evbuffer *buf" "const char *fmt" "va_list ap"
+.Ft void
+.Fn "evbuffer_drain" "struct evbuffer *buf" "size_t size"
+.Ft int
+.Fn "evbuffer_write" "struct evbuffer *buf" "int fd"
+.Ft int
+.Fn "evbuffer_read" "struct evbuffer *buf" "int fd" "int size"
+.Ft "u_char *"
+.Fn "evbuffer_find" "struct evbuffer *buf" "const u_char *data" "size_t size"
+.Ft "char *"
+.Fn "evbuffer_readline" "struct evbuffer *buf"
+.Ft "struct evhttp *"
+.Fn "evhttp_new" "struct event_base *base"
+.Ft int
+.Fn "evhttp_bind_socket" "struct evhttp *http" "const char *address" "u_short port"
+.Ft "void"
+.Fn "evhttp_free" "struct evhttp *http"
+.Ft int
+.Fa (*event_sigcb)(void) ;
+.Ft volatile sig_atomic_t
+.Fa event_gotsig ;
+.Sh DESCRIPTION
+The
+.Nm event
+API provides a mechanism to execute a function when a specific event
+on a file descriptor occurs or after a given time has passed.
+.Pp
+The
+.Nm event
+API needs to be initialized with
+.Fn event_init
+before it can be used.
+.Pp
+In order to process events, an application needs to call
+.Fn event_dispatch .
+This function only returns on error, and should replace the event core
+of the application program.
+.Pp
+The function
+.Fn event_set
+prepares the event structure
+.Fa ev
+to be used in future calls to
+.Fn event_add
+and
+.Fn event_del .
+The event will be prepared to call the function specified by the
+.Fa fn
+argument with an
+.Fa int
+argument indicating the file descriptor, a
+.Fa short
+argument indicating the type of event, and a
+.Fa void *
+argument given in the
+.Fa arg
+argument.
+The
+.Fa fd
+indicates the file descriptor that should be monitored for events.
+The events can be either
+.Va EV_READ ,
+.Va EV_WRITE ,
+or both,
+indicating that an application can read or write from the file descriptor
+respectively without blocking.
+.Pp
+The function
+.Fa fn
+will be called with the file descriptor that triggered the event and
+the type of event which will be either
+.Va EV_TIMEOUT ,
+.Va EV_SIGNAL ,
+.Va EV_READ ,
+or
+.Va EV_WRITE .
+Additionally, an event which has registered interest in more than one of the
+preceeding events, via bitwise-OR to
+.Fn event_set ,
+can provide its callback function with a bitwise-OR of more than one triggered
+event.
+The additional flag
+.Va EV_PERSIST
+makes an
+.Fn event_add
+persistent until
+.Fn event_del
+has been called.
+.Pp
+Once initialized, the
+.Fa ev
+structure can be used repeatedly with
+.Fn event_add
+and
+.Fn event_del
+and does not need to be reinitialized unless the function called and/or
+the argument to it are to be changed.
+However, when an
+.Fa ev
+structure has been added to libevent using
+.Fn event_add
+the structure must persist until the event occurs (assuming
+.Fa EV_PERSIST
+is not set) or is removed
+using
+.Fn event_del .
+You may not reuse the same
+.Fa ev
+structure for multiple monitored descriptors; each descriptor
+needs its own
+.Fa ev .
+.Pp
+The function
+.Fn event_add
+schedules the execution of the
+.Fa ev
+event when the event specified in
+.Fn event_set
+occurs or in at least the time specified in the
+.Fa tv .
+If
+.Fa tv
+is
+.Dv NULL ,
+no timeout occurs and the function will only be called
+if a matching event occurs on the file descriptor.
+The event in the
+.Fa ev
+argument must be already initialized by
+.Fn event_set
+and may not be used in calls to
+.Fn event_set
+until it has timed out or been removed with
+.Fn event_del .
+If the event in the
+.Fa ev
+argument already has a scheduled timeout, the old timeout will be
+replaced by the new one.
+.Pp
+The function
+.Fn event_del
+will cancel the event in the argument
+.Fa ev .
+If the event has already executed or has never been added
+the call will have no effect.
+.Pp
+The functions
+.Fn evtimer_set ,
+.Fn evtimer_add ,
+.Fn evtimer_del ,
+.Fn evtimer_initialized ,
+and
+.Fn evtimer_pending
+are abbreviations for common situations where only a timeout is required.
+The file descriptor passed will be \-1, and the event type will be
+.Va EV_TIMEOUT .
+.Pp
+The functions
+.Fn signal_set ,
+.Fn signal_add ,
+.Fn signal_del ,
+.Fn signal_initialized ,
+and
+.Fn signal_pending
+are abbreviations.
+The event type will be a persistent
+.Va EV_SIGNAL .
+That means
+.Fn signal_set
+adds
+.Va EV_PERSIST .
+.Pp
+In order to avoid races in signal handlers, the
+.Nm event
+API provides two variables:
+.Va event_sigcb
+and
+.Va event_gotsig .
+A signal handler
+sets
+.Va event_gotsig
+to indicate that a signal has been received.
+The application sets
+.Va event_sigcb
+to a callback function.
+After the signal handler sets
+.Va event_gotsig ,
+.Nm event_dispatch
+will execute the callback function to process received signals.
+The callback returns 1 when no events are registered any more.
+It can return \-1 to indicate an error to the
+.Nm event
+library, causing
+.Fn event_dispatch
+to terminate with
+.Va errno
+set to
+.Er EINTR .
+.Pp
+The function
+.Fn event_once
+is similar to
+.Fn event_set .
+However, it schedules a callback to be called exactly once and does not
+require the caller to prepare an
+.Fa event
+structure.
+This function supports
+.Fa EV_TIMEOUT ,
+.Fa EV_READ ,
+and
+.Fa EV_WRITE .
+.Pp
+The
+.Fn event_pending
+function can be used to check if the event specified by
+.Fa event
+is pending to run.
+If
+.Va EV_TIMEOUT
+was specified and
+.Fa tv
+is not
+.Dv NULL ,
+the expiration time of the event will be returned in
+.Fa tv .
+.Pp
+The
+.Fn event_initialized
+macro can be used to check if an event has been initialized.
+.Pp
+The
+.Nm event_loop
+function provides an interface for single pass execution of pending
+events.
+The flags
+.Va EVLOOP_ONCE
+and
+.Va EVLOOP_NONBLOCK
+are recognized.
+The
+.Nm event_loopexit
+function exits from the event loop. The next
+.Fn event_loop
+iteration after the
+given timer expires will complete normally (handling all queued events) then
+exit without blocking for events again. Subsequent invocations of
+.Fn event_loop
+will proceed normally.
+The
+.Nm event_loopbreak
+function exits from the event loop immediately.
+.Fn event_loop
+will abort after the next event is completed;
+.Fn event_loopbreak
+is typically invoked from this event's callback. This behavior is analogous
+to the "break;" statement. Subsequent invocations of
+.Fn event_loop
+will proceed normally.
+.Pp
+It is the responsibility of the caller to provide these functions with
+pre-allocated event structures.
+.Pp
+.Sh EVENT PRIORITIES
+By default
+.Nm libevent
+schedules all active events with the same priority.
+However, sometimes it is desirable to process some events with a higher
+priority than others.
+For that reason,
+.Nm libevent
+supports strict priority queues.
+Active events with a lower priority are always processed before events
+with a higher priority.
+.Pp
+The number of different priorities can be set initially with the
+.Fn event_priority_init
+function.
+This function should be called before the first call to
+.Fn event_dispatch .
+The
+.Fn event_priority_set
+function can be used to assign a priority to an event.
+By default,
+.Nm libevent
+assigns the middle priority to all events unless their priority
+is explicitly set.
+.Sh THREAD SAFE EVENTS
+.Nm Libevent
+has experimental support for thread-safe events.
+When initializing the library via
+.Fn event_init ,
+an event base is returned.
+This event base can be used in conjunction with calls to
+.Fn event_base_set ,
+.Fn event_base_dispatch ,
+.Fn event_base_loop ,
+.Fn event_base_loopexit ,
+.Fn bufferevent_base_set
+and
+.Fn event_base_free .
+.Fn event_base_set
+should be called after preparing an event with
+.Fn event_set ,
+as
+.Fn event_set
+assigns the provided event to the most recently created event base.
+.Fn bufferevent_base_set
+should be called after preparing a bufferevent with
+.Fn bufferevent_new .
+.Fn event_base_free
+should be used to free memory associated with the event base
+when it is no longer needed.
+.Sh BUFFERED EVENTS
+.Nm libevent
+provides an abstraction on top of the regular event callbacks.
+This abstraction is called a
+.Va "buffered event" .
+A buffered event provides input and output buffers that get filled
+and drained automatically.
+The user of a buffered event no longer deals directly with the IO,
+but instead is reading from input and writing to output buffers.
+.Pp
+A new bufferevent is created by
+.Fn bufferevent_new .
+The parameter
+.Fa fd
+specifies the file descriptor from which data is read and written to.
+This file descriptor is not allowed to be a
+.Xr pipe 2 .
+The next three parameters are callbacks.
+The read and write callback have the following form:
+.Ft void
+.Fn "(*cb)" "struct bufferevent *bufev" "void *arg" .
+The error callback has the following form:
+.Ft void
+.Fn "(*cb)" "struct bufferevent *bufev" "short what" "void *arg" .
+The argument is specified by the fourth parameter
+.Fa "cbarg" .
+A
+.Fa bufferevent struct
+pointer is returned on success, NULL on error.
+Both the read and the write callback may be NULL.
+The error callback has to be always provided.
+.Pp
+Once initialized, the bufferevent structure can be used repeatedly with
+bufferevent_enable() and bufferevent_disable().
+The flags parameter can be a combination of
+.Va EV_READ
+and
+.Va EV_WRITE .
+When read enabled the bufferevent will try to read from the file
+descriptor and call the read callback.
+The write callback is executed
+whenever the output buffer is drained below the write low watermark,
+which is
+.Va 0
+by default.
+.Pp
+The
+.Fn bufferevent_write
+function can be used to write data to the file descriptor.
+The data is appended to the output buffer and written to the descriptor
+automatically as it becomes available for writing.
+.Fn bufferevent_write
+returns 0 on success or \-1 on failure.
+The
+.Fn bufferevent_read
+function is used to read data from the input buffer,
+returning the amount of data read.
+.Pp
+If multiple bases are in use, bufferevent_base_set() must be called before
+enabling the bufferevent for the first time.
+.Sh NON-BLOCKING HTTP SUPPORT
+.Nm libevent
+provides a very thin HTTP layer that can be used both to host an HTTP
+server and also to make HTTP requests.
+An HTTP server can be created by calling
+.Fn evhttp_new .
+It can be bound to any port and address with the
+.Fn evhttp_bind_socket
+function.
+When the HTTP server is no longer used, it can be freed via
+.Fn evhttp_free .
+.Pp
+To be notified of HTTP requests, a user needs to register callbacks with the
+HTTP server.
+This can be done by calling
+.Fn evhttp_set_cb .
+The second argument is the URI for which a callback is being registered.
+The corresponding callback will receive an
+.Va struct evhttp_request
+object that contains all information about the request.
+.Pp
+This section does not document all the possible function calls; please
+check
+.Va event.h
+for the public interfaces.
+.Sh ADDITIONAL NOTES
+It is possible to disable support for
+.Va epoll , kqueue , devpoll , poll
+or
+.Va select
+by setting the environment variable
+.Va EVENT_NOEPOLL , EVENT_NOKQUEUE , EVENT_NODEVPOLL , EVENT_NOPOLL
+or
+.Va EVENT_NOSELECT ,
+respectively.
+By setting the environment variable
+.Va EVENT_SHOW_METHOD ,
+.Nm libevent
+displays the kernel notification method that it uses.
+.Sh RETURN VALUES
+Upon successful completion
+.Fn event_add
+and
+.Fn event_del
+return 0.
+Otherwise, \-1 is returned and the global variable errno is
+set to indicate the error.
+.Sh SEE ALSO
+.Xr kqueue 2 ,
+.Xr poll 2 ,
+.Xr select 2 ,
+.Xr evdns 3 ,
+.Xr timeout 9
+.Sh HISTORY
+The
+.Nm event
+API manpage is based on the
+.Xr timeout 9
+manpage by Artur Grabowski.
+The port of
+.Nm libevent
+to Windows is due to Michael A. Davis.
+Support for real-time signals is due to Taral.
+.Sh AUTHORS
+The
+.Nm event
+library was written by Niels Provos.
+.Sh BUGS
+This documentation is neither complete nor authoritative.
+If you are in doubt about the usage of this API then
+check the source code to find out how it works, write
+up the missing piece of documentation and send it to
+me for inclusion in this man page.
#include "event2/event-config.h"
#include "evconfig-private.h"
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
#endif
#include <sys/types.h>
-#if !defined(WIN32) && defined(_EVENT_HAVE_SYS_TIME_H)
+#if !defined(_WIN32) && defined(_EVENT_HAVE_SYS_TIME_H)
#include <sys/time.h>
#endif
#include <sys/queue.h>
#ifdef _EVENT_HAVE_DEVPOLL
extern const struct eventop devpollops;
#endif
-#ifdef WIN32
+#ifdef _WIN32
extern const struct eventop win32ops;
#endif
#ifdef _EVENT_HAVE_SELECT
&selectops,
#endif
-#ifdef WIN32
+#ifdef _WIN32
&win32ops,
#endif
NULL
}
#endif
-#ifdef WIN32
+#ifdef _WIN32
if (cfg && (cfg->flags & EVENT_BASE_FLAG_STARTUP_IOCP))
event_base_start_iocp(base, cfg->n_cpus_hint);
#endif
int
event_base_start_iocp(struct event_base *base, int n_cpus)
{
-#ifdef WIN32
+#ifdef _WIN32
if (base->iocp)
return 0;
base->iocp = event_iocp_port_launch(n_cpus);
void
event_base_stop_iocp(struct event_base *base)
{
-#ifdef WIN32
+#ifdef _WIN32
int rv;
if (!base->iocp)
/* XXX(niels) - check for internal events first */
EVUTIL_ASSERT(base);
-#ifdef WIN32
+#ifdef _WIN32
event_base_stop_iocp(base);
#endif
char buf[1];
int r;
buf[0] = (char) 0;
-#ifdef WIN32
+#ifdef _WIN32
r = send(base->th_notify_fd[1], buf, 1, 0);
#else
r = write(base->th_notify_fd[1], buf, 1);
memcpy(p, str, ln+1);
return p;
} else
-#ifdef WIN32
+#ifdef _WIN32
return _strdup(str);
#else
return strdup(str);
{
unsigned char buf[1024];
struct event_base *base = arg;
-#ifdef WIN32
+#ifdef _WIN32
while (recv(fd, (char*)buf, sizeof(buf), 0) > 0)
;
#else
}
#endif
-#ifdef WIN32
+#ifdef _WIN32
#define LOCAL_SOCKETPAIR_AF AF_INET
#else
#define LOCAL_SOCKETPAIR_AF AF_UNIX
/* For int types. */
#include <evutil.h>
-#ifdef WIN32
+#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
struct event_iocp_port *
event_base_get_iocp(struct event_base *base)
{
-#ifdef WIN32
+#ifdef _WIN32
return base->iocp;
#else
return NULL;
#include <sys/param.h>
#endif
-#ifdef WIN32
+#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#ifndef WIN32
+#ifndef _WIN32
#include <syslog.h>
#endif
#ifdef _EVENT_HAVE_UNISTD_H
#include "event2/event-config.h"
#include "evconfig-private.h"
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
#endif
#include <sys/types.h>
-#if !defined(WIN32) && defined(_EVENT_HAVE_SYS_TIME_H)
+#if !defined(_WIN32) && defined(_EVENT_HAVE_SYS_TIME_H)
#include <sys/time.h>
#endif
#include <sys/queue.h>
#include <stdio.h>
#include <stdlib.h>
-#ifndef WIN32
+#ifndef _WIN32
#include <unistd.h>
#endif
#include <errno.h>
next = HT_NEXT_RMV(event_io_map, ctx, ent);
mm_free(this);
}
+ HT_CLEAR(event_io_map, ctx); /* remove all storage held by the ctx. */
}
#endif
#define GET_SIGNAL_SLOT_AND_CTOR(x, map, slot, type, ctor, fdinfo_len) \
do { \
if ((map)->entries[slot] == NULL) { \
- EVUTIL_ASSERT(ctor != NULL); \
(map)->entries[slot] = \
mm_calloc(1,sizeof(struct type)+fdinfo_len); \
EVUTIL_ASSERT((map)->entries[slot] != NULL); \
#include "event2/event-config.h"
#include "evconfig-private.h"
-#ifdef WIN32
+#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <windows.h>
#endif
#include <sys/types.h>
-#ifndef WIN32
+#ifndef _WIN32
#include <sys/socket.h>
#endif
#ifdef _EVENT_HAVE_SYS_TIME_H
#include <sys/queue.h>
#include <stdio.h>
#include <stdlib.h>
-#ifndef WIN32
+#ifndef _WIN32
#include <unistd.h>
#endif
#include <errno.h>
struct event_base;
-#ifndef WIN32
+#ifndef _WIN32
/* On Windows, the way we currently make DLLs, it's not allowed for us to
* have shared global structures. Thus, we only do the direct-call-to-function
* code path if we know that the local shared library system supports it.
{
int r;
struct debug_lock *lock = _lock;
+ EVUTIL_ASSERT(lock);
EVUTIL_ASSERT(DEBUG_LOCK_SIG == lock->signature);
EVLOCK_ASSERT_LOCKED(_lock);
evthread_debug_lock_mark_unlocked(0, lock);
#include "event2/event-config.h"
#include "evconfig-private.h"
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "event2/event-config.h"
#include "evconfig-private.h"
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#define WIN32_LEAN_AND_MEAN
#include "strlcpy-internal.h"
#include "ipv6-internal.h"
-#ifdef WIN32
+#ifdef _WIN32
#define open _open
#define read _read
#define close _close
return -2;
}
read_so_far = 0;
-#ifdef WIN32
+#ifdef _WIN32
#define N_TO_READ(x) ((x) > INT_MAX) ? INT_MAX : ((int)(x))
#else
#define N_TO_READ(x) (x)
int
evutil_socketpair(int family, int type, int protocol, evutil_socket_t fd[2])
{
-#ifndef WIN32
+#ifndef _WIN32
return socketpair(family, type, protocol, fd);
#else
return evutil_ersatz_socketpair(family, type, protocol, fd);
* for now, and really, when localhost is down sometimes, we
* have other problems too.
*/
-#ifdef WIN32
+#ifdef _WIN32
#define ERR(e) WSA##e
#else
#define ERR(e) e
int
evutil_make_socket_nonblocking(evutil_socket_t fd)
{
-#ifdef WIN32
+#ifdef _WIN32
{
u_long nonblocking = 1;
if (ioctlsocket(fd, FIONBIO, &nonblocking) == SOCKET_ERROR) {
int
evutil_make_listen_socket_reuseable(evutil_socket_t sock)
{
-#ifndef WIN32
+#ifndef _WIN32
int one = 1;
/* REUSEADDR on Unix means, "don't hang on to this address after the
* listener is closed." On Windows, though, it means "don't keep other
int
evutil_make_socket_closeonexec(evutil_socket_t fd)
{
-#if !defined(WIN32) && defined(_EVENT_HAVE_SETFD)
+#if !defined(_WIN32) && defined(_EVENT_HAVE_SETFD)
int flags;
if ((flags = fcntl(fd, F_GETFD, NULL)) < 0) {
event_warn("fcntl(%d, F_GETFD)", fd);
int
evutil_closesocket(evutil_socket_t sock)
{
-#ifndef WIN32
+#ifndef _WIN32
return close(sock);
#else
return closesocket(sock);
return (ev_int64_t)strtoll(s, endptr, base);
#elif _EVENT_SIZEOF_LONG == 8
return (ev_int64_t)strtol(s, endptr, base);
-#elif defined(WIN32) && defined(_MSC_VER) && _MSC_VER < 1300
+#elif defined(_WIN32) && defined(_MSC_VER) && _MSC_VER < 1300
/* XXXX on old versions of MS APIs, we only support base
* 10. */
ev_int64_t r;
if (endptr)
*endptr = (char*) s;
return r;
-#elif defined(WIN32)
+#elif defined(_WIN32)
return (ev_int64_t) _strtoi64(s, endptr, base);
#elif defined(_EVENT_SIZEOF_LONG_LONG) && _EVENT_SIZEOF_LONG_LONG == 8
long long r;
}
#endif
-#ifdef WIN32
+#ifdef _WIN32
int
evutil_socket_geterror(evutil_socket_t sock)
{
int n = parse_numeric_servname(servname);
if (n>=0)
return n;
-#if defined(_EVENT_HAVE_GETSERVBYNAME) || defined(WIN32)
+#if defined(_EVENT_HAVE_GETSERVBYNAME) || defined(_WIN32)
if (!(hints->ai_flags & EVUTIL_AI_NUMERICSERV)) {
struct servent *ent = getservbyname(servname, protocol);
if (ent) {
* ever resolving even a literal IPv6 address when
* ai_addrtype is PF_UNSPEC.
*/
-#ifdef WIN32
+#ifdef _WIN32
{
int tmp_port;
err = evutil_getaddrinfo_common(nodename,servname,&hints,
/* fall back to gethostbyname. */
/* XXXX This needs a lock everywhere but Windows. */
ent = gethostbyname(nodename);
-#ifdef WIN32
+#ifdef _WIN32
err = WSAGetLastError();
#else
err = h_errno;
case EVUTIL_EAI_SYSTEM:
return "system error";
default:
-#if defined(USE_NATIVE_GETADDRINFO) && defined(WIN32)
+#if defined(USE_NATIVE_GETADDRINFO) && defined(_WIN32)
return gai_strerrorA(err);
#elif defined(USE_NATIVE_GETADDRINFO)
return gai_strerror(err);
}
}
-#ifdef WIN32
+#ifdef _WIN32
#define E(code, s) { code, (s " [" #code " ]") }
static struct { int code; const char *msg; } windows_socket_errors[] = {
E(WSAEINTR, "Interrupted function call"),
long
_evutil_weakrand(void)
{
-#ifdef WIN32
+#ifdef _WIN32
return rand();
#else
return random();
return -1;
}
-#ifdef WIN32
+#ifdef _WIN32
HANDLE
evutil_load_windows_system_library(const TCHAR *library_name)
{
#include <sys/ioccom.h>
#endif
-#ifndef WIN32
+#ifndef _WIN32
#include <sys/resource.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <netdb.h>
#endif
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#ifndef WIN32
+#ifndef _WIN32
#include <syslog.h>
#endif
#include <signal.h>
}
#endif
-static const char *
-html_replace(char ch, char *buf)
+static size_t
+html_replace(const char ch, const char **escaped)
{
switch (ch) {
case '<':
- return "<";
+ *escaped = "<";
+ return 4;
case '>':
- return ">";
+ *escaped = ">";
+ return 4;
case '"':
- return """;
+ *escaped = """;
+ return 6;
case '\'':
- return "'";
+ *escaped = "'";
+ return 6;
case '&':
- return "&";
+ *escaped = "&";
+ return 5;
default:
break;
}
- /* Echo the character back */
- buf[0] = ch;
- buf[1] = '\0';
-
- return buf;
+ return 1;
}
/*
evhttp_htmlescape(const char *html)
{
size_t i;
- size_t new_size = 0, old_size = strlen(html);
+ size_t new_size = 0, old_size = 0;
char *escaped_html, *p;
- char scratch_space[2];
- for (i = 0; i < old_size; ++i)
- new_size += strlen(html_replace(html[i], scratch_space));
+ if (html == NULL)
+ return (NULL);
+
+ old_size = strlen(html);
+ for (i = 0; i < old_size; ++i) {
+ const char *replaced = NULL;
+ const size_t replace_size = html_replace(html[i], &replaced);
+ if (replace_size > EV_SIZE_MAX - new_size) {
+ event_warn("%s: html_replace overflow", __func__);
+ return (NULL);
+ }
+ new_size += replace_size;
+ }
+ if (new_size == EV_SIZE_MAX)
+ return (NULL);
p = escaped_html = mm_malloc(new_size + 1);
if (escaped_html == NULL) {
- event_warn("%s: malloc(%ld)", __func__, (long)(new_size + 1));
+ event_warn("%s: malloc(%lu)", __func__,
+ (unsigned long)(new_size + 1));
return (NULL);
}
for (i = 0; i < old_size; ++i) {
- const char *replaced = html_replace(html[i], scratch_space);
- size_t len = strlen(replaced);
+ const char *replaced = &html[i];
+ const size_t len = html_replace(html[i], &replaced);
memcpy(p, replaced, len);
p += len;
}
{
if (evhttp_find_header(headers, "Date") == NULL) {
char date[50];
-#ifndef WIN32
+#ifndef _WIN32
struct tm cur;
#endif
struct tm *cur_p;
time_t t = time(NULL);
-#ifdef WIN32
+#ifdef _WIN32
cur_p = gmtime(&t);
#else
gmtime_r(&t, &cur);
break;
case EVCON_IDLE:
{
+#ifdef USE_DEBUG
struct evbuffer *input;
size_t total_len;
event_debug(("%s: read %d bytes in EVCON_IDLE state,"
" resetting connection",
__func__, (int)total_len));
+#endif
evhttp_connection_reset(evcon);
}
* when connecting to a local address. the cleanup is going
* to reschedule this function call.
*/
-#ifndef WIN32
+#ifndef _WIN32
if (errno == ECONNREFUSED)
goto cleanup;
#endif
char *version;
const char *hostname;
const char *scheme;
+ size_t method_len;
+ enum evhttp_cmd_type type;
/* Parse the request line */
method = strsep(&line, " ");
if (line != NULL)
return (-1);
+ method_len = (uri - method) - 1;
+ type = _EVHTTP_REQ_UNKNOWN;
+
/* First line */
- if (strcmp(method, "GET") == 0) {
- req->type = EVHTTP_REQ_GET;
- } else if (strcmp(method, "POST") == 0) {
- req->type = EVHTTP_REQ_POST;
- } else if (strcmp(method, "HEAD") == 0) {
- req->type = EVHTTP_REQ_HEAD;
- } else if (strcmp(method, "PUT") == 0) {
- req->type = EVHTTP_REQ_PUT;
- } else if (strcmp(method, "DELETE") == 0) {
- req->type = EVHTTP_REQ_DELETE;
- } else if (strcmp(method, "OPTIONS") == 0) {
- req->type = EVHTTP_REQ_OPTIONS;
- } else if (strcmp(method, "TRACE") == 0) {
- req->type = EVHTTP_REQ_TRACE;
- } else if (strcmp(method, "PATCH") == 0) {
- req->type = EVHTTP_REQ_PATCH;
- } else {
- req->type = _EVHTTP_REQ_UNKNOWN;
- event_debug(("%s: bad method %s on request %p from %s",
+ switch (method_len) {
+ case 3:
+ /* The length of the method string is 3, meaning it can only be one of two methods: GET or PUT */
+
+ /* Since both GET and PUT share the same character 'T' at the end,
+ * if the string doesn't have 'T', we can immediately determine this
+ * is an invalid HTTP method */
+
+ if (method[2] != 'T') {
+ break;
+ }
+
+ switch (*method) {
+ case 'G':
+ /* This first byte is 'G', so make sure the next byte is
+ * 'E', if it isn't then this isn't a valid method */
+
+ if (method[1] == 'E') {
+ type = EVHTTP_REQ_GET;
+ }
+
+ break;
+ case 'P':
+ /* First byte is P, check second byte for 'U', if not,
+ * we know it's an invalid method */
+ if (method[1] == 'U') {
+ type = EVHTTP_REQ_PUT;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ case 4:
+ /* The method length is 4 bytes, leaving only the methods "POST" and "HEAD" */
+ switch (*method) {
+ case 'P':
+ if (method[3] == 'T' && method[2] == 'S' && method[1] == 'O') {
+ type = EVHTTP_REQ_POST;
+ }
+ break;
+ case 'H':
+ if (method[3] == 'D' && method[2] == 'A' && method[1] == 'E') {
+ type = EVHTTP_REQ_HEAD;
+ }
+ break;
+ default:
+ break;
+ }
+ case 5:
+ /* Method length is 5 bytes, which can only encompass PATCH and TRACE */
+ switch (*method) {
+ case 'P':
+ if (method[4] == 'H' && method[3] == 'C' && method[2] == 'T' && method[1] == 'A') {
+ type = EVHTTP_REQ_PATCH;
+ }
+ break;
+ case 'T':
+ if (method[4] == 'E' && method[3] == 'C' && method[2] == 'A' && method[1] == 'R') {
+ type = EVHTTP_REQ_TRACE;
+ }
+
+ break;
+ default:
+ break;
+ }
+ break;
+ case 6:
+ /* Method length is 6, only valid method 6 bytes in length is DELEte */
+
+ /* If the first byte isn't 'D' then it's invalid */
+ if (*method != 'D') {
+ break;
+ }
+
+ if (method[5] == 'E' && method[4] == 'T' && method[3] == 'E' && method[2] == 'L' && method[1] == 'E') {
+ type = EVHTTP_REQ_DELETE;
+ }
+
+ break;
+ case 7:
+ /* Method length is 7, only valid methods are "OPTIONS" and "CONNECT" */
+ switch (*method) {
+ case 'O':
+ if (method[6] == 'S' && method[5] == 'N' && method[4] == 'O' &&
+ method[3] == 'I' && method[2] == 'T' && method[1] == 'P') {
+ type = EVHTTP_REQ_OPTIONS;
+ }
+
+ break;
+ case 'C':
+ if (method[6] == 'T' && method[5] == 'C' && method[4] == 'E' &&
+ method[3] == 'N' && method[2] == 'N' && method[1] == 'O') {
+ type = EVHTTP_REQ_CONNECT;
+ }
+
+ break;
+ default:
+ break;
+ }
+ break;
+ } /* switch */
+
+ if (type == _EVHTTP_REQ_UNKNOWN) {
+ event_debug(("%s: bad method %s on request %p from %s",
__func__, method, req, req->remote_host));
- /* No error yet; we'll give a better error later when
- * we see that req->type is unsupported. */
+ /* No error yet; we'll give a better error later when
+ * we see that req->type is unsupported. */
}
+
+ req->type = type;
if (evhttp_parse_http_version(version, req) < 0)
return (-1);
}
if (status == MORE_DATA_EXPECTED) {
- if (req->headers_size + evbuffer_get_length(buffer) > req->evcon->max_headers_size)
+ if (req->evcon != NULL &&
+ req->headers_size + evbuffer_get_length(buffer) > req->evcon->max_headers_size)
return (DATA_TOO_LONG);
}
req->evcon = evcon;
EVUTIL_ASSERT(!(req->flags & EVHTTP_REQ_OWN_CONNECTION));
+ TAILQ_INSERT_TAIL(&evcon->requests, req, next);
+
/* If the connection object is not connected; make it so */
if (!evhttp_connected(evcon)) {
int res = evhttp_connection_connect(evcon);
- /*
- * Enqueue the request only if we aren't going to
- * return failure from evhttp_make_request().
- */
- if (res == 0)
- TAILQ_INSERT_TAIL(&evcon->requests, req, next);
+ /* evhttp_connection_fail(), which is called through
+ * evhttp_connection_connect(), assumes that req lies in
+ * evcon->requests. Thus, enqueue the request in advance and r
+ * it in the error case. */
+ if (res != 0)
+ TAILQ_REMOVE(&evcon->requests, req, next);
return res;
}
- TAILQ_INSERT_TAIL(&evcon->requests, req, next);
-
/*
* If it's connected already and we are the first in the queue,
* then we can dispatch this request immediately. Otherwise, it
EXTRA_SRC = $(EVENT2_EXPORT)
-nobase_include_HEADERS = $(EVENT2_EXPORT)
+## Without the nobase_ prefixing, Automake would strip "event2/" from
+## the source header filename to derive the installed header filename.
+## With nobase_ the installed path is $(includedir)/event2/ev*.h.
+if INSTALL_LIBEVENT
+nobase_include_HEADERS = $(EVENT2_EXPORT)
nobase_nodist_include_HEADERS = ./event2/event-config.h
-
+else
+noinst_HEADERS = $(EVENT2_EXPORT)
+nodist_noinst_HEADERS = ./event2/event-config.h
+endif
@return 0 if successful, or -1 if an error occurred
@see evdns_resolv_conf_parse()
*/
-#ifdef WIN32
+#ifdef _WIN32
int evdns_base_config_windows_nameservers(struct evdns_base *);
#define EVDNS_BASE_CONFIG_WINDOWS_NAMESERVERS_IMPLEMENTED
#endif
*/
struct evdns_server_port *evdns_add_server_port(evutil_socket_t socket, int flags, evdns_request_callback_fn_type callback, void *user_data);
-#ifdef WIN32
+#ifdef _WIN32
int evdns_config_windows_nameservers(void);
#define EVDNS_CONFIG_WINDOWS_NAMESERVERS_IMPLEMENTED
#endif
* have had their callbacks run. */
#define EVLOOP_ONCE 0x01
/** Do not block: see which events are ready now, run the callbacks
- * highest-priority ones, then exit. */
+ * of the highest-priority ones, then exit. */
#define EVLOOP_NONBLOCK 0x02
/*@}*/
EVRPC_OUTPUT /**< apply the function to an output hook */
};
-#ifndef WIN32
+#ifndef _WIN32
/** Deprecated alias for EVRPC_INPUT. Not available on windows, where it
* conflicts with platform headers. */
#define INPUT EVRPC_INPUT
void evthread_set_id_callback(
unsigned long (*id_fn)(void));
-#if defined(WIN32) && !defined(_EVENT_DISABLE_THREAD_SUPPORT)
+#if defined(_WIN32) && !defined(_EVENT_DISABLE_THREAD_SUPPORT)
/** Sets up Libevent for use with Windows builtin locking and thread ID
functions. Unavailable if Libevent is not built for Windows.
#include <netdb.h>
#endif
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#else
#include <sys/socket.h>
#ifdef _EVENT_HAVE_UINT64_T
#define ev_uint64_t uint64_t
#define ev_int64_t int64_t
-#elif defined(WIN32)
+#elif defined(_WIN32)
#define ev_uint64_t unsigned __int64
#define ev_int64_t signed __int64
#elif _EVENT_SIZEOF_LONG_LONG == 8
#ifdef _EVENT_HAVE_UINT32_T
#define ev_uint32_t uint32_t
#define ev_int32_t int32_t
-#elif defined(WIN32)
+#elif defined(_WIN32)
#define ev_uint32_t unsigned int
#define ev_int32_t signed int
#elif _EVENT_SIZEOF_LONG == 4
#ifdef _EVENT_HAVE_UINT16_T
#define ev_uint16_t uint16_t
#define ev_int16_t int16_t
-#elif defined(WIN32)
+#elif defined(_WIN32)
#define ev_uint16_t unsigned short
#define ev_int16_t signed short
#elif _EVENT_SIZEOF_INT == 2
#define ev_ssize_t ssize_t
#endif
-#ifdef WIN32
+#ifdef _WIN32
#define ev_off_t ev_int64_t
#else
#define ev_off_t off_t
#define EV_SSIZE_MIN ((-EV_SSIZE_MAX) - 1)
-#ifdef WIN32
+#ifdef _WIN32
#define ev_socklen_t int
#elif defined(_EVENT_socklen_t)
#define ev_socklen_t _EVENT_socklen_t
#endif
#endif
-#ifdef WIN32
+#ifdef _WIN32
/** A type wide enough to hold the output of "socket()" or "accept()". On
* Windows, this is an intptr_t; elsewhere, it is an int. */
#define evutil_socket_t intptr_t
* function, and don't let you use strerror for the error codes. And handling
* EWOULDBLOCK is ... different. */
-#ifdef WIN32
+#ifdef _WIN32
/** Return the most recent socket error. Not idempotent on all platforms. */
#define EVUTIL_SOCKET_ERROR() WSAGetLastError()
/** Replace the most recent socket error with errcode */
/* This whole file is actually win32 only. We wrap the structures in a win32
* ifdef so that we can test-compile code that uses these interfaces on
* non-win32 platforms. */
-#ifdef WIN32
+#ifdef _WIN32
/**
Internal use only. Wraps an OVERLAPPED that we're using for libevent
return n_changes;
}
+static int
+kq_grow_events(struct kqop *kqop, size_t new_size)
+{
+ struct kevent *newresult;
+
+ newresult = mm_realloc(kqop->events,
+ new_size * sizeof(struct kevent));
+
+ if (newresult) {
+ kqop->events = newresult;
+ kqop->events_size = new_size;
+ return 0;
+ } else {
+ return -1;
+ }
+}
+
static int
kq_dispatch(struct event_base *base, struct timeval *tv)
{
changes = kqop->changes;
kqop->changes = NULL;
+ /* Make sure that 'events' is at least as long as the list of changes:
+ * otherwise errors in the changes can get reported as a -1 return
+ * value from kevent() rather than as EV_ERROR events in the events
+ * array.
+ *
+ * (We could instead handle -1 return values from kevent() by
+ * retrying with a smaller changes array or a larger events array,
+ * but this approach seems less risky for now.)
+ */
+ if (kqop->events_size < n_changes) {
+ int new_size = kqop->events_size;
+ do {
+ new_size *= 2;
+ } while (new_size < n_changes);
+
+ kq_grow_events(kqop, new_size);
+ events = kqop->events;
+ }
+
EVBASE_RELEASE_LOCK(base, th_base_lock);
res = kevent(kqop->kq, changes, n_changes,
}
if (res == kqop->events_size) {
- struct kevent *newresult;
- int size = kqop->events_size;
/* We used all the events space that we have. Maybe we should
make it bigger. */
- size *= 2;
- newresult = mm_realloc(kqop->events,
- size * sizeof(struct kevent));
- if (newresult) {
- kqop->events = newresult;
- kqop->events_size = size;
- }
+ kq_grow_events(kqop, kqop->events_size * 2);
}
return (0);
Requires: libevent
Conflicts:
Libs: -L${libdir} -levent_openssl
-Libs.private: @LIBS@ -lcrypto -lssl
+Libs.private: @LIBS@ -lssl -lcrypto
Cflags: -I${includedir}
#include <sys/types.h>
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#include <mswsock.h>
#include "util-internal.h"
#include "log-internal.h"
#include "evthread-internal.h"
-#ifdef WIN32
+#ifdef _WIN32
#include "iocp-internal.h"
#include "defer-internal.h"
#include "event-internal.h"
struct event listener;
};
-#ifdef WIN32
+#ifdef _WIN32
struct evconnlistener_iocp {
struct evconnlistener base;
evutil_socket_t fd;
{
struct evconnlistener_event *lev;
-#ifdef WIN32
+#ifdef _WIN32
if (base && event_base_get_iocp(base)) {
const struct win32_extension_fns *ext =
event_get_win32_extension_fns();
LOCK(lev);
while (1) {
struct sockaddr_storage ss;
-#ifdef WIN32
+#ifdef _WIN32
int socklen = sizeof(ss);
#else
socklen_t socklen = sizeof(ss);
}
}
-#ifdef WIN32
+#ifdef _WIN32
struct accepting_socket {
CRITICAL_SECTION lock;
struct event_overlapped overlapped;
#include "event2/event-config.h"
#include "evconfig-private.h"
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
--- /dev/null
+AN_IDENTIFIER([ssize_t], [AC_TYPE_SSIZE_T])
+AC_DEFUN([AC_TYPE_SSIZE_T], [AC_CHECK_TYPE(ssize_t, int)])
+
--- /dev/null
+#!/usr/bin/python
+
+def get(old,wc,rc):
+ if ('xxx' in (rc, wc)):
+ return "0",-1
+
+ if ('add' in (rc, wc)):
+ events = []
+ if rc == 'add' or (rc != 'del' and 'r' in old):
+ events.append("EPOLLIN")
+ if wc == 'add' or (wc != 'del' and 'w' in old):
+ events.append("EPOLLOUT")
+
+ if old == "0":
+ op = "EPOLL_CTL_ADD"
+ else:
+ op = "EPOLL_CTL_MOD"
+ return "|".join(events), op
+
+ if ('del' in (rc, wc)):
+ op = "EPOLL_CTL_DEL"
+ if rc == 'del':
+ if wc == 'del':
+ events = "EPOLLIN|EPOLLOUT"
+ elif 'w' in old:
+ events = "EPOLLOUT"
+ op = "EPOLL_CTL_MOD"
+ else:
+ events = "EPOLLIN"
+ else:
+ assert wc == 'del'
+ if 'r' in old:
+ events = "EPOLLIN"
+ op = "EPOLL_CTL_MOD"
+ else:
+ events = "EPOLLOUT"
+ return events, op
+
+ return 0, 0
+
+
+def fmt(op, ev, old, wc, rc):
+ entry = "{ %s, %s },"%(op, ev)
+ assert len(entry)<=36
+ sp = " "*(36-len(entry))
+ print "\t%s%s/* old=%2s, write:%3s, read:%3s */" % (
+ entry, sp, old, wc, rc)
+
+
+for old in ('0','r','w','rw'):
+ for wc in ('0', 'add', 'del', 'xxx'):
+ for rc in ('0', 'add', 'del', 'xxx'):
+
+ op,ev = get(old,wc,rc)
+
+ fmt(op, ev, old, wc, rc)
+
if OPENSSL
noinst_PROGRAMS += le-proxy
le_proxy_sources = le-proxy.c
-le_proxy_LDADD = $(LDADD) ../libevent_openssl.la -lcrypto -lssl
+le_proxy_LDADD = $(LDADD) ../libevent_openssl.la
endif
verify:
#include <sys/types.h>
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#else
gai_callback(int err, struct evutil_addrinfo *ai, void *arg)
{
const char *name = arg;
- struct evutil_addrinfo *ai_first = NULL;
int i;
if (err) {
printf("%s: %s\n", name, evutil_gai_strerror(err));
printf("[%d] %s: %s\n",i,name,buf);
}
}
- if (ai_first)
- evutil_freeaddrinfo(ai_first);
}
static void
printf(" -- replying for %s (PTR)\n", req->questions[i]->name);
r = evdns_server_request_add_ptr_reply(req, NULL, req->questions[i]->name,
"foo.bar.example.com", 10);
+ if (r<0)
+ printf("ugh, no luck");
} else {
printf(" -- skipping %s [%d %d]\n", req->questions[i]->name,
req->questions[i]->type, req->questions[i]->dns_question_class);
evdns_add_server_port_with_base(event_base, sock, 0, evdns_server_callback, NULL);
}
if (idx < c) {
-#ifdef WIN32
+#ifdef _WIN32
evdns_base_config_windows_nameservers(evdns_base);
#else
evdns_base_resolv_conf_parse(evdns_base, DNS_OPTION_NAMESERVERS,
#include <sys/types.h>
#include <sys/stat.h>
-#ifndef WIN32
+#ifndef _WIN32
#include <sys/queue.h>
#include <unistd.h>
#include <sys/time.h>
char buf[255];
int len;
struct event *ev = arg;
-#ifdef WIN32
+#ifdef _WIN32
DWORD dwBytesRead;
#endif
fprintf(stderr, "fifo_read called with fd: %d, event: %d, arg: %p\n",
fd, event, arg);
-#ifdef WIN32
+#ifdef _WIN32
len = ReadFile((HANDLE)fd, buf, sizeof(buf) - 1, &dwBytesRead, NULL);
/* Check for end of file. */
main(int argc, char **argv)
{
struct event evfifo;
-#ifdef WIN32
+#ifdef _WIN32
HANDLE socket;
/* Open a file. */
socket = CreateFileA("test.txt", /* open File */
event_init();
/* Initalize one event */
-#ifdef WIN32
+#ifdef _WIN32
event_set(&evfifo, (int)socket, EV_READ, fifo_read, &evfifo);
#else
event_set(&evfifo, socket, EV_READ, fifo_read, &evfifo);
event_add(&evfifo, NULL);
event_dispatch();
-#ifdef WIN32
+#ifdef _WIN32
CloseHandle(socket);
#endif
return (0);
#include <errno.h>
#include <stdio.h>
#include <signal.h>
-#ifndef WIN32
+#ifndef _WIN32
#include <netinet/in.h>
# ifdef _XOPEN_SOURCE_EXTENDED
# include <arpa/inet.h>
struct event *signal_event;
struct sockaddr_in sin;
-#ifdef WIN32
+#ifdef _WIN32
WSADATA wsa_data;
WSAStartup(0x0201, &wsa_data);
#endif
#include <sys/types.h>
#include <sys/stat.h>
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
#include <io.h>
#include <fcntl.h>
+#ifndef S_ISDIR
+#define S_ISDIR(x) (((x) & S_IFMT) == S_IFDIR)
+#endif
#else
#include <sys/stat.h>
#include <sys/socket.h>
/* Compatibility for possible missing IPv6 declarations */
#include "../util-internal.h"
-#ifdef WIN32
+#ifdef _WIN32
#define stat _stat
#define fstat _fstat
#define open _open
if (S_ISDIR(st.st_mode)) {
/* If it's a directory, read the comments and make a little
* index page */
-#ifdef WIN32
+#ifdef _WIN32
HANDLE d;
WIN32_FIND_DATAA ent;
char *pattern;
if (!strlen(path) || path[strlen(path)-1] != '/')
trailing_slash = "/";
-#ifdef WIN32
+#ifdef _WIN32
dirlen = strlen(whole_path);
pattern = malloc(dirlen+3);
memcpy(pattern, whole_path, dirlen);
uri_root, path, /* XXX html-escape this? */
trailing_slash,
decoded_path /* XXX html-escape this */);
-#ifdef WIN32
+#ifdef _WIN32
do {
const char *name = ent.cFileName;
#else
evbuffer_add_printf(evb,
" <li><a href=\"%s\">%s</a>\n",
name, name);/* XXX escape this */
-#ifdef WIN32
+#ifdef _WIN32
} while (FindNextFileA(d, &ent));
#else
}
#endif
evbuffer_add_printf(evb, "</ul></body></html>\n");
-#ifdef WIN32
+#ifdef _WIN32
CloseHandle(d);
#else
closedir(d);
struct evhttp_bound_socket *handle;
unsigned short port = 0;
-#ifdef WIN32
+#ifdef _WIN32
WSADATA WSAData;
WSAStartup(0x101, &WSAData);
#else
#include <string.h>
#include <errno.h>
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <event2/event-config.h>
#include <sys/stat.h>
-#ifndef WIN32
+#ifndef _WIN32
#include <sys/queue.h>
#include <unistd.h>
#include <sys/time.h>
{
struct event signal_int;
struct event_base* base;
-#ifdef WIN32
+#ifdef _WIN32
WORD wVersionRequested;
WSADATA wsaData;
int err;
#include <event2/event-config.h>
#include <sys/stat.h>
-#ifndef WIN32
+#ifndef _WIN32
#include <sys/queue.h>
#include <unistd.h>
#endif
#include <event2/event_struct.h>
#include <event2/util.h>
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#endif
struct event_base *base;
int flags;
-#ifdef WIN32
+#ifdef _WIN32
WORD wVersionRequested;
WSADATA wsaData;
int err;
#include "event2/event-config.h"
#include "evconfig-private.h"
-#ifdef WIN32
+#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <windows.h>
on Linux do a reasonable thing using signalfd.
*/
-#ifndef WIN32
+#ifndef _WIN32
/* Windows wants us to call our signal handlers as __cdecl. Nobody else
* expects you to do anything crazy like this. */
#define __cdecl
*/
if (evutil_socketpair(
AF_UNIX, SOCK_STREAM, 0, base->sig.ev_signal_pair) == -1) {
-#ifdef WIN32
+#ifdef _WIN32
/* Make this nonfatal on win32, where sometimes people
have localhost firewalled. */
event_sock_warn(-1, "%s: socketpair", __func__);
evsig_handler(int sig)
{
int save_errno = errno;
-#ifdef WIN32
+#ifdef _WIN32
int socket_errno = EVUTIL_SOCKET_ERROR();
#endif
ev_uint8_t msg;
msg = sig;
send(evsig_base_fd, (char*)&msg, 1, 0);
errno = save_errno;
-#ifdef WIN32
+#ifdef _WIN32
EVUTIL_SET_SOCKET_ERROR(socket_errno);
#endif
}
EXTRA_DIST = regress.rpc regress.gen.h regress.gen.c test.sh
-noinst_PROGRAMS = test-init test-eof test-weof test-time @CHECK_REGRESS@ \
+noinst_PROGRAMS = test-init test-eof test-weof test-time \
bench bench_cascade bench_http bench_httpclient test-ratelim \
test-changelist
+if BUILD_REGRESS
+noinst_PROGRAMS += regress
+endif
EXTRA_PROGRAMS = regress
noinst_HEADERS = tinytest.h tinytest_macros.h regress.h tinytest_local.h
endif
regress_LDADD = $(LIBEVENT_GC_SECTIONS) ../libevent.la $(PTHREAD_LIBS) $(ZLIB_LIBS)
-regress_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/compat \
- -I$(top_srcdir)/include -I../include $(PTHREAD_CFLAGS) $(ZLIB_CFLAGS)
+regress_CPPFLAGS = $(AM_CPPFLAGS) $(PTHREAD_CFLAGS) $(ZLIB_CFLAGS)
regress_LDFLAGS = $(PTHREAD_CFLAGS)
if OPENSSL
regress_SOURCES += regress_ssl.c
-regress_LDADD += ../libevent_openssl.la -lcrypto -lssl
+regress_LDADD += ../libevent_openssl.la
endif
bench_SOURCES = bench.c
-CFLAGS=/I.. /I../WIN32-Code /I../include /I../compat /DWIN32 /DHAVE_CONFIG_H /DTINYTEST_LOCAL
+CFLAGS=/I.. /I../WIN32-Code /I../include /I../compat /DHAVE_CONFIG_H /DTINYTEST_LOCAL
CFLAGS=$(CFLAGS) /Ox /W3 /wd4996 /nologo
#include <sys/types.h>
#include <sys/stat.h>
+#ifdef _EVENT_HAVE_SYS_TIME_H
#include <sys/time.h>
-#ifdef WIN32
+#endif
+#ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#else
#include <sys/socket.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#ifdef _EVENT_HAVE_UNISTD_H
#include <unistd.h>
+#endif
#include <errno.h>
#include <event.h>
count = 0;
writes = num_writes;
{ int xcount = 0;
- gettimeofday(&ts, NULL);
+ evutil_gettimeofday(&ts, NULL);
do {
event_loop(EVLOOP_ONCE | EVLOOP_NONBLOCK);
xcount++;
} while (count != fired);
- gettimeofday(&te, NULL);
+ evutil_gettimeofday(&te, NULL);
if (xcount != count) fprintf(stderr, "Xcount: %d, Rcount: %d\n", xcount, count);
}
int
main(int argc, char **argv)
{
-#ifndef WIN32
+#ifndef _WIN32
struct rlimit rl;
#endif
int i, c;
struct timeval *tv;
int *cp;
-#ifdef WIN32
+#ifdef _WIN32
WSADATA WSAData;
WSAStartup(0x101, &WSAData);
#endif
}
}
-#ifndef WIN32
+#ifndef _WIN32
rl.rlim_cur = rl.rlim_max = num_pipes * 2 + 50;
if (setrlimit(RLIMIT_NOFILE, &rl) == -1) {
perror("setrlimit");
#include <sys/types.h>
#include <sys/stat.h>
+#ifdef _EVENT_HAVE_SYS_TIME_H
#include <sys/time.h>
-#ifdef WIN32
+#endif
+#ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#else
#include <sys/socket.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#ifdef _EVENT_HAVE_UNISTD_H
#include <unistd.h>
+#endif
#include <errno.h>
#include <event.h>
}
/* measurements includes event setup */
- gettimeofday(&ts, NULL);
+ evutil_gettimeofday(&ts, NULL);
/* provide a default timeout for events */
evutil_timerclear(&tv_timeout);
event_dispatch();
- gettimeofday(&te, NULL);
+ evutil_gettimeofday(&te, NULL);
evutil_timersub(&te, &ts, &te);
for (cp = pipes, i = 0; i < num_pipes; i++, cp += 2) {
int
main(int argc, char **argv)
{
-#ifndef WIN32
+#ifndef _WIN32
struct rlimit rl;
#endif
int i, c;
}
}
-#ifndef WIN32
+#ifndef _WIN32
rl.rlim_cur = rl.rlim_max = num_pipes * 2 + 50;
if (setrlimit(RLIMIT_NOFILE, &rl) == -1) {
perror("setrlimit");
#include <sys/types.h>
#include <sys/stat.h>
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#else
#include <sys/socket.h>
int use_iocp = 0;
unsigned short port = 8080;
-#ifdef WIN32
+#ifdef _WIN32
WSADATA WSAData;
WSAStartup(0x101, &WSAData);
#else
exit(1);
}
break;
-#ifdef WIN32
+#ifdef _WIN32
case 'i':
use_iocp = 1;
evthread_use_windows_threads();
*/
#include <sys/types.h>
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#else
#include <sys/socket.h>
# endif
#endif
#include <stdlib.h>
+#include <string.h>
#include <errno.h>
#include "event2/event.h"
if (what & BEV_EVENT_EOF) {
++total_n_handled;
total_n_bytes += ri->n_read;
- gettimeofday(&now, NULL);
+ evutil_gettimeofday(&now, NULL);
evutil_timersub(&now, &ri->started, &diff);
evutil_timeradd(&diff, &total_time, &total_time);
struct request_info *ri;
+ memset(&sin, 0, sizeof(sin));
+
++total_n_launched;
sin.sin_family = AF_INET;
ri = malloc(sizeof(*ri));
ri->n_read = 0;
- gettimeofday(&ri->started, NULL);
+ evutil_gettimeofday(&ri->started, NULL);
b = bufferevent_socket_new(base, sock, BEV_OPT_CLOSE_ON_FREE);
perror("launch");
}
- gettimeofday(&start, NULL);
+ evutil_gettimeofday(&start, NULL);
event_base_dispatch(base);
- gettimeofday(&end, NULL);
+ evutil_gettimeofday(&end, NULL);
evutil_timersub(&end, &start, &total);
usec = total_time.tv_sec * 1000000 + total_time.tv_usec;
throughput = total_n_handled /
(total.tv_sec+ ((double)total.tv_usec)/1000000.0);
-#ifdef WIN32
+#ifdef _WIN32
#define I64_FMT "%I64d"
#define I64_TYP __int64
#else
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#include <windows.h>
#endif
#include <sys/time.h>
#endif
#include <sys/queue.h>
-#ifndef WIN32
+#ifndef _WIN32
#include <sys/socket.h>
#include <sys/wait.h>
#include <signal.h>
#include "regress.h"
-#ifndef WIN32
+#ifndef _WIN32
#include "regress.gen.h"
#endif
#define SHUT_WR 1
#endif
-#ifdef WIN32
+#ifdef _WIN32
#define write(fd,buf,len) send((fd),(buf),(int)(len),0)
#define read(fd,buf,len) recv((fd),(buf),(int)(len),0)
#endif
short got_read_on_close = 0, got_write_on_close = 0;
char buf[1024];
memset(buf, 99, sizeof(buf));
-#ifdef WIN32
+#ifdef _WIN32
#define LOCAL_SOCKETPAIR_AF AF_INET
#else
#define LOCAL_SOCKETPAIR_AF AF_UNIX
data->base = NULL;
}
-#ifndef WIN32
+#ifndef _WIN32
static void signal_cb(evutil_socket_t fd, short event, void *arg);
#define current_base event_global_current_base_
}
}
-#ifndef WIN32
+#ifndef _WIN32
/* You can't do this test on windows, since dup2 doesn't work on sockets */
static void
static void
test_many_events(void *arg)
{
- /* Try 70 events that should all be aready at once. This will
+ /* Try 70 events that should all be ready at once. This will
* exercise the "resize" code on most of the backends, and will make
* sure that we can get past the 64-handle limit of some windows
* functions. */
struct basic_test_data *data = arg;
struct event_base *base = data->base;
+ int one_at_a_time = data->setup_data != NULL;
evutil_socket_t sock[MANY];
struct event *ev[MANY];
int called[MANY];
int i;
+ int loopflags = EVLOOP_NONBLOCK, evflags=0;
+ if (one_at_a_time) {
+ loopflags |= EVLOOP_ONCE;
+ evflags = EV_PERSIST;
+ }
memset(sock, 0xff, sizeof(sock));
memset(ev, 0, sizeof(ev));
sock[i] = socket(AF_INET, SOCK_DGRAM, 0);
tt_assert(sock[i] >= 0);
called[i] = 0;
- ev[i] = event_new(base, sock[i], EV_WRITE, many_event_cb,
- &called[i]);
+ ev[i] = event_new(base, sock[i], EV_WRITE|evflags,
+ many_event_cb, &called[i]);
event_add(ev[i], NULL);
+ if (one_at_a_time)
+ event_base_loop(base, EVLOOP_NONBLOCK|EVLOOP_ONCE);
}
- event_base_loop(base, EVLOOP_NONBLOCK);
+ event_base_loop(base, loopflags);
for (i = 0; i < MANY; ++i) {
- tt_int_op(called[i], ==, 1);
+ if (one_at_a_time)
+ tt_int_op(called[i], ==, MANY - i + 1);
+ else
+ tt_int_op(called[i], ==, 1);
}
end:
{ "event_once", test_event_once, TT_ISOLATED, &basic_setup, NULL },
{ "event_pending", test_event_pending, TT_ISOLATED, &basic_setup,
NULL },
-#ifndef WIN32
+#ifndef _WIN32
{ "dup_fd", test_dup_fd, TT_ISOLATED, &basic_setup, NULL },
#endif
{ "mm_functions", test_mm_functions, TT_FORK, NULL, NULL },
- BASIC(many_events, TT_ISOLATED),
+ { "many_events", test_many_events, TT_ISOLATED, &basic_setup, NULL },
+ { "many_events_slow_add", test_many_events, TT_ISOLATED, &basic_setup, (void*)1 },
{ "struct_event_size", test_struct_event_size, 0, NULL, NULL },
-#ifndef WIN32
+#ifndef _WIN32
LEGACY(fork, TT_ISOLATED),
#endif
END_OF_TESTCASES
};
struct testcase_t signal_testcases[] = {
-#ifndef WIN32
+#ifndef _WIN32
LEGACY(simplesignal, TT_ISOLATED),
LEGACY(multiplesignal, TT_ISOLATED),
LEGACY(immediatesignal, TT_ISOLATED),
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#include <windows.h>
#endif
#include <sys/time.h>
#endif
#include <sys/queue.h>
-#ifndef WIN32
+#ifndef _WIN32
#include <sys/socket.h>
#include <sys/wait.h>
#include <signal.h>
evbuffer_drain(buf_out2, evbuffer_get_length(buf_out2));
/* Let's test the obsolete buffer_setcb function too. */
cb1 = evbuffer_add_cb(buf, log_change_callback, buf_out1);
+ tt_assert(cb1 != NULL);
cb2 = evbuffer_add_cb(buf, log_change_callback, buf_out2);
+ tt_assert(cb2 != NULL);
evbuffer_setcb(buf, self_draining_callback, NULL);
evbuffer_add_printf(buf, "This should get drained right away.");
tt_uint_op(evbuffer_get_length(buf), ==, 0);
/* The old tests here need assertions to work. */
#undef NDEBUG
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#include <windows.h>
#endif
#include <sys/time.h>
#endif
#include <sys/queue.h>
-#ifndef WIN32
+#ifndef _WIN32
#include <sys/socket.h>
#include <sys/wait.h>
#include <signal.h>
#include "event2/util.h"
#include "bufferevent-internal.h"
-#ifdef WIN32
+#ifdef _WIN32
#include "iocp-internal.h"
#endif
be_flags |= BEV_OPT_THREADSAFE;
}
bufferevent_connect_test_flags = be_flags;
-#ifdef WIN32
+#ifdef _WIN32
if (!strcmp((char*)data->setup_data, "unset_connectex")) {
struct win32_extension_fns *ext =
(struct win32_extension_fns *)
if (what & BEV_EVENT_ERROR) {
s = bufferevent_getfd(bev);
err = evutil_socket_error_to_string(evutil_socket_geterror(s));
- TT_BLATHER(("connection failure %s", err));
+ TT_BLATHER(("connection failure on %d: %s", s, err));
test_ok = 1;
} else {
TT_FAIL(("didn't fail? what %hd", what));
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#include <sys/time.h>
#endif
#include <sys/queue.h>
-#ifndef WIN32
+#ifndef _WIN32
#include <sys/socket.h>
#include <signal.h>
#include <netinet/in.h>
}
static void
-test_getaddrinfo_async_cancel_stress(void *arg)
+test_getaddrinfo_async_cancel_stress(void *ptr)
{
- struct basic_test_data *data = arg;
- struct event_base *base = data->base;
+ struct event_base *base;
struct evdns_base *dns_base = NULL;
struct evdns_server_port *server = NULL;
evutil_socket_t fd = -1;
{ "getaddrinfo_async", test_getaddrinfo_async,
TT_FORK|TT_NEED_BASE, &basic_setup, (char*)"" },
{ "getaddrinfo_cancel_stress", test_getaddrinfo_async_cancel_stress,
- TT_FORK|TT_NEED_BASE, &basic_setup, (char*)"" },
+ TT_FORK, NULL, NULL },
END_OF_TESTCASES
};
#include "event2/event-config.h"
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#endif
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
-#ifndef WIN32
+#ifndef _WIN32
#include <sys/time.h>
#include <unistd.h>
#endif
#define SHUT_WR 1
#endif
-#ifdef WIN32
+#ifdef _WIN32
#define LOCAL_SOCKETPAIR_AF AF_INET
#else
#define LOCAL_SOCKETPAIR_AF AF_UNIX
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
+#include <ws2tcpip.h>
#include <windows.h>
#endif
#include <sys/time.h>
#endif
#include <sys/queue.h>
-#ifndef WIN32
+#ifndef _WIN32
#include <sys/socket.h>
#include <signal.h>
#include <unistd.h>
evutil_make_socket_nonblocking(fd);
if (connect(fd, sa, slen) == -1) {
-#ifdef WIN32
+#ifdef _WIN32
int tmp_err = WSAGetLastError();
if (tmp_err != WSAEINPROGRESS && tmp_err != WSAEINVAL &&
tmp_err != WSAEWOULDBLOCK)
}
#ifndef SHUT_WR
-#ifdef WIN32
+#ifdef _WIN32
#define SHUT_WR SD_SEND
#else
#define SHUT_WR 1
/* real NULL request */
http_request = "";
+ bufferevent_write(bev, http_request, strlen(http_request));
+
shutdown(fd, SHUT_WR);
timerclear(&tv);
tv.tv_usec = 10000;
}
+static void
+http_connection_fail_done(struct evhttp_request *req, void *arg)
+{
+ /* An ENETUNREACH error results in an unrecoverable
+ * evhttp_connection error (see evhttp_connection_fail()). The
+ * connection will be reset, and the user will be notified with a NULL
+ * req parameter. */
+ tt_assert(!req);
+
+ test_ok = 1;
+
+ end:
+ event_base_loopexit(arg, NULL);
+}
+
+/* Test unrecoverable evhttp_connection errors by generating an ENETUNREACH
+ * error on connection. */
+static void
+http_connection_fail_test(void *arg)
+{
+ struct basic_test_data *data = arg;
+ ev_uint16_t port = 0;
+ struct evhttp_connection *evcon = NULL;
+ struct evhttp_request *req = NULL;
+
+ exit_base = data->base;
+ test_ok = 0;
+
+ /* auto detect a port */
+ http = http_setup(&port, data->base);
+ evhttp_free(http);
+ http = NULL;
+
+ /* Pick an unroutable address. The limited broadcast address should do
+ * when working with TCP. */
+ evcon = evhttp_connection_base_new(data->base, NULL, "255.255.255.255", 80);
+ tt_assert(evcon);
+
+ /*
+ * At this point, we want to schedule an HTTP GET request
+ * server using our make request method.
+ */
+
+ req = evhttp_request_new(http_connection_fail_done, data->base);
+ tt_assert(req);
+
+ if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/") == -1) {
+ tt_abort_msg("Couldn't make request");
+ }
+
+ event_base_dispatch(data->base);
+
+ tt_int_op(test_ok, ==, 1);
+
+ end:
+ if (evcon)
+ evhttp_connection_free(evcon);
+}
+
static void
http_connection_retry_done(struct evhttp_request *req, void *arg)
{
HTTP(stream_in),
HTTP(stream_in_cancel),
+ HTTP(connection_fail),
HTTP(connection_retry),
HTTP(data_length_constraints),
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#include <windows.h>
#endif
#include <sys/types.h>
-#ifndef WIN32
+#ifndef _WIN32
#include <sys/socket.h>
#include <netinet/in.h>
# ifdef _XOPEN_SOURCE_EXTENDED
evutil_socket_connect(&fd2, (struct sockaddr*)&ss1, slen1);
evutil_socket_connect(&fd3, (struct sockaddr*)&ss2, slen2);
-#ifdef WIN32
+#ifdef _WIN32
Sleep(100); /* XXXX this is a stupid stopgap. */
#endif
event_base_dispatch(base);
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#include <windows.h>
#include <io.h>
#include <sys/types.h>
-#ifndef WIN32
+#ifndef _WIN32
#include <sys/socket.h>
#include <sys/wait.h>
#include <signal.h>
int
regress_make_tmpfile(const void *data, size_t datalen, char **filename_out)
{
-#ifndef WIN32
+#ifndef _WIN32
char tmpfilename[32];
int fd;
*filename_out = NULL;
evutil_socket_t spair[2] = { -1, -1 };
struct basic_test_data *data = NULL;
-#ifndef WIN32
+#ifndef _WIN32
if (testcase->flags & TT_ENABLE_IOCP_FLAG)
return (void*)TT_SKIP;
#endif
/* ============================================================ */
-#if (!defined(_EVENT_HAVE_PTHREADS) && !defined(WIN32)) || defined(_EVENT_DISABLE_THREAD_SUPPORT)
+#if (!defined(_EVENT_HAVE_PTHREADS) && !defined(_WIN32)) || defined(_EVENT_DISABLE_THREAD_SUPPORT)
struct testcase_t thread_testcases[] = {
{ "basic", NULL, TT_SKIP, NULL, NULL },
END_OF_TESTCASES
{ "rpc/", rpc_testcases },
{ "thread/", thread_testcases },
{ "listener/", listener_testcases },
-#ifdef WIN32
+#ifdef _WIN32
{ "iocp/", iocp_testcases },
{ "iocp/bufferevent/", bufferevent_iocp_testcases },
{ "iocp/listener/", listener_iocp_testcases },
int
main(int argc, const char **argv)
{
-#ifdef WIN32
+#ifdef _WIN32
WORD wVersionRequested;
WSADATA wsaData;
int err;
err = WSAStartup(wVersionRequested, &wsaData);
#endif
-#ifndef WIN32
+#ifndef _WIN32
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
return 1;
#endif
-#ifdef WIN32
+#ifdef _WIN32
tinytest_skip(testgroups, "http/connection_retry");
#endif
/* The old tests here need assertions to work. */
#undef NDEBUG
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#include <windows.h>
#endif
#include <sys/time.h>
#endif
#include <sys/queue.h>
-#ifndef WIN32
+#ifndef _WIN32
#include <sys/socket.h>
#include <signal.h>
#include <unistd.h>
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#include <windows.h>
#endif
-#ifndef WIN32
+#ifndef _WIN32
#include <sys/socket.h>
#include <netinet/in.h>
#endif
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#include <sys/time.h>
#endif
#include <sys/queue.h>
-#ifndef WIN32
+#ifndef _WIN32
#include <sys/socket.h>
#include <signal.h>
#include <netinet/in.h>
#ifdef _EVENT_HAVE_PTHREADS
#include <pthread.h>
-#elif defined(WIN32)
+#elif defined(_WIN32)
#include <process.h>
#endif
#include <assert.h>
}
static int notification_fd_used = 0;
-#ifndef WIN32
+#ifndef _WIN32
static int got_sigchld = 0;
static void
sigchld_cb(evutil_socket_t fd, short event, void *arg)
tt_abort_msg("Couldn't make base notifiable!");
}
-#ifndef WIN32
+#ifndef _WIN32
if (data->setup_data && !strcmp(data->setup_data, "forking")) {
pid_t pid;
int status;
#define CB_COUNT 128
#define QUEUE_THREAD_COUNT 8
-#ifdef WIN32
+#ifdef _WIN32
#define SLEEP_MS(ms) Sleep(ms)
#else
#define SLEEP_MS(ms) usleep((ms) * 1000)
struct testcase_t thread_testcases[] = {
{ "basic", thread_basic, TT_FORK|TT_NEED_THREADS|TT_NEED_BASE,
&basic_setup, NULL },
-#ifndef WIN32
+#ifndef _WIN32
{ "forking", thread_basic, TT_FORK|TT_NEED_THREADS|TT_NEED_BASE,
&basic_setup, (char*)"forking" },
#endif
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#include <sys/types.h>
-#ifndef WIN32
+#ifndef _WIN32
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
exit(exitcode);
}
-#ifndef WIN32
+#ifndef _WIN32
#define CAN_CHECK_ERR
static void
check_error_logging(void (*fn)(void), int wantexitcode,
sock_err_fn(void)
{
evutil_socket_t fd = socket(AF_INET, SOCK_STREAM, 0);
-#ifdef WIN32
+#ifdef _WIN32
EVUTIL_SET_SOCKET_ERROR(WSAEWOULDBLOCK);
#else
errno = EAGAIN;
/* Try with a socket errno. */
fd = socket(AF_INET, SOCK_STREAM, 0);
-#ifdef WIN32
+#ifdef _WIN32
evutil_snprintf(buf, sizeof(buf),
"Unhappy socket: %s",
evutil_socket_error_to_string(WSAEWOULDBLOCK));
evutil_freeaddrinfo(ai);
}
-#ifdef WIN32
+#ifdef _WIN32
static void
test_evutil_loadsyslib(void *arg)
{
{ "integers", test_evutil_integers, 0, NULL, NULL },
{ "rand", test_evutil_rand, TT_FORK, NULL, NULL },
{ "getaddrinfo", test_evutil_getaddrinfo, TT_FORK, NULL, NULL },
-#ifdef WIN32
+#ifdef _WIN32
{ "loadsyslib", test_evutil_loadsyslib, TT_FORK, NULL, NULL },
#endif
END_OF_TESTCASES,
/* The old tests here need assertions to work. */
#undef NDEBUG
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#include <windows.h>
#endif
#include "event2/event-config.h"
#include <sys/types.h>
-#ifndef WIN32
+#ifndef _WIN32
#include <sys/socket.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
-#include <zlib.h>
#include <assert.h>
#include <errno.h>
#include "regress.h"
+/* zlib 1.2.4 and 1.2.5 do some "clever" things with macros. Instead of
+ saying "(defined(FOO) ? FOO : 0)" they like to say "FOO-0", on the theory
+ that nobody will care if the compile outputs a no-such-identifier warning.
+
+ Sorry, but we like -Werror over here, so I guess we need to define these.
+ I hope that zlib 1.2.6 doesn't break these too.
+*/
+#ifndef _LARGEFILE64_SOURCE
+#define _LARGEFILE64_SOURCE 0
+#endif
+#ifndef _LFS64_LARGEFILE
+#define _LFS64_LARGEFILE 0
+#endif
+#ifndef _FILE_OFFSET_BITS
+#define _FILE_OFFSET_BITS 0
+#endif
+#ifndef off64_t
+#define off64_t ev_int64_t
+#endif
+
+#include <zlib.h>
+
static int infilter_calls;
static int outfilter_calls;
static int readcb_finished;
tt_int_op(r, ==, Z_OK);
memset(&z_input, 0, sizeof(z_input));
r = inflateInit(&z_input);
+ tt_int_op(r, ==, Z_OK);
/* initialize filters */
bev1 = bufferevent_filter_new(bev1, NULL, zlib_output_filter,
#include "event2/event-config.h"
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#include <windows.h>
#else
#include <time.h>
struct cpu_usage_timer {
-#ifdef WIN32
+#ifdef _WIN32
HANDLE thread;
FILETIME usertimeBegin;
FILETIME kerneltimeBegin;
static void
start_cpu_usage_timer(struct cpu_usage_timer *timer)
{
-#ifdef WIN32
+#ifdef _WIN32
int r;
FILETIME createtime, exittime;
timer->thread = GetCurrentThread();
evutil_gettimeofday(&timer->timeBegin, NULL);
}
-#ifdef WIN32
+#ifdef _WIN32
static ev_int64_t
filetime_to_100nsec(const FILETIME *ft)
{
get_cpu_usage(struct cpu_usage_timer *timer, double *secElapsedOut,
double *secUsedOut, double *usageOut)
{
-#ifdef WIN32
+#ifdef _WIN32
double usertime_seconds, kerneltime_seconds;
FILETIME createtime, exittime, usertimeEnd, kerneltimeEnd;
int r;
struct timeval timeEnd, timeDiff;
double secondsPassed, secondsUsed;
-#ifdef WIN32
+#ifdef _WIN32
r = GetThreadTimes(timer->thread, &createtime, &exittime,
&usertimeEnd, &kerneltimeEnd);
if (r==0) printf("GetThreadTimes failed.");
double usage, secPassed, secUsed;
-#ifdef WIN32
+#ifdef _WIN32
WORD wVersionRequested;
WSADATA wsaData;
int err;
*/
#include "event2/event-config.h"
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#else
#include <unistd.h>
const char *test = "test string";
evutil_socket_t pair[2];
-#ifdef WIN32
+#ifdef _WIN32
WORD wVersionRequested;
WSADATA wsaData;
int err;
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
-#ifndef WIN32
+#ifndef _WIN32
#include <unistd.h>
#endif
#include <errno.h>
int
main(int argc, char **argv)
{
-#ifdef WIN32
+#ifdef _WIN32
WORD wVersionRequested;
WSADATA wsaData;
int err;
#include <assert.h>
#include <math.h>
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#else
struct client_state *cs = ctx;
struct evbuffer *output = bufferevent_get_output(bev);
char buf[1024];
-#ifdef WIN32
+#ifdef _WIN32
int r = rand() % 256;
#else
int r = random() % 256;
int i,j;
double ratio;
-#ifdef WIN32
+#ifdef _WIN32
WORD wVersionRequested = MAKEWORD(2,2);
WSADATA wsaData;
int err;
err = WSAStartup(wVersionRequested, &wsaData);
#endif
-#ifndef WIN32
+#ifndef _WIN32
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
return 1;
#endif
{
struct timeval tv;
evutil_gettimeofday(&tv, NULL);
-#ifdef WIN32
+#ifdef _WIN32
srand(tv.tv_usec);
#else
srandom(tv.tv_usec);
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
-#ifndef WIN32
+#ifndef _WIN32
#include <unistd.h>
#include <sys/time.h>
#endif
static int
rand_int(int n)
{
-#ifdef WIN32
+#ifdef _WIN32
return (int)(rand() % n);
#else
return (int)(random() % n);
{
struct timeval tv;
int i;
-#ifdef WIN32
+#ifdef _WIN32
WORD wVersionRequested;
WSADATA wsaData;
int err;
*/
#include "event2/event-config.h"
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#else
#include <unistd.h>
{
struct event ev;
-#ifdef WIN32
+#ifdef _WIN32
WORD wVersionRequested;
WSADATA wsaData;
int err;
err = WSAStartup(wVersionRequested, &wsaData);
#endif
-#ifndef WIN32
+#ifndef _WIN32
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
return (1);
#endif
#include "tinytest_local.h"
#endif
-#ifdef WIN32
+#ifdef _WIN32
#include <windows.h>
#else
#include <sys/types.h>
/** Name of the current test, if we haven't logged is yet. Used for --quiet */
const char *cur_test_name = NULL;
-#ifdef WIN32
+#ifdef _WIN32
/** Pointer to argv[0] for win32. */
static const char *commandname = NULL;
#endif
_testcase_run_forked(const struct testgroup_t *group,
const struct testcase_t *testcase)
{
-#ifdef WIN32
+#ifdef _WIN32
/* Fork? On Win32? How primitive! We'll do what the smart kids do:
we'll invoke our own exe (whose name we recall from the command
line) with a command line that tells it to run just the test we
{
int i, j, n=0;
-#ifdef WIN32
+#ifdef _WIN32
commandname = v[0];
#endif
for (i=1; i<c; ++i) {
-#ifdef WIN32
+#ifdef _WIN32
#include <winsock2.h>
#endif
#include "event2/util.h"
#include "util-internal.h"
+#ifdef snprintf
+#undef snprintf
+#endif
#define snprintf evutil_snprintf
data," and we need to look at the error code. Second, Windows defines
a different set of error codes for sockets. */
-#ifndef WIN32
+#ifndef _WIN32
/* True iff e is an error that means a read/write operation can be retried. */
#define EVUTIL_ERR_RW_RETRIABLE(e) \
/* Evaluates to the same boolean value as 'p', and hints to the compiler that
* we expect this value to be false. */
-#ifdef __GNUC__
+#if defined(__GNUC__) && __GNUC__ >= 3 /* gcc 3.0 or later */
#define EVUTIL_UNLIKELY(p) __builtin_expect(!!(p),0)
#else
#define EVUTIL_UNLIKELY(p) (p)
int evutil_hex_char_to_int(char c);
-#ifdef WIN32
+#ifdef _WIN32
HANDLE evutil_load_windows_system_library(const TCHAR *library_name);
#endif