summaryrefslogtreecommitdiff
path: root/extra
diff options
context:
space:
mode:
authorVladislav Vaintroub <wlad@montyprogram.com>2012-02-27 19:53:49 +0100
committerVladislav Vaintroub <wlad@montyprogram.com>2012-02-27 19:53:49 +0100
commit0d168ce514ea506a292c12d8624bfbc67fb3530f (patch)
tree4977b543850dd1c38f92e7e964071821f815852b /extra
parent62dcaf8c2911572d730ba5e617a7c3cbbf86b22a (diff)
downloadmariadb-git-0d168ce514ea506a292c12d8624bfbc67fb3530f.tar.gz
Remove libevent from sources - not needed now
Diffstat (limited to 'extra')
-rw-r--r--extra/libevent/CMakeLists.txt43
-rw-r--r--extra/libevent/README57
-rw-r--r--extra/libevent/WIN32-Code/config.h247
-rw-r--r--extra/libevent/WIN32-Code/misc.c38
-rw-r--r--extra/libevent/WIN32-Code/misc.h11
-rw-r--r--extra/libevent/WIN32-Code/tree.h1354
-rw-r--r--extra/libevent/WIN32-Code/win32.c471
-rw-r--r--extra/libevent/buffer.c455
-rw-r--r--extra/libevent/compat/sys/_time.h163
-rw-r--r--extra/libevent/compat/sys/queue.h488
-rw-r--r--extra/libevent/compat/sys/tree.h677
-rw-r--r--extra/libevent/devpoll.c421
-rw-r--r--extra/libevent/epoll.c360
-rw-r--r--extra/libevent/epoll_sub.c60
-rw-r--r--extra/libevent/evbuffer.c420
-rw-r--r--extra/libevent/evdns.c3150
-rw-r--r--extra/libevent/evdns.h528
-rw-r--r--extra/libevent/event-internal.h103
-rw-r--r--extra/libevent/event.c989
-rw-r--r--extra/libevent/event.h1129
-rw-r--r--extra/libevent/event_tagging.c443
-rw-r--r--extra/libevent/evhttp.h340
-rw-r--r--extra/libevent/evport.c517
-rw-r--r--extra/libevent/evrpc-internal.h87
-rw-r--r--extra/libevent/evrpc.c658
-rw-r--r--extra/libevent/evrpc.h477
-rw-r--r--extra/libevent/evsignal.h52
-rw-r--r--extra/libevent/evutil.c198
-rw-r--r--extra/libevent/evutil.h174
-rw-r--r--extra/libevent/http-internal.h133
-rw-r--r--extra/libevent/http.c2512
-rw-r--r--extra/libevent/kqueue.c426
-rw-r--r--extra/libevent/log.c218
-rw-r--r--extra/libevent/log.h51
-rw-r--r--extra/libevent/min_heap.h138
-rw-r--r--extra/libevent/poll.c378
-rw-r--r--extra/libevent/select.c356
-rw-r--r--extra/libevent/signal.c305
-rw-r--r--extra/libevent/strlcpy-internal.h23
-rw-r--r--extra/libevent/strlcpy.c76
40 files changed, 0 insertions, 18726 deletions
diff --git a/extra/libevent/CMakeLists.txt b/extra/libevent/CMakeLists.txt
deleted file mode 100644
index 6be15641d3e..00000000000
--- a/extra/libevent/CMakeLists.txt
+++ /dev/null
@@ -1,43 +0,0 @@
-INCLUDE_DIRECTORIES(
- ${CMAKE_SOURCE_DIR}/extra/libevent
- ${CMAKE_SOURCE_DIR}/extra/libevent/compat
- ${CMAKE_SOURCE_DIR}/extra/libevent/WIN32-Code
- ${CMAKE_BINARY_DIR}/extra/libevent
- ${CMAKE_SOURCE_DIR}/include
-)
-
-IF(MSVC)
- ADD_DEFINITIONS("-DWIN32 -DHAVE_CONFIG_H")
-ENDIF(MSVC)
-
-SET(LIBEVENT_SOURCES
- buffer.c
- evbuffer.c
- event.c
- evutil.c
- log.c
- signal.c
- strlcpy.c
- WIN32-Code/win32.c
- WIN32-Code/config.h
- WIN32-Code/misc.c
- WIN32-Code/misc.h
- event-internal.h
- event.h
- evsignal.h
- evutil.h
- log.h
- min_heap.h
- strlcpy-internal.h
- )
-IF(WIN32)
- # Workaround source distribution bug, remove preconfigured event-config
- IF(NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
- FILE(REMOVE ${CMAKE_SOURCE_DIR}/extra/libevent/event-config.h)
- ENDIF()
- CONFIGURE_FILE(WIN32-Code/config.h ${CMAKE_BINARY_DIR}/extra/libevent/event-config.h COPYONLY)
-ENDIF()
-
-IF(NOT SOURCE_SUBLIBS)
- ADD_LIBRARY(libevent ${LIBEVENT_SOURCES})
-ENDIF(NOT SOURCE_SUBLIBS)
diff --git a/extra/libevent/README b/extra/libevent/README
deleted file mode 100644
index b0650392ed4..00000000000
--- a/extra/libevent/README
+++ /dev/null
@@ -1,57 +0,0 @@
-To build libevent, type
-
-$ ./configure && make
-
- (If you got libevent from the subversion repository, you will
- first need to run the included "autogen.sh" script in order to
- generate the configure script.)
-
-Install as root via
-
-# make install
-
-You can run the regression tests by
-
-$ make verify
-
-Before, reporting any problems, please run the regression tests.
-
-To enable the low-level tracing build the library as:
-
-CFLAGS=-DUSE_DEBUG ./configure [...]
-
-Acknowledgements:
------------------
-
-The following people have helped with suggestions, ideas, code or
-fixing bugs:
-
- Alejo
- Weston Andros Adamson
- William Ahern
- Stas Bekman
- Andrew Danforth
- Mike Davis
- Shie Erlich
- Alexander von Gernler
- Artur Grabowski
- Aaron Hopkins
- Claudio Jeker
- Scott Lamb
- Adam Langley
- Philip Lewis
- David Libenzi
- Nick Mathewson
- Andrey Matveev
- Richard Nyberg
- Jon Oberheide
- Phil Oleson
- Dave Pacheco
- Tassilo von Parseval
- Pierre Phaneuf
- Jon Poland
- Bert JW Regeer
- Dug Song
- Taral
-
-If I have forgotten your name, please contact me.
diff --git a/extra/libevent/WIN32-Code/config.h b/extra/libevent/WIN32-Code/config.h
deleted file mode 100644
index 99365edd96a..00000000000
--- a/extra/libevent/WIN32-Code/config.h
+++ /dev/null
@@ -1,247 +0,0 @@
-/* config.h. Generated by configure. */
-/* config.h.in. Generated from configure.in by autoheader. */
-
-/* Define if clock_gettime is available in libc */
-/* #undef DNS_USE_CPU_CLOCK_FOR_ID */
-
-/* Define if no secure id variant is available */
-#define DNS_USE_FTIME_FOR_ID 1
-
-/* Define if no secure id variant is available */
-/* #define DNS_USE_GETTIMEOFDAY_FOR_ID 1 */
-
-/* Define to 1 if you have the `clock_gettime' function. */
-/* #undef HAVE_CLOCK_GETTIME */
-
-/* Define if /dev/poll is available */
-/* #undef HAVE_DEVPOLL */
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-/* #undef HAVE_DLFCN_H */
-
-/* Define if your system supports the epoll system calls */
-/* #undef HAVE_EPOLL */
-
-/* Define to 1 if you have the `epoll_ctl' function. */
-/* #undef HAVE_EPOLL_CTL */
-
-/* Define if your system supports event ports */
-/* #undef HAVE_EVENT_PORTS */
-
-/* Define to 1 if you have the `fcntl' function. */
-/* #undef HAVE_FCNTL */
-
-/* Define to 1 if you have the <fcntl.h> header file. */
-#define HAVE_FCNTL_H 1
-
-/* Define to 1 if you have the `getaddrinfo' function. */
-/* #undef HAVE_GETADDRINFO */
-
-/* Define to 1 if you have the `getnameinfo' function. */
-/* #undef HAVE_GETNAMEINFO */
-
-/* Define to 1 if you have the `gettimeofday' function. */
-/* #define HAVE_GETTIMEOFDAY 1 */
-
-/* Define to 1 if you have the `inet_ntop' function. */
-/* #undef HAVE_INET_NTOP */
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-/* #undef HAVE_INTTYPES_H 1 */
-
-/* Define to 1 if you have the `kqueue' function. */
-/* #undef HAVE_KQUEUE */
-
-/* Define to 1 if you have the `nsl' library (-lnsl). */
-/* #undef HAVE_LIBNSL */
-
-/* Define to 1 if you have the `resolv' library (-lresolv). */
-/* #undef HAVE_LIBRESOLV */
-
-/* Define to 1 if you have the `rt' library (-lrt). */
-/* #undef HAVE_LIBRT */
-
-/* Define to 1 if you have the `socket' library (-lsocket). */
-/* #undef HAVE_LIBSOCKET */
-
-/* Define to 1 if you have the <memory.h> header file. */
-#define HAVE_MEMORY_H 1
-
-/* Define to 1 if you have the <netinet/in6.h> header file. */
-/* #undef HAVE_NETINET_IN6_H */
-
-/* Define to 1 if you have the `poll' function. */
-/* #undef HAVE_POLL */
-
-/* Define to 1 if you have the <poll.h> header file. */
-/* #undef HAVE_POLL_H */
-
-/* Define to 1 if you have the `port_create' function. */
-/* #undef HAVE_PORT_CREATE */
-
-/* Define to 1 if you have the <port.h> header file. */
-/* #undef HAVE_PORT_H */
-
-/* Define to 1 if you have the `select' function. */
-/* #undef HAVE_SELECT */
-
-/* Define if F_SETFD is defined in <fcntl.h> */
-/* #undef HAVE_SETFD */
-
-/* Define to 1 if you have the `sigaction' function. */
-/* #undef HAVE_SIGACTION */
-
-/* Define to 1 if you have the `signal' function. */
-#define HAVE_SIGNAL 1
-
-/* Define to 1 if you have the <signal.h> header file. */
-#define HAVE_SIGNAL_H 1
-
-/* Define to 1 if you have the <stdarg.h> header file. */
-#define HAVE_STDARG_H 1
-
-/* Define to 1 if you have the <stdint.h> header file. */
-/* #define HAVE_STDINT_H 1 */
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the <strings.h> header file. */
-#define HAVE_STRINGS_H 1
-
-/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* Define to 1 if you have the `strlcpy' function. */
-/* #undef HAVE_STRLCPY */
-
-/* Define to 1 if you have the `strsep' function. */
-/* #undef HAVE_STRSEP */
-
-/* Define to 1 if you have the `strtok_r' function. */
-/* #undef HAVE_STRTOK_R */
-
-/* Define to 1 if the system has the type `struct in6_addr'. */
-#define HAVE_STRUCT_IN6_ADDR 1
-
-/* Define to 1 if you have the <sys/devpoll.h> header file. */
-/* #undef HAVE_SYS_DEVPOLL_H */
-
-/* Define to 1 if you have the <sys/epoll.h> header file. */
-/* #undef HAVE_SYS_EPOLL_H */
-
-/* Define to 1 if you have the <sys/event.h> header file. */
-/* #undef HAVE_SYS_EVENT_H */
-
-/* Define to 1 if you have the <sys/ioctl.h> header file. */
-/* #undef HAVE_SYS_IOCTL_H */
-
-/* Define to 1 if you have the <sys/queue.h> header file. */
-/* #undef HAVE_SYS_QUEUE_H */
-
-/* Define to 1 if you have the <sys/select.h> header file. */
-/* #undef HAVE_SYS_SELECT_H */
-
-/* Define to 1 if you have the <sys/socket.h> header file. */
-/* #undef HAVE_SYS_SOCKET_H */
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-/* #define HAVE_SYS_STAT_H 1 */
-
-/* Define to 1 if you have the <sys/time.h> header file. */
-/* #define HAVE_SYS_TIME_H 1 */
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-/* #define HAVE_SYS_TYPES_H 1 */
-
-/* Define if TAILQ_FOREACH is defined in <sys/queue.h> */
-/* #undef HAVE_TAILQFOREACH */
-
-/* Define if timeradd is defined in <sys/time.h> */
-/* #undef HAVE_TIMERADD */
-
-/* Define if timerclear is defined in <sys/time.h> */
-/* #define HAVE_TIMERCLEAR 1 */
-
-/* Define if timercmp is defined in <sys/time.h> */
-#define HAVE_TIMERCMP 1
-
-/* Define if timerisset is defined in <sys/time.h> */
-#define HAVE_TIMERISSET 1
-
-/* Define to 1 if you have the <unistd.h> header file. */
-/* #define HAVE_UNISTD_H 1 */
-
-/* Define to 1 if you have the `vasprintf' function. */
-/* #undef HAVE_VASPRINTF */
-
-/* Define if kqueue works correctly with pipes */
-/* #undef HAVE_WORKING_KQUEUE */
-
-/* Name of package */
-#ifndef PACKAGE
-#define PACKAGE "libevent"
-#endif
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT ""
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME ""
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING ""
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME ""
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION ""
-
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
-#define TIME_WITH_SYS_TIME 1
-
-/* Version number of package */
-#define VERSION "1.3.99-trunk"
-
-#ifndef __func__
-/* Define to appropriate substitue if compiler doesnt have __func__ */
-#if defined(_MSC_VER) && _MSC_VER < 1300
-#define __func__ "??"
-#else
-#define __func__ __FUNCTION__
-#endif
-#endif
-
-/* Define to empty if `const' does not conform to ANSI C. */
-/* #undef const */
-
-/* Define to `__inline__' or `__inline' if that's what the C compiler
- calls it, or to nothing if 'inline' is not supported under any name. */
-#ifndef __cplusplus
-#define inline __inline
-#endif
-
-/* Define to `int' if <sys/types.h> does not define. */
-/* #undef pid_t */
-
-/* Define to `unsigned' if <sys/types.h> does not define. */
-/* #undef size_t */
-
-/* Define to unsigned int if you dont have it */
-#define socklen_t unsigned int
-
-/* Define to `unsigned short' if <sys/types.h> does not define. */
-#define uint16_t unsigned short
-
-/* Define to `unsigned int' if <sys/types.h> does not define. */
-#define uint32_t unsigned int
-
-/* Define to `unsigned long long' if <sys/types.h> does not define. */
-#define uint64_t __uint64_t
-
-/* Define to `unsigned char' if <sys/types.h> does not define. */
-#define uint8_t unsigned char
diff --git a/extra/libevent/WIN32-Code/misc.c b/extra/libevent/WIN32-Code/misc.c
deleted file mode 100644
index 271c9bb399e..00000000000
--- a/extra/libevent/WIN32-Code/misc.c
+++ /dev/null
@@ -1,38 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <windows.h>
-#include <sys/timeb.h>
-#include <time.h>
-
-#ifdef __GNUC__
-/*our prototypes for timeval and timezone are in here, just in case the above
- headers don't have them*/
-#include "misc.h"
-#endif
-
-/****************************************************************************
- *
- * Function: gettimeofday(struct timeval *, struct timezone *)
- *
- * Purpose: Get current time of day.
- *
- * Arguments: tv => Place to store the curent time of day.
- * tz => Ignored.
- *
- * Returns: 0 => Success.
- *
- ****************************************************************************/
-
-#ifndef HAVE_GETTIMEOFDAY
-int gettimeofday(struct timeval *tv, struct timezone *tz) {
- struct _timeb tb;
-
- if(tv == NULL)
- return -1;
-
- _ftime(&tb);
- tv->tv_sec = (long) tb.time;
- tv->tv_usec = ((int) tb.millitm) * 1000;
- return 0;
-}
-#endif
diff --git a/extra/libevent/WIN32-Code/misc.h b/extra/libevent/WIN32-Code/misc.h
deleted file mode 100644
index aced574687c..00000000000
--- a/extra/libevent/WIN32-Code/misc.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef MISC_H
-#define MISC_H
-
-struct timezone;
-struct timeval;
-
-#ifndef HAVE_GETTIMEOFDAY
-int gettimeofday(struct timeval *,struct timezone *);
-#endif
-
-#endif
diff --git a/extra/libevent/WIN32-Code/tree.h b/extra/libevent/WIN32-Code/tree.h
deleted file mode 100644
index 79e8d91f0eb..00000000000
--- a/extra/libevent/WIN32-Code/tree.h
+++ /dev/null
@@ -1,1354 +0,0 @@
-/* $OpenBSD: tree.h,v 1.7 2002/10/17 21:51:54 art Exp $ */
-/*
- * Copyright 2002 Niels Provos <provos@citi.umich.edu>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef _SYS_TREE_H_
-#define _SYS_TREE_H_
-
-/*
- * This file defines data structures for different types of trees:
- * splay trees and red-black trees.
- *
- * A splay tree is a self-organizing data structure. Every operation
- * on the tree causes a splay to happen. The splay moves the requested
- * node to the root of the tree and partly rebalances it.
- *
- * This has the benefit that request locality causes faster lookups as
- * the requested nodes move to the top of the tree. On the other hand,
- * every lookup causes memory writes.
- *
- * The Balance Theorem bounds the total access time for m operations
- * and n inserts on an initially empty tree as O((m + n)lg n). The
- * amortized cost for a sequence of m accesses to a splay tree is O(lg n);
- *
- * A red-black tree is a binary search tree with the node color as an
- * extra attribute. It fulfills a set of conditions:
- * - every search path from the root to a leaf consists of the
- * same number of black nodes,
- * - each red node (except for the root) has a black parent,
- * - each leaf node is black.
- *
- * Every operation on a red-black tree is bounded as O(lg n).
- * The maximum height of a red-black tree is 2lg (n+1).
- */
-
-#define SPLAY_HEAD(name, type) \
-struct name { \
- struct type *sph_root; /* root of the tree */ \
-}
-
-#define SPLAY_INITIALIZER(root) \
- { NULL }
-
-#define SPLAY_INIT(root) do { \
- (root)->sph_root = NULL; \
-} while (0)
-
-#define SPLAY_ENTRY(type) \
-struct { \
- struct type *spe_left; /* left element */ \
- struct type *spe_right; /* right element */ \
-}
-
-#define SPLAY_LEFT(elm, field) (elm)->field.spe_left
-#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right
-#define SPLAY_ROOT(head) (head)->sph_root
-#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL)
-
-/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */
-#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \
- SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \
- SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
- (head)->sph_root = tmp; \
-} while (0)
-
-#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \
- SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \
- SPLAY_LEFT(tmp, field) = (head)->sph_root; \
- (head)->sph_root = tmp; \
-} while (0)
-
-#define SPLAY_LINKLEFT(head, tmp, field) do { \
- SPLAY_LEFT(tmp, field) = (head)->sph_root; \
- tmp = (head)->sph_root; \
- (head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \
-} while (0)
-
-#define SPLAY_LINKRIGHT(head, tmp, field) do { \
- SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
- tmp = (head)->sph_root; \
- (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \
-} while (0)
-
-#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \
- SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \
- SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\
- SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \
- SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \
-} while (0)
-
-/* Generates prototypes and inline functions */
-
-#define SPLAY_PROTOTYPE(name, type, field, cmp) \
-void name##_SPLAY(struct name *, struct type *); \
-void name##_SPLAY_MINMAX(struct name *, int); \
-struct type *name##_SPLAY_INSERT(struct name *, struct type *); \
-struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \
- \
-/* Finds the node with the same key as elm */ \
-static __inline struct type * \
-name##_SPLAY_FIND(struct name *head, struct type *elm) \
-{ \
- if (SPLAY_EMPTY(head)) \
- return(NULL); \
- name##_SPLAY(head, elm); \
- if ((cmp)(elm, (head)->sph_root) == 0) \
- return (head->sph_root); \
- return (NULL); \
-} \
- \
-static __inline struct type * \
-name##_SPLAY_NEXT(struct name *head, struct type *elm) \
-{ \
- name##_SPLAY(head, elm); \
- if (SPLAY_RIGHT(elm, field) != NULL) { \
- elm = SPLAY_RIGHT(elm, field); \
- while (SPLAY_LEFT(elm, field) != NULL) { \
- elm = SPLAY_LEFT(elm, field); \
- } \
- } else \
- elm = NULL; \
- return (elm); \
-} \
- \
-static __inline struct type * \
-name##_SPLAY_MIN_MAX(struct name *head, int val) \
-{ \
- name##_SPLAY_MINMAX(head, val); \
- return (SPLAY_ROOT(head)); \
-}
-
-/* Main splay operation.
- * Moves node close to the key of elm to top
- */
-#define SPLAY_GENERATE(name, type, field, cmp) \
-struct type * \
-name##_SPLAY_INSERT(struct name *head, struct type *elm) \
-{ \
- if (SPLAY_EMPTY(head)) { \
- SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \
- } else { \
- int __comp; \
- name##_SPLAY(head, elm); \
- __comp = (cmp)(elm, (head)->sph_root); \
- if(__comp < 0) { \
- SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\
- SPLAY_RIGHT(elm, field) = (head)->sph_root; \
- SPLAY_LEFT((head)->sph_root, field) = NULL; \
- } else if (__comp > 0) { \
- SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\
- SPLAY_LEFT(elm, field) = (head)->sph_root; \
- SPLAY_RIGHT((head)->sph_root, field) = NULL; \
- } else \
- return ((head)->sph_root); \
- } \
- (head)->sph_root = (elm); \
- return (NULL); \
-} \
- \
-struct type * \
-name##_SPLAY_REMOVE(struct name *head, struct type *elm) \
-{ \
- struct type *__tmp; \
- if (SPLAY_EMPTY(head)) \
- return (NULL); \
- name##_SPLAY(head, elm); \
- if ((cmp)(elm, (head)->sph_root) == 0) { \
- if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \
- (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\
- } else { \
- __tmp = SPLAY_RIGHT((head)->sph_root, field); \
- (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\
- name##_SPLAY(head, elm); \
- SPLAY_RIGHT((head)->sph_root, field) = __tmp; \
- } \
- return (elm); \
- } \
- return (NULL); \
-} \
- \
-void \
-name##_SPLAY(struct name *head, struct type *elm) \
-{ \
- struct type __node, *__left, *__right, *__tmp; \
- int __comp; \
-\
- SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
- __left = __right = &__node; \
-\
- while ((__comp = (cmp)(elm, (head)->sph_root))) { \
- if (__comp < 0) { \
- __tmp = SPLAY_LEFT((head)->sph_root, field); \
- if (__tmp == NULL) \
- break; \
- if ((cmp)(elm, __tmp) < 0){ \
- SPLAY_ROTATE_RIGHT(head, __tmp, field); \
- if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
- break; \
- } \
- SPLAY_LINKLEFT(head, __right, field); \
- } else if (__comp > 0) { \
- __tmp = SPLAY_RIGHT((head)->sph_root, field); \
- if (__tmp == NULL) \
- break; \
- if ((cmp)(elm, __tmp) > 0){ \
- SPLAY_ROTATE_LEFT(head, __tmp, field); \
- if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
- break; \
- } \
- SPLAY_LINKRIGHT(head, __left, field); \
- } \
- } \
- SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
-} \
- \
-/* Splay with either the minimum or the maximum element \
- * Used to find minimum or maximum element in tree. \
- */ \
-void name##_SPLAY_MINMAX(struct name *head, int __comp) \
-{ \
- struct type __node, *__left, *__right, *__tmp; \
-\
- SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
- __left = __right = &__node; \
-\
- while (1) { \
- if (__comp < 0) { \
- __tmp = SPLAY_LEFT((head)->sph_root, field); \
- if (__tmp == NULL) \
- break; \
- if (__comp < 0){ \
- SPLAY_ROTATE_RIGHT(head, __tmp, field); \
- if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
- break; \
- } \
- SPLAY_LINKLEFT(head, __right, field); \
- } else if (__comp > 0) { \
- __tmp = SPLAY_RIGHT((head)->sph_root, field); \
- if (__tmp == NULL) \
- break; \
- if (__comp > 0) { \
- SPLAY_ROTATE_LEFT(head, __tmp, field); \
- if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
- break; \
- } \
- SPLAY_LINKRIGHT(head, __left, field); \
- } \
- } \
- SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
-}
-
-#define SPLAY_NEGINF -1
-#define SPLAY_INF 1
-
-#define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y)
-#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y)
-#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y)
-#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y)
-#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \
- : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF))
-#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \
- : name##_SPLAY_MIN_MAX(x, SPLAY_INF))
-
-#define SPLAY_FOREACH(x, name, head) \
- for ((x) = SPLAY_MIN(name, head); \
- (x) != NULL; \
- (x) = SPLAY_NEXT(name, head, x))
-
-/* Macros that define a red-back tree */
-#define RB_HEAD(name, type) \
-struct name { \
- struct type *rbh_root; /* root of the tree */ \
-}
-
-#define RB_INITIALIZER(root) \
- { NULL }
-
-#define RB_INIT(root) do { \
- (root)->rbh_root = NULL; \
-} while (0)
-
-#define RB_BLACK 0
-#define RB_RED 1
-#define RB_ENTRY(type) \
-struct { \
- struct type *rbe_left; /* left element */ \
- struct type *rbe_right; /* right element */ \
- struct type *rbe_parent; /* parent element */ \
- int rbe_color; /* node color */ \
-}
-
-#define RB_LEFT(elm, field) (elm)->field.rbe_left
-#define RB_RIGHT(elm, field) (elm)->field.rbe_right
-#define RB_PARENT(elm, field) (elm)->field.rbe_parent
-#define RB_COLOR(elm, field) (elm)->field.rbe_color
-#define RB_ROOT(head) (head)->rbh_root
-#define RB_EMPTY(head) (RB_ROOT(head) == NULL)
-
-#define RB_SET(elm, parent, field) do { \
- RB_PARENT(elm, field) = parent; \
- RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \
- RB_COLOR(elm, field) = RB_RED; \
-} while (0)
-
-#define RB_SET_BLACKRED(black, red, field) do { \
- RB_COLOR(black, field) = RB_BLACK; \
- RB_COLOR(red, field) = RB_RED; \
-} while (0)
-
-#ifndef RB_AUGMENT
-#define RB_AUGMENT(x)
-#endif
-
-#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \
- (tmp) = RB_RIGHT(elm, field); \
- if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field))) { \
- RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \
- } \
- RB_AUGMENT(elm); \
- if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \
- if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
- RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
- else \
- RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
- } else \
- (head)->rbh_root = (tmp); \
- RB_LEFT(tmp, field) = (elm); \
- RB_PARENT(elm, field) = (tmp); \
- RB_AUGMENT(tmp); \
- if ((RB_PARENT(tmp, field))) \
- RB_AUGMENT(RB_PARENT(tmp, field)); \
-} while (0)
-
-#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \
- (tmp) = RB_LEFT(elm, field); \
- if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field))) { \
- RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \
- } \
- RB_AUGMENT(elm); \
- if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \
- if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
- RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
- else \
- RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
- } else \
- (head)->rbh_root = (tmp); \
- RB_RIGHT(tmp, field) = (elm); \
- RB_PARENT(elm, field) = (tmp); \
- RB_AUGMENT(tmp); \
- if ((RB_PARENT(tmp, field))) \
- RB_AUGMENT(RB_PARENT(tmp, field)); \
-} while (0)
-
-/* Generates prototypes and inline functions */
-#define RB_PROTOTYPE(name, type, field, cmp) \
-void name##_RB_INSERT_COLOR(struct name *, struct type *); \
-void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\
-struct type *name##_RB_REMOVE(struct name *, struct type *); \
-struct type *name##_RB_INSERT(struct name *, struct type *); \
-struct type *name##_RB_FIND(struct name *, struct type *); \
-struct type *name##_RB_NEXT(struct type *); \
-struct type *name##_RB_MINMAX(struct name *, int); \
- \
-
-/* Main rb operation.
- * Moves node close to the key of elm to top
- */
-#define RB_GENERATE(name, type, field, cmp) \
-void \
-name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
-{ \
- struct type *parent, *gparent, *tmp; \
- while ((parent = RB_PARENT(elm, field)) && \
- RB_COLOR(parent, field) == RB_RED) { \
- gparent = RB_PARENT(parent, field); \
- if (parent == RB_LEFT(gparent, field)) { \
- tmp = RB_RIGHT(gparent, field); \
- if (tmp && RB_COLOR(tmp, field) == RB_RED) { \
- RB_COLOR(tmp, field) = RB_BLACK; \
- RB_SET_BLACKRED(parent, gparent, field);\
- elm = gparent; \
- continue; \
- } \
- if (RB_RIGHT(parent, field) == elm) { \
- RB_ROTATE_LEFT(head, parent, tmp, field);\
- tmp = parent; \
- parent = elm; \
- elm = tmp; \
- } \
- RB_SET_BLACKRED(parent, gparent, field); \
- RB_ROTATE_RIGHT(head, gparent, tmp, field); \
- } else { \
- tmp = RB_LEFT(gparent, field); \
- if (tmp && RB_COLOR(tmp, field) == RB_RED) { \
- RB_COLOR(tmp, field) = RB_BLACK; \
- RB_SET_BLACKRED(parent, gparent, field);\
- elm = gparent; \
- continue; \
- } \
- if (RB_LEFT(parent, field) == elm) { \
- RB_ROTATE_RIGHT(head, parent, tmp, field);\
- tmp = parent; \
- parent = elm; \
- elm = tmp; \
- } \
- RB_SET_BLACKRED(parent, gparent, field); \
- RB_ROTATE_LEFT(head, gparent, tmp, field); \
- } \
- } \
- RB_COLOR(head->rbh_root, field) = RB_BLACK; \
-} \
- \
-void \
-name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \
-{ \
- struct type *tmp; \
- while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \
- elm != RB_ROOT(head)) { \
- if (RB_LEFT(parent, field) == elm) { \
- tmp = RB_RIGHT(parent, field); \
- if (RB_COLOR(tmp, field) == RB_RED) { \
- RB_SET_BLACKRED(tmp, parent, field); \
- RB_ROTATE_LEFT(head, parent, tmp, field);\
- tmp = RB_RIGHT(parent, field); \
- } \
- if ((RB_LEFT(tmp, field) == NULL || \
- RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
- (RB_RIGHT(tmp, field) == NULL || \
- RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
- RB_COLOR(tmp, field) = RB_RED; \
- elm = parent; \
- parent = RB_PARENT(elm, field); \
- } else { \
- if (RB_RIGHT(tmp, field) == NULL || \
- RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\
- struct type *oleft; \
- if ((oleft = RB_LEFT(tmp, field)))\
- RB_COLOR(oleft, field) = RB_BLACK;\
- RB_COLOR(tmp, field) = RB_RED; \
- RB_ROTATE_RIGHT(head, tmp, oleft, field);\
- tmp = RB_RIGHT(parent, field); \
- } \
- RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
- RB_COLOR(parent, field) = RB_BLACK; \
- if (RB_RIGHT(tmp, field)) \
- RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\
- RB_ROTATE_LEFT(head, parent, tmp, field);\
- elm = RB_ROOT(head); \
- break; \
- } \
- } else { \
- tmp = RB_LEFT(parent, field); \
- if (RB_COLOR(tmp, field) == RB_RED) { \
- RB_SET_BLACKRED(tmp, parent, field); \
- RB_ROTATE_RIGHT(head, parent, tmp, field);\
- tmp = RB_LEFT(parent, field); \
- } \
- if ((RB_LEFT(tmp, field) == NULL || \
- RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
- (RB_RIGHT(tmp, field) == NULL || \
- RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
- RB_COLOR(tmp, field) = RB_RED; \
- elm = parent; \
- parent = RB_PARENT(elm, field); \
- } else { \
- if (RB_LEFT(tmp, field) == NULL || \
- RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\
- struct type *oright; \
- if ((oright = RB_RIGHT(tmp, field)))\
- RB_COLOR(oright, field) = RB_BLACK;\
- RB_COLOR(tmp, field) = RB_RED; \
- RB_ROTATE_LEFT(head, tmp, oright, field);\
- tmp = RB_LEFT(parent, field); \
- } \
- RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
- RB_COLOR(parent, field) = RB_BLACK; \
- if (RB_LEFT(tmp, field)) \
- RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\
- RB_ROTATE_RIGHT(head, parent, tmp, field);\
- elm = RB_ROOT(head); \
- break; \
- } \
- } \
- } \
- if (elm) \
- RB_COLOR(elm, field) = RB_BLACK; \
-} \
- \
-struct type * \
-name##_RB_REMOVE(struct name *head, struct type *elm) \
-{ \
- struct type *child, *parent, *old = elm; \
- int color; \
- if (RB_LEFT(elm, field) == NULL) \
- child = RB_RIGHT(elm, field); \
- else if (RB_RIGHT(elm, field) == NULL) \
- child = RB_LEFT(elm, field); \
- else { \
- struct type *left; \
- elm = RB_RIGHT(elm, field); \
- while ((left = RB_LEFT(elm, field))) \
- elm = left; \
- child = RB_RIGHT(elm, field); \
- parent = RB_PARENT(elm, field); \
- color = RB_COLOR(elm, field); \
- if (child) \
- RB_PARENT(child, field) = parent; \
- if (parent) { \
- if (RB_LEFT(parent, field) == elm) \
- RB_LEFT(parent, field) = child; \
- else \
- RB_RIGHT(parent, field) = child; \
- RB_AUGMENT(parent); \
- } else \
- RB_ROOT(head) = child; \
- if (RB_PARENT(elm, field) == old) \
- parent = elm; \
- (elm)->field = (old)->field; \
- if (RB_PARENT(old, field)) { \
- if (RB_LEFT(RB_PARENT(old, field), field) == old)\
- RB_LEFT(RB_PARENT(old, field), field) = elm;\
- else \
- RB_RIGHT(RB_PARENT(old, field), field) = elm;\
- RB_AUGMENT(RB_PARENT(old, field)); \
- } else \
- RB_ROOT(head) = elm; \
- RB_PARENT(RB_LEFT(old, field), field) = elm; \
- if (RB_RIGHT(old, field)) \
- RB_PARENT(RB_RIGHT(old, field), field) = elm; \
- if (parent) { \
- left = parent; \
- do { \
- RB_AUGMENT(left); \
- } while ((left = RB_PARENT(left, field))); \
- } \
- goto color; \
- } \
- parent = RB_PARENT(elm, field); \
- color = RB_COLOR(elm, field); \
- if (child) \
- RB_PARENT(child, field) = parent; \
- if (parent) { \
- if (RB_LEFT(parent, field) == elm) \
- RB_LEFT(parent, field) = child; \
- else \
- RB_RIGHT(parent, field) = child; \
- RB_AUGMENT(parent); \
- } else \
- RB_ROOT(head) = child; \
-color: \
- if (color == RB_BLACK) \
- name##_RB_REMOVE_COLOR(head, parent, child); \
- return (old); \
-} \
- \
-/* Inserts a node into the RB tree */ \
-struct type * \
-name##_RB_INSERT(struct name *head, struct type *elm) \
-{ \
- struct type *tmp; \
- struct type *parent = NULL; \
- int comp = 0; \
- tmp = RB_ROOT(head); \
- while (tmp) { \
- parent = tmp; \
- comp = (cmp)(elm, parent); \
- if (comp < 0) \
- tmp = RB_LEFT(tmp, field); \
- else if (comp > 0) \
- tmp = RB_RIGHT(tmp, field); \
- else \
- return (tmp); \
- } \
- RB_SET(elm, parent, field); \
- if (parent != NULL) { \
- if (comp < 0) \
- RB_LEFT(parent, field) = elm; \
- else \
- RB_RIGHT(parent, field) = elm; \
- RB_AUGMENT(parent); \
- } else \
- RB_ROOT(head) = elm; \
- name##_RB_INSERT_COLOR(head, elm); \
- return (NULL); \
-} \
- \
-/* Finds the node with the same key as elm */ \
-struct type * \
-name##_RB_FIND(struct name *head, struct type *elm) \
-{ \
- struct type *tmp = RB_ROOT(head); \
- int comp; \
- while (tmp) { \
- comp = cmp(elm, tmp); \
- if (comp < 0) \
- tmp = RB_LEFT(tmp, field); \
- else if (comp > 0) \
- tmp = RB_RIGHT(tmp, field); \
- else \
- return (tmp); \
- } \
- return (NULL); \
-} \
- \
-struct type * \
-name##_RB_NEXT(struct type *elm) \
-{ \
- if (RB_RIGHT(elm, field)) { \
- elm = RB_RIGHT(elm, field); \
- while (RB_LEFT(elm, field)) \
- elm = RB_LEFT(elm, field); \
- } else { \
- if (RB_PARENT(elm, field) && \
- (elm == RB_LEFT(RB_PARENT(elm, field), field))) \
- elm = RB_PARENT(elm, field); \
- else { \
- while (RB_PARENT(elm, field) && \
- (elm == RB_RIGHT(RB_PARENT(elm, field), field)))\
- elm = RB_PARENT(elm, field); \
- elm = RB_PARENT(elm, field); \
- } \
- } \
- return (elm); \
-} \
- \
-struct type * \
-name##_RB_MINMAX(struct name *head, int val) \
-{ \
- struct type *tmp = RB_ROOT(head); \
- struct type *parent = NULL; \
- while (tmp) { \
- parent = tmp; \
- if (val < 0) \
- tmp = RB_LEFT(tmp, field); \
- else \
- tmp = RB_RIGHT(tmp, field); \
- } \
- return (parent); \
-}
-
-#define RB_NEGINF -1
-#define RB_INF 1
-
-#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y)
-#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y)
-#define RB_FIND(name, x, y) name##_RB_FIND(x, y)
-#define RB_NEXT(name, x, y) name##_RB_NEXT(y)
-#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF)
-#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF)
-
-#define RB_FOREACH(x, name, head) \
- for ((x) = RB_MIN(name, head); \
- (x) != NULL; \
- (x) = name##_RB_NEXT(x))
-
-#endif /* _SYS_TREE_H_ */
-/* $OpenBSD: tree.h,v 1.7 2002/10/17 21:51:54 art Exp $ */
-/*
- * Copyright 2002 Niels Provos <provos@citi.umich.edu>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef _SYS_TREE_H_
-#define _SYS_TREE_H_
-
-/*
- * This file defines data structures for different types of trees:
- * splay trees and red-black trees.
- *
- * A splay tree is a self-organizing data structure. Every operation
- * on the tree causes a splay to happen. The splay moves the requested
- * node to the root of the tree and partly rebalances it.
- *
- * This has the benefit that request locality causes faster lookups as
- * the requested nodes move to the top of the tree. On the other hand,
- * every lookup causes memory writes.
- *
- * The Balance Theorem bounds the total access time for m operations
- * and n inserts on an initially empty tree as O((m + n)lg n). The
- * amortized cost for a sequence of m accesses to a splay tree is O(lg n);
- *
- * A red-black tree is a binary search tree with the node color as an
- * extra attribute. It fulfills a set of conditions:
- * - every search path from the root to a leaf consists of the
- * same number of black nodes,
- * - each red node (except for the root) has a black parent,
- * - each leaf node is black.
- *
- * Every operation on a red-black tree is bounded as O(lg n).
- * The maximum height of a red-black tree is 2lg (n+1).
- */
-
-#define SPLAY_HEAD(name, type) \
-struct name { \
- struct type *sph_root; /* root of the tree */ \
-}
-
-#define SPLAY_INITIALIZER(root) \
- { NULL }
-
-#define SPLAY_INIT(root) do { \
- (root)->sph_root = NULL; \
-} while (0)
-
-#define SPLAY_ENTRY(type) \
-struct { \
- struct type *spe_left; /* left element */ \
- struct type *spe_right; /* right element */ \
-}
-
-#define SPLAY_LEFT(elm, field) (elm)->field.spe_left
-#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right
-#define SPLAY_ROOT(head) (head)->sph_root
-#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL)
-
-/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */
-#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \
- SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \
- SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
- (head)->sph_root = tmp; \
-} while (0)
-
-#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \
- SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \
- SPLAY_LEFT(tmp, field) = (head)->sph_root; \
- (head)->sph_root = tmp; \
-} while (0)
-
-#define SPLAY_LINKLEFT(head, tmp, field) do { \
- SPLAY_LEFT(tmp, field) = (head)->sph_root; \
- tmp = (head)->sph_root; \
- (head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \
-} while (0)
-
-#define SPLAY_LINKRIGHT(head, tmp, field) do { \
- SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
- tmp = (head)->sph_root; \
- (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \
-} while (0)
-
-#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \
- SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \
- SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\
- SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \
- SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \
-} while (0)
-
-/* Generates prototypes and inline functions */
-
-#define SPLAY_PROTOTYPE(name, type, field, cmp) \
-void name##_SPLAY(struct name *, struct type *); \
-void name##_SPLAY_MINMAX(struct name *, int); \
-struct type *name##_SPLAY_INSERT(struct name *, struct type *); \
-struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \
- \
-/* Finds the node with the same key as elm */ \
-static __inline struct type * \
-name##_SPLAY_FIND(struct name *head, struct type *elm) \
-{ \
- if (SPLAY_EMPTY(head)) \
- return(NULL); \
- name##_SPLAY(head, elm); \
- if ((cmp)(elm, (head)->sph_root) == 0) \
- return (head->sph_root); \
- return (NULL); \
-} \
- \
-static __inline struct type * \
-name##_SPLAY_NEXT(struct name *head, struct type *elm) \
-{ \
- name##_SPLAY(head, elm); \
- if (SPLAY_RIGHT(elm, field) != NULL) { \
- elm = SPLAY_RIGHT(elm, field); \
- while (SPLAY_LEFT(elm, field) != NULL) { \
- elm = SPLAY_LEFT(elm, field); \
- } \
- } else \
- elm = NULL; \
- return (elm); \
-} \
- \
-static __inline struct type * \
-name##_SPLAY_MIN_MAX(struct name *head, int val) \
-{ \
- name##_SPLAY_MINMAX(head, val); \
- return (SPLAY_ROOT(head)); \
-}
-
-/* Main splay operation.
- * Moves node close to the key of elm to top
- */
-#define SPLAY_GENERATE(name, type, field, cmp) \
-struct type * \
-name##_SPLAY_INSERT(struct name *head, struct type *elm) \
-{ \
- if (SPLAY_EMPTY(head)) { \
- SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \
- } else { \
- int __comp; \
- name##_SPLAY(head, elm); \
- __comp = (cmp)(elm, (head)->sph_root); \
- if(__comp < 0) { \
- SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\
- SPLAY_RIGHT(elm, field) = (head)->sph_root; \
- SPLAY_LEFT((head)->sph_root, field) = NULL; \
- } else if (__comp > 0) { \
- SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\
- SPLAY_LEFT(elm, field) = (head)->sph_root; \
- SPLAY_RIGHT((head)->sph_root, field) = NULL; \
- } else \
- return ((head)->sph_root); \
- } \
- (head)->sph_root = (elm); \
- return (NULL); \
-} \
- \
-struct type * \
-name##_SPLAY_REMOVE(struct name *head, struct type *elm) \
-{ \
- struct type *__tmp; \
- if (SPLAY_EMPTY(head)) \
- return (NULL); \
- name##_SPLAY(head, elm); \
- if ((cmp)(elm, (head)->sph_root) == 0) { \
- if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \
- (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\
- } else { \
- __tmp = SPLAY_RIGHT((head)->sph_root, field); \
- (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\
- name##_SPLAY(head, elm); \
- SPLAY_RIGHT((head)->sph_root, field) = __tmp; \
- } \
- return (elm); \
- } \
- return (NULL); \
-} \
- \
-void \
-name##_SPLAY(struct name *head, struct type *elm) \
-{ \
- struct type __node, *__left, *__right, *__tmp; \
- int __comp; \
-\
- SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
- __left = __right = &__node; \
-\
- while ((__comp = (cmp)(elm, (head)->sph_root))) { \
- if (__comp < 0) { \
- __tmp = SPLAY_LEFT((head)->sph_root, field); \
- if (__tmp == NULL) \
- break; \
- if ((cmp)(elm, __tmp) < 0){ \
- SPLAY_ROTATE_RIGHT(head, __tmp, field); \
- if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
- break; \
- } \
- SPLAY_LINKLEFT(head, __right, field); \
- } else if (__comp > 0) { \
- __tmp = SPLAY_RIGHT((head)->sph_root, field); \
- if (__tmp == NULL) \
- break; \
- if ((cmp)(elm, __tmp) > 0){ \
- SPLAY_ROTATE_LEFT(head, __tmp, field); \
- if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
- break; \
- } \
- SPLAY_LINKRIGHT(head, __left, field); \
- } \
- } \
- SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
-} \
- \
-/* Splay with either the minimum or the maximum element \
- * Used to find minimum or maximum element in tree. \
- */ \
-void name##_SPLAY_MINMAX(struct name *head, int __comp) \
-{ \
- struct type __node, *__left, *__right, *__tmp; \
-\
- SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
- __left = __right = &__node; \
-\
- while (1) { \
- if (__comp < 0) { \
- __tmp = SPLAY_LEFT((head)->sph_root, field); \
- if (__tmp == NULL) \
- break; \
- if (__comp < 0){ \
- SPLAY_ROTATE_RIGHT(head, __tmp, field); \
- if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
- break; \
- } \
- SPLAY_LINKLEFT(head, __right, field); \
- } else if (__comp > 0) { \
- __tmp = SPLAY_RIGHT((head)->sph_root, field); \
- if (__tmp == NULL) \
- break; \
- if (__comp > 0) { \
- SPLAY_ROTATE_LEFT(head, __tmp, field); \
- if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
- break; \
- } \
- SPLAY_LINKRIGHT(head, __left, field); \
- } \
- } \
- SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
-}
-
-#define SPLAY_NEGINF -1
-#define SPLAY_INF 1
-
-#define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y)
-#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y)
-#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y)
-#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y)
-#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \
- : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF))
-#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \
- : name##_SPLAY_MIN_MAX(x, SPLAY_INF))
-
-#define SPLAY_FOREACH(x, name, head) \
- for ((x) = SPLAY_MIN(name, head); \
- (x) != NULL; \
- (x) = SPLAY_NEXT(name, head, x))
-
-/* Macros that define a red-back tree */
-#define RB_HEAD(name, type) \
-struct name { \
- struct type *rbh_root; /* root of the tree */ \
-}
-
-#define RB_INITIALIZER(root) \
- { NULL }
-
-#define RB_INIT(root) do { \
- (root)->rbh_root = NULL; \
-} while (0)
-
-#define RB_BLACK 0
-#define RB_RED 1
-#define RB_ENTRY(type) \
-struct { \
- struct type *rbe_left; /* left element */ \
- struct type *rbe_right; /* right element */ \
- struct type *rbe_parent; /* parent element */ \
- int rbe_color; /* node color */ \
-}
-
-#define RB_LEFT(elm, field) (elm)->field.rbe_left
-#define RB_RIGHT(elm, field) (elm)->field.rbe_right
-#define RB_PARENT(elm, field) (elm)->field.rbe_parent
-#define RB_COLOR(elm, field) (elm)->field.rbe_color
-#define RB_ROOT(head) (head)->rbh_root
-#define RB_EMPTY(head) (RB_ROOT(head) == NULL)
-
-#define RB_SET(elm, parent, field) do { \
- RB_PARENT(elm, field) = parent; \
- RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \
- RB_COLOR(elm, field) = RB_RED; \
-} while (0)
-
-#define RB_SET_BLACKRED(black, red, field) do { \
- RB_COLOR(black, field) = RB_BLACK; \
- RB_COLOR(red, field) = RB_RED; \
-} while (0)
-
-#ifndef RB_AUGMENT
-#define RB_AUGMENT(x)
-#endif
-
-#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \
- (tmp) = RB_RIGHT(elm, field); \
- if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field))) { \
- RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \
- } \
- RB_AUGMENT(elm); \
- if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \
- if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
- RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
- else \
- RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
- } else \
- (head)->rbh_root = (tmp); \
- RB_LEFT(tmp, field) = (elm); \
- RB_PARENT(elm, field) = (tmp); \
- RB_AUGMENT(tmp); \
- if ((RB_PARENT(tmp, field))) \
- RB_AUGMENT(RB_PARENT(tmp, field)); \
-} while (0)
-
-#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \
- (tmp) = RB_LEFT(elm, field); \
- if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field))) { \
- RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \
- } \
- RB_AUGMENT(elm); \
- if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \
- if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
- RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
- else \
- RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
- } else \
- (head)->rbh_root = (tmp); \
- RB_RIGHT(tmp, field) = (elm); \
- RB_PARENT(elm, field) = (tmp); \
- RB_AUGMENT(tmp); \
- if ((RB_PARENT(tmp, field))) \
- RB_AUGMENT(RB_PARENT(tmp, field)); \
-} while (0)
-
-/* Generates prototypes and inline functions */
-#define RB_PROTOTYPE(name, type, field, cmp) \
-void name##_RB_INSERT_COLOR(struct name *, struct type *); \
-void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\
-struct type *name##_RB_REMOVE(struct name *, struct type *); \
-struct type *name##_RB_INSERT(struct name *, struct type *); \
-struct type *name##_RB_FIND(struct name *, struct type *); \
-struct type *name##_RB_NEXT(struct type *); \
-struct type *name##_RB_MINMAX(struct name *, int); \
- \
-
-/* Main rb operation.
- * Moves node close to the key of elm to top
- */
-#define RB_GENERATE(name, type, field, cmp) \
-void \
-name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
-{ \
- struct type *parent, *gparent, *tmp; \
- while ((parent = RB_PARENT(elm, field)) && \
- RB_COLOR(parent, field) == RB_RED) { \
- gparent = RB_PARENT(parent, field); \
- if (parent == RB_LEFT(gparent, field)) { \
- tmp = RB_RIGHT(gparent, field); \
- if (tmp && RB_COLOR(tmp, field) == RB_RED) { \
- RB_COLOR(tmp, field) = RB_BLACK; \
- RB_SET_BLACKRED(parent, gparent, field);\
- elm = gparent; \
- continue; \
- } \
- if (RB_RIGHT(parent, field) == elm) { \
- RB_ROTATE_LEFT(head, parent, tmp, field);\
- tmp = parent; \
- parent = elm; \
- elm = tmp; \
- } \
- RB_SET_BLACKRED(parent, gparent, field); \
- RB_ROTATE_RIGHT(head, gparent, tmp, field); \
- } else { \
- tmp = RB_LEFT(gparent, field); \
- if (tmp && RB_COLOR(tmp, field) == RB_RED) { \
- RB_COLOR(tmp, field) = RB_BLACK; \
- RB_SET_BLACKRED(parent, gparent, field);\
- elm = gparent; \
- continue; \
- } \
- if (RB_LEFT(parent, field) == elm) { \
- RB_ROTATE_RIGHT(head, parent, tmp, field);\
- tmp = parent; \
- parent = elm; \
- elm = tmp; \
- } \
- RB_SET_BLACKRED(parent, gparent, field); \
- RB_ROTATE_LEFT(head, gparent, tmp, field); \
- } \
- } \
- RB_COLOR(head->rbh_root, field) = RB_BLACK; \
-} \
- \
-void \
-name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \
-{ \
- struct type *tmp; \
- while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \
- elm != RB_ROOT(head)) { \
- if (RB_LEFT(parent, field) == elm) { \
- tmp = RB_RIGHT(parent, field); \
- if (RB_COLOR(tmp, field) == RB_RED) { \
- RB_SET_BLACKRED(tmp, parent, field); \
- RB_ROTATE_LEFT(head, parent, tmp, field);\
- tmp = RB_RIGHT(parent, field); \
- } \
- if ((RB_LEFT(tmp, field) == NULL || \
- RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
- (RB_RIGHT(tmp, field) == NULL || \
- RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
- RB_COLOR(tmp, field) = RB_RED; \
- elm = parent; \
- parent = RB_PARENT(elm, field); \
- } else { \
- if (RB_RIGHT(tmp, field) == NULL || \
- RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\
- struct type *oleft; \
- if ((oleft = RB_LEFT(tmp, field)))\
- RB_COLOR(oleft, field) = RB_BLACK;\
- RB_COLOR(tmp, field) = RB_RED; \
- RB_ROTATE_RIGHT(head, tmp, oleft, field);\
- tmp = RB_RIGHT(parent, field); \
- } \
- RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
- RB_COLOR(parent, field) = RB_BLACK; \
- if (RB_RIGHT(tmp, field)) \
- RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\
- RB_ROTATE_LEFT(head, parent, tmp, field);\
- elm = RB_ROOT(head); \
- break; \
- } \
- } else { \
- tmp = RB_LEFT(parent, field); \
- if (RB_COLOR(tmp, field) == RB_RED) { \
- RB_SET_BLACKRED(tmp, parent, field); \
- RB_ROTATE_RIGHT(head, parent, tmp, field);\
- tmp = RB_LEFT(parent, field); \
- } \
- if ((RB_LEFT(tmp, field) == NULL || \
- RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
- (RB_RIGHT(tmp, field) == NULL || \
- RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
- RB_COLOR(tmp, field) = RB_RED; \
- elm = parent; \
- parent = RB_PARENT(elm, field); \
- } else { \
- if (RB_LEFT(tmp, field) == NULL || \
- RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\
- struct type *oright; \
- if ((oright = RB_RIGHT(tmp, field)))\
- RB_COLOR(oright, field) = RB_BLACK;\
- RB_COLOR(tmp, field) = RB_RED; \
- RB_ROTATE_LEFT(head, tmp, oright, field);\
- tmp = RB_LEFT(parent, field); \
- } \
- RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
- RB_COLOR(parent, field) = RB_BLACK; \
- if (RB_LEFT(tmp, field)) \
- RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\
- RB_ROTATE_RIGHT(head, parent, tmp, field);\
- elm = RB_ROOT(head); \
- break; \
- } \
- } \
- } \
- if (elm) \
- RB_COLOR(elm, field) = RB_BLACK; \
-} \
- \
-struct type * \
-name##_RB_REMOVE(struct name *head, struct type *elm) \
-{ \
- struct type *child, *parent, *old = elm; \
- int color; \
- if (RB_LEFT(elm, field) == NULL) \
- child = RB_RIGHT(elm, field); \
- else if (RB_RIGHT(elm, field) == NULL) \
- child = RB_LEFT(elm, field); \
- else { \
- struct type *left; \
- elm = RB_RIGHT(elm, field); \
- while ((left = RB_LEFT(elm, field))) \
- elm = left; \
- child = RB_RIGHT(elm, field); \
- parent = RB_PARENT(elm, field); \
- color = RB_COLOR(elm, field); \
- if (child) \
- RB_PARENT(child, field) = parent; \
- if (parent) { \
- if (RB_LEFT(parent, field) == elm) \
- RB_LEFT(parent, field) = child; \
- else \
- RB_RIGHT(parent, field) = child; \
- RB_AUGMENT(parent); \
- } else \
- RB_ROOT(head) = child; \
- if (RB_PARENT(elm, field) == old) \
- parent = elm; \
- (elm)->field = (old)->field; \
- if (RB_PARENT(old, field)) { \
- if (RB_LEFT(RB_PARENT(old, field), field) == old)\
- RB_LEFT(RB_PARENT(old, field), field) = elm;\
- else \
- RB_RIGHT(RB_PARENT(old, field), field) = elm;\
- RB_AUGMENT(RB_PARENT(old, field)); \
- } else \
- RB_ROOT(head) = elm; \
- RB_PARENT(RB_LEFT(old, field), field) = elm; \
- if (RB_RIGHT(old, field)) \
- RB_PARENT(RB_RIGHT(old, field), field) = elm; \
- if (parent) { \
- left = parent; \
- do { \
- RB_AUGMENT(left); \
- } while ((left = RB_PARENT(left, field))); \
- } \
- goto color; \
- } \
- parent = RB_PARENT(elm, field); \
- color = RB_COLOR(elm, field); \
- if (child) \
- RB_PARENT(child, field) = parent; \
- if (parent) { \
- if (RB_LEFT(parent, field) == elm) \
- RB_LEFT(parent, field) = child; \
- else \
- RB_RIGHT(parent, field) = child; \
- RB_AUGMENT(parent); \
- } else \
- RB_ROOT(head) = child; \
-color: \
- if (color == RB_BLACK) \
- name##_RB_REMOVE_COLOR(head, parent, child); \
- return (old); \
-} \
- \
-/* Inserts a node into the RB tree */ \
-struct type * \
-name##_RB_INSERT(struct name *head, struct type *elm) \
-{ \
- struct type *tmp; \
- struct type *parent = NULL; \
- int comp = 0; \
- tmp = RB_ROOT(head); \
- while (tmp) { \
- parent = tmp; \
- comp = (cmp)(elm, parent); \
- if (comp < 0) \
- tmp = RB_LEFT(tmp, field); \
- else if (comp > 0) \
- tmp = RB_RIGHT(tmp, field); \
- else \
- return (tmp); \
- } \
- RB_SET(elm, parent, field); \
- if (parent != NULL) { \
- if (comp < 0) \
- RB_LEFT(parent, field) = elm; \
- else \
- RB_RIGHT(parent, field) = elm; \
- RB_AUGMENT(parent); \
- } else \
- RB_ROOT(head) = elm; \
- name##_RB_INSERT_COLOR(head, elm); \
- return (NULL); \
-} \
- \
-/* Finds the node with the same key as elm */ \
-struct type * \
-name##_RB_FIND(struct name *head, struct type *elm) \
-{ \
- struct type *tmp = RB_ROOT(head); \
- int comp; \
- while (tmp) { \
- comp = cmp(elm, tmp); \
- if (comp < 0) \
- tmp = RB_LEFT(tmp, field); \
- else if (comp > 0) \
- tmp = RB_RIGHT(tmp, field); \
- else \
- return (tmp); \
- } \
- return (NULL); \
-} \
- \
-struct type * \
-name##_RB_NEXT(struct type *elm) \
-{ \
- if (RB_RIGHT(elm, field)) { \
- elm = RB_RIGHT(elm, field); \
- while (RB_LEFT(elm, field)) \
- elm = RB_LEFT(elm, field); \
- } else { \
- if (RB_PARENT(elm, field) && \
- (elm == RB_LEFT(RB_PARENT(elm, field), field))) \
- elm = RB_PARENT(elm, field); \
- else { \
- while (RB_PARENT(elm, field) && \
- (elm == RB_RIGHT(RB_PARENT(elm, field), field)))\
- elm = RB_PARENT(elm, field); \
- elm = RB_PARENT(elm, field); \
- } \
- } \
- return (elm); \
-} \
- \
-struct type * \
-name##_RB_MINMAX(struct name *head, int val) \
-{ \
- struct type *tmp = RB_ROOT(head); \
- struct type *parent = NULL; \
- while (tmp) { \
- parent = tmp; \
- if (val < 0) \
- tmp = RB_LEFT(tmp, field); \
- else \
- tmp = RB_RIGHT(tmp, field); \
- } \
- return (parent); \
-}
-
-#define RB_NEGINF -1
-#define RB_INF 1
-
-#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y)
-#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y)
-#define RB_FIND(name, x, y) name##_RB_FIND(x, y)
-#define RB_NEXT(name, x, y) name##_RB_NEXT(y)
-#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF)
-#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF)
-
-#define RB_FOREACH(x, name, head) \
- for ((x) = RB_MIN(name, head); \
- (x) != NULL; \
- (x) = name##_RB_NEXT(x))
-
-#endif /* _SYS_TREE_H_ */
diff --git a/extra/libevent/WIN32-Code/win32.c b/extra/libevent/WIN32-Code/win32.c
deleted file mode 100644
index 0d7dcfb276f..00000000000
--- a/extra/libevent/WIN32-Code/win32.c
+++ /dev/null
@@ -1,471 +0,0 @@
-/*
- * Copyright 2000-2002 Niels Provos <provos@citi.umich.edu>
- * Copyright 2003 Michael A. Davis <mike@datanerds.net>
- * 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 BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#ifdef _MSC_VER
-#include "./config.h"
-#else
-/* Avoid the windows/msvc thing. */
-#include "../config.h"
-#endif
-
-#include <winsock2.h>
-#include <windows.h>
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <assert.h>
-
-#define RB_AUGMENT(x) (void)(x)
-#include "./tree.h"
-#include "log.h"
-#include "event.h"
-#include "event-internal.h"
-
-#define XFREE(ptr) do { if (ptr) free(ptr); } while(0)
-
-extern struct event_list timequeue;
-extern struct event_list addqueue;
-#if 0
-extern struct event_list signalqueue;
-#endif
-
-struct win_fd_set {
- u_int fd_count;
- SOCKET fd_array[1];
-};
-
-int evsigcaught[NSIG];
-volatile sig_atomic_t signal_caught = 0;
-/* MSDN says this is required to handle SIGFPE */
-volatile double SIGFPE_REQ = 0.0f;
-
-#if 0
-static void signal_handler(int sig);
-
-void signal_process(void);
-int signal_recalc(void);
-#endif
-
-struct event_entry {
- RB_ENTRY(event_entry) node;
- SOCKET sock;
- int read_pos;
- int write_pos;
- struct event *read_event;
- struct event *write_event;
-};
-
-static int
-compare(struct event_entry *a, struct event_entry *b)
-{
- if (a->sock < b->sock)
- return -1;
- else if (a->sock > b->sock)
- return 1;
- else
- return 0;
-}
-
-struct win32op {
- int fd_setsz;
- struct win_fd_set *readset_in;
- struct win_fd_set *writeset_in;
- struct win_fd_set *readset_out;
- struct win_fd_set *writeset_out;
- struct win_fd_set *exset_out;
- RB_HEAD(event_map, event_entry) event_root;
-};
-
-RB_PROTOTYPE(event_map, event_entry, node, compare);
-RB_GENERATE(event_map, event_entry, node, compare);
-
-void *win32_init (struct event_base *);
-int win32_insert (void *, struct event *);
-int win32_del (void *, struct event *);
-int win32_dispatch (struct event_base *base, void *, struct timeval *);
-void win32_dealloc (struct event_base *, void *);
-
-struct eventop win32ops = {
- "win32",
- win32_init,
- win32_insert,
- win32_del,
- win32_dispatch,
- win32_dealloc,
- 0
-};
-
-#define FD_SET_ALLOC_SIZE(n) ((sizeof(struct win_fd_set) + ((n)-1)*sizeof(SOCKET)))
-
-static int
-realloc_fd_sets(struct win32op *op, size_t new_size)
-{
- size_t size;
-
- assert(new_size >= op->readset_in->fd_count &&
- new_size >= op->writeset_in->fd_count);
- assert(new_size >= 1);
-
- size = FD_SET_ALLOC_SIZE(new_size);
- if (!(op->readset_in = realloc(op->readset_in, size)))
- return (-1);
- if (!(op->writeset_in = realloc(op->writeset_in, size)))
- return (-1);
- if (!(op->readset_out = realloc(op->readset_out, size)))
- return (-1);
- if (!(op->exset_out = realloc(op->exset_out, size)))
- return (-1);
- if (!(op->writeset_out = realloc(op->writeset_out, size)))
- return (-1);
- op->fd_setsz = (int)new_size;
- return (0);
-}
-
-static int
-timeval_to_ms(struct timeval *tv)
-{
- return ((tv->tv_sec * 1000) + (tv->tv_usec / 1000));
-}
-
-static struct event_entry*
-get_event_entry(struct win32op *op, SOCKET s, int create)
-{
- struct event_entry key, *val;
- key.sock = s;
- val = RB_FIND(event_map, &op->event_root, &key);
- if (val || !create)
- return val;
- if (!(val = calloc(1, sizeof(struct event_entry)))) {
- event_warn("%s: calloc", __func__);
- return NULL;
- }
- val->sock = s;
- val->read_pos = val->write_pos = -1;
- RB_INSERT(event_map, &op->event_root, val);
- return val;
-}
-
-static int
-do_fd_set(struct win32op *op, struct event_entry *ent, int read)
-{
- SOCKET s = ent->sock;
- struct win_fd_set *set = read ? op->readset_in : op->writeset_in;
- if (read) {
- if (ent->read_pos >= 0)
- return (0);
- } else {
- if (ent->write_pos >= 0)
- return (0);
- }
- if (set->fd_count == op->fd_setsz) {
- if (realloc_fd_sets(op, op->fd_setsz*2))
- return (-1);
- /* set pointer will have changed and needs reiniting! */
- set = read ? op->readset_in : op->writeset_in;
- }
- set->fd_array[set->fd_count] = s;
- if (read)
- ent->read_pos = set->fd_count;
- else
- ent->write_pos = set->fd_count;
- return (set->fd_count++);
-}
-
-static int
-do_fd_clear(struct win32op *op, struct event_entry *ent, int read)
-{
- int i;
- struct win_fd_set *set = read ? op->readset_in : op->writeset_in;
- if (read) {
- i = ent->read_pos;
- ent->read_pos = -1;
- } else {
- i = ent->write_pos;
- ent->write_pos = -1;
- }
- if (i < 0)
- return (0);
- if (--set->fd_count != i) {
- struct event_entry *ent2;
- SOCKET s2;
- s2 = set->fd_array[i] = set->fd_array[set->fd_count];
- ent2 = get_event_entry(op, s2, 0);
- if (!ent) /* This indicates a bug. */
- return (0);
- if (read)
- ent2->read_pos = i;
- else
- ent2->write_pos = i;
- }
- return (0);
-}
-
-#define NEVENT 64
-void *
-win32_init(struct event_base *_base)
-{
- struct win32op *winop;
- size_t size;
- if (!(winop = calloc(1, sizeof(struct win32op))))
- return NULL;
- winop->fd_setsz = NEVENT;
- size = FD_SET_ALLOC_SIZE(NEVENT);
- if (!(winop->readset_in = malloc(size)))
- goto err;
- if (!(winop->writeset_in = malloc(size)))
- goto err;
- if (!(winop->readset_out = malloc(size)))
- goto err;
- if (!(winop->writeset_out = malloc(size)))
- goto err;
- if (!(winop->exset_out = malloc(size)))
- goto err;
- RB_INIT(&winop->event_root);
- winop->readset_in->fd_count = winop->writeset_in->fd_count = 0;
- winop->readset_out->fd_count = winop->writeset_out->fd_count
- = winop->exset_out->fd_count = 0;
-
- evsignal_init(_base);
-
- return (winop);
- err:
- XFREE(winop->readset_in);
- XFREE(winop->writeset_in);
- XFREE(winop->readset_out);
- XFREE(winop->writeset_out);
- XFREE(winop->exset_out);
- XFREE(winop);
- return (NULL);
-}
-
-int
-win32_insert(void *op, struct event *ev)
-{
- struct win32op *win32op = op;
- struct event_entry *ent;
-
- if (ev->ev_events & EV_SIGNAL) {
- return (evsignal_add(ev));
- }
- if (!(ev->ev_events & (EV_READ|EV_WRITE)))
- return (0);
- ent = get_event_entry(win32op, ev->ev_fd, 1);
- if (!ent)
- return (-1); /* out of memory */
-
- event_debug(("%s: adding event for %d", __func__, (int)ev->ev_fd));
- if (ev->ev_events & EV_READ) {
- if (do_fd_set(win32op, ent, 1)<0)
- return (-1);
- ent->read_event = ev;
- }
- if (ev->ev_events & EV_WRITE) {
- if (do_fd_set(win32op, ent, 0)<0)
- return (-1);
- ent->write_event = ev;
- }
- return (0);
-}
-
-int
-win32_del(void *op, struct event *ev)
-{
- struct win32op *win32op = op;
- struct event_entry *ent;
-
- if (ev->ev_events & EV_SIGNAL)
- return (evsignal_del(ev));
-
- if (!(ent = get_event_entry(win32op, ev->ev_fd, 0)))
- return (-1);
- event_debug(("%s: Removing event for %d", __func__, ev->ev_fd));
- if (ev == ent->read_event) {
- do_fd_clear(win32op, ent, 1);
- ent->read_event = NULL;
- }
- if (ev == ent->write_event) {
- do_fd_clear(win32op, ent, 0);
- ent->write_event = NULL;
- }
- if (!ent->read_event && !ent->write_event) {
- RB_REMOVE(event_map, &win32op->event_root, ent);
- free(ent);
- }
-
- return 0;
-}
-
-static void
-fd_set_copy(struct win_fd_set *out, const struct win_fd_set *in)
-{
- out->fd_count = in->fd_count;
- memcpy(out->fd_array, in->fd_array, in->fd_count * (sizeof(SOCKET)));
-}
-
-/*
- static void dump_fd_set(struct win_fd_set *s)
- {
- unsigned int i;
- printf("[ ");
- for(i=0;i<s->fd_count;++i)
- printf("%d ",(int)s->fd_array[i]);
- printf("]\n");
- }
-*/
-
-int
-win32_dispatch(struct event_base *base, void *op,
- struct timeval *tv)
-{
- struct win32op *win32op = op;
- int res = 0;
- u_int i;
- int fd_count;
-
- fd_set_copy(win32op->readset_out, win32op->readset_in);
- fd_set_copy(win32op->exset_out, win32op->readset_in);
- fd_set_copy(win32op->writeset_out, win32op->writeset_in);
-
- fd_count =
- (win32op->readset_out->fd_count > win32op->writeset_out->fd_count) ?
- win32op->readset_out->fd_count : win32op->writeset_out->fd_count;
-
- if (!fd_count) {
- /* Windows doesn't like you to call select() with no sockets */
- Sleep(timeval_to_ms(tv));
- evsignal_process(base);
- return (0);
- }
-
- res = select(fd_count,
- (struct fd_set*)win32op->readset_out,
- (struct fd_set*)win32op->writeset_out,
- (struct fd_set*)win32op->exset_out, tv);
-
- event_debug(("%s: select returned %d", __func__, res));
-
- if(res <= 0) {
- evsignal_process(base);
- return res;
- } else if (base->sig.evsignal_caught) {
- evsignal_process(base);
- }
-
- for (i=0; i<win32op->readset_out->fd_count; ++i) {
- struct event_entry *ent;
- SOCKET s = win32op->readset_out->fd_array[i];
- if ((ent = get_event_entry(win32op, s, 0)) && ent->read_event)
- event_active(ent->read_event, EV_READ, 1);
- }
- for (i=0; i<win32op->exset_out->fd_count; ++i) {
- struct event_entry *ent;
- SOCKET s = win32op->exset_out->fd_array[i];
- if ((ent = get_event_entry(win32op, s, 0)) && ent->read_event)
- event_active(ent->read_event, EV_READ, 1);
- }
- for (i=0; i<win32op->writeset_out->fd_count; ++i) {
- struct event_entry *ent;
- SOCKET s = win32op->writeset_out->fd_array[i];
- if ((ent = get_event_entry(win32op, s, 0)) && ent->write_event)
- event_active(ent->write_event, EV_WRITE, 1);
- }
-
-#if 0
- if (signal_recalc() == -1)
- return (-1);
-#endif
-
- return (0);
-}
-
-void
-win32_dealloc(struct event_base *_base, void *arg)
-{
- struct win32op *win32op = arg;
-
- evsignal_dealloc(_base);
- if (win32op->readset_in)
- free(win32op->readset_in);
- if (win32op->writeset_in)
- free(win32op->writeset_in);
- if (win32op->readset_out)
- free(win32op->readset_out);
- if (win32op->writeset_out)
- free(win32op->writeset_out);
- if (win32op->exset_out)
- free(win32op->exset_out);
- /* XXXXX free the tree. */
-
- memset(win32op, 0, sizeof(win32op));
- free(win32op);
-}
-
-#if 0
-static void
-signal_handler(int sig)
-{
- evsigcaught[sig]++;
- signal_caught = 1;
-}
-
-int
-signal_recalc(void)
-{
- struct event *ev;
-
- /* Reinstall our signal handler. */
- TAILQ_FOREACH(ev, &signalqueue, ev_signal_next) {
- if((int)signal(EVENT_SIGNAL(ev), signal_handler) == -1)
- return (-1);
- }
- return (0);
-}
-
-void
-signal_process(void)
-{
- struct event *ev;
- short ncalls;
-
- TAILQ_FOREACH(ev, &signalqueue, ev_signal_next) {
- ncalls = evsigcaught[EVENT_SIGNAL(ev)];
- if (ncalls) {
- if (!(ev->ev_events & EV_PERSIST))
- event_del(ev);
- event_active(ev, EV_SIGNAL, ncalls);
- }
- }
-
- memset(evsigcaught, 0, sizeof(evsigcaught));
- signal_caught = 0;
-}
-#endif
-
diff --git a/extra/libevent/buffer.c b/extra/libevent/buffer.c
deleted file mode 100644
index d3394dae470..00000000000
--- a/extra/libevent/buffer.c
+++ /dev/null
@@ -1,455 +0,0 @@
-/*
- * Copyright (c) 2002, 2003 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 BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef WIN32
-#include <winsock2.h>
-#include <windows.h>
-#endif
-
-#ifdef HAVE_VASPRINTF
-/* If we have vasprintf, we need to define this before we include stdio.h. */
-#define _GNU_SOURCE
-#endif
-
-#include <sys/types.h>
-
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#ifdef HAVE_STDARG_H
-#include <stdarg.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "event.h"
-#include "config.h"
-
-struct evbuffer *
-evbuffer_new(void)
-{
- struct evbuffer *buffer;
-
- buffer = calloc(1, sizeof(struct evbuffer));
-
- return (buffer);
-}
-
-void
-evbuffer_free(struct evbuffer *buffer)
-{
- if (buffer->orig_buffer != NULL)
- free(buffer->orig_buffer);
- free(buffer);
-}
-
-/*
- * This is a destructive add. The data from one buffer moves into
- * the other buffer.
- */
-
-#define SWAP(x,y) do { \
- (x)->buffer = (y)->buffer; \
- (x)->orig_buffer = (y)->orig_buffer; \
- (x)->misalign = (y)->misalign; \
- (x)->totallen = (y)->totallen; \
- (x)->off = (y)->off; \
-} while (0)
-
-int
-evbuffer_add_buffer(struct evbuffer *outbuf, struct evbuffer *inbuf)
-{
- int res;
-
- /* Short cut for better performance */
- if (outbuf->off == 0) {
- struct evbuffer tmp;
- size_t oldoff = inbuf->off;
-
- /* Swap them directly */
- SWAP(&tmp, outbuf);
- SWAP(outbuf, inbuf);
- SWAP(inbuf, &tmp);
-
- /*
- * Optimization comes with a price; we need to notify the
- * buffer if necessary of the changes. oldoff is the amount
- * of data that we transfered from inbuf to outbuf
- */
- if (inbuf->off != oldoff && inbuf->cb != NULL)
- (*inbuf->cb)(inbuf, oldoff, inbuf->off, inbuf->cbarg);
- if (oldoff && outbuf->cb != NULL)
- (*outbuf->cb)(outbuf, 0, oldoff, outbuf->cbarg);
-
- return (0);
- }
-
- res = evbuffer_add(outbuf, inbuf->buffer, inbuf->off);
- if (res == 0) {
- /* We drain the input buffer on success */
- evbuffer_drain(inbuf, inbuf->off);
- }
-
- return (res);
-}
-
-int
-evbuffer_add_vprintf(struct evbuffer *buf, const char *fmt, va_list ap)
-{
- char *buffer;
- size_t space;
- size_t oldoff = buf->off;
- int sz;
- va_list aq;
-
- /* make sure that at least some space is available */
- evbuffer_expand(buf, 64);
- for (;;) {
- size_t used = buf->misalign + buf->off;
- buffer = (char *)buf->buffer + buf->off;
- assert(buf->totallen >= used);
- space = buf->totallen - used;
-
-#ifndef va_copy
-#define va_copy(dst, src) memcpy(&(dst), &(src), sizeof(va_list))
-#endif
- va_copy(aq, ap);
-
-#ifdef WIN32
- sz = _vsnprintf(buffer, space - 1, fmt, aq);
- buffer[space - 1] = '\0';
-#else
- sz = vsnprintf(buffer, space, fmt, aq);
-#endif
-
- va_end(aq);
-
- if (sz < 0)
- return (-1);
- if ((size_t)sz < space) {
- buf->off += sz;
- if (buf->cb != NULL)
- (*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
- return (sz);
- }
- if (evbuffer_expand(buf, sz + 1) == -1)
- return (-1);
-
- }
- /* NOTREACHED */
-}
-
-int
-evbuffer_add_printf(struct evbuffer *buf, const char *fmt, ...)
-{
- int res = -1;
- va_list ap;
-
- va_start(ap, fmt);
- res = evbuffer_add_vprintf(buf, fmt, ap);
- va_end(ap);
-
- return (res);
-}
-
-/* Reads data from an event buffer and drains the bytes read */
-
-int
-evbuffer_remove(struct evbuffer *buf, void *data, size_t datlen)
-{
- size_t nread = datlen;
- if (nread >= buf->off)
- nread = buf->off;
-
- memcpy(data, buf->buffer, nread);
- evbuffer_drain(buf, nread);
-
- return (int)(nread);
-}
-
-/*
- * Reads a line terminated by either '\r\n', '\n\r' or '\r' or '\n'.
- * The returned buffer needs to be freed by the called.
- */
-
-char *
-evbuffer_readline(struct evbuffer *buffer)
-{
- u_char *data = EVBUFFER_DATA(buffer);
- size_t len = EVBUFFER_LENGTH(buffer);
- char *line;
- unsigned int i;
-
- for (i = 0; i < len; i++) {
- if (data[i] == '\r' || data[i] == '\n')
- break;
- }
-
- if (i == len)
- return (NULL);
-
- if ((line = malloc(i + 1)) == NULL) {
- fprintf(stderr, "%s: out of memory\n", __func__);
- evbuffer_drain(buffer, i);
- return (NULL);
- }
-
- memcpy(line, data, i);
- line[i] = '\0';
-
- /*
- * Some protocols terminate a line with '\r\n', so check for
- * that, too.
- */
- if ( i < len - 1 ) {
- char fch = data[i], sch = data[i+1];
-
- /* Drain one more character if needed */
- if ( (sch == '\r' || sch == '\n') && sch != fch )
- i += 1;
- }
-
- evbuffer_drain(buffer, i + 1);
-
- return (line);
-}
-
-/* Adds data to an event buffer */
-
-static void
-evbuffer_align(struct evbuffer *buf)
-{
- memmove(buf->orig_buffer, buf->buffer, buf->off);
- buf->buffer = buf->orig_buffer;
- buf->misalign = 0;
-}
-
-/* Expands the available space in the event buffer to at least datlen */
-
-int
-evbuffer_expand(struct evbuffer *buf, size_t datlen)
-{
- size_t need = buf->misalign + buf->off + datlen;
-
- /* If we can fit all the data, then we don't have to do anything */
- if (buf->totallen >= need)
- return (0);
-
- /*
- * If the misalignment fulfills our data needs, we just force an
- * alignment to happen. Afterwards, we have enough space.
- */
- if (buf->misalign >= datlen) {
- evbuffer_align(buf);
- } else {
- void *newbuf;
- size_t length = buf->totallen;
-
- if (length < 256)
- length = 256;
- while (length < need)
- length <<= 1;
-
- if (buf->orig_buffer != buf->buffer)
- evbuffer_align(buf);
- if ((newbuf = realloc(buf->buffer, length)) == NULL)
- return (-1);
-
- buf->orig_buffer = buf->buffer = newbuf;
- buf->totallen = length;
- }
-
- return (0);
-}
-
-int
-evbuffer_add(struct evbuffer *buf, const void *data, size_t datlen)
-{
- size_t need = buf->misalign + buf->off + datlen;
- size_t oldoff = buf->off;
-
- if (buf->totallen < need) {
- if (evbuffer_expand(buf, datlen) == -1)
- return (-1);
- }
-
- memcpy(buf->buffer + buf->off, data, datlen);
- buf->off += datlen;
-
- if (datlen && buf->cb != NULL)
- (*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
-
- return (0);
-}
-
-void
-evbuffer_drain(struct evbuffer *buf, size_t len)
-{
- size_t oldoff = buf->off;
-
- if (len >= buf->off) {
- buf->off = 0;
- buf->buffer = buf->orig_buffer;
- buf->misalign = 0;
- goto done;
- }
-
- buf->buffer += len;
- buf->misalign += len;
-
- buf->off -= len;
-
- done:
- /* Tell someone about changes in this buffer */
- if (buf->off != oldoff && buf->cb != NULL)
- (*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
-
-}
-
-/*
- * Reads data from a file descriptor into a buffer.
- */
-
-#define EVBUFFER_MAX_READ 4096
-
-int
-evbuffer_read(struct evbuffer *buf, int fd, int howmuch)
-{
- u_char *p;
- size_t oldoff = buf->off;
- int n = EVBUFFER_MAX_READ;
-
-#if defined(FIONREAD)
-#ifdef WIN32
- long lng = (long)n;
- if (ioctlsocket(fd, FIONREAD, &lng) == -1 || (n=lng) == 0) {
-#else
- if (ioctl(fd, FIONREAD, &n) == -1 || n == 0) {
-#endif
- n = EVBUFFER_MAX_READ;
- } else if (n > EVBUFFER_MAX_READ && n > howmuch) {
- /*
- * It's possible that a lot of data is available for
- * reading. We do not want to exhaust resources
- * before the reader has a chance to do something
- * about it. If the reader does not tell us how much
- * data we should read, we artifically limit it.
- */
- if ((size_t)n > (buf->totallen << 2))
- n = (int)(buf->totallen << 2);
- if (n < EVBUFFER_MAX_READ)
- n = EVBUFFER_MAX_READ;
- }
-#endif
- if (howmuch < 0 || howmuch > n)
- howmuch = n;
-
- /* If we don't have FIONREAD, we might waste some space here */
- if (evbuffer_expand(buf, howmuch) == -1)
- return (-1);
-
- /* We can append new data at this point */
- p = buf->buffer + buf->off;
-
-#ifndef WIN32
- n = read(fd, p, howmuch);
-#else
- n = recv(fd, p, howmuch, 0);
-#endif
- if (n == -1)
- return (-1);
- if (n == 0)
- return (0);
-
- buf->off += n;
-
- /* Tell someone about changes in this buffer */
- if (buf->off != oldoff && buf->cb != NULL)
- (*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
-
- return (n);
-}
-
-int
-evbuffer_write(struct evbuffer *buffer, int fd)
-{
- int n;
-
-#ifndef WIN32
- n = write(fd, buffer->buffer, buffer->off);
-#else
- n = send(fd, buffer->buffer, (int)buffer->off, 0);
-#endif
- if (n == -1)
- return (-1);
- if (n == 0)
- return (0);
- evbuffer_drain(buffer, n);
-
- return (n);
-}
-
-u_char *
-evbuffer_find(struct evbuffer *buffer, const u_char *what, size_t len)
-{
- u_char *search = buffer->buffer, *end = search + buffer->off;
- u_char *p;
-
- while (search < end &&
- (p = memchr(search, *what, end - search)) != NULL) {
- if (p + len > end)
- break;
- if (memcmp(p, what, len) == 0)
- return (p);
- search = p + 1;
- }
-
- return (NULL);
-}
-
-void evbuffer_setcb(struct evbuffer *buffer,
- void (*cb)(struct evbuffer *, size_t, size_t, void *),
- void *cbarg)
-{
- buffer->cb = cb;
- buffer->cbarg = cbarg;
-}
diff --git a/extra/libevent/compat/sys/_time.h b/extra/libevent/compat/sys/_time.h
deleted file mode 100644
index 8cabb0d55e7..00000000000
--- a/extra/libevent/compat/sys/_time.h
+++ /dev/null
@@ -1,163 +0,0 @@
-/* $OpenBSD: time.h,v 1.11 2000/10/10 13:36:48 itojun Exp $ */
-/* $NetBSD: time.h,v 1.18 1996/04/23 10:29:33 mycroft Exp $ */
-
-/*
- * Copyright (c) 1982, 1986, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)time.h 8.2 (Berkeley) 7/10/94
- */
-
-#ifndef _SYS_TIME_H_
-#define _SYS_TIME_H_
-
-#include <sys/types.h>
-
-/*
- * Structure returned by gettimeofday(2) system call,
- * and used in other calls.
- */
-struct timeval {
- long tv_sec; /* seconds */
- long tv_usec; /* and microseconds */
-};
-
-/*
- * Structure defined by POSIX.1b to be like a timeval.
- */
-struct timespec {
- time_t tv_sec; /* seconds */
- long tv_nsec; /* and nanoseconds */
-};
-
-#define TIMEVAL_TO_TIMESPEC(tv, ts) { \
- (ts)->tv_sec = (tv)->tv_sec; \
- (ts)->tv_nsec = (tv)->tv_usec * 1000; \
-}
-#define TIMESPEC_TO_TIMEVAL(tv, ts) { \
- (tv)->tv_sec = (ts)->tv_sec; \
- (tv)->tv_usec = (ts)->tv_nsec / 1000; \
-}
-
-struct timezone {
- int tz_minuteswest; /* minutes west of Greenwich */
- int tz_dsttime; /* type of dst correction */
-};
-#define DST_NONE 0 /* not on dst */
-#define DST_USA 1 /* USA style dst */
-#define DST_AUST 2 /* Australian style dst */
-#define DST_WET 3 /* Western European dst */
-#define DST_MET 4 /* Middle European dst */
-#define DST_EET 5 /* Eastern European dst */
-#define DST_CAN 6 /* Canada */
-
-/* Operations on timevals. */
-#define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0
-#define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec)
-#define timercmp(tvp, uvp, cmp) \
- (((tvp)->tv_sec == (uvp)->tv_sec) ? \
- ((tvp)->tv_usec cmp (uvp)->tv_usec) : \
- ((tvp)->tv_sec cmp (uvp)->tv_sec))
-#define timeradd(tvp, uvp, vvp) \
- do { \
- (vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec; \
- (vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec; \
- if ((vvp)->tv_usec >= 1000000) { \
- (vvp)->tv_sec++; \
- (vvp)->tv_usec -= 1000000; \
- } \
- } while (0)
-#define timersub(tvp, uvp, vvp) \
- do { \
- (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \
- (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \
- if ((vvp)->tv_usec < 0) { \
- (vvp)->tv_sec--; \
- (vvp)->tv_usec += 1000000; \
- } \
- } while (0)
-
-/* Operations on timespecs. */
-#define timespecclear(tsp) (tsp)->tv_sec = (tsp)->tv_nsec = 0
-#define timespecisset(tsp) ((tsp)->tv_sec || (tsp)->tv_nsec)
-#define timespeccmp(tsp, usp, cmp) \
- (((tsp)->tv_sec == (usp)->tv_sec) ? \
- ((tsp)->tv_nsec cmp (usp)->tv_nsec) : \
- ((tsp)->tv_sec cmp (usp)->tv_sec))
-#define timespecadd(tsp, usp, vsp) \
- do { \
- (vsp)->tv_sec = (tsp)->tv_sec + (usp)->tv_sec; \
- (vsp)->tv_nsec = (tsp)->tv_nsec + (usp)->tv_nsec; \
- if ((vsp)->tv_nsec >= 1000000000L) { \
- (vsp)->tv_sec++; \
- (vsp)->tv_nsec -= 1000000000L; \
- } \
- } while (0)
-#define timespecsub(tsp, usp, vsp) \
- do { \
- (vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec; \
- (vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec; \
- if ((vsp)->tv_nsec < 0) { \
- (vsp)->tv_sec--; \
- (vsp)->tv_nsec += 1000000000L; \
- } \
- } while (0)
-
-/*
- * Names of the interval timers, and structure
- * defining a timer setting.
- */
-#define ITIMER_REAL 0
-#define ITIMER_VIRTUAL 1
-#define ITIMER_PROF 2
-
-struct itimerval {
- struct timeval it_interval; /* timer interval */
- struct timeval it_value; /* current value */
-};
-
-/*
- * Getkerninfo clock information structure
- */
-struct clockinfo {
- int hz; /* clock frequency */
- int tick; /* micro-seconds per hz tick */
- int tickadj; /* clock skew rate for adjtime() */
- int stathz; /* statistics clock frequency */
- int profhz; /* profiling clock frequency */
-};
-
-#define CLOCK_REALTIME 0
-#define CLOCK_VIRTUAL 1
-#define CLOCK_PROF 2
-
-#define TIMER_RELTIME 0x0 /* relative timer */
-#define TIMER_ABSTIME 0x1 /* absolute timer */
-
-/* --- stuff got cut here - niels --- */
-
-#endif /* !_SYS_TIME_H_ */
diff --git a/extra/libevent/compat/sys/queue.h b/extra/libevent/compat/sys/queue.h
deleted file mode 100644
index c0956ddce43..00000000000
--- a/extra/libevent/compat/sys/queue.h
+++ /dev/null
@@ -1,488 +0,0 @@
-/* $OpenBSD: queue.h,v 1.16 2000/09/07 19:47:59 art Exp $ */
-/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */
-
-/*
- * Copyright (c) 1991, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)queue.h 8.5 (Berkeley) 8/20/94
- */
-
-#ifndef _SYS_QUEUE_H_
-#define _SYS_QUEUE_H_
-
-/*
- * This file defines five types of data structures: singly-linked lists,
- * lists, simple queues, tail queues, and circular queues.
- *
- *
- * A singly-linked list is headed by a single forward pointer. The elements
- * are singly linked for minimum space and pointer manipulation overhead at
- * the expense of O(n) removal for arbitrary elements. New elements can be
- * added to the list after an existing element or at the head of the list.
- * Elements being removed from the head of the list should use the explicit
- * macro for this purpose for optimum efficiency. A singly-linked list may
- * only be traversed in the forward direction. Singly-linked lists are ideal
- * for applications with large datasets and few or no removals or for
- * implementing a LIFO queue.
- *
- * A list is headed by a single forward pointer (or an array of forward
- * pointers for a hash table header). The elements are doubly linked
- * so that an arbitrary element can be removed without a need to
- * traverse the list. New elements can be added to the list before
- * or after an existing element or at the head of the list. A list
- * may only be traversed in the forward direction.
- *
- * A simple queue is headed by a pair of pointers, one the head of the
- * list and the other to the tail of the list. The elements are singly
- * linked to save space, so elements can only be removed from the
- * head of the list. New elements can be added to the list before or after
- * an existing element, at the head of the list, or at the end of the
- * list. A simple queue may only be traversed in the forward direction.
- *
- * A tail queue is headed by a pair of pointers, one to the head of the
- * list and the other to the tail of the list. The elements are doubly
- * linked so that an arbitrary element can be removed without a need to
- * traverse the list. New elements can be added to the list before or
- * after an existing element, at the head of the list, or at the end of
- * the list. A tail queue may be traversed in either direction.
- *
- * A circle queue is headed by a pair of pointers, one to the head of the
- * list and the other to the tail of the list. The elements are doubly
- * linked so that an arbitrary element can be removed without a need to
- * traverse the list. New elements can be added to the list before or after
- * an existing element, at the head of the list, or at the end of the list.
- * A circle queue may be traversed in either direction, but has a more
- * complex end of list detection.
- *
- * For details on the use of these macros, see the queue(3) manual page.
- */
-
-/*
- * Singly-linked List definitions.
- */
-#define SLIST_HEAD(name, type) \
-struct name { \
- struct type *slh_first; /* first element */ \
-}
-
-#define SLIST_HEAD_INITIALIZER(head) \
- { NULL }
-
-#ifndef WIN32
-#define SLIST_ENTRY(type) \
-struct { \
- struct type *sle_next; /* next element */ \
-}
-#endif
-
-/*
- * Singly-linked List access methods.
- */
-#define SLIST_FIRST(head) ((head)->slh_first)
-#define SLIST_END(head) NULL
-#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head))
-#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
-
-#define SLIST_FOREACH(var, head, field) \
- for((var) = SLIST_FIRST(head); \
- (var) != SLIST_END(head); \
- (var) = SLIST_NEXT(var, field))
-
-/*
- * Singly-linked List functions.
- */
-#define SLIST_INIT(head) { \
- SLIST_FIRST(head) = SLIST_END(head); \
-}
-
-#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
- (elm)->field.sle_next = (slistelm)->field.sle_next; \
- (slistelm)->field.sle_next = (elm); \
-} while (0)
-
-#define SLIST_INSERT_HEAD(head, elm, field) do { \
- (elm)->field.sle_next = (head)->slh_first; \
- (head)->slh_first = (elm); \
-} while (0)
-
-#define SLIST_REMOVE_HEAD(head, field) do { \
- (head)->slh_first = (head)->slh_first->field.sle_next; \
-} while (0)
-
-/*
- * List definitions.
- */
-#define LIST_HEAD(name, type) \
-struct name { \
- struct type *lh_first; /* first element */ \
-}
-
-#define LIST_HEAD_INITIALIZER(head) \
- { NULL }
-
-#define LIST_ENTRY(type) \
-struct { \
- struct type *le_next; /* next element */ \
- struct type **le_prev; /* address of previous next element */ \
-}
-
-/*
- * List access methods
- */
-#define LIST_FIRST(head) ((head)->lh_first)
-#define LIST_END(head) NULL
-#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head))
-#define LIST_NEXT(elm, field) ((elm)->field.le_next)
-
-#define LIST_FOREACH(var, head, field) \
- for((var) = LIST_FIRST(head); \
- (var)!= LIST_END(head); \
- (var) = LIST_NEXT(var, field))
-
-/*
- * List functions.
- */
-#define LIST_INIT(head) do { \
- LIST_FIRST(head) = LIST_END(head); \
-} while (0)
-
-#define LIST_INSERT_AFTER(listelm, elm, field) do { \
- if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
- (listelm)->field.le_next->field.le_prev = \
- &(elm)->field.le_next; \
- (listelm)->field.le_next = (elm); \
- (elm)->field.le_prev = &(listelm)->field.le_next; \
-} while (0)
-
-#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
- (elm)->field.le_prev = (listelm)->field.le_prev; \
- (elm)->field.le_next = (listelm); \
- *(listelm)->field.le_prev = (elm); \
- (listelm)->field.le_prev = &(elm)->field.le_next; \
-} while (0)
-
-#define LIST_INSERT_HEAD(head, elm, field) do { \
- if (((elm)->field.le_next = (head)->lh_first) != NULL) \
- (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
- (head)->lh_first = (elm); \
- (elm)->field.le_prev = &(head)->lh_first; \
-} while (0)
-
-#define LIST_REMOVE(elm, field) do { \
- if ((elm)->field.le_next != NULL) \
- (elm)->field.le_next->field.le_prev = \
- (elm)->field.le_prev; \
- *(elm)->field.le_prev = (elm)->field.le_next; \
-} while (0)
-
-#define LIST_REPLACE(elm, elm2, field) do { \
- if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \
- (elm2)->field.le_next->field.le_prev = \
- &(elm2)->field.le_next; \
- (elm2)->field.le_prev = (elm)->field.le_prev; \
- *(elm2)->field.le_prev = (elm2); \
-} while (0)
-
-/*
- * Simple queue definitions.
- */
-#define SIMPLEQ_HEAD(name, type) \
-struct name { \
- struct type *sqh_first; /* first element */ \
- struct type **sqh_last; /* addr of last next element */ \
-}
-
-#define SIMPLEQ_HEAD_INITIALIZER(head) \
- { NULL, &(head).sqh_first }
-
-#define SIMPLEQ_ENTRY(type) \
-struct { \
- struct type *sqe_next; /* next element */ \
-}
-
-/*
- * Simple queue access methods.
- */
-#define SIMPLEQ_FIRST(head) ((head)->sqh_first)
-#define SIMPLEQ_END(head) NULL
-#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head))
-#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
-
-#define SIMPLEQ_FOREACH(var, head, field) \
- for((var) = SIMPLEQ_FIRST(head); \
- (var) != SIMPLEQ_END(head); \
- (var) = SIMPLEQ_NEXT(var, field))
-
-/*
- * Simple queue functions.
- */
-#define SIMPLEQ_INIT(head) do { \
- (head)->sqh_first = NULL; \
- (head)->sqh_last = &(head)->sqh_first; \
-} while (0)
-
-#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \
- if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
- (head)->sqh_last = &(elm)->field.sqe_next; \
- (head)->sqh_first = (elm); \
-} while (0)
-
-#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \
- (elm)->field.sqe_next = NULL; \
- *(head)->sqh_last = (elm); \
- (head)->sqh_last = &(elm)->field.sqe_next; \
-} while (0)
-
-#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
- if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
- (head)->sqh_last = &(elm)->field.sqe_next; \
- (listelm)->field.sqe_next = (elm); \
-} while (0)
-
-#define SIMPLEQ_REMOVE_HEAD(head, elm, field) do { \
- if (((head)->sqh_first = (elm)->field.sqe_next) == NULL) \
- (head)->sqh_last = &(head)->sqh_first; \
-} while (0)
-
-/*
- * Tail queue definitions.
- */
-#define TAILQ_HEAD(name, type) \
-struct name { \
- struct type *tqh_first; /* first element */ \
- struct type **tqh_last; /* addr of last next element */ \
-}
-
-#define TAILQ_HEAD_INITIALIZER(head) \
- { NULL, &(head).tqh_first }
-
-#define TAILQ_ENTRY(type) \
-struct { \
- struct type *tqe_next; /* next element */ \
- struct type **tqe_prev; /* address of previous next element */ \
-}
-
-/*
- * tail queue access methods
- */
-#define TAILQ_FIRST(head) ((head)->tqh_first)
-#define TAILQ_END(head) NULL
-#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
-#define TAILQ_LAST(head, headname) \
- (*(((struct headname *)((head)->tqh_last))->tqh_last))
-/* XXX */
-#define TAILQ_PREV(elm, headname, field) \
- (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
-#define TAILQ_EMPTY(head) \
- (TAILQ_FIRST(head) == TAILQ_END(head))
-
-#define TAILQ_FOREACH(var, head, field) \
- for((var) = TAILQ_FIRST(head); \
- (var) != TAILQ_END(head); \
- (var) = TAILQ_NEXT(var, field))
-
-#define TAILQ_FOREACH_REVERSE(var, head, field, headname) \
- for((var) = TAILQ_LAST(head, headname); \
- (var) != TAILQ_END(head); \
- (var) = TAILQ_PREV(var, headname, field))
-
-/*
- * Tail queue functions.
- */
-#define TAILQ_INIT(head) do { \
- (head)->tqh_first = NULL; \
- (head)->tqh_last = &(head)->tqh_first; \
-} while (0)
-
-#define TAILQ_INSERT_HEAD(head, elm, field) do { \
- if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
- (head)->tqh_first->field.tqe_prev = \
- &(elm)->field.tqe_next; \
- else \
- (head)->tqh_last = &(elm)->field.tqe_next; \
- (head)->tqh_first = (elm); \
- (elm)->field.tqe_prev = &(head)->tqh_first; \
-} while (0)
-
-#define TAILQ_INSERT_TAIL(head, elm, field) do { \
- (elm)->field.tqe_next = NULL; \
- (elm)->field.tqe_prev = (head)->tqh_last; \
- *(head)->tqh_last = (elm); \
- (head)->tqh_last = &(elm)->field.tqe_next; \
-} while (0)
-
-#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
- if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
- (elm)->field.tqe_next->field.tqe_prev = \
- &(elm)->field.tqe_next; \
- else \
- (head)->tqh_last = &(elm)->field.tqe_next; \
- (listelm)->field.tqe_next = (elm); \
- (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
-} while (0)
-
-#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
- (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
- (elm)->field.tqe_next = (listelm); \
- *(listelm)->field.tqe_prev = (elm); \
- (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
-} while (0)
-
-#define TAILQ_REMOVE(head, elm, field) do { \
- if (((elm)->field.tqe_next) != NULL) \
- (elm)->field.tqe_next->field.tqe_prev = \
- (elm)->field.tqe_prev; \
- else \
- (head)->tqh_last = (elm)->field.tqe_prev; \
- *(elm)->field.tqe_prev = (elm)->field.tqe_next; \
-} while (0)
-
-#define TAILQ_REPLACE(head, elm, elm2, field) do { \
- if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \
- (elm2)->field.tqe_next->field.tqe_prev = \
- &(elm2)->field.tqe_next; \
- else \
- (head)->tqh_last = &(elm2)->field.tqe_next; \
- (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \
- *(elm2)->field.tqe_prev = (elm2); \
-} while (0)
-
-/*
- * Circular queue definitions.
- */
-#define CIRCLEQ_HEAD(name, type) \
-struct name { \
- struct type *cqh_first; /* first element */ \
- struct type *cqh_last; /* last element */ \
-}
-
-#define CIRCLEQ_HEAD_INITIALIZER(head) \
- { CIRCLEQ_END(&head), CIRCLEQ_END(&head) }
-
-#define CIRCLEQ_ENTRY(type) \
-struct { \
- struct type *cqe_next; /* next element */ \
- struct type *cqe_prev; /* previous element */ \
-}
-
-/*
- * Circular queue access methods
- */
-#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
-#define CIRCLEQ_LAST(head) ((head)->cqh_last)
-#define CIRCLEQ_END(head) ((void *)(head))
-#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)
-#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)
-#define CIRCLEQ_EMPTY(head) \
- (CIRCLEQ_FIRST(head) == CIRCLEQ_END(head))
-
-#define CIRCLEQ_FOREACH(var, head, field) \
- for((var) = CIRCLEQ_FIRST(head); \
- (var) != CIRCLEQ_END(head); \
- (var) = CIRCLEQ_NEXT(var, field))
-
-#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
- for((var) = CIRCLEQ_LAST(head); \
- (var) != CIRCLEQ_END(head); \
- (var) = CIRCLEQ_PREV(var, field))
-
-/*
- * Circular queue functions.
- */
-#define CIRCLEQ_INIT(head) do { \
- (head)->cqh_first = CIRCLEQ_END(head); \
- (head)->cqh_last = CIRCLEQ_END(head); \
-} while (0)
-
-#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
- (elm)->field.cqe_next = (listelm)->field.cqe_next; \
- (elm)->field.cqe_prev = (listelm); \
- if ((listelm)->field.cqe_next == CIRCLEQ_END(head)) \
- (head)->cqh_last = (elm); \
- else \
- (listelm)->field.cqe_next->field.cqe_prev = (elm); \
- (listelm)->field.cqe_next = (elm); \
-} while (0)
-
-#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
- (elm)->field.cqe_next = (listelm); \
- (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
- if ((listelm)->field.cqe_prev == CIRCLEQ_END(head)) \
- (head)->cqh_first = (elm); \
- else \
- (listelm)->field.cqe_prev->field.cqe_next = (elm); \
- (listelm)->field.cqe_prev = (elm); \
-} while (0)
-
-#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
- (elm)->field.cqe_next = (head)->cqh_first; \
- (elm)->field.cqe_prev = CIRCLEQ_END(head); \
- if ((head)->cqh_last == CIRCLEQ_END(head)) \
- (head)->cqh_last = (elm); \
- else \
- (head)->cqh_first->field.cqe_prev = (elm); \
- (head)->cqh_first = (elm); \
-} while (0)
-
-#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
- (elm)->field.cqe_next = CIRCLEQ_END(head); \
- (elm)->field.cqe_prev = (head)->cqh_last; \
- if ((head)->cqh_first == CIRCLEQ_END(head)) \
- (head)->cqh_first = (elm); \
- else \
- (head)->cqh_last->field.cqe_next = (elm); \
- (head)->cqh_last = (elm); \
-} while (0)
-
-#define CIRCLEQ_REMOVE(head, elm, field) do { \
- if ((elm)->field.cqe_next == CIRCLEQ_END(head)) \
- (head)->cqh_last = (elm)->field.cqe_prev; \
- else \
- (elm)->field.cqe_next->field.cqe_prev = \
- (elm)->field.cqe_prev; \
- if ((elm)->field.cqe_prev == CIRCLEQ_END(head)) \
- (head)->cqh_first = (elm)->field.cqe_next; \
- else \
- (elm)->field.cqe_prev->field.cqe_next = \
- (elm)->field.cqe_next; \
-} while (0)
-
-#define CIRCLEQ_REPLACE(head, elm, elm2, field) do { \
- if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \
- CIRCLEQ_END(head)) \
- (head).cqh_last = (elm2); \
- else \
- (elm2)->field.cqe_next->field.cqe_prev = (elm2); \
- if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \
- CIRCLEQ_END(head)) \
- (head).cqh_first = (elm2); \
- else \
- (elm2)->field.cqe_prev->field.cqe_next = (elm2); \
-} while (0)
-
-#endif /* !_SYS_QUEUE_H_ */
diff --git a/extra/libevent/compat/sys/tree.h b/extra/libevent/compat/sys/tree.h
deleted file mode 100644
index 6a3381caee4..00000000000
--- a/extra/libevent/compat/sys/tree.h
+++ /dev/null
@@ -1,677 +0,0 @@
-/* $OpenBSD: tree.h,v 1.7 2002/10/17 21:51:54 art Exp $ */
-/*
- * Copyright 2002 Niels Provos <provos@citi.umich.edu>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef _SYS_TREE_H_
-#define _SYS_TREE_H_
-
-/*
- * This file defines data structures for different types of trees:
- * splay trees and red-black trees.
- *
- * A splay tree is a self-organizing data structure. Every operation
- * on the tree causes a splay to happen. The splay moves the requested
- * node to the root of the tree and partly rebalances it.
- *
- * This has the benefit that request locality causes faster lookups as
- * the requested nodes move to the top of the tree. On the other hand,
- * every lookup causes memory writes.
- *
- * The Balance Theorem bounds the total access time for m operations
- * and n inserts on an initially empty tree as O((m + n)lg n). The
- * amortized cost for a sequence of m accesses to a splay tree is O(lg n);
- *
- * A red-black tree is a binary search tree with the node color as an
- * extra attribute. It fulfills a set of conditions:
- * - every search path from the root to a leaf consists of the
- * same number of black nodes,
- * - each red node (except for the root) has a black parent,
- * - each leaf node is black.
- *
- * Every operation on a red-black tree is bounded as O(lg n).
- * The maximum height of a red-black tree is 2lg (n+1).
- */
-
-#define SPLAY_HEAD(name, type) \
-struct name { \
- struct type *sph_root; /* root of the tree */ \
-}
-
-#define SPLAY_INITIALIZER(root) \
- { NULL }
-
-#define SPLAY_INIT(root) do { \
- (root)->sph_root = NULL; \
-} while (0)
-
-#define SPLAY_ENTRY(type) \
-struct { \
- struct type *spe_left; /* left element */ \
- struct type *spe_right; /* right element */ \
-}
-
-#define SPLAY_LEFT(elm, field) (elm)->field.spe_left
-#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right
-#define SPLAY_ROOT(head) (head)->sph_root
-#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL)
-
-/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */
-#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \
- SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \
- SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
- (head)->sph_root = tmp; \
-} while (0)
-
-#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \
- SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \
- SPLAY_LEFT(tmp, field) = (head)->sph_root; \
- (head)->sph_root = tmp; \
-} while (0)
-
-#define SPLAY_LINKLEFT(head, tmp, field) do { \
- SPLAY_LEFT(tmp, field) = (head)->sph_root; \
- tmp = (head)->sph_root; \
- (head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \
-} while (0)
-
-#define SPLAY_LINKRIGHT(head, tmp, field) do { \
- SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
- tmp = (head)->sph_root; \
- (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \
-} while (0)
-
-#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \
- SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \
- SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\
- SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \
- SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \
-} while (0)
-
-/* Generates prototypes and inline functions */
-
-#define SPLAY_PROTOTYPE(name, type, field, cmp) \
-void name##_SPLAY(struct name *, struct type *); \
-void name##_SPLAY_MINMAX(struct name *, int); \
-struct type *name##_SPLAY_INSERT(struct name *, struct type *); \
-struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \
- \
-/* Finds the node with the same key as elm */ \
-static __inline struct type * \
-name##_SPLAY_FIND(struct name *head, struct type *elm) \
-{ \
- if (SPLAY_EMPTY(head)) \
- return(NULL); \
- name##_SPLAY(head, elm); \
- if ((cmp)(elm, (head)->sph_root) == 0) \
- return (head->sph_root); \
- return (NULL); \
-} \
- \
-static __inline struct type * \
-name##_SPLAY_NEXT(struct name *head, struct type *elm) \
-{ \
- name##_SPLAY(head, elm); \
- if (SPLAY_RIGHT(elm, field) != NULL) { \
- elm = SPLAY_RIGHT(elm, field); \
- while (SPLAY_LEFT(elm, field) != NULL) { \
- elm = SPLAY_LEFT(elm, field); \
- } \
- } else \
- elm = NULL; \
- return (elm); \
-} \
- \
-static __inline struct type * \
-name##_SPLAY_MIN_MAX(struct name *head, int val) \
-{ \
- name##_SPLAY_MINMAX(head, val); \
- return (SPLAY_ROOT(head)); \
-}
-
-/* Main splay operation.
- * Moves node close to the key of elm to top
- */
-#define SPLAY_GENERATE(name, type, field, cmp) \
-struct type * \
-name##_SPLAY_INSERT(struct name *head, struct type *elm) \
-{ \
- if (SPLAY_EMPTY(head)) { \
- SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \
- } else { \
- int __comp; \
- name##_SPLAY(head, elm); \
- __comp = (cmp)(elm, (head)->sph_root); \
- if(__comp < 0) { \
- SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\
- SPLAY_RIGHT(elm, field) = (head)->sph_root; \
- SPLAY_LEFT((head)->sph_root, field) = NULL; \
- } else if (__comp > 0) { \
- SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\
- SPLAY_LEFT(elm, field) = (head)->sph_root; \
- SPLAY_RIGHT((head)->sph_root, field) = NULL; \
- } else \
- return ((head)->sph_root); \
- } \
- (head)->sph_root = (elm); \
- return (NULL); \
-} \
- \
-struct type * \
-name##_SPLAY_REMOVE(struct name *head, struct type *elm) \
-{ \
- struct type *__tmp; \
- if (SPLAY_EMPTY(head)) \
- return (NULL); \
- name##_SPLAY(head, elm); \
- if ((cmp)(elm, (head)->sph_root) == 0) { \
- if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \
- (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\
- } else { \
- __tmp = SPLAY_RIGHT((head)->sph_root, field); \
- (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\
- name##_SPLAY(head, elm); \
- SPLAY_RIGHT((head)->sph_root, field) = __tmp; \
- } \
- return (elm); \
- } \
- return (NULL); \
-} \
- \
-void \
-name##_SPLAY(struct name *head, struct type *elm) \
-{ \
- struct type __node, *__left, *__right, *__tmp; \
- int __comp; \
-\
- SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
- __left = __right = &__node; \
-\
- while ((__comp = (cmp)(elm, (head)->sph_root))) { \
- if (__comp < 0) { \
- __tmp = SPLAY_LEFT((head)->sph_root, field); \
- if (__tmp == NULL) \
- break; \
- if ((cmp)(elm, __tmp) < 0){ \
- SPLAY_ROTATE_RIGHT(head, __tmp, field); \
- if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
- break; \
- } \
- SPLAY_LINKLEFT(head, __right, field); \
- } else if (__comp > 0) { \
- __tmp = SPLAY_RIGHT((head)->sph_root, field); \
- if (__tmp == NULL) \
- break; \
- if ((cmp)(elm, __tmp) > 0){ \
- SPLAY_ROTATE_LEFT(head, __tmp, field); \
- if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
- break; \
- } \
- SPLAY_LINKRIGHT(head, __left, field); \
- } \
- } \
- SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
-} \
- \
-/* Splay with either the minimum or the maximum element \
- * Used to find minimum or maximum element in tree. \
- */ \
-void name##_SPLAY_MINMAX(struct name *head, int __comp) \
-{ \
- struct type __node, *__left, *__right, *__tmp; \
-\
- SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
- __left = __right = &__node; \
-\
- while (1) { \
- if (__comp < 0) { \
- __tmp = SPLAY_LEFT((head)->sph_root, field); \
- if (__tmp == NULL) \
- break; \
- if (__comp < 0){ \
- SPLAY_ROTATE_RIGHT(head, __tmp, field); \
- if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
- break; \
- } \
- SPLAY_LINKLEFT(head, __right, field); \
- } else if (__comp > 0) { \
- __tmp = SPLAY_RIGHT((head)->sph_root, field); \
- if (__tmp == NULL) \
- break; \
- if (__comp > 0) { \
- SPLAY_ROTATE_LEFT(head, __tmp, field); \
- if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
- break; \
- } \
- SPLAY_LINKRIGHT(head, __left, field); \
- } \
- } \
- SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
-}
-
-#define SPLAY_NEGINF -1
-#define SPLAY_INF 1
-
-#define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y)
-#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y)
-#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y)
-#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y)
-#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \
- : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF))
-#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \
- : name##_SPLAY_MIN_MAX(x, SPLAY_INF))
-
-#define SPLAY_FOREACH(x, name, head) \
- for ((x) = SPLAY_MIN(name, head); \
- (x) != NULL; \
- (x) = SPLAY_NEXT(name, head, x))
-
-/* Macros that define a red-back tree */
-#define RB_HEAD(name, type) \
-struct name { \
- struct type *rbh_root; /* root of the tree */ \
-}
-
-#define RB_INITIALIZER(root) \
- { NULL }
-
-#define RB_INIT(root) do { \
- (root)->rbh_root = NULL; \
-} while (0)
-
-#define RB_BLACK 0
-#define RB_RED 1
-#define RB_ENTRY(type) \
-struct { \
- struct type *rbe_left; /* left element */ \
- struct type *rbe_right; /* right element */ \
- struct type *rbe_parent; /* parent element */ \
- int rbe_color; /* node color */ \
-}
-
-#define RB_LEFT(elm, field) (elm)->field.rbe_left
-#define RB_RIGHT(elm, field) (elm)->field.rbe_right
-#define RB_PARENT(elm, field) (elm)->field.rbe_parent
-#define RB_COLOR(elm, field) (elm)->field.rbe_color
-#define RB_ROOT(head) (head)->rbh_root
-#define RB_EMPTY(head) (RB_ROOT(head) == NULL)
-
-#define RB_SET(elm, parent, field) do { \
- RB_PARENT(elm, field) = parent; \
- RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \
- RB_COLOR(elm, field) = RB_RED; \
-} while (0)
-
-#define RB_SET_BLACKRED(black, red, field) do { \
- RB_COLOR(black, field) = RB_BLACK; \
- RB_COLOR(red, field) = RB_RED; \
-} while (0)
-
-#ifndef RB_AUGMENT
-#define RB_AUGMENT(x)
-#endif
-
-#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \
- (tmp) = RB_RIGHT(elm, field); \
- if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field))) { \
- RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \
- } \
- RB_AUGMENT(elm); \
- if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \
- if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
- RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
- else \
- RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
- } else \
- (head)->rbh_root = (tmp); \
- RB_LEFT(tmp, field) = (elm); \
- RB_PARENT(elm, field) = (tmp); \
- RB_AUGMENT(tmp); \
- if ((RB_PARENT(tmp, field))) \
- RB_AUGMENT(RB_PARENT(tmp, field)); \
-} while (0)
-
-#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \
- (tmp) = RB_LEFT(elm, field); \
- if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field))) { \
- RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \
- } \
- RB_AUGMENT(elm); \
- if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \
- if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
- RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
- else \
- RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
- } else \
- (head)->rbh_root = (tmp); \
- RB_RIGHT(tmp, field) = (elm); \
- RB_PARENT(elm, field) = (tmp); \
- RB_AUGMENT(tmp); \
- if ((RB_PARENT(tmp, field))) \
- RB_AUGMENT(RB_PARENT(tmp, field)); \
-} while (0)
-
-/* Generates prototypes and inline functions */
-#define RB_PROTOTYPE(name, type, field, cmp) \
-void name##_RB_INSERT_COLOR(struct name *, struct type *); \
-void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\
-struct type *name##_RB_REMOVE(struct name *, struct type *); \
-struct type *name##_RB_INSERT(struct name *, struct type *); \
-struct type *name##_RB_FIND(struct name *, struct type *); \
-struct type *name##_RB_NEXT(struct type *); \
-struct type *name##_RB_MINMAX(struct name *, int); \
- \
-
-/* Main rb operation.
- * Moves node close to the key of elm to top
- */
-#define RB_GENERATE(name, type, field, cmp) \
-void \
-name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
-{ \
- struct type *parent, *gparent, *tmp; \
- while ((parent = RB_PARENT(elm, field)) && \
- RB_COLOR(parent, field) == RB_RED) { \
- gparent = RB_PARENT(parent, field); \
- if (parent == RB_LEFT(gparent, field)) { \
- tmp = RB_RIGHT(gparent, field); \
- if (tmp && RB_COLOR(tmp, field) == RB_RED) { \
- RB_COLOR(tmp, field) = RB_BLACK; \
- RB_SET_BLACKRED(parent, gparent, field);\
- elm = gparent; \
- continue; \
- } \
- if (RB_RIGHT(parent, field) == elm) { \
- RB_ROTATE_LEFT(head, parent, tmp, field);\
- tmp = parent; \
- parent = elm; \
- elm = tmp; \
- } \
- RB_SET_BLACKRED(parent, gparent, field); \
- RB_ROTATE_RIGHT(head, gparent, tmp, field); \
- } else { \
- tmp = RB_LEFT(gparent, field); \
- if (tmp && RB_COLOR(tmp, field) == RB_RED) { \
- RB_COLOR(tmp, field) = RB_BLACK; \
- RB_SET_BLACKRED(parent, gparent, field);\
- elm = gparent; \
- continue; \
- } \
- if (RB_LEFT(parent, field) == elm) { \
- RB_ROTATE_RIGHT(head, parent, tmp, field);\
- tmp = parent; \
- parent = elm; \
- elm = tmp; \
- } \
- RB_SET_BLACKRED(parent, gparent, field); \
- RB_ROTATE_LEFT(head, gparent, tmp, field); \
- } \
- } \
- RB_COLOR(head->rbh_root, field) = RB_BLACK; \
-} \
- \
-void \
-name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \
-{ \
- struct type *tmp; \
- while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \
- elm != RB_ROOT(head)) { \
- if (RB_LEFT(parent, field) == elm) { \
- tmp = RB_RIGHT(parent, field); \
- if (RB_COLOR(tmp, field) == RB_RED) { \
- RB_SET_BLACKRED(tmp, parent, field); \
- RB_ROTATE_LEFT(head, parent, tmp, field);\
- tmp = RB_RIGHT(parent, field); \
- } \
- if ((RB_LEFT(tmp, field) == NULL || \
- RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
- (RB_RIGHT(tmp, field) == NULL || \
- RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
- RB_COLOR(tmp, field) = RB_RED; \
- elm = parent; \
- parent = RB_PARENT(elm, field); \
- } else { \
- if (RB_RIGHT(tmp, field) == NULL || \
- RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\
- struct type *oleft; \
- if ((oleft = RB_LEFT(tmp, field)))\
- RB_COLOR(oleft, field) = RB_BLACK;\
- RB_COLOR(tmp, field) = RB_RED; \
- RB_ROTATE_RIGHT(head, tmp, oleft, field);\
- tmp = RB_RIGHT(parent, field); \
- } \
- RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
- RB_COLOR(parent, field) = RB_BLACK; \
- if (RB_RIGHT(tmp, field)) \
- RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\
- RB_ROTATE_LEFT(head, parent, tmp, field);\
- elm = RB_ROOT(head); \
- break; \
- } \
- } else { \
- tmp = RB_LEFT(parent, field); \
- if (RB_COLOR(tmp, field) == RB_RED) { \
- RB_SET_BLACKRED(tmp, parent, field); \
- RB_ROTATE_RIGHT(head, parent, tmp, field);\
- tmp = RB_LEFT(parent, field); \
- } \
- if ((RB_LEFT(tmp, field) == NULL || \
- RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
- (RB_RIGHT(tmp, field) == NULL || \
- RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
- RB_COLOR(tmp, field) = RB_RED; \
- elm = parent; \
- parent = RB_PARENT(elm, field); \
- } else { \
- if (RB_LEFT(tmp, field) == NULL || \
- RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\
- struct type *oright; \
- if ((oright = RB_RIGHT(tmp, field)))\
- RB_COLOR(oright, field) = RB_BLACK;\
- RB_COLOR(tmp, field) = RB_RED; \
- RB_ROTATE_LEFT(head, tmp, oright, field);\
- tmp = RB_LEFT(parent, field); \
- } \
- RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
- RB_COLOR(parent, field) = RB_BLACK; \
- if (RB_LEFT(tmp, field)) \
- RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\
- RB_ROTATE_RIGHT(head, parent, tmp, field);\
- elm = RB_ROOT(head); \
- break; \
- } \
- } \
- } \
- if (elm) \
- RB_COLOR(elm, field) = RB_BLACK; \
-} \
- \
-struct type * \
-name##_RB_REMOVE(struct name *head, struct type *elm) \
-{ \
- struct type *child, *parent, *old = elm; \
- int color; \
- if (RB_LEFT(elm, field) == NULL) \
- child = RB_RIGHT(elm, field); \
- else if (RB_RIGHT(elm, field) == NULL) \
- child = RB_LEFT(elm, field); \
- else { \
- struct type *left; \
- elm = RB_RIGHT(elm, field); \
- while ((left = RB_LEFT(elm, field))) \
- elm = left; \
- child = RB_RIGHT(elm, field); \
- parent = RB_PARENT(elm, field); \
- color = RB_COLOR(elm, field); \
- if (child) \
- RB_PARENT(child, field) = parent; \
- if (parent) { \
- if (RB_LEFT(parent, field) == elm) \
- RB_LEFT(parent, field) = child; \
- else \
- RB_RIGHT(parent, field) = child; \
- RB_AUGMENT(parent); \
- } else \
- RB_ROOT(head) = child; \
- if (RB_PARENT(elm, field) == old) \
- parent = elm; \
- (elm)->field = (old)->field; \
- if (RB_PARENT(old, field)) { \
- if (RB_LEFT(RB_PARENT(old, field), field) == old)\
- RB_LEFT(RB_PARENT(old, field), field) = elm;\
- else \
- RB_RIGHT(RB_PARENT(old, field), field) = elm;\
- RB_AUGMENT(RB_PARENT(old, field)); \
- } else \
- RB_ROOT(head) = elm; \
- RB_PARENT(RB_LEFT(old, field), field) = elm; \
- if (RB_RIGHT(old, field)) \
- RB_PARENT(RB_RIGHT(old, field), field) = elm; \
- if (parent) { \
- left = parent; \
- do { \
- RB_AUGMENT(left); \
- } while ((left = RB_PARENT(left, field))); \
- } \
- goto color; \
- } \
- parent = RB_PARENT(elm, field); \
- color = RB_COLOR(elm, field); \
- if (child) \
- RB_PARENT(child, field) = parent; \
- if (parent) { \
- if (RB_LEFT(parent, field) == elm) \
- RB_LEFT(parent, field) = child; \
- else \
- RB_RIGHT(parent, field) = child; \
- RB_AUGMENT(parent); \
- } else \
- RB_ROOT(head) = child; \
-color: \
- if (color == RB_BLACK) \
- name##_RB_REMOVE_COLOR(head, parent, child); \
- return (old); \
-} \
- \
-/* Inserts a node into the RB tree */ \
-struct type * \
-name##_RB_INSERT(struct name *head, struct type *elm) \
-{ \
- struct type *tmp; \
- struct type *parent = NULL; \
- int comp = 0; \
- tmp = RB_ROOT(head); \
- while (tmp) { \
- parent = tmp; \
- comp = (cmp)(elm, parent); \
- if (comp < 0) \
- tmp = RB_LEFT(tmp, field); \
- else if (comp > 0) \
- tmp = RB_RIGHT(tmp, field); \
- else \
- return (tmp); \
- } \
- RB_SET(elm, parent, field); \
- if (parent != NULL) { \
- if (comp < 0) \
- RB_LEFT(parent, field) = elm; \
- else \
- RB_RIGHT(parent, field) = elm; \
- RB_AUGMENT(parent); \
- } else \
- RB_ROOT(head) = elm; \
- name##_RB_INSERT_COLOR(head, elm); \
- return (NULL); \
-} \
- \
-/* Finds the node with the same key as elm */ \
-struct type * \
-name##_RB_FIND(struct name *head, struct type *elm) \
-{ \
- struct type *tmp = RB_ROOT(head); \
- int comp; \
- while (tmp) { \
- comp = cmp(elm, tmp); \
- if (comp < 0) \
- tmp = RB_LEFT(tmp, field); \
- else if (comp > 0) \
- tmp = RB_RIGHT(tmp, field); \
- else \
- return (tmp); \
- } \
- return (NULL); \
-} \
- \
-struct type * \
-name##_RB_NEXT(struct type *elm) \
-{ \
- if (RB_RIGHT(elm, field)) { \
- elm = RB_RIGHT(elm, field); \
- while (RB_LEFT(elm, field)) \
- elm = RB_LEFT(elm, field); \
- } else { \
- if (RB_PARENT(elm, field) && \
- (elm == RB_LEFT(RB_PARENT(elm, field), field))) \
- elm = RB_PARENT(elm, field); \
- else { \
- while (RB_PARENT(elm, field) && \
- (elm == RB_RIGHT(RB_PARENT(elm, field), field)))\
- elm = RB_PARENT(elm, field); \
- elm = RB_PARENT(elm, field); \
- } \
- } \
- return (elm); \
-} \
- \
-struct type * \
-name##_RB_MINMAX(struct name *head, int val) \
-{ \
- struct type *tmp = RB_ROOT(head); \
- struct type *parent = NULL; \
- while (tmp) { \
- parent = tmp; \
- if (val < 0) \
- tmp = RB_LEFT(tmp, field); \
- else \
- tmp = RB_RIGHT(tmp, field); \
- } \
- return (parent); \
-}
-
-#define RB_NEGINF -1
-#define RB_INF 1
-
-#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y)
-#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y)
-#define RB_FIND(name, x, y) name##_RB_FIND(x, y)
-#define RB_NEXT(name, x, y) name##_RB_NEXT(y)
-#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF)
-#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF)
-
-#define RB_FOREACH(x, name, head) \
- for ((x) = RB_MIN(name, head); \
- (x) != NULL; \
- (x) = name##_RB_NEXT(x))
-
-#endif /* _SYS_TREE_H_ */
diff --git a/extra/libevent/devpoll.c b/extra/libevent/devpoll.c
deleted file mode 100644
index 3a3ec7e64a8..00000000000
--- a/extra/libevent/devpoll.c
+++ /dev/null
@@ -1,421 +0,0 @@
-/*
- * Copyright 2000-2004 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 BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef HAVE_DEVPOLL
-
-#include <sys/types.h>
-#include <sys/resource.h>
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#else
-#include <sys/_time.h>
-#endif
-#include <sys/queue.h>
-#include <sys/devpoll.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <assert.h>
-
-#include "event.h"
-#include "event-internal.h"
-#include "evsignal.h"
-#include "log.h"
-
-/* due to limitations in the devpoll interface, we need to keep track of
- * all file descriptors outself.
- */
-struct evdevpoll {
- struct event *evread;
- struct event *evwrite;
-};
-
-struct devpollop {
- struct evdevpoll *fds;
- int nfds;
- struct pollfd *events;
- int nevents;
- int dpfd;
- struct pollfd *changes;
- int nchanges;
-};
-
-static void *devpoll_init (struct event_base *);
-static int devpoll_add (void *, struct event *);
-static int devpoll_del (void *, struct event *);
-static int devpoll_dispatch (struct event_base *, void *, struct timeval *);
-static void devpoll_dealloc (struct event_base *, void *);
-
-struct eventop devpollops = {
- "devpoll",
- devpoll_init,
- devpoll_add,
- devpoll_del,
- devpoll_dispatch,
- devpoll_dealloc,
- 1 /* need reinit */
-};
-
-#define NEVENT 32000
-
-static int
-devpoll_commit(struct devpollop *devpollop)
-{
- /*
- * Due to a bug in Solaris, we have to use pwrite with an offset of 0.
- * Write is limited to 2GB of data, until it will fail.
- */
- if (pwrite(devpollop->dpfd, devpollop->changes,
- sizeof(struct pollfd) * devpollop->nchanges, 0) == -1)
- return(-1);
-
- devpollop->nchanges = 0;
- return(0);
-}
-
-static int
-devpoll_queue(struct devpollop *devpollop, int fd, int events) {
- struct pollfd *pfd;
-
- if (devpollop->nchanges >= devpollop->nevents) {
- /*
- * Change buffer is full, must commit it to /dev/poll before
- * adding more
- */
- if (devpoll_commit(devpollop) != 0)
- return(-1);
- }
-
- pfd = &devpollop->changes[devpollop->nchanges++];
- pfd->fd = fd;
- pfd->events = events;
- pfd->revents = 0;
-
- return(0);
-}
-
-static void *
-devpoll_init(struct event_base *base)
-{
- int dpfd, nfiles = NEVENT;
- struct rlimit rl;
- struct devpollop *devpollop;
-
- /* Disable devpoll when this environment variable is set */
- if (getenv("EVENT_NODEVPOLL"))
- return (NULL);
-
- if (!(devpollop = calloc(1, sizeof(struct devpollop))))
- return (NULL);
-
- if (getrlimit(RLIMIT_NOFILE, &rl) == 0 &&
- (unsigned long long) rl.rlim_cur != (unsigned long long) RLIM_INFINITY)
- nfiles = rl.rlim_cur - 1;
-
- /* Initialize the kernel queue */
- if ((dpfd = open("/dev/poll", O_RDWR)) == -1) {
- event_warn("open: /dev/poll");
- free(devpollop);
- return (NULL);
- }
-
- devpollop->dpfd = dpfd;
-
- /* Initialize fields */
- devpollop->events = calloc(nfiles, sizeof(struct pollfd));
- if (devpollop->events == NULL) {
- free(devpollop);
- close(dpfd);
- return (NULL);
- }
- devpollop->nevents = nfiles;
-
- devpollop->fds = calloc(nfiles, sizeof(struct evdevpoll));
- if (devpollop->fds == NULL) {
- free(devpollop->events);
- free(devpollop);
- close(dpfd);
- return (NULL);
- }
- devpollop->nfds = nfiles;
-
- devpollop->changes = calloc(nfiles, sizeof(struct pollfd));
- if (devpollop->changes == NULL) {
- free(devpollop->fds);
- free(devpollop->events);
- free(devpollop);
- close(dpfd);
- return (NULL);
- }
-
- evsignal_init(base);
-
- return (devpollop);
-}
-
-static int
-devpoll_recalc(struct event_base *base __attribute__((unused)), void *arg, int max)
-{
- struct devpollop *devpollop = arg;
-
- if (max > devpollop->nfds) {
- struct evdevpoll *fds;
- int nfds;
-
- nfds = devpollop->nfds;
- while (nfds < max)
- nfds <<= 1;
-
- fds = realloc(devpollop->fds, nfds * sizeof(struct evdevpoll));
- if (fds == NULL) {
- event_warn("realloc");
- return (-1);
- }
- devpollop->fds = fds;
- memset(fds + devpollop->nfds, 0,
- (nfds - devpollop->nfds) * sizeof(struct evdevpoll));
- devpollop->nfds = nfds;
- }
-
- return (0);
-}
-
-static int
-devpoll_dispatch(struct event_base *base, void *arg, struct timeval *tv)
-{
- struct devpollop *devpollop = arg;
- struct pollfd *events = devpollop->events;
- struct dvpoll dvp;
- struct evdevpoll *evdp;
- int i, res, timeout = -1;
-
- if (devpollop->nchanges)
- devpoll_commit(devpollop);
-
- if (tv != NULL)
- timeout = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000;
-
- dvp.dp_fds = devpollop->events;
- dvp.dp_nfds = devpollop->nevents;
- dvp.dp_timeout = timeout;
-
- res = ioctl(devpollop->dpfd, DP_POLL, &dvp);
-
- if (res == -1) {
- if (errno != EINTR) {
- event_warn("ioctl: DP_POLL");
- return (-1);
- }
-
- evsignal_process(base);
- return (0);
- } else if (base->sig.evsignal_caught) {
- evsignal_process(base);
- }
-
- event_debug(("%s: devpoll_wait reports %d", __func__, res));
-
- for (i = 0; i < res; i++) {
- int which = 0;
- int what = events[i].revents;
- struct event *evread = NULL, *evwrite = NULL;
-
- assert(events[i].fd < devpollop->nfds);
- evdp = &devpollop->fds[events[i].fd];
-
- if (what & POLLHUP)
- what |= POLLIN | POLLOUT;
- else if (what & POLLERR)
- what |= POLLIN | POLLOUT;
-
- if (what & POLLIN) {
- evread = evdp->evread;
- which |= EV_READ;
- }
-
- if (what & POLLOUT) {
- evwrite = evdp->evwrite;
- which |= EV_WRITE;
- }
-
- if (!which)
- continue;
-
- if (evread != NULL && !(evread->ev_events & EV_PERSIST))
- event_del(evread);
- if (evwrite != NULL && evwrite != evread &&
- !(evwrite->ev_events & EV_PERSIST))
- event_del(evwrite);
-
- if (evread != NULL)
- event_active(evread, EV_READ, 1);
- if (evwrite != NULL)
- event_active(evwrite, EV_WRITE, 1);
- }
-
- return (0);
-}
-
-
-static int
-devpoll_add(void *arg, struct event *ev)
-{
- struct devpollop *devpollop = arg;
- struct evdevpoll *evdp;
- int fd, events;
-
- if (ev->ev_events & EV_SIGNAL)
- return (evsignal_add(ev));
-
- fd = ev->ev_fd;
- if (fd >= devpollop->nfds) {
- /* Extend the file descriptor array as necessary */
- if (devpoll_recalc(ev->ev_base, devpollop, fd) == -1)
- return (-1);
- }
- evdp = &devpollop->fds[fd];
-
- /*
- * It's not necessary to OR the existing read/write events that we
- * are currently interested in with the new event we are adding.
- * The /dev/poll driver ORs any new events with the existing events
- * that it has cached for the fd.
- */
-
- events = 0;
- if (ev->ev_events & EV_READ) {
- if (evdp->evread && evdp->evread != ev) {
- /* There is already a different read event registered */
- return(-1);
- }
- events |= POLLIN;
- }
-
- if (ev->ev_events & EV_WRITE) {
- if (evdp->evwrite && evdp->evwrite != ev) {
- /* There is already a different write event registered */
- return(-1);
- }
- events |= POLLOUT;
- }
-
- if (devpoll_queue(devpollop, fd, events) != 0)
- return(-1);
-
- /* Update events responsible */
- if (ev->ev_events & EV_READ)
- evdp->evread = ev;
- if (ev->ev_events & EV_WRITE)
- evdp->evwrite = ev;
-
- return (0);
-}
-
-static int
-devpoll_del(void *arg, struct event *ev)
-{
- struct devpollop *devpollop = arg;
- struct evdevpoll *evdp;
- int fd, events;
- int needwritedelete = 1, needreaddelete = 1;
-
- if (ev->ev_events & EV_SIGNAL)
- return (evsignal_del(ev));
-
- fd = ev->ev_fd;
- if (fd >= devpollop->nfds)
- return (0);
- evdp = &devpollop->fds[fd];
-
- events = 0;
- if (ev->ev_events & EV_READ)
- events |= POLLIN;
- if (ev->ev_events & EV_WRITE)
- events |= POLLOUT;
-
- /*
- * The only way to remove an fd from the /dev/poll monitored set is
- * to use POLLREMOVE by itself. This removes ALL events for the fd
- * provided so if we care about two events and are only removing one
- * we must re-add the other event after POLLREMOVE.
- */
-
- if (devpoll_queue(devpollop, fd, POLLREMOVE) != 0)
- return(-1);
-
- if ((events & (POLLIN|POLLOUT)) != (POLLIN|POLLOUT)) {
- /*
- * We're not deleting all events, so we must resubmit the
- * event that we are still interested in if one exists.
- */
-
- if ((events & POLLIN) && evdp->evwrite != NULL) {
- /* Deleting read, still care about write */
- devpoll_queue(devpollop, fd, POLLOUT);
- needwritedelete = 0;
- } else if ((events & POLLOUT) && evdp->evread != NULL) {
- /* Deleting write, still care about read */
- devpoll_queue(devpollop, fd, POLLIN);
- needreaddelete = 0;
- }
- }
-
- if (needreaddelete)
- evdp->evread = NULL;
- if (needwritedelete)
- evdp->evwrite = NULL;
-
- return (0);
-}
-
-static void
-devpoll_dealloc(struct event_base *base, void *arg)
-{
- struct devpollop *devpollop = arg;
-
- evsignal_dealloc(base);
- if (devpollop->fds)
- free(devpollop->fds);
- if (devpollop->events)
- free(devpollop->events);
- if (devpollop->changes)
- free(devpollop->changes);
- if (devpollop->dpfd >= 0)
- close(devpollop->dpfd);
-
- memset(devpollop, 0, sizeof(struct devpollop));
- free(devpollop);
-}
-
-#endif /* HAVE_DEVPOLL */
diff --git a/extra/libevent/epoll.c b/extra/libevent/epoll.c
deleted file mode 100644
index 93ed5b83aa4..00000000000
--- a/extra/libevent/epoll.c
+++ /dev/null
@@ -1,360 +0,0 @@
-/*
- * Copyright 2000-2003 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 BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef HAVE_EPOLL
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <sys/resource.h>
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#else
-#include <sys/_time.h>
-#endif
-#include <sys/queue.h>
-#include <sys/epoll.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-
-#include "event.h"
-#include "event-internal.h"
-#include "evsignal.h"
-#include "log.h"
-
-/* due to limitations in the epoll interface, we need to keep track of
- * all file descriptors outself.
- */
-struct evepoll {
- struct event *evread;
- struct event *evwrite;
-};
-
-struct epollop {
- struct evepoll *fds;
- int nfds;
- struct epoll_event *events;
- int nevents;
- int epfd;
-};
-
-static void *epoll_init (struct event_base *);
-static int epoll_add (void *, struct event *);
-static int epoll_del (void *, struct event *);
-static int epoll_dispatch (struct event_base *, void *, struct timeval *);
-static void epoll_dealloc (struct event_base *, void *);
-
-struct eventop epollops = {
- "epoll",
- epoll_init,
- epoll_add,
- epoll_del,
- epoll_dispatch,
- epoll_dealloc,
- 1 /* need reinit */
-};
-
-#ifdef HAVE_SETFD
-#define FD_CLOSEONEXEC(x) do { \
- if (fcntl(x, F_SETFD, 1) == -1) \
- event_warn("fcntl(%d, F_SETFD)", x); \
-} while (0)
-#else
-#define FD_CLOSEONEXEC(x)
-#endif
-
-#define NEVENT 32000
-
-static void *
-epoll_init(struct event_base *base)
-{
- int epfd, nfiles = NEVENT;
- struct rlimit rl;
- struct epollop *epollop;
-
- /* Disable epollueue when this environment variable is set */
- if (getenv("EVENT_NOEPOLL"))
- return (NULL);
-
- if (getrlimit(RLIMIT_NOFILE, &rl) == 0 &&
- rl.rlim_cur != RLIM_INFINITY) {
- /*
- * Solaris is somewhat retarded - it's important to drop
- * backwards compatibility when making changes. So, don't
- * dare to put rl.rlim_cur here.
- */
- nfiles = rl.rlim_cur - 1;
- }
-
- /* Initalize the kernel queue */
-
- if ((epfd = epoll_create(nfiles)) == -1) {
- event_warn("epoll_create");
- return (NULL);
- }
-
- FD_CLOSEONEXEC(epfd);
-
- if (!(epollop = calloc(1, sizeof(struct epollop))))
- return (NULL);
-
- epollop->epfd = epfd;
-
- /* Initalize fields */
- epollop->events = malloc(nfiles * sizeof(struct epoll_event));
- if (epollop->events == NULL) {
- free(epollop);
- return (NULL);
- }
- epollop->nevents = nfiles;
-
- epollop->fds = calloc(nfiles, sizeof(struct evepoll));
- if (epollop->fds == NULL) {
- free(epollop->events);
- free(epollop);
- return (NULL);
- }
- epollop->nfds = nfiles;
-
- evsignal_init(base);
-
- return (epollop);
-}
-
-static int
-epoll_recalc(struct event_base *base __attribute__((unused)), void *arg,
- int max)
-{
- struct epollop *epollop = arg;
-
- if (max > epollop->nfds) {
- struct evepoll *fds;
- int nfds;
-
- nfds = epollop->nfds;
- while (nfds < max)
- nfds <<= 1;
-
- fds = realloc(epollop->fds, nfds * sizeof(struct evepoll));
- if (fds == NULL) {
- event_warn("realloc");
- return (-1);
- }
- epollop->fds = fds;
- memset(fds + epollop->nfds, 0,
- (nfds - epollop->nfds) * sizeof(struct evepoll));
- epollop->nfds = nfds;
- }
-
- return (0);
-}
-
-static int
-epoll_dispatch(struct event_base *base, void *arg, struct timeval *tv)
-{
- struct epollop *epollop = arg;
- struct epoll_event *events = epollop->events;
- struct evepoll *evep;
- int i, res, timeout = -1;
-
- if (tv != NULL)
- timeout = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000;
-
- res = epoll_wait(epollop->epfd, events, epollop->nevents, timeout);
-
- if (res == -1) {
- if (errno != EINTR) {
- event_warn("epoll_wait");
- return (-1);
- }
-
- evsignal_process(base);
- return (0);
- } else if (base->sig.evsignal_caught) {
- evsignal_process(base);
- }
-
- event_debug(("%s: epoll_wait reports %d", __func__, res));
-
- for (i = 0; i < res; i++) {
- int what = events[i].events;
- struct event *evread = NULL, *evwrite = NULL;
-
- evep = (struct evepoll *)events[i].data.ptr;
-
- if (what & (EPOLLHUP|EPOLLERR)) {
- evread = evep->evread;
- evwrite = evep->evwrite;
- } else {
- if (what & EPOLLIN) {
- evread = evep->evread;
- }
-
- if (what & EPOLLOUT) {
- evwrite = evep->evwrite;
- }
- }
-
- if (!(evread||evwrite))
- continue;
-
- if (evread != NULL)
- event_active(evread, EV_READ, 1);
- if (evwrite != NULL)
- event_active(evwrite, EV_WRITE, 1);
- }
-
- return (0);
-}
-
-
-static int
-epoll_add(void *arg, struct event *ev)
-{
- struct epollop *epollop = arg;
- struct epoll_event epev = {0, {0}};
- struct evepoll *evep;
- int fd, op, events;
-
- if (ev->ev_events & EV_SIGNAL)
- return (evsignal_add(ev));
-
- fd = ev->ev_fd;
- if (fd >= epollop->nfds) {
- /* Extent the file descriptor array as necessary */
- if (epoll_recalc(ev->ev_base, epollop, fd) == -1)
- return (-1);
- }
- evep = &epollop->fds[fd];
- op = EPOLL_CTL_ADD;
- events = 0;
- if (evep->evread != NULL) {
- events |= EPOLLIN;
- op = EPOLL_CTL_MOD;
- }
- if (evep->evwrite != NULL) {
- events |= EPOLLOUT;
- op = EPOLL_CTL_MOD;
- }
-
- if (ev->ev_events & EV_READ)
- events |= EPOLLIN;
- if (ev->ev_events & EV_WRITE)
- events |= EPOLLOUT;
-
- epev.data.ptr = evep;
- epev.events = events;
- if (epoll_ctl(epollop->epfd, op, ev->ev_fd, &epev) == -1)
- return (-1);
-
- /* Update events responsible */
- if (ev->ev_events & EV_READ)
- evep->evread = ev;
- if (ev->ev_events & EV_WRITE)
- evep->evwrite = ev;
-
- return (0);
-}
-
-static int
-epoll_del(void *arg, struct event *ev)
-{
- struct epollop *epollop = arg;
- struct epoll_event epev = {0, {0}};
- struct evepoll *evep;
- int fd, events, op;
- int needwritedelete = 1, needreaddelete = 1;
-
- if (ev->ev_events & EV_SIGNAL)
- return (evsignal_del(ev));
-
- fd = ev->ev_fd;
- if (fd >= epollop->nfds)
- return (0);
- evep = &epollop->fds[fd];
-
- op = EPOLL_CTL_DEL;
- events = 0;
-
- if (ev->ev_events & EV_READ)
- events |= EPOLLIN;
- if (ev->ev_events & EV_WRITE)
- events |= EPOLLOUT;
-
- if ((events & (EPOLLIN|EPOLLOUT)) != (EPOLLIN|EPOLLOUT)) {
- if ((events & EPOLLIN) && evep->evwrite != NULL) {
- needwritedelete = 0;
- events = EPOLLOUT;
- op = EPOLL_CTL_MOD;
- } else if ((events & EPOLLOUT) && evep->evread != NULL) {
- needreaddelete = 0;
- events = EPOLLIN;
- op = EPOLL_CTL_MOD;
- }
- }
-
- epev.events = events;
- epev.data.ptr = evep;
-
- if (needreaddelete)
- evep->evread = NULL;
- if (needwritedelete)
- evep->evwrite = NULL;
-
- if (epoll_ctl(epollop->epfd, op, fd, &epev) == -1)
- return (-1);
-
- return (0);
-}
-
-static void
-epoll_dealloc(struct event_base *base, void *arg)
-{
- struct epollop *epollop = arg;
-
- evsignal_dealloc(base);
- if (epollop->fds)
- free(epollop->fds);
- if (epollop->events)
- free(epollop->events);
- if (epollop->epfd >= 0)
- close(epollop->epfd);
-
- memset(epollop, 0, sizeof(struct epollop));
- free(epollop);
-}
-
-#endif /* HAVE_EPOLL */
diff --git a/extra/libevent/epoll_sub.c b/extra/libevent/epoll_sub.c
deleted file mode 100644
index 95daac3b276..00000000000
--- a/extra/libevent/epoll_sub.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 2003 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 BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef HAVE_EPOLL
-
-#include <stdint.h>
-
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/syscall.h>
-#include <sys/epoll.h>
-#include <unistd.h>
-
-int
-epoll_create(int size)
-{
- return (syscall(__NR_epoll_create, size));
-}
-
-int
-epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
-{
-
- return (syscall(__NR_epoll_ctl, epfd, op, fd, event));
-}
-
-int
-epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)
-{
- return (syscall(__NR_epoll_wait, epfd, events, maxevents, timeout));
-}
-
-#endif /* HAVE_EPOLL */
diff --git a/extra/libevent/evbuffer.c b/extra/libevent/evbuffer.c
deleted file mode 100644
index 97dc40c0e41..00000000000
--- a/extra/libevent/evbuffer.c
+++ /dev/null
@@ -1,420 +0,0 @@
-/*
- * Copyright (c) 2002-2004 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 BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <sys/types.h>
-
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#ifdef HAVE_STDARG_H
-#include <stdarg.h>
-#endif
-
-#ifdef WIN32
-#include <winsock2.h>
-#endif
-
-#include "evutil.h"
-#include "event.h"
-
-/* prototypes */
-
-void bufferevent_setwatermark(struct bufferevent *, short, size_t, size_t);
-void bufferevent_read_pressure_cb(struct evbuffer *, size_t, size_t, void *);
-
-static int
-bufferevent_add(struct event *ev, int timeout)
-{
- struct timeval tv, *ptv = NULL;
-
- if (timeout) {
- evutil_timerclear(&tv);
- tv.tv_sec = timeout;
- ptv = &tv;
- }
-
- return (event_add(ev, ptv));
-}
-
-/*
- * This callback is executed when the size of the input buffer changes.
- * We use it to apply back pressure on the reading side.
- */
-
-void
-bufferevent_read_pressure_cb(struct evbuffer *buf,
- size_t old __attribute__((unused)), size_t now,
- void *arg)
-{
- struct bufferevent *bufev = arg;
- /*
- * If we are below the watermark then reschedule reading if it's
- * still enabled.
- */
- if (bufev->wm_read.high == 0 || now < bufev->wm_read.high) {
- evbuffer_setcb(buf, NULL, NULL);
-
- if (bufev->enabled & EV_READ)
- bufferevent_add(&bufev->ev_read, bufev->timeout_read);
- }
-}
-
-static void
-bufferevent_readcb(int fd, short event, void *arg)
-{
- struct bufferevent *bufev = arg;
- int res = 0;
- short what = EVBUFFER_READ;
- size_t len;
- int howmuch = -1;
-
- if (event == EV_TIMEOUT) {
- what |= EVBUFFER_TIMEOUT;
- goto error;
- }
-
- /*
- * If we have a high watermark configured then we don't want to
- * read more data than would make us reach the watermark.
- */
- if (bufev->wm_read.high != 0)
- howmuch = (int)bufev->wm_read.high;
-
- res = evbuffer_read(bufev->input, fd, howmuch);
- if (res == -1) {
- if (errno == EAGAIN || errno == EINTR)
- goto reschedule;
- /* error case */
- what |= EVBUFFER_ERROR;
- } else if (res == 0) {
- /* eof case */
- what |= EVBUFFER_EOF;
- }
-
- if (res <= 0)
- goto error;
-
- bufferevent_add(&bufev->ev_read, bufev->timeout_read);
-
- /* See if this callbacks meets the water marks */
- len = EVBUFFER_LENGTH(bufev->input);
- if (bufev->wm_read.low != 0 && len < bufev->wm_read.low)
- return;
- if (bufev->wm_read.high != 0 && len > bufev->wm_read.high) {
- struct evbuffer *buf = bufev->input;
- event_del(&bufev->ev_read);
-
- /* Now schedule a callback for us */
- evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev);
- return;
- }
-
- /* Invoke the user callback - must always be called last */
- if (bufev->readcb != NULL)
- (*bufev->readcb)(bufev, bufev->cbarg);
- return;
-
- reschedule:
- bufferevent_add(&bufev->ev_read, bufev->timeout_read);
- return;
-
- error:
- (*bufev->errorcb)(bufev, what, bufev->cbarg);
-}
-
-static void
-bufferevent_writecb(int fd, short event, void *arg)
-{
- struct bufferevent *bufev = arg;
- int res = 0;
- short what = EVBUFFER_WRITE;
-
- if (event == EV_TIMEOUT) {
- what |= EVBUFFER_TIMEOUT;
- goto error;
- }
-
- if (EVBUFFER_LENGTH(bufev->output)) {
- res = evbuffer_write(bufev->output, fd);
- if (res == -1) {
-#ifndef WIN32
-/*todo. evbuffer uses WriteFile when WIN32 is set. WIN32 system calls do not
- *set errno. thus this error checking is not portable*/
- if (errno == EAGAIN ||
- errno == EINTR ||
- errno == EINPROGRESS)
- goto reschedule;
- /* error case */
- what |= EVBUFFER_ERROR;
-
-#else
- goto reschedule;
-#endif
-
- } else if (res == 0) {
- /* eof case */
- what |= EVBUFFER_EOF;
- }
- if (res <= 0)
- goto error;
- }
-
- if (EVBUFFER_LENGTH(bufev->output) != 0)
- bufferevent_add(&bufev->ev_write, bufev->timeout_write);
-
- /*
- * Invoke the user callback if our buffer is drained or below the
- * low watermark.
- */
- if (bufev->writecb != NULL &&
- EVBUFFER_LENGTH(bufev->output) <= bufev->wm_write.low)
- (*bufev->writecb)(bufev, bufev->cbarg);
-
- return;
-
- reschedule:
- if (EVBUFFER_LENGTH(bufev->output) != 0)
- bufferevent_add(&bufev->ev_write, bufev->timeout_write);
- return;
-
- error:
- (*bufev->errorcb)(bufev, what, bufev->cbarg);
-}
-
-/*
- * Create a new buffered event object.
- *
- * The read callback is invoked whenever we read new data.
- * The write callback is invoked whenever the output buffer is drained.
- * The error callback is invoked on a write/read error or on EOF.
- *
- * Both read and write callbacks maybe NULL. The error callback is not
- * allowed to be NULL and have to be provided always.
- */
-
-struct bufferevent *
-bufferevent_new(int fd, evbuffercb readcb, evbuffercb writecb,
- everrorcb errorcb, void *cbarg)
-{
- struct bufferevent *bufev;
-
- if ((bufev = calloc(1, sizeof(struct bufferevent))) == NULL)
- return (NULL);
-
- if ((bufev->input = evbuffer_new()) == NULL) {
- free(bufev);
- return (NULL);
- }
-
- if ((bufev->output = evbuffer_new()) == NULL) {
- evbuffer_free(bufev->input);
- free(bufev);
- return (NULL);
- }
-
- event_set(&bufev->ev_read, fd, EV_READ, bufferevent_readcb, bufev);
- event_set(&bufev->ev_write, fd, EV_WRITE, bufferevent_writecb, bufev);
-
- bufev->readcb = readcb;
- bufev->writecb = writecb;
- bufev->errorcb = errorcb;
-
- bufev->cbarg = cbarg;
-
- /*
- * Set to EV_WRITE so that using bufferevent_write is going to
- * trigger a callback. Reading needs to be explicitly enabled
- * because otherwise no data will be available.
- */
- bufev->enabled = EV_WRITE;
-
- return (bufev);
-}
-
-int
-bufferevent_priority_set(struct bufferevent *bufev, int priority)
-{
- if (event_priority_set(&bufev->ev_read, priority) == -1)
- return (-1);
- if (event_priority_set(&bufev->ev_write, priority) == -1)
- return (-1);
-
- return (0);
-}
-
-/* Closing the file descriptor is the responsibility of the caller */
-
-void
-bufferevent_free(struct bufferevent *bufev)
-{
- event_del(&bufev->ev_read);
- event_del(&bufev->ev_write);
-
- evbuffer_free(bufev->input);
- evbuffer_free(bufev->output);
-
- free(bufev);
-}
-
-/*
- * Returns 0 on success;
- * -1 on failure.
- */
-
-int
-bufferevent_write(struct bufferevent *bufev, const void *data, size_t size)
-{
- int res;
-
- res = evbuffer_add(bufev->output, data, size);
-
- if (res == -1)
- return (res);
-
- /* If everything is okay, we need to schedule a write */
- if (size > 0 && (bufev->enabled & EV_WRITE))
- bufferevent_add(&bufev->ev_write, bufev->timeout_write);
-
- return (res);
-}
-
-int
-bufferevent_write_buffer(struct bufferevent *bufev, struct evbuffer *buf)
-{
- int res;
-
- res = bufferevent_write(bufev, buf->buffer, buf->off);
- if (res != -1)
- evbuffer_drain(buf, buf->off);
-
- return (res);
-}
-
-size_t
-bufferevent_read(struct bufferevent *bufev, void *data, size_t size)
-{
- struct evbuffer *buf = bufev->input;
-
- if (buf->off < size)
- size = buf->off;
-
- /* Copy the available data to the user buffer */
- memcpy(data, buf->buffer, size);
-
- if (size)
- evbuffer_drain(buf, size);
-
- return (size);
-}
-
-int
-bufferevent_enable(struct bufferevent *bufev, short event)
-{
- if (event & EV_READ) {
- if (bufferevent_add(&bufev->ev_read, bufev->timeout_read) == -1)
- return (-1);
- }
- if (event & EV_WRITE) {
- if (bufferevent_add(&bufev->ev_write, bufev->timeout_write) == -1)
- return (-1);
- }
-
- bufev->enabled |= event;
- return (0);
-}
-
-int
-bufferevent_disable(struct bufferevent *bufev, short event)
-{
- if (event & EV_READ) {
- if (event_del(&bufev->ev_read) == -1)
- return (-1);
- }
- if (event & EV_WRITE) {
- if (event_del(&bufev->ev_write) == -1)
- return (-1);
- }
-
- bufev->enabled &= ~event;
- return (0);
-}
-
-/*
- * Sets the read and write timeout for a buffered event.
- */
-
-void
-bufferevent_settimeout(struct bufferevent *bufev,
- int timeout_read, int timeout_write) {
- bufev->timeout_read = timeout_read;
- bufev->timeout_write = timeout_write;
-}
-
-/*
- * Sets the water marks
- */
-
-void
-bufferevent_setwatermark(struct bufferevent *bufev, short events,
- size_t lowmark, size_t highmark)
-{
- if (events & EV_READ) {
- bufev->wm_read.low = lowmark;
- bufev->wm_read.high = highmark;
- }
-
- if (events & EV_WRITE) {
- bufev->wm_write.low = lowmark;
- bufev->wm_write.high = highmark;
- }
-
- /* If the watermarks changed then see if we should call read again */
- bufferevent_read_pressure_cb(bufev->input,
- 0, EVBUFFER_LENGTH(bufev->input), bufev);
-}
-
-int
-bufferevent_base_set(struct event_base *base, struct bufferevent *bufev)
-{
- int res;
-
- res = event_base_set(base, &bufev->ev_read);
- if (res == -1)
- return (res);
-
- res = event_base_set(base, &bufev->ev_write);
- return (res);
-}
diff --git a/extra/libevent/evdns.c b/extra/libevent/evdns.c
deleted file mode 100644
index de08a18ca19..00000000000
--- a/extra/libevent/evdns.c
+++ /dev/null
@@ -1,3150 +0,0 @@
-/* $Id: evdns.c 6979 2006-08-04 18:31:13Z nickm $ */
-
-/* The original version of this module was written by Adam Langley; for
- * a history of modifications, check out the subversion logs.
- *
- * When editing this module, try to keep it re-mergeable by Adam. Don't
- * reformat the whitespace, add Tor dependencies, or so on.
- *
- * TODO:
- * - Support IPv6 and PTR records.
- * - Replace all externally visible magic numbers with #defined constants.
- * - Write doccumentation for APIs of all external functions.
- */
-
-/* Async DNS Library
- * Adam Langley <agl@imperialviolet.org>
- * http://www.imperialviolet.org/eventdns.html
- * Public Domain code
- *
- * This software is Public Domain. To view a copy of the public domain dedication,
- * visit http://creativecommons.org/licenses/publicdomain/ or send a letter to
- * Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.
- *
- * I ask and expect, but do not require, that all derivative works contain an
- * attribution similar to:
- * Parts developed by Adam Langley <agl@imperialviolet.org>
- *
- * You may wish to replace the word "Parts" with something else depending on
- * the amount of original code.
- *
- * (Derivative works does not include programs which link against, run or include
- * the source verbatim in their source distributions)
- *
- * Version: 0.1b
- */
-
-#include <sys/types.h>
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef WIN32
-#include "misc.h"
-#endif
-
-#ifdef DNS_USE_FTIME_FOR_ID
-#include <sys/timeb.h>
-#endif
-
-#ifndef DNS_USE_CPU_CLOCK_FOR_ID
-#ifndef DNS_USE_GETTIMEOFDAY_FOR_ID
-#ifndef DNS_USE_OPENSSL_FOR_ID
-#ifndef DNS_USE_FTIME_FOR_ID
-#error Must configure at least one id generation method.
-#error Please see the documentation.
-#endif
-#endif
-#endif
-#endif
-
-/* #define _POSIX_C_SOURCE 200507 */
-#define _GNU_SOURCE
-
-#ifdef DNS_USE_CPU_CLOCK_FOR_ID
-#ifdef DNS_USE_OPENSSL_FOR_ID
-#error Multiple id options selected
-#endif
-#ifdef DNS_USE_GETTIMEOFDAY_FOR_ID
-#error Multiple id options selected
-#endif
-#include <time.h>
-#endif
-
-#ifdef DNS_USE_OPENSSL_FOR_ID
-#ifdef DNS_USE_GETTIMEOFDAY_FOR_ID
-#error Multiple id options selected
-#endif
-#include <openssl/rand.h>
-#endif
-
-#define _FORTIFY_SOURCE 3
-
-#include <string.h>
-#include <fcntl.h>
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#ifdef HAVE_STDINT_H
-#include <stdint.h>
-#endif
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <assert.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <limits.h>
-#include <sys/stat.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <stdarg.h>
-
-#include "evdns.h"
-#include "evutil.h"
-#include "log.h"
-#ifdef WIN32
-#include <winsock2.h>
-#include <windows.h>
-#include <iphlpapi.h>
-#include <io.h>
-#else
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#endif
-
-#ifdef HAVE_NETINET_IN6_H
-#include <netinet/in6.h>
-#endif
-
-#define EVDNS_LOG_DEBUG 0
-#define EVDNS_LOG_WARN 1
-
-#ifndef HOST_NAME_MAX
-#define HOST_NAME_MAX 255
-#endif
-
-#include <stdio.h>
-
-#undef MIN
-#define MIN(a,b) ((a)<(b)?(a):(b))
-
-#ifdef __USE_ISOC99B
-/* libevent doesn't work without this */
-typedef ev_uint8_t u_char;
-typedef unsigned int uint;
-#endif
-#include <event.h>
-
-#define u64 ev_uint64_t
-#define u32 ev_uint32_t
-#define u16 ev_uint16_t
-#define u8 ev_uint8_t
-
-#ifdef WIN32
-#define snprintf _snprintf
-#define open _open
-#define read _read
-#define close _close
-#define strdup _strdup
-#endif
-
-#define MAX_ADDRS 32 /* maximum number of addresses from a single packet */
-/* which we bother recording */
-
-#define TYPE_A EVDNS_TYPE_A
-#define TYPE_CNAME 5
-#define TYPE_PTR EVDNS_TYPE_PTR
-#define TYPE_AAAA EVDNS_TYPE_AAAA
-
-#define CLASS_INET EVDNS_CLASS_INET
-
-struct request {
- u8 *request; /* the dns packet data */
- unsigned int request_len;
- int reissue_count;
- int tx_count; /* the number of times that this packet has been sent */
- unsigned int request_type; /* TYPE_PTR or TYPE_A */
- void *user_pointer; /* the pointer given to us for this request */
- evdns_callback_type user_callback;
- struct nameserver *ns; /* the server which we last sent it */
-
- /* elements used by the searching code */
- int search_index;
- struct search_state *search_state;
- char *search_origname; /* needs to be free()ed */
- int search_flags;
-
- /* these objects are kept in a circular list */
- struct request *next, *prev;
-
- struct event timeout_event;
-
- u16 trans_id; /* the transaction id */
- char request_appended; /* true if the request pointer is data which follows this struct */
- char transmit_me; /* needs to be transmitted */
-};
-
-#ifndef HAVE_STRUCT_IN6_ADDR
-struct in6_addr {
- u8 s6_addr[16];
-};
-#endif
-
-struct reply {
- unsigned int type;
- unsigned int have_answer;
- union {
- struct {
- u32 addrcount;
- u32 addresses[MAX_ADDRS];
- } a;
- struct {
- u32 addrcount;
- struct in6_addr addresses[MAX_ADDRS];
- } aaaa;
- struct {
- char name[HOST_NAME_MAX];
- } ptr;
- } data;
-};
-
-struct nameserver {
- int socket; /* a connected UDP socket */
- u32 address;
- int failed_times; /* number of times which we have given this server a chance */
- int timedout; /* number of times in a row a request has timed out */
- struct event event;
- /* these objects are kept in a circular list */
- struct nameserver *next, *prev;
- struct event timeout_event; /* used to keep the timeout for */
- /* when we next probe this server. */
- /* Valid if state == 0 */
- char state; /* zero if we think that this server is down */
- char choked; /* true if we have an EAGAIN from this server's socket */
- char write_waiting; /* true if we are waiting for EV_WRITE events */
-};
-
-static struct request *req_head = NULL, *req_waiting_head = NULL;
-static struct nameserver *server_head = NULL;
-
-/* Represents a local port where we're listening for DNS requests. Right now, */
-/* only UDP is supported. */
-struct evdns_server_port {
- int socket; /* socket we use to read queries and write replies. */
- int refcnt; /* reference count. */
- char choked; /* Are we currently blocked from writing? */
- char closing; /* Are we trying to close this port, pending writes? */
- evdns_request_callback_fn_type user_callback; /* Fn to handle requests */
- void *user_data; /* Opaque pointer passed to user_callback */
- struct event event; /* Read/write event */
- /* circular list of replies that we want to write. */
- struct server_request *pending_replies;
-};
-
-/* Represents part of a reply being built. (That is, a single RR.) */
-struct server_reply_item {
- struct server_reply_item *next; /* next item in sequence. */
- char *name; /* name part of the RR */
- u16 type : 16; /* The RR type */
- u16 class : 16; /* The RR class (usually CLASS_INET) */
- u32 ttl; /* The RR TTL */
- char is_name; /* True iff data is a label */
- u16 datalen; /* Length of data; -1 if data is a label */
- void *data; /* The contents of the RR */
-};
-
-/* Represents a request that we've received as a DNS server, and holds */
-/* the components of the reply as we're constructing it. */
-struct server_request {
- /* Pointers to the next and previous entries on the list of replies */
- /* that we're waiting to write. Only set if we have tried to respond */
- /* and gotten EAGAIN. */
- struct server_request *next_pending;
- struct server_request *prev_pending;
-
- u16 trans_id; /* Transaction id. */
- struct evdns_server_port *port; /* Which port received this request on? */
- struct sockaddr_storage addr; /* Where to send the response */
- socklen_t addrlen; /* length of addr */
-
- int n_answer; /* how many answer RRs have been set? */
- int n_authority; /* how many authority RRs have been set? */
- int n_additional; /* how many additional RRs have been set? */
-
- struct server_reply_item *answer; /* linked list of answer RRs */
- struct server_reply_item *authority; /* linked list of authority RRs */
- struct server_reply_item *additional; /* linked list of additional RRs */
-
- /* Constructed response. Only set once we're ready to send a reply. */
- /* Once this is set, the RR fields are cleared, and no more should be set. */
- char *response;
- size_t response_len;
-
- /* Caller-visible fields: flags, questions. */
- struct evdns_server_request base;
-};
-
-/* helper macro */
-#define OFFSET_OF(st, member) ((off_t) (((char*)&((st*)0)->member)-(char*)0))
-
-/* Given a pointer to an evdns_server_request, get the corresponding */
-/* server_request. */
-#define TO_SERVER_REQUEST(base_ptr) \
- ((struct server_request*) \
- (((char*)(base_ptr) - OFFSET_OF(struct server_request, base))))
-
-/* The number of good nameservers that we have */
-static int global_good_nameservers = 0;
-
-/* inflight requests are contained in the req_head list */
-/* and are actually going out across the network */
-static int global_requests_inflight = 0;
-/* requests which aren't inflight are in the waiting list */
-/* and are counted here */
-static int global_requests_waiting = 0;
-
-static int global_max_requests_inflight = 64;
-
-static struct timeval global_timeout = {5, 0}; /* 5 seconds */
-static int global_max_reissues = 1; /* a reissue occurs when we get some errors from the server */
-static int global_max_retransmits = 3; /* number of times we'll retransmit a request which timed out */
-/* number of timeouts in a row before we consider this server to be down */
-static int global_max_nameserver_timeout = 3;
-
-/* These are the timeout values for nameservers. If we find a nameserver is down */
-/* we try to probe it at intervals as given below. Values are in seconds. */
-static const struct timeval global_nameserver_timeouts[] = {{10, 0}, {60, 0}, {300, 0}, {900, 0}, {3600, 0}};
-static const int global_nameserver_timeouts_length = sizeof(global_nameserver_timeouts)/sizeof(struct timeval);
-
-static struct nameserver *nameserver_pick(void);
-static void evdns_request_insert(struct request *req, struct request **head);
-static void nameserver_ready_callback(int fd, short events, void *arg);
-static int evdns_transmit(void);
-static int evdns_request_transmit(struct request *req);
-static void nameserver_send_probe(struct nameserver *const ns);
-static void search_request_finished(struct request *const);
-static int search_try_next(struct request *const req);
-static int search_request_new(int type, const char *const name, int flags, evdns_callback_type user_callback, void *user_arg);
-static void evdns_requests_pump_waiting_queue(void);
-static u16 transaction_id_pick(void);
-static struct request *request_new(int type, const char *name, int flags, evdns_callback_type callback, void *ptr);
-static void request_submit(struct request *const req);
-
-static int server_request_free(struct server_request *req);
-static void server_request_free_answers(struct server_request *req);
-static void server_port_free(struct evdns_server_port *port);
-static void server_port_ready_callback(int fd, short events, void *arg);
-
-static int strtoint(const char *const str);
-
-#ifdef WIN32
-static int
-last_error(int sock)
-{
- int optval, optvallen=sizeof(optval);
- int err = WSAGetLastError();
- if (err == WSAEWOULDBLOCK && sock >= 0) {
- if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)&optval,
- &optvallen))
- return err;
- if (optval)
- return optval;
- }
- return err;
-
-}
-static int
-error_is_eagain(int err)
-{
- return err == EAGAIN || err == WSAEWOULDBLOCK;
-}
-static int
-inet_aton(const char *c, struct in_addr *addr)
-{
- ev_uint32_t r;
- if (strcmp(c, "255.255.255.255") == 0) {
- addr->s_addr = 0xffffffffu;
- } else {
- r = inet_addr(c);
- if (r == INADDR_NONE)
- return 0;
- addr->s_addr = r;
- }
- return 1;
-}
-#else
-#define last_error(sock) (errno)
-#define error_is_eagain(err) ((err) == EAGAIN)
-#endif
-#define CLOSE_SOCKET(s) EVUTIL_CLOSESOCKET(s)
-
-#define ISSPACE(c) isspace((int)(unsigned char)(c))
-#define ISDIGIT(c) isdigit((int)(unsigned char)(c))
-
-static const char *
-debug_ntoa(u32 address)
-{
- static char buf[32];
- u32 a = ntohl(address);
- snprintf(buf, sizeof(buf), "%d.%d.%d.%d",
- (int)(u8)((a>>24)&0xff),
- (int)(u8)((a>>16)&0xff),
- (int)(u8)((a>>8 )&0xff),
- (int)(u8)((a )&0xff));
- return buf;
-}
-
-static evdns_debug_log_fn_type evdns_log_fn = NULL;
-
-void
-evdns_set_log_fn(evdns_debug_log_fn_type fn)
-{
- evdns_log_fn = fn;
-}
-
-#ifdef __GNUC__
-#define EVDNS_LOG_CHECK __attribute__ ((format(printf, 2, 3)))
-#else
-#define EVDNS_LOG_CHECK
-#endif
-
-static void _evdns_log(int warn, const char *fmt, ...) EVDNS_LOG_CHECK;
-static void
-_evdns_log(int warn, const char *fmt, ...)
-{
- va_list args;
- static char buf[512];
- if (!evdns_log_fn)
- return;
- va_start(args,fmt);
-#ifdef WIN32
- _vsnprintf(buf, sizeof(buf), fmt, args);
-#else
- vsnprintf(buf, sizeof(buf), fmt, args);
-#endif
- buf[sizeof(buf)-1] = '\0';
- evdns_log_fn(warn, buf);
- va_end(args);
-}
-
-#define log _evdns_log
-
-/* This walks the list of inflight requests to find the */
-/* one with a matching transaction id. Returns NULL on */
-/* failure */
-static struct request *
-request_find_from_trans_id(u16 trans_id) {
- struct request *req = req_head, *const started_at = req_head;
-
- if (req) {
- do {
- if (req->trans_id == trans_id) return req;
- req = req->next;
- } while (req != started_at);
- }
-
- return NULL;
-}
-
-/* a libevent callback function which is called when a nameserver */
-/* has gone down and we want to test if it has came back to life yet */
-static void
-nameserver_prod_callback(int fd, short events, void *arg) {
- struct nameserver *const ns = (struct nameserver *) arg;
- (void)fd;
- (void)events;
-
- nameserver_send_probe(ns);
-}
-
-/* a libevent callback which is called when a nameserver probe (to see if */
-/* it has come back to life) times out. We increment the count of failed_times */
-/* and wait longer to send the next probe packet. */
-static void
-nameserver_probe_failed(struct nameserver *const ns) {
- const struct timeval * timeout;
- (void) evtimer_del(&ns->timeout_event);
- if (ns->state == 1) {
- /* This can happen if the nameserver acts in a way which makes us mark */
- /* it as bad and then starts sending good replies. */
- return;
- }
-
- timeout =
- &global_nameserver_timeouts[MIN(ns->failed_times,
- global_nameserver_timeouts_length - 1)];
- ns->failed_times++;
-
- evtimer_set(&ns->timeout_event, nameserver_prod_callback, ns);
- if (evtimer_add(&ns->timeout_event, (struct timeval *) timeout) < 0) {
- log(EVDNS_LOG_WARN,
- "Error from libevent when adding timer event for %s",
- debug_ntoa(ns->address));
- /* ???? Do more? */
- }
-}
-
-/* called when a nameserver has been deemed to have failed. For example, too */
-/* many packets have timed out etc */
-static void
-nameserver_failed(struct nameserver *const ns, const char *msg) {
- struct request *req, *started_at;
- /* if this nameserver has already been marked as failed */
- /* then don't do anything */
- if (!ns->state) return;
-
- log(EVDNS_LOG_WARN, "Nameserver %s has failed: %s",
- debug_ntoa(ns->address), msg);
- global_good_nameservers--;
- assert(global_good_nameservers >= 0);
- if (global_good_nameservers == 0) {
- log(EVDNS_LOG_WARN, "All nameservers have failed");
- }
-
- ns->state = 0;
- ns->failed_times = 1;
-
- evtimer_set(&ns->timeout_event, nameserver_prod_callback, ns);
- if (evtimer_add(&ns->timeout_event, (struct timeval *) &global_nameserver_timeouts[0]) < 0) {
- log(EVDNS_LOG_WARN,
- "Error from libevent when adding timer event for %s",
- debug_ntoa(ns->address));
- /* ???? Do more? */
- }
-
- /* walk the list of inflight requests to see if any can be reassigned to */
- /* a different server. Requests in the waiting queue don't have a */
- /* nameserver assigned yet */
-
- /* if we don't have *any* good nameservers then there's no point */
- /* trying to reassign requests to one */
- if (!global_good_nameservers) return;
-
- req = req_head;
- started_at = req_head;
- if (req) {
- do {
- if (req->tx_count == 0 && req->ns == ns) {
- /* still waiting to go out, can be moved */
- /* to another server */
- req->ns = nameserver_pick();
- }
- req = req->next;
- } while (req != started_at);
- }
-}
-
-static void
-nameserver_up(struct nameserver *const ns) {
- if (ns->state) return;
- log(EVDNS_LOG_WARN, "Nameserver %s is back up",
- debug_ntoa(ns->address));
- evtimer_del(&ns->timeout_event);
- ns->state = 1;
- ns->failed_times = 0;
- ns->timedout = 0;
- global_good_nameservers++;
-}
-
-static void
-request_trans_id_set(struct request *const req, const u16 trans_id) {
- req->trans_id = trans_id;
- *((u16 *) req->request) = htons(trans_id);
-}
-
-/* Called to remove a request from a list and dealloc it. */
-/* head is a pointer to the head of the list it should be */
-/* removed from or NULL if the request isn't in a list. */
-static void
-request_finished(struct request *const req, struct request **head) {
- if (head) {
- if (req->next == req) {
- /* only item in the list */
- *head = NULL;
- } else {
- req->next->prev = req->prev;
- req->prev->next = req->next;
- if (*head == req) *head = req->next;
- }
- }
-
- log(EVDNS_LOG_DEBUG, "Removing timeout for request %lx",
- (unsigned long) req);
- evtimer_del(&req->timeout_event);
-
- search_request_finished(req);
- global_requests_inflight--;
-
- if (!req->request_appended) {
- /* need to free the request data on it's own */
- free(req->request);
- } else {
- /* the request data is appended onto the header */
- /* so everything gets free()ed when we: */
- }
-
- free(req);
-
- evdns_requests_pump_waiting_queue();
-}
-
-/* This is called when a server returns a funny error code. */
-/* We try the request again with another server. */
-/* */
-/* return: */
-/* 0 ok */
-/* 1 failed/reissue is pointless */
-static int
-request_reissue(struct request *req) {
- const struct nameserver *const last_ns = req->ns;
- /* the last nameserver should have been marked as failing */
- /* by the caller of this function, therefore pick will try */
- /* not to return it */
- req->ns = nameserver_pick();
- if (req->ns == last_ns) {
- /* ... but pick did return it */
- /* not a lot of point in trying again with the */
- /* same server */
- return 1;
- }
-
- req->reissue_count++;
- req->tx_count = 0;
- req->transmit_me = 1;
-
- return 0;
-}
-
-/* this function looks for space on the inflight queue and promotes */
-/* requests from the waiting queue if it can. */
-static void
-evdns_requests_pump_waiting_queue(void) {
- while (global_requests_inflight < global_max_requests_inflight &&
- global_requests_waiting) {
- struct request *req;
- /* move a request from the waiting queue to the inflight queue */
- assert(req_waiting_head);
- if (req_waiting_head->next == req_waiting_head) {
- /* only one item in the queue */
- req = req_waiting_head;
- req_waiting_head = NULL;
- } else {
- req = req_waiting_head;
- req->next->prev = req->prev;
- req->prev->next = req->next;
- req_waiting_head = req->next;
- }
-
- global_requests_waiting--;
- global_requests_inflight++;
-
- req->ns = nameserver_pick();
- request_trans_id_set(req, transaction_id_pick());
-
- evdns_request_insert(req, &req_head);
- evdns_request_transmit(req);
- evdns_transmit();
- }
-}
-
-static void
-reply_callback(struct request *const req, u32 ttl, u32 err, struct reply *reply) {
- switch (req->request_type) {
- case TYPE_A:
- if (reply)
- req->user_callback(DNS_ERR_NONE, DNS_IPv4_A,
- reply->data.a.addrcount, ttl,
- reply->data.a.addresses,
- req->user_pointer);
- else
- req->user_callback(err, 0, 0, 0, NULL, req->user_pointer);
- return;
- case TYPE_PTR:
- if (reply) {
- char *name = reply->data.ptr.name;
- req->user_callback(DNS_ERR_NONE, DNS_PTR, 1, ttl,
- &name, req->user_pointer);
- } else {
- req->user_callback(err, 0, 0, 0, NULL,
- req->user_pointer);
- }
- return;
- case TYPE_AAAA:
- if (reply)
- req->user_callback(DNS_ERR_NONE, DNS_IPv6_AAAA,
- reply->data.aaaa.addrcount, ttl,
- reply->data.aaaa.addresses,
- req->user_pointer);
- else
- req->user_callback(err, 0, 0, 0, NULL, req->user_pointer);
- return;
- }
- assert(0);
-}
-
-/* this processes a parsed reply packet */
-static void
-reply_handle(struct request *const req, u16 flags, u32 ttl, struct reply *reply) {
- int error;
- static const int error_codes[] = {DNS_ERR_FORMAT, DNS_ERR_SERVERFAILED, DNS_ERR_NOTEXIST, DNS_ERR_NOTIMPL, DNS_ERR_REFUSED};
-
- if (flags & 0x020f || !reply || !reply->have_answer) {
- /* there was an error */
- if (flags & 0x0200) {
- error = DNS_ERR_TRUNCATED;
- } else {
- u16 error_code = (flags & 0x000f) - 1;
- if (error_code > 4) {
- error = DNS_ERR_UNKNOWN;
- } else {
- error = error_codes[error_code];
- }
- }
-
- switch(error) {
- case DNS_ERR_NOTIMPL:
- case DNS_ERR_REFUSED:
- /* we regard these errors as marking a bad nameserver */
- if (req->reissue_count < global_max_reissues) {
- char msg[64];
- snprintf(msg, sizeof(msg), "Bad response %d (%s)",
- error, evdns_err_to_string(error));
- nameserver_failed(req->ns, msg);
- if (!request_reissue(req)) return;
- }
- break;
- case DNS_ERR_SERVERFAILED:
- /* rcode 2 (servfailed) sometimes means "we are broken" and
- * sometimes (with some binds) means "that request was very
- * confusing." Treat this as a timeout, not a failure.
- */
- log(EVDNS_LOG_DEBUG, "Got a SERVERFAILED from nameserver %s; "
- "will allow the request to time out.",
- debug_ntoa(req->ns->address));
- break;
- default:
- /* we got a good reply from the nameserver */
- nameserver_up(req->ns);
- }
-
- if (req->search_state && req->request_type != TYPE_PTR) {
- /* if we have a list of domains to search in, try the next one */
- if (!search_try_next(req)) {
- /* a new request was issued so this request is finished and */
- /* the user callback will be made when that request (or a */
- /* child of it) finishes. */
- request_finished(req, &req_head);
- return;
- }
- }
-
- /* all else failed. Pass the failure up */
- reply_callback(req, 0, error, NULL);
- request_finished(req, &req_head);
- } else {
- /* all ok, tell the user */
- reply_callback(req, ttl, 0, reply);
- nameserver_up(req->ns);
- request_finished(req, &req_head);
- }
-}
-
-static int
-name_parse(u8 *packet, int length, int *idx, char *name_out, int name_out_len) {
- int name_end = -1;
- int j = *idx;
- int ptr_count = 0;
-#define GET32(x) do { if (j + 4 > length) goto err; memcpy(&_t32, packet + j, 4); j += 4; x = ntohl(_t32); } while(0)
-#define GET16(x) do { if (j + 2 > length) goto err; memcpy(&_t, packet + j, 2); j += 2; x = ntohs(_t); } while(0)
-#define GET8(x) do { if (j >= length) goto err; x = packet[j++]; } while(0)
-
- char *cp = name_out;
- const char *const end = name_out + name_out_len;
-
- /* Normally, names are a series of length prefixed strings terminated */
- /* with a length of 0 (the lengths are u8's < 63). */
- /* However, the length can start with a pair of 1 bits and that */
- /* means that the next 14 bits are a pointer within the current */
- /* packet. */
-
- for(;;) {
- u8 label_len;
- if (j >= length) return -1;
- GET8(label_len);
- if (!label_len) break;
- if (label_len & 0xc0) {
- u8 ptr_low;
- GET8(ptr_low);
- if (name_end < 0) name_end = j;
- j = (((int)label_len & 0x3f) << 8) + ptr_low;
- /* Make sure that the target offset is in-bounds. */
- if (j < 0 || j >= length) return -1;
- /* If we've jumped more times than there are characters in the
- * message, we must have a loop. */
- if (++ptr_count > length) return -1;
- continue;
- }
- if (label_len > 63) return -1;
- if (cp != name_out) {
- if (cp + 1 >= end) return -1;
- *cp++ = '.';
- }
- if (cp + label_len >= end) return -1;
- memcpy(cp, packet + j, label_len);
- cp += label_len;
- j += label_len;
- }
- if (cp >= end) return -1;
- *cp = '\0';
- if (name_end < 0)
- *idx = j;
- else
- *idx = name_end;
- return 0;
- err:
- return -1;
-}
-
-/* parses a raw request from a nameserver */
-static int
-reply_parse(u8 *packet, int length) {
- int j = 0; /* index into packet */
- u16 _t; /* used by the macros */
- u32 _t32; /* used by the macros */
- char tmp_name[256]; /* used by the macros */
-
- u16 trans_id, questions, answers, authority, additional, datalength;
- u16 flags = 0;
- u32 ttl, ttl_r = 0xffffffff;
- struct reply reply;
- struct request *req = NULL;
- unsigned int i;
-
- GET16(trans_id);
- GET16(flags);
- GET16(questions);
- GET16(answers);
- GET16(authority);
- GET16(additional);
- (void) authority; /* suppress "unused variable" warnings. */
- (void) additional; /* suppress "unused variable" warnings. */
-
- req = request_find_from_trans_id(trans_id);
- if (!req) return -1;
-
- memset(&reply, 0, sizeof(reply));
-
- /* If it's not an answer, it doesn't correspond to any request. */
- if (!(flags & 0x8000)) return -1; /* must be an answer */
- if (flags & 0x020f) {
- /* there was an error */
- goto err;
- }
- /* if (!answers) return; */ /* must have an answer of some form */
-
- /* This macro skips a name in the DNS reply. */
-#define SKIP_NAME \
- do { tmp_name[0] = '\0'; \
- if (name_parse(packet, length, &j, tmp_name, sizeof(tmp_name))<0) \
- goto err; \
- } while(0);
-
- reply.type = req->request_type;
-
- /* skip over each question in the reply */
- for (i = 0; i < questions; ++i) {
- /* the question looks like
- * <label:name><u16:type><u16:class>
- */
- SKIP_NAME;
- j += 4;
- if (j > length) goto err;
- }
-
- /* now we have the answer section which looks like
- * <label:name><u16:type><u16:class><u32:ttl><u16:len><data...>
- */
-
- for (i = 0; i < answers; ++i) {
- u16 type, class;
-
- SKIP_NAME;
- GET16(type);
- GET16(class);
- GET32(ttl);
- GET16(datalength);
-
- if (type == TYPE_A && class == CLASS_INET) {
- int addrcount, addrtocopy;
- if (req->request_type != TYPE_A) {
- j += datalength; continue;
- }
- if ((datalength & 3) != 0) /* not an even number of As. */
- goto err;
- addrcount = datalength >> 2;
- addrtocopy = MIN(MAX_ADDRS - reply.data.a.addrcount, (unsigned)addrcount);
-
- ttl_r = MIN(ttl_r, ttl);
- /* we only bother with the first four addresses. */
- if (j + 4*addrtocopy > length) goto err;
- memcpy(&reply.data.a.addresses[reply.data.a.addrcount],
- packet + j, 4*addrtocopy);
- j += 4*addrtocopy;
- reply.data.a.addrcount += addrtocopy;
- reply.have_answer = 1;
- if (reply.data.a.addrcount == MAX_ADDRS) break;
- } else if (type == TYPE_PTR && class == CLASS_INET) {
- if (req->request_type != TYPE_PTR) {
- j += datalength; continue;
- }
- if (name_parse(packet, length, &j, reply.data.ptr.name,
- sizeof(reply.data.ptr.name))<0)
- goto err;
- ttl_r = MIN(ttl_r, ttl);
- reply.have_answer = 1;
- break;
- } else if (type == TYPE_AAAA && class == CLASS_INET) {
- int addrcount, addrtocopy;
- if (req->request_type != TYPE_AAAA) {
- j += datalength; continue;
- }
- if ((datalength & 15) != 0) /* not an even number of AAAAs. */
- goto err;
- addrcount = datalength >> 4; /* each address is 16 bytes long */
- addrtocopy = MIN(MAX_ADDRS - reply.data.aaaa.addrcount, (unsigned)addrcount);
- ttl_r = MIN(ttl_r, ttl);
-
- /* we only bother with the first four addresses. */
- if (j + 16*addrtocopy > length) goto err;
- memcpy(&reply.data.aaaa.addresses[reply.data.aaaa.addrcount],
- packet + j, 16*addrtocopy);
- reply.data.aaaa.addrcount += addrtocopy;
- j += 16*addrtocopy;
- reply.have_answer = 1;
- if (reply.data.aaaa.addrcount == MAX_ADDRS) break;
- } else {
- /* skip over any other type of resource */
- j += datalength;
- }
- }
-
- reply_handle(req, flags, ttl_r, &reply);
- return 0;
- err:
- if (req)
- reply_handle(req, flags, 0, NULL);
- return -1;
-}
-
-/* Parse a raw request (packet,length) sent to a nameserver port (port) from */
-/* a DNS client (addr,addrlen), and if it's well-formed, call the corresponding */
-/* callback. */
-static int
-request_parse(u8 *packet, int length, struct evdns_server_port *port, struct sockaddr *addr, socklen_t addrlen)
-{
- int j = 0; /* index into packet */
- u16 _t; /* used by the macros */
- char tmp_name[256]; /* used by the macros */
-
- int i;
- u16 trans_id, flags, questions, answers, authority, additional;
- struct server_request *server_req = NULL;
-
- /* Get the header fields */
- GET16(trans_id);
- GET16(flags);
- GET16(questions);
- GET16(answers);
- GET16(authority);
- GET16(additional);
-
- if (flags & 0x8000) return -1; /* Must not be an answer. */
- flags &= 0x0110; /* Only RD and CD get preserved. */
-
- server_req = malloc(sizeof(struct server_request));
- if (server_req == NULL) return -1;
- memset(server_req, 0, sizeof(struct server_request));
-
- server_req->trans_id = trans_id;
- memcpy(&server_req->addr, addr, addrlen);
- server_req->addrlen = addrlen;
-
- server_req->base.flags = flags;
- server_req->base.nquestions = 0;
- server_req->base.questions = malloc(sizeof(struct evdns_server_question *) * questions);
- if (server_req->base.questions == NULL)
- goto err;
-
- for (i = 0; i < questions; ++i) {
- u16 type, class;
- struct evdns_server_question *q;
- int namelen;
- if (name_parse(packet, length, &j, tmp_name, sizeof(tmp_name))<0)
- goto err;
- GET16(type);
- GET16(class);
- namelen = strlen(tmp_name);
- q = malloc(sizeof(struct evdns_server_question) + namelen);
- if (!q)
- goto err;
- q->type = type;
- q->dns_question_class = class;
- memcpy(q->name, tmp_name, namelen+1);
- server_req->base.questions[server_req->base.nquestions++] = q;
- }
-
- /* Ignore answers, authority, and additional. */
-
- server_req->port = port;
- port->refcnt++;
-
- /* Only standard queries are supported. */
- if (flags & 0x7800) {
- evdns_server_request_respond(&(server_req->base), DNS_ERR_NOTIMPL);
- return -1;
- }
-
- port->user_callback(&(server_req->base), port->user_data);
-
- return 0;
-err:
- if (server_req) {
- if (server_req->base.questions) {
- for (i = 0; i < server_req->base.nquestions; ++i)
- free(server_req->base.questions[i]);
- free(server_req->base.questions);
- }
- free(server_req);
- }
- return -1;
-
-#undef SKIP_NAME
-#undef GET32
-#undef GET16
-#undef GET8
-}
-
-static u16
-default_transaction_id_fn(void)
-{
- u16 trans_id;
-#ifdef DNS_USE_CPU_CLOCK_FOR_ID
- struct timespec ts;
-#ifdef CLOCK_MONOTONIC
- if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
-#else
- if (clock_gettime(CLOCK_REALTIME, &ts) == -1)
-#endif
- event_err(1, "clock_gettime");
- trans_id = ts.tv_nsec & 0xffff;
-#endif
-
-#ifdef DNS_USE_FTIME_FOR_ID
- struct _timeb tb;
- _ftime(&tb);
- trans_id = tb.millitm & 0xffff;
-#endif
-
-#ifdef DNS_USE_GETTIMEOFDAY_FOR_ID
- struct timeval tv;
- gettimeofday(&tv, NULL);
- trans_id = tv.tv_usec & 0xffff;
-#endif
-
-#ifdef DNS_USE_OPENSSL_FOR_ID
- if (RAND_pseudo_bytes((u8 *) &trans_id, 2) == -1) {
- /* in the case that the RAND call fails we back */
- /* down to using gettimeofday. */
- /*
- struct timeval tv;
- gettimeofday(&tv, NULL);
- trans_id = tv.tv_usec & 0xffff;
- */
- abort();
- }
-#endif
- return trans_id;
-}
-
-static ev_uint16_t (*trans_id_function)(void) = default_transaction_id_fn;
-
-void
-evdns_set_transaction_id_fn(ev_uint16_t (*fn)(void))
-{
- if (fn)
- trans_id_function = fn;
- else
- trans_id_function = default_transaction_id_fn;
-}
-
-/* Try to choose a strong transaction id which isn't already in flight */
-static u16
-transaction_id_pick(void) {
- for (;;) {
- const struct request *req = req_head, *started_at;
- u16 trans_id = trans_id_function();
-
- if (trans_id == 0xffff) continue;
- /* now check to see if that id is already inflight */
- req = started_at = req_head;
- if (req) {
- do {
- if (req->trans_id == trans_id) break;
- req = req->next;
- } while (req != started_at);
- }
- /* we didn't find it, so this is a good id */
- if (req == started_at) return trans_id;
- }
-}
-
-/* choose a namesever to use. This function will try to ignore */
-/* nameservers which we think are down and load balance across the rest */
-/* by updating the server_head global each time. */
-static struct nameserver *
-nameserver_pick(void) {
- struct nameserver *started_at = server_head, *picked;
- if (!server_head) return NULL;
-
- /* if we don't have any good nameservers then there's no */
- /* point in trying to find one. */
- if (!global_good_nameservers) {
- server_head = server_head->next;
- return server_head;
- }
-
- /* remember that nameservers are in a circular list */
- for (;;) {
- if (server_head->state) {
- /* we think this server is currently good */
- picked = server_head;
- server_head = server_head->next;
- return picked;
- }
-
- server_head = server_head->next;
- if (server_head == started_at) {
- /* all the nameservers seem to be down */
- /* so we just return this one and hope for the */
- /* best */
- assert(global_good_nameservers == 0);
- picked = server_head;
- server_head = server_head->next;
- return picked;
- }
- }
-}
-
-/* this is called when a namesever socket is ready for reading */
-static void
-nameserver_read(struct nameserver *ns) {
- u8 packet[1500];
-
- for (;;) {
- const int r = recv(ns->socket, packet, sizeof(packet), 0);
- if (r < 0) {
- int err = last_error(ns->socket);
- if (error_is_eagain(err)) return;
- nameserver_failed(ns, strerror(err));
- return;
- }
- ns->timedout = 0;
- reply_parse(packet, r);
- }
-}
-
-/* Read a packet from a DNS client on a server port s, parse it, and */
-/* act accordingly. */
-static void
-server_port_read(struct evdns_server_port *s) {
- u8 packet[1500];
- struct sockaddr_storage addr;
- socklen_t addrlen;
- int r;
-
- for (;;) {
- addrlen = sizeof(struct sockaddr_storage);
- r = recvfrom(s->socket, packet, sizeof(packet), 0,
- (struct sockaddr*) &addr, &addrlen);
- if (r < 0) {
- int err = last_error(s->socket);
- if (error_is_eagain(err)) return;
- log(EVDNS_LOG_WARN, "Error %s (%d) while reading request.",
- strerror(err), err);
- return;
- }
- request_parse(packet, r, s, (struct sockaddr*) &addr, addrlen);
- }
-}
-
-/* Try to write all pending replies on a given DNS server port. */
-static void
-server_port_flush(struct evdns_server_port *port)
-{
- while (port->pending_replies) {
- struct server_request *req = port->pending_replies;
- int r = sendto(port->socket, req->response, req->response_len, 0,
- (struct sockaddr*) &req->addr, req->addrlen);
- if (r < 0) {
- int err = last_error(port->socket);
- if (error_is_eagain(err))
- return;
- log(EVDNS_LOG_WARN, "Error %s (%d) while writing response to port; dropping", strerror(err), err);
- }
- if (server_request_free(req)) {
- /* we released the last reference to req->port. */
- return;
- }
- }
-
- /* We have no more pending requests; stop listening for 'writeable' events. */
- (void) event_del(&port->event);
- event_set(&port->event, port->socket, EV_READ | EV_PERSIST,
- server_port_ready_callback, port);
- if (event_add(&port->event, NULL) < 0) {
- log(EVDNS_LOG_WARN, "Error from libevent when adding event for DNS server.");
- /* ???? Do more? */
- }
-}
-
-/* set if we are waiting for the ability to write to this server. */
-/* if waiting is true then we ask libevent for EV_WRITE events, otherwise */
-/* we stop these events. */
-static void
-nameserver_write_waiting(struct nameserver *ns, char waiting) {
- if (ns->write_waiting == waiting) return;
-
- ns->write_waiting = waiting;
- (void) event_del(&ns->event);
- event_set(&ns->event, ns->socket, EV_READ | (waiting ? EV_WRITE : 0) | EV_PERSIST,
- nameserver_ready_callback, ns);
- if (event_add(&ns->event, NULL) < 0) {
- log(EVDNS_LOG_WARN, "Error from libevent when adding event for %s",
- debug_ntoa(ns->address));
- /* ???? Do more? */
- }
-}
-
-/* a callback function. Called by libevent when the kernel says that */
-/* a nameserver socket is ready for writing or reading */
-static void
-nameserver_ready_callback(int fd, short events, void *arg) {
- struct nameserver *ns = (struct nameserver *) arg;
- (void)fd;
-
- if (events & EV_WRITE) {
- ns->choked = 0;
- if (!evdns_transmit()) {
- nameserver_write_waiting(ns, 0);
- }
- }
- if (events & EV_READ) {
- nameserver_read(ns);
- }
-}
-
-/* a callback function. Called by libevent when the kernel says that */
-/* a server socket is ready for writing or reading. */
-static void
-server_port_ready_callback(int fd, short events, void *arg) {
- struct evdns_server_port *port = (struct evdns_server_port *) arg;
- (void) fd;
-
- if (events & EV_WRITE) {
- port->choked = 0;
- server_port_flush(port);
- }
- if (events & EV_READ) {
- server_port_read(port);
- }
-}
-
-/* This is an inefficient representation; only use it via the dnslabel_table_*
- * functions, so that is can be safely replaced with something smarter later. */
-#define MAX_LABELS 128
-/* Structures used to implement name compression */
-struct dnslabel_entry { char *v; off_t pos; };
-struct dnslabel_table {
- int n_labels; /* number of current entries */
- /* map from name to position in message */
- struct dnslabel_entry labels[MAX_LABELS];
-};
-
-/* Initialize dnslabel_table. */
-static void
-dnslabel_table_init(struct dnslabel_table *table)
-{
- table->n_labels = 0;
-}
-
-/* Free all storage held by table, but not the table itself. */
-static void
-dnslabel_clear(struct dnslabel_table *table)
-{
- int i;
- for (i = 0; i < table->n_labels; ++i)
- free(table->labels[i].v);
- table->n_labels = 0;
-}
-
-/* return the position of the label in the current message, or -1 if the label */
-/* hasn't been used yet. */
-static int
-dnslabel_table_get_pos(const struct dnslabel_table *table, const char *label)
-{
- int i;
- for (i = 0; i < table->n_labels; ++i) {
- if (!strcmp(label, table->labels[i].v))
- return table->labels[i].pos;
- }
- return -1;
-}
-
-/* remember that we've used the label at position pos */
-static int
-dnslabel_table_add(struct dnslabel_table *table, const char *label, off_t pos)
-{
- char *v;
- int p;
- if (table->n_labels == MAX_LABELS)
- return (-1);
- v = strdup(label);
- if (v == NULL)
- return (-1);
- p = table->n_labels++;
- table->labels[p].v = v;
- table->labels[p].pos = pos;
-
- return (0);
-}
-
-/* Converts a string to a length-prefixed set of DNS labels, starting */
-/* at buf[j]. name and buf must not overlap. name_len should be the length */
-/* of name. table is optional, and is used for compression. */
-/* */
-/* Input: abc.def */
-/* Output: <3>abc<3>def<0> */
-/* */
-/* Returns the first index after the encoded name, or negative on error. */
-/* -1 label was > 63 bytes */
-/* -2 name too long to fit in buffer. */
-/* */
-static off_t
-dnsname_to_labels(u8 *const buf, size_t buf_len, off_t j,
- const char *name, const int name_len,
- struct dnslabel_table *table) {
- const char *end = name + name_len;
- int ref = 0;
- u16 _t;
-
-#define APPEND16(x) do { \
- if (j + 2 > (off_t)buf_len) \
- goto overflow; \
- _t = htons(x); \
- memcpy(buf + j, &_t, 2); \
- j += 2; \
- } while (0)
-#define APPEND32(x) do { \
- if (j + 4 > (off_t)buf_len) \
- goto overflow; \
- _t32 = htonl(x); \
- memcpy(buf + j, &_t32, 4); \
- j += 4; \
- } while (0)
-
- if (name_len > 255) return -2;
-
- for (;;) {
- const char *const start = name;
- if (table && (ref = dnslabel_table_get_pos(table, name)) >= 0) {
- APPEND16(ref | 0xc000);
- return j;
- }
- name = strchr(name, '.');
- if (!name) {
- const unsigned int label_len = end - start;
- if (label_len > 63) return -1;
- if ((size_t)(j+label_len+1) > buf_len) return -2;
- if (table) dnslabel_table_add(table, start, j);
- buf[j++] = label_len;
-
- memcpy(buf + j, start, end - start);
- j += end - start;
- break;
- } else {
- /* append length of the label. */
- const unsigned int label_len = name - start;
- if (label_len > 63) return -1;
- if ((size_t)(j+label_len+1) > buf_len) return -2;
- if (table) dnslabel_table_add(table, start, j);
- buf[j++] = label_len;
-
- memcpy(buf + j, start, name - start);
- j += name - start;
- /* hop over the '.' */
- name++;
- }
- }
-
- /* the labels must be terminated by a 0. */
- /* It's possible that the name ended in a . */
- /* in which case the zero is already there */
- if (!j || buf[j-1]) buf[j++] = 0;
- return j;
- overflow:
- return (-2);
-}
-
-/* Finds the length of a dns request for a DNS name of the given */
-/* length. The actual request may be smaller than the value returned */
-/* here */
-static int
-evdns_request_len(const int name_len) {
- return 96 + /* length of the DNS standard header */
- name_len + 2 +
- 4; /* space for the resource type */
-}
-
-/* build a dns request packet into buf. buf should be at least as long */
-/* as evdns_request_len told you it should be. */
-/* */
-/* Returns the amount of space used. Negative on error. */
-static int
-evdns_request_data_build(const char *const name, const int name_len,
- const u16 trans_id, const u16 type, const u16 class,
- u8 *const buf, size_t buf_len) {
- off_t j = 0; /* current offset into buf */
- u16 _t; /* used by the macros */
-
- APPEND16(trans_id);
- APPEND16(0x0100); /* standard query, recusion needed */
- APPEND16(1); /* one question */
- APPEND16(0); /* no answers */
- APPEND16(0); /* no authority */
- APPEND16(0); /* no additional */
-
- j = dnsname_to_labels(buf, buf_len, j, name, name_len, NULL);
- if (j < 0) {
- return (int)j;
- }
-
- APPEND16(type);
- APPEND16(class);
-
- return (int)j;
- overflow:
- return (-1);
-}
-
-/* exported function */
-struct evdns_server_port *
-evdns_add_server_port(int socket, int is_tcp, evdns_request_callback_fn_type cb, void *user_data)
-{
- struct evdns_server_port *port;
- if (!(port = malloc(sizeof(struct evdns_server_port))))
- return NULL;
- memset(port, 0, sizeof(struct evdns_server_port));
-
- assert(!is_tcp); /* TCP sockets not yet implemented */
- port->socket = socket;
- port->refcnt = 1;
- port->choked = 0;
- port->closing = 0;
- port->user_callback = cb;
- port->user_data = user_data;
- port->pending_replies = NULL;
-
- event_set(&port->event, port->socket, EV_READ | EV_PERSIST,
- server_port_ready_callback, port);
- event_add(&port->event, NULL); /* check return. */
- return port;
-}
-
-/* exported function */
-void
-evdns_close_server_port(struct evdns_server_port *port)
-{
- if (--port->refcnt == 0)
- server_port_free(port);
- port->closing = 1;
-}
-
-/* exported function */
-int
-evdns_server_request_add_reply(struct evdns_server_request *_req, int section, const char *name, int type, int class, int ttl, int datalen, int is_name, const char *data)
-{
- struct server_request *req = TO_SERVER_REQUEST(_req);
- struct server_reply_item **itemp, *item;
- int *countp;
-
- if (req->response) /* have we already answered? */
- return (-1);
-
- switch (section) {
- case EVDNS_ANSWER_SECTION:
- itemp = &req->answer;
- countp = &req->n_answer;
- break;
- case EVDNS_AUTHORITY_SECTION:
- itemp = &req->authority;
- countp = &req->n_authority;
- break;
- case EVDNS_ADDITIONAL_SECTION:
- itemp = &req->additional;
- countp = &req->n_additional;
- break;
- default:
- return (-1);
- }
- while (*itemp) {
- itemp = &((*itemp)->next);
- }
- item = malloc(sizeof(struct server_reply_item));
- if (!item)
- return -1;
- item->next = NULL;
- if (!(item->name = strdup(name))) {
- free(item);
- return -1;
- }
- item->type = type;
- item->dns_question_class = class;
- item->ttl = ttl;
- item->is_name = is_name != 0;
- item->datalen = 0;
- item->data = NULL;
- if (data) {
- if (item->is_name) {
- if (!(item->data = strdup(data))) {
- free(item->name);
- free(item);
- return -1;
- }
- item->datalen = (u16)-1;
- } else {
- if (!(item->data = malloc(datalen))) {
- free(item->name);
- free(item);
- return -1;
- }
- item->datalen = datalen;
- memcpy(item->data, data, datalen);
- }
- }
-
- *itemp = item;
- ++(*countp);
- return 0;
-}
-
-/* exported function */
-int
-evdns_server_request_add_a_reply(struct evdns_server_request *req, const char *name, int n, void *addrs, int ttl)
-{
- return evdns_server_request_add_reply(
- req, EVDNS_ANSWER_SECTION, name, TYPE_A, CLASS_INET,
- ttl, n*4, 0, addrs);
-}
-
-/* exported function */
-int
-evdns_server_request_add_aaaa_reply(struct evdns_server_request *req, const char *name, int n, void *addrs, int ttl)
-{
- return evdns_server_request_add_reply(
- req, EVDNS_ANSWER_SECTION, name, TYPE_AAAA, CLASS_INET,
- ttl, n*16, 0, addrs);
-}
-
-/* exported function */
-int
-evdns_server_request_add_ptr_reply(struct evdns_server_request *req, struct in_addr *in, const char *inaddr_name, const char *hostname, int ttl)
-{
- u32 a;
- char buf[32];
- assert(in || inaddr_name);
- assert(!(in && inaddr_name));
- if (in) {
- a = ntohl(in->s_addr);
- snprintf(buf, sizeof(buf), "%d.%d.%d.%d.in-addr.arpa",
- (int)(u8)((a )&0xff),
- (int)(u8)((a>>8 )&0xff),
- (int)(u8)((a>>16)&0xff),
- (int)(u8)((a>>24)&0xff));
- inaddr_name = buf;
- }
- return evdns_server_request_add_reply(
- req, EVDNS_ANSWER_SECTION, inaddr_name, TYPE_PTR, CLASS_INET,
- ttl, -1, 1, hostname);
-}
-
-/* exported function */
-int
-evdns_server_request_add_cname_reply(struct evdns_server_request *req, const char *name, const char *cname, int ttl)
-{
- return evdns_server_request_add_reply(
- req, EVDNS_ANSWER_SECTION, name, TYPE_A, CLASS_INET,
- ttl, -1, 1, cname);
-}
-
-
-static int
-evdns_server_request_format_response(struct server_request *req, int err)
-{
- unsigned char buf[1500];
- size_t buf_len = sizeof(buf);
- off_t j = 0, r;
- u16 _t;
- u32 _t32;
- int i;
- u16 flags;
- struct dnslabel_table table;
-
- if (err < 0 || err > 15) return -1;
-
- /* Set response bit and error code; copy OPCODE and RD fields from
- * question; copy RA and AA if set by caller. */
- flags = req->base.flags;
- flags |= (0x8000 | err);
-
- dnslabel_table_init(&table);
- APPEND16(req->trans_id);
- APPEND16(flags);
- APPEND16(req->base.nquestions);
- APPEND16(req->n_answer);
- APPEND16(req->n_authority);
- APPEND16(req->n_additional);
-
- /* Add questions. */
- for (i=0; i < req->base.nquestions; ++i) {
- const char *s = req->base.questions[i]->name;
- j = dnsname_to_labels(buf, buf_len, j, s, strlen(s), &table);
- if (j < 0) {
- dnslabel_clear(&table);
- return (int) j;
- }
- APPEND16(req->base.questions[i]->type);
- APPEND16(req->base.questions[i]->dns_question_class);
- }
-
- /* Add answer, authority, and additional sections. */
- for (i=0; i<3; ++i) {
- struct server_reply_item *item;
- if (i==0)
- item = req->answer;
- else if (i==1)
- item = req->authority;
- else
- item = req->additional;
- while (item) {
- r = dnsname_to_labels(buf, buf_len, j, item->name, strlen(item->name), &table);
- if (r < 0)
- goto overflow;
- j = r;
-
- APPEND16(item->type);
- APPEND16(item->dns_question_class);
- APPEND32(item->ttl);
- if (item->is_name) {
- off_t len_idx = j, name_start;
- j += 2;
- name_start = j;
- r = dnsname_to_labels(buf, buf_len, j, item->data, strlen(item->data), &table);
- if (r < 0)
- goto overflow;
- j = r;
- _t = htons( (short) (j-name_start) );
- memcpy(buf+len_idx, &_t, 2);
- } else {
- APPEND16(item->datalen);
- if (j+item->datalen > (off_t)buf_len)
- goto overflow;
- memcpy(buf+j, item->data, item->datalen);
- j += item->datalen;
- }
- item = item->next;
- }
- }
-
- if (j > 512) {
-overflow:
- j = 512;
- buf[3] |= 0x02; /* set the truncated bit. */
- }
-
- req->response_len = j;
-
- if (!(req->response = malloc(req->response_len))) {
- server_request_free_answers(req);
- dnslabel_clear(&table);
- return (-1);
- }
- memcpy(req->response, buf, req->response_len);
- server_request_free_answers(req);
- dnslabel_clear(&table);
- return (0);
-}
-
-/* exported function */
-int
-evdns_server_request_respond(struct evdns_server_request *_req, int err)
-{
- struct server_request *req = TO_SERVER_REQUEST(_req);
- struct evdns_server_port *port = req->port;
- int r;
- if (!req->response) {
- if ((r = evdns_server_request_format_response(req, err))<0)
- return r;
- }
-
- r = sendto(port->socket, req->response, req->response_len, 0,
- (struct sockaddr*) &req->addr, req->addrlen);
- if (r<0) {
- int sock_err = last_error(port->socket);
- if (! error_is_eagain(sock_err))
- return -1;
-
- if (port->pending_replies) {
- req->prev_pending = port->pending_replies->prev_pending;
- req->next_pending = port->pending_replies;
- req->prev_pending->next_pending =
- req->next_pending->prev_pending = req;
- } else {
- req->prev_pending = req->next_pending = req;
- port->pending_replies = req;
- port->choked = 1;
-
- (void) event_del(&port->event);
- event_set(&port->event, port->socket, (port->closing?0:EV_READ) | EV_WRITE | EV_PERSIST, server_port_ready_callback, port);
-
- if (event_add(&port->event, NULL) < 0) {
- log(EVDNS_LOG_WARN, "Error from libevent when adding event for DNS server");
- }
-
- }
-
- return 1;
- }
- if (server_request_free(req))
- return 0;
-
- if (port->pending_replies)
- server_port_flush(port);
-
- return 0;
-}
-
-/* Free all storage held by RRs in req. */
-static void
-server_request_free_answers(struct server_request *req)
-{
- struct server_reply_item *victim, *next, **list;
- int i;
- for (i = 0; i < 3; ++i) {
- if (i==0)
- list = &req->answer;
- else if (i==1)
- list = &req->authority;
- else
- list = &req->additional;
-
- victim = *list;
- while (victim) {
- next = victim->next;
- free(victim->name);
- if (victim->data)
- free(victim->data);
- free(victim);
- victim = next;
- }
- *list = NULL;
- }
-}
-
-/* Free all storage held by req, and remove links to it. */
-/* return true iff we just wound up freeing the server_port. */
-static int
-server_request_free(struct server_request *req)
-{
- int i, rc=1;
- if (req->base.questions) {
- for (i = 0; i < req->base.nquestions; ++i)
- free(req->base.questions[i]);
- free(req->base.questions);
- }
-
- if (req->port) {
- if (req->port->pending_replies == req) {
- if (req->next_pending)
- req->port->pending_replies = req->next_pending;
- else
- req->port->pending_replies = NULL;
- }
- rc = --req->port->refcnt;
- }
-
- if (req->response) {
- free(req->response);
- }
-
- server_request_free_answers(req);
-
- if (req->next_pending && req->next_pending != req) {
- req->next_pending->prev_pending = req->prev_pending;
- req->prev_pending->next_pending = req->next_pending;
- }
-
- if (rc == 0) {
- server_port_free(req->port);
- free(req);
- return (1);
- }
- free(req);
- return (0);
-}
-
-/* Free all storage held by an evdns_server_port. Only called when */
-static void
-server_port_free(struct evdns_server_port *port)
-{
- assert(port);
- assert(!port->refcnt);
- assert(!port->pending_replies);
- if (port->socket > 0) {
- CLOSE_SOCKET(port->socket);
- port->socket = -1;
- }
- (void) event_del(&port->event);
- /* XXXX actually free the port? -NM */
-}
-
-/* exported function */
-int
-evdns_server_request_drop(struct evdns_server_request *_req)
-{
- struct server_request *req = TO_SERVER_REQUEST(_req);
- server_request_free(req);
- return 0;
-}
-
-/* exported function */
-int
-evdns_server_request_get_requesting_addr(struct evdns_server_request *_req, struct sockaddr *sa, int addr_len)
-{
- struct server_request *req = TO_SERVER_REQUEST(_req);
- if (addr_len < (int)req->addrlen)
- return -1;
- memcpy(sa, &(req->addr), req->addrlen);
- return req->addrlen;
-}
-
-#undef APPEND16
-#undef APPEND32
-
-/* this is a libevent callback function which is called when a request */
-/* has timed out. */
-static void
-evdns_request_timeout_callback(int fd, short events, void *arg) {
- struct request *const req = (struct request *) arg;
- (void) fd;
- (void) events;
-
- log(EVDNS_LOG_DEBUG, "Request %lx timed out", (unsigned long) arg);
-
- req->ns->timedout++;
- if (req->ns->timedout > global_max_nameserver_timeout) {
- req->ns->timedout = 0;
- nameserver_failed(req->ns, "request timed out.");
- }
-
- (void) evtimer_del(&req->timeout_event);
- if (req->tx_count >= global_max_retransmits) {
- /* this request has failed */
- reply_callback(req, 0, DNS_ERR_TIMEOUT, NULL);
- request_finished(req, &req_head);
- } else {
- /* retransmit it */
- evdns_request_transmit(req);
- }
-}
-
-/* try to send a request to a given server. */
-/* */
-/* return: */
-/* 0 ok */
-/* 1 temporary failure */
-/* 2 other failure */
-static int
-evdns_request_transmit_to(struct request *req, struct nameserver *server) {
- const int r = send(server->socket, req->request, req->request_len, 0);
- if (r < 0) {
- int err = last_error(server->socket);
- if (error_is_eagain(err)) return 1;
- nameserver_failed(req->ns, strerror(err));
- return 2;
- } else if (r != (int)req->request_len) {
- return 1; /* short write */
- } else {
- return 0;
- }
-}
-
-/* try to send a request, updating the fields of the request */
-/* as needed */
-/* */
-/* return: */
-/* 0 ok */
-/* 1 failed */
-static int
-evdns_request_transmit(struct request *req) {
- int retcode = 0, r;
-
- /* if we fail to send this packet then this flag marks it */
- /* for evdns_transmit */
- req->transmit_me = 1;
- if (req->trans_id == 0xffff) abort();
-
- if (req->ns->choked) {
- /* don't bother trying to write to a socket */
- /* which we have had EAGAIN from */
- return 1;
- }
-
- r = evdns_request_transmit_to(req, req->ns);
- switch (r) {
- case 1:
- /* temp failure */
- req->ns->choked = 1;
- nameserver_write_waiting(req->ns, 1);
- return 1;
- case 2:
- /* failed in some other way */
- retcode = 1;
- /* fall through */
- default:
- /* all ok */
- log(EVDNS_LOG_DEBUG,
- "Setting timeout for request %lx", (unsigned long) req);
- evtimer_set(&req->timeout_event, evdns_request_timeout_callback, req);
- if (evtimer_add(&req->timeout_event, &global_timeout) < 0) {
- log(EVDNS_LOG_WARN,
- "Error from libevent when adding timer for request %lx",
- (unsigned long) req);
- /* ???? Do more? */
- }
- req->tx_count++;
- req->transmit_me = 0;
- return retcode;
- }
-}
-
-static void
-nameserver_probe_callback(int result, char type, int count, int ttl, void *addresses, void *arg) {
- struct nameserver *const ns = (struct nameserver *) arg;
- (void) type;
- (void) count;
- (void) ttl;
- (void) addresses;
-
- if (result == DNS_ERR_NONE || result == DNS_ERR_NOTEXIST) {
- /* this is a good reply */
- nameserver_up(ns);
- } else nameserver_probe_failed(ns);
-}
-
-static void
-nameserver_send_probe(struct nameserver *const ns) {
- struct request *req;
- /* here we need to send a probe to a given nameserver */
- /* in the hope that it is up now. */
-
- log(EVDNS_LOG_DEBUG, "Sending probe to %s", debug_ntoa(ns->address));
-
- req = request_new(TYPE_A, "www.google.com", DNS_QUERY_NO_SEARCH, nameserver_probe_callback, ns);
- if (!req) return;
- /* we force this into the inflight queue no matter what */
- request_trans_id_set(req, transaction_id_pick());
- req->ns = ns;
- request_submit(req);
-}
-
-/* returns: */
-/* 0 didn't try to transmit anything */
-/* 1 tried to transmit something */
-static int
-evdns_transmit(void) {
- char did_try_to_transmit = 0;
-
- if (req_head) {
- struct request *const started_at = req_head, *req = req_head;
- /* first transmit all the requests which are currently waiting */
- do {
- if (req->transmit_me) {
- did_try_to_transmit = 1;
- evdns_request_transmit(req);
- }
-
- req = req->next;
- } while (req != started_at);
- }
-
- return did_try_to_transmit;
-}
-
-/* exported function */
-int
-evdns_count_nameservers(void)
-{
- const struct nameserver *server = server_head;
- int n = 0;
- if (!server)
- return 0;
- do {
- ++n;
- server = server->next;
- } while (server != server_head);
- return n;
-}
-
-/* exported function */
-int
-evdns_clear_nameservers_and_suspend(void)
-{
- struct nameserver *server = server_head, *started_at = server_head;
- struct request *req = req_head, *req_started_at = req_head;
-
- if (!server)
- return 0;
- while (1) {
- struct nameserver *next = server->next;
- (void) event_del(&server->event);
- if (evtimer_initialized(&server->timeout_event))
- (void) evtimer_del(&server->timeout_event);
- if (server->socket >= 0)
- CLOSE_SOCKET(server->socket);
- free(server);
- if (next == started_at)
- break;
- server = next;
- }
- server_head = NULL;
- global_good_nameservers = 0;
-
- while (req) {
- struct request *next = req->next;
- req->tx_count = req->reissue_count = 0;
- req->ns = NULL;
- /* ???? What to do about searches? */
- (void) evtimer_del(&req->timeout_event);
- req->trans_id = 0;
- req->transmit_me = 0;
-
- global_requests_waiting++;
- evdns_request_insert(req, &req_waiting_head);
- /* We want to insert these suspended elements at the front of
- * the waiting queue, since they were pending before any of
- * the waiting entries were added. This is a circular list,
- * so we can just shift the start back by one.*/
- req_waiting_head = req_waiting_head->prev;
-
- if (next == req_started_at)
- break;
- req = next;
- }
- req_head = NULL;
- global_requests_inflight = 0;
-
- return 0;
-}
-
-
-/* exported function */
-int
-evdns_resume(void)
-{
- evdns_requests_pump_waiting_queue();
- return 0;
-}
-
-static int
-_evdns_nameserver_add_impl(unsigned long int address, int port) {
- /* first check to see if we already have this nameserver */
-
- const struct nameserver *server = server_head, *const started_at = server_head;
- struct nameserver *ns;
- struct sockaddr_in sin;
- int err = 0;
- if (server) {
- do {
- if (server->address == address) return 3;
- server = server->next;
- } while (server != started_at);
- }
-
- ns = (struct nameserver *) malloc(sizeof(struct nameserver));
- if (!ns) return -1;
-
- memset(ns, 0, sizeof(struct nameserver));
-
- ns->socket = socket(PF_INET, SOCK_DGRAM, 0);
- if (ns->socket < 0) { err = 1; goto out1; }
- evutil_make_socket_nonblocking(ns->socket);
- sin.sin_addr.s_addr = address;
- sin.sin_port = htons(port);
- sin.sin_family = AF_INET;
- if (connect(ns->socket, (struct sockaddr *) &sin, sizeof(sin)) != 0) {
- err = 2;
- goto out2;
- }
-
- ns->address = address;
- ns->state = 1;
- event_set(&ns->event, ns->socket, EV_READ | EV_PERSIST, nameserver_ready_callback, ns);
- if (event_add(&ns->event, NULL) < 0) {
- err = 2;
- goto out2;
- }
-
- log(EVDNS_LOG_DEBUG, "Added nameserver %s", debug_ntoa(address));
-
- /* insert this nameserver into the list of them */
- if (!server_head) {
- ns->next = ns->prev = ns;
- server_head = ns;
- } else {
- ns->next = server_head->next;
- ns->prev = server_head;
- server_head->next = ns;
- if (server_head->prev == server_head) {
- server_head->prev = ns;
- }
- }
-
- global_good_nameservers++;
-
- return 0;
-
-out2:
- CLOSE_SOCKET(ns->socket);
-out1:
- free(ns);
- log(EVDNS_LOG_WARN, "Unable to add nameserver %s: error %d", debug_ntoa(address), err);
- return err;
-}
-
-/* exported function */
-int
-evdns_nameserver_add(unsigned long int address) {
- return _evdns_nameserver_add_impl(address, 53);
-}
-
-/* exported function */
-int
-evdns_nameserver_ip_add(const char *ip_as_string) {
- struct in_addr ina;
- int port;
- char buf[20];
- const char *cp;
- cp = strchr(ip_as_string, ':');
- if (! cp) {
- cp = ip_as_string;
- port = 53;
- } else {
- port = strtoint(cp+1);
- if (port < 0 || port > 65535) {
- return 4;
- }
- if ((cp-ip_as_string) >= (int)sizeof(buf)) {
- return 4;
- }
- memcpy(buf, ip_as_string, cp-ip_as_string);
- buf[cp-ip_as_string] = '\0';
- cp = buf;
- }
- if (!inet_aton(cp, &ina)) {
- return 4;
- }
- return _evdns_nameserver_add_impl(ina.s_addr, port);
-}
-
-/* insert into the tail of the queue */
-static void
-evdns_request_insert(struct request *req, struct request **head) {
- if (!*head) {
- *head = req;
- req->next = req->prev = req;
- return;
- }
-
- req->prev = (*head)->prev;
- req->prev->next = req;
- req->next = *head;
- (*head)->prev = req;
-}
-
-static int
-string_num_dots(const char *s) {
- int count = 0;
- while ((s = strchr(s, '.'))) {
- s++;
- count++;
- }
- return count;
-}
-
-static struct request *
-request_new(int type, const char *name, int flags,
- evdns_callback_type callback, void *user_ptr) {
- const char issuing_now =
- (global_requests_inflight < global_max_requests_inflight) ? 1 : 0;
-
- const int name_len = strlen(name);
- const int request_max_len = evdns_request_len(name_len);
- const u16 trans_id = issuing_now ? transaction_id_pick() : 0xffff;
- /* the request data is alloced in a single block with the header */
- struct request *const req =
- (struct request *) malloc(sizeof(struct request) + request_max_len);
- int rlen;
- (void) flags;
-
- if (!req) return NULL;
- memset(req, 0, sizeof(struct request));
-
- /* request data lives just after the header */
- req->request = ((u8 *) req) + sizeof(struct request);
- /* denotes that the request data shouldn't be free()ed */
- req->request_appended = 1;
- rlen = evdns_request_data_build(name, name_len, trans_id,
- type, CLASS_INET, req->request, request_max_len);
- if (rlen < 0)
- goto err1;
- req->request_len = rlen;
- req->trans_id = trans_id;
- req->tx_count = 0;
- req->request_type = type;
- req->user_pointer = user_ptr;
- req->user_callback = callback;
- req->ns = issuing_now ? nameserver_pick() : NULL;
- req->next = req->prev = NULL;
-
- return req;
-err1:
- free(req);
- return NULL;
-}
-
-static void
-request_submit(struct request *const req) {
- if (req->ns) {
- /* if it has a nameserver assigned then this is going */
- /* straight into the inflight queue */
- evdns_request_insert(req, &req_head);
- global_requests_inflight++;
- evdns_request_transmit(req);
- } else {
- evdns_request_insert(req, &req_waiting_head);
- global_requests_waiting++;
- }
-}
-
-/* exported function */
-int evdns_resolve_ipv4(const char *name, int flags,
- evdns_callback_type callback, void *ptr) {
- log(EVDNS_LOG_DEBUG, "Resolve requested for %s", name);
- if (flags & DNS_QUERY_NO_SEARCH) {
- struct request *const req =
- request_new(TYPE_A, name, flags, callback, ptr);
- if (req == NULL)
- return (1);
- request_submit(req);
- return (0);
- } else {
- return (search_request_new(TYPE_A, name, flags, callback, ptr));
- }
-}
-
-/* exported function */
-int evdns_resolve_ipv6(const char *name, int flags,
- evdns_callback_type callback, void *ptr) {
- log(EVDNS_LOG_DEBUG, "Resolve requested for %s", name);
- if (flags & DNS_QUERY_NO_SEARCH) {
- struct request *const req =
- request_new(TYPE_AAAA, name, flags, callback, ptr);
- if (req == NULL)
- return (1);
- request_submit(req);
- return (0);
- } else {
- return (search_request_new(TYPE_AAAA, name, flags, callback, ptr));
- }
-}
-
-int evdns_resolve_reverse(struct in_addr *in, int flags, evdns_callback_type callback, void *ptr) {
- char buf[32];
- struct request *req;
- u32 a;
- assert(in);
- a = ntohl(in->s_addr);
- snprintf(buf, sizeof(buf), "%d.%d.%d.%d.in-addr.arpa",
- (int)(u8)((a )&0xff),
- (int)(u8)((a>>8 )&0xff),
- (int)(u8)((a>>16)&0xff),
- (int)(u8)((a>>24)&0xff));
- log(EVDNS_LOG_DEBUG, "Resolve requested for %s (reverse)", buf);
- req = request_new(TYPE_PTR, buf, flags, callback, ptr);
- if (!req) return 1;
- request_submit(req);
- return 0;
-}
-
-int evdns_resolve_reverse_ipv6(struct in6_addr *in, int flags, evdns_callback_type callback, void *ptr) {
- /* 32 nybbles, 32 periods, "ip6.arpa", NUL. */
- char buf[73];
- char *cp;
- struct request *req;
- int i;
- assert(in);
- cp = buf;
- for (i=15; i >= 0; --i) {
- u8 byte = in->s6_addr[i];
- *cp++ = "0123456789abcdef"[byte & 0x0f];
- *cp++ = '.';
- *cp++ = "0123456789abcdef"[byte >> 4];
- *cp++ = '.';
- }
- assert(cp + strlen("ip6.arpa") < buf+sizeof(buf));
- memcpy(cp, "ip6.arpa", strlen("ip6.arpa")+1);
- log(EVDNS_LOG_DEBUG, "Resolve requested for %s (reverse)", buf);
- req = request_new(TYPE_PTR, buf, flags, callback, ptr);
- if (!req) return 1;
- request_submit(req);
- return 0;
-}
-
-/*/////////////////////////////////////////////////////////////////// */
-/* Search support */
-/* */
-/* the libc resolver has support for searching a number of domains */
-/* to find a name. If nothing else then it takes the single domain */
-/* from the gethostname() call. */
-/* */
-/* It can also be configured via the domain and search options in a */
-/* resolv.conf. */
-/* */
-/* The ndots option controls how many dots it takes for the resolver */
-/* to decide that a name is non-local and so try a raw lookup first. */
-
-struct search_domain {
- int len;
- struct search_domain *next;
- /* the text string is appended to this structure */
-};
-
-struct search_state {
- int refcount;
- int ndots;
- int num_domains;
- struct search_domain *head;
-};
-
-static struct search_state *global_search_state = NULL;
-
-static void
-search_state_decref(struct search_state *const state) {
- if (!state) return;
- state->refcount--;
- if (!state->refcount) {
- struct search_domain *next, *dom;
- for (dom = state->head; dom; dom = next) {
- next = dom->next;
- free(dom);
- }
- free(state);
- }
-}
-
-static struct search_state *
-search_state_new(void) {
- struct search_state *state = (struct search_state *) malloc(sizeof(struct search_state));
- if (!state) return NULL;
- memset(state, 0, sizeof(struct search_state));
- state->refcount = 1;
- state->ndots = 1;
-
- return state;
-}
-
-static void
-search_postfix_clear(void) {
- search_state_decref(global_search_state);
-
- global_search_state = search_state_new();
-}
-
-/* exported function */
-void
-evdns_search_clear(void) {
- search_postfix_clear();
-}
-
-static void
-search_postfix_add(const char *domain) {
- int domain_len;
- struct search_domain *sdomain;
- while (domain[0] == '.') domain++;
- domain_len = strlen(domain);
-
- if (!global_search_state) global_search_state = search_state_new();
- if (!global_search_state) return;
- global_search_state->num_domains++;
-
- sdomain = (struct search_domain *) malloc(sizeof(struct search_domain) + domain_len);
- if (!sdomain) return;
- memcpy( ((u8 *) sdomain) + sizeof(struct search_domain), domain, domain_len);
- sdomain->next = global_search_state->head;
- sdomain->len = domain_len;
-
- global_search_state->head = sdomain;
-}
-
-/* reverse the order of members in the postfix list. This is needed because, */
-/* when parsing resolv.conf we push elements in the wrong order */
-static void
-search_reverse(void) {
- struct search_domain *cur, *prev = NULL, *next;
- cur = global_search_state->head;
- while (cur) {
- next = cur->next;
- cur->next = prev;
- prev = cur;
- cur = next;
- }
-
- global_search_state->head = prev;
-}
-
-/* exported function */
-void
-evdns_search_add(const char *domain) {
- search_postfix_add(domain);
-}
-
-/* exported function */
-void
-evdns_search_ndots_set(const int ndots) {
- if (!global_search_state) global_search_state = search_state_new();
- if (!global_search_state) return;
- global_search_state->ndots = ndots;
-}
-
-static void
-search_set_from_hostname(void) {
- char hostname[HOST_NAME_MAX + 1], *domainname;
-
- search_postfix_clear();
- if (gethostname(hostname, sizeof(hostname))) return;
- domainname = strchr(hostname, '.');
- if (!domainname) return;
- search_postfix_add(domainname);
-}
-
-/* warning: returns malloced string */
-static char *
-search_make_new(const struct search_state *const state, int n, const char *const base_name) {
- const int base_len = strlen(base_name);
- const char need_to_append_dot = base_name[base_len - 1] == '.' ? 0 : 1;
- struct search_domain *dom;
-
- for (dom = state->head; dom; dom = dom->next) {
- if (!n--) {
- /* this is the postfix we want */
- /* the actual postfix string is kept at the end of the structure */
- const u8 *const postfix = ((u8 *) dom) + sizeof(struct search_domain);
- const int postfix_len = dom->len;
- char *const newname = (char *) malloc(base_len + need_to_append_dot + postfix_len + 1);
- if (!newname) return NULL;
- memcpy(newname, base_name, base_len);
- if (need_to_append_dot) newname[base_len] = '.';
- memcpy(newname + base_len + need_to_append_dot, postfix, postfix_len);
- newname[base_len + need_to_append_dot + postfix_len] = 0;
- return newname;
- }
- }
-
- /* we ran off the end of the list and still didn't find the requested string */
- abort();
- return NULL; /* unreachable; stops warnings in some compilers. */
-}
-
-static int
-search_request_new(int type, const char *const name, int flags, evdns_callback_type user_callback, void *user_arg) {
- assert(type == TYPE_A || type == TYPE_AAAA);
- if ( ((flags & DNS_QUERY_NO_SEARCH) == 0) &&
- global_search_state &&
- global_search_state->num_domains) {
- /* we have some domains to search */
- struct request *req;
- if (string_num_dots(name) >= global_search_state->ndots) {
- req = request_new(type, name, flags, user_callback, user_arg);
- if (!req) return 1;
- req->search_index = -1;
- } else {
- char *const new_name = search_make_new(global_search_state, 0, name);
- if (!new_name) return 1;
- req = request_new(type, new_name, flags, user_callback, user_arg);
- free(new_name);
- if (!req) return 1;
- req->search_index = 0;
- }
- req->search_origname = strdup(name);
- req->search_state = global_search_state;
- req->search_flags = flags;
- global_search_state->refcount++;
- request_submit(req);
- return 0;
- } else {
- struct request *const req = request_new(type, name, flags, user_callback, user_arg);
- if (!req) return 1;
- request_submit(req);
- return 0;
- }
-}
-
-/* this is called when a request has failed to find a name. We need to check */
-/* if it is part of a search and, if so, try the next name in the list */
-/* returns: */
-/* 0 another request has been submitted */
-/* 1 no more requests needed */
-static int
-search_try_next(struct request *const req) {
- if (req->search_state) {
- /* it is part of a search */
- char *new_name;
- struct request *newreq;
- req->search_index++;
- if (req->search_index >= req->search_state->num_domains) {
- /* no more postfixes to try, however we may need to try */
- /* this name without a postfix */
- if (string_num_dots(req->search_origname) < req->search_state->ndots) {
- /* yep, we need to try it raw */
- newreq = request_new(req->request_type, req->search_origname, req->search_flags, req->user_callback, req->user_pointer);
- log(EVDNS_LOG_DEBUG, "Search: trying raw query %s", req->search_origname);
- if (newreq) {
- request_submit(newreq);
- return 0;
- }
- }
- return 1;
- }
-
- new_name = search_make_new(req->search_state, req->search_index, req->search_origname);
- if (!new_name) return 1;
- log(EVDNS_LOG_DEBUG, "Search: now trying %s (%d)", new_name, req->search_index);
- newreq = request_new(req->request_type, new_name, req->search_flags, req->user_callback, req->user_pointer);
- free(new_name);
- if (!newreq) return 1;
- newreq->search_origname = req->search_origname;
- req->search_origname = NULL;
- newreq->search_state = req->search_state;
- newreq->search_flags = req->search_flags;
- newreq->search_index = req->search_index;
- newreq->search_state->refcount++;
- request_submit(newreq);
- return 0;
- }
- return 1;
-}
-
-static void
-search_request_finished(struct request *const req) {
- if (req->search_state) {
- search_state_decref(req->search_state);
- req->search_state = NULL;
- }
- if (req->search_origname) {
- free(req->search_origname);
- req->search_origname = NULL;
- }
-}
-
-/*/////////////////////////////////////////////////////////////////// */
-/* Parsing resolv.conf files */
-
-static void
-evdns_resolv_set_defaults(int flags) {
- /* if the file isn't found then we assume a local resolver */
- if (flags & DNS_OPTION_SEARCH) search_set_from_hostname();
- if (flags & DNS_OPTION_NAMESERVERS) evdns_nameserver_ip_add("127.0.0.1");
-}
-
-#ifndef HAVE_STRTOK_R
-static char *
-strtok_r(char *s, const char *delim, char **state) {
- return strtok(s, delim);
-}
-#endif
-
-/* helper version of atoi which returns -1 on error */
-static int
-strtoint(const char *const str) {
- char *endptr;
- const int r = strtol(str, &endptr, 10);
- if (*endptr) return -1;
- return r;
-}
-
-/* helper version of atoi that returns -1 on error and clips to bounds. */
-static int
-strtoint_clipped(const char *const str, int min, int max)
-{
- int r = strtoint(str);
- if (r == -1)
- return r;
- else if (r<min)
- return min;
- else if (r>max)
- return max;
- else
- return r;
-}
-
-/* exported function */
-int
-evdns_set_option(const char *option, const char *val, int flags)
-{
- if (!strncmp(option, "ndots:", 6)) {
- const int ndots = strtoint(val);
- if (ndots == -1) return -1;
- if (!(flags & DNS_OPTION_SEARCH)) return 0;
- log(EVDNS_LOG_DEBUG, "Setting ndots to %d", ndots);
- if (!global_search_state) global_search_state = search_state_new();
- if (!global_search_state) return -1;
- global_search_state->ndots = ndots;
- } else if (!strncmp(option, "timeout:", 8)) {
- const int timeout = strtoint(val);
- if (timeout == -1) return -1;
- if (!(flags & DNS_OPTION_MISC)) return 0;
- log(EVDNS_LOG_DEBUG, "Setting timeout to %d", timeout);
- global_timeout.tv_sec = timeout;
- } else if (!strncmp(option, "max-timeouts:", 12)) {
- const int maxtimeout = strtoint_clipped(val, 1, 255);
- if (maxtimeout == -1) return -1;
- if (!(flags & DNS_OPTION_MISC)) return 0;
- log(EVDNS_LOG_DEBUG, "Setting maximum allowed timeouts to %d",
- maxtimeout);
- global_max_nameserver_timeout = maxtimeout;
- } else if (!strncmp(option, "max-inflight:", 13)) {
- const int maxinflight = strtoint_clipped(val, 1, 65000);
- if (maxinflight == -1) return -1;
- if (!(flags & DNS_OPTION_MISC)) return 0;
- log(EVDNS_LOG_DEBUG, "Setting maximum inflight requests to %d",
- maxinflight);
- global_max_requests_inflight = maxinflight;
- } else if (!strncmp(option, "attempts:", 9)) {
- int retries = strtoint(val);
- if (retries == -1) return -1;
- if (retries > 255) retries = 255;
- if (!(flags & DNS_OPTION_MISC)) return 0;
- log(EVDNS_LOG_DEBUG, "Setting retries to %d", retries);
- global_max_retransmits = retries;
- }
- return 0;
-}
-
-static void
-resolv_conf_parse_line(char *const start, int flags) {
- char *strtok_state;
- static const char *const delims = " \t";
-#define NEXT_TOKEN strtok_r(NULL, delims, &strtok_state)
-
- char *const first_token = strtok_r(start, delims, &strtok_state);
- if (!first_token) return;
-
- if (!strcmp(first_token, "nameserver") && (flags & DNS_OPTION_NAMESERVERS)) {
- const char *const nameserver = NEXT_TOKEN;
- struct in_addr ina;
-
- if (inet_aton(nameserver, &ina)) {
- /* address is valid */
- evdns_nameserver_add(ina.s_addr);
- }
- } else if (!strcmp(first_token, "domain") && (flags & DNS_OPTION_SEARCH)) {
- const char *const domain = NEXT_TOKEN;
- if (domain) {
- search_postfix_clear();
- search_postfix_add(domain);
- }
- } else if (!strcmp(first_token, "search") && (flags & DNS_OPTION_SEARCH)) {
- const char *domain;
- search_postfix_clear();
-
- while ((domain = NEXT_TOKEN)) {
- search_postfix_add(domain);
- }
- search_reverse();
- } else if (!strcmp(first_token, "options")) {
- const char *option;
- while ((option = NEXT_TOKEN)) {
- const char *val = strchr(option, ':');
- evdns_set_option(option, val ? val+1 : "", flags);
- }
- }
-#undef NEXT_TOKEN
-}
-
-/* exported function */
-/* returns: */
-/* 0 no errors */
-/* 1 failed to open file */
-/* 2 failed to stat file */
-/* 3 file too large */
-/* 4 out of memory */
-/* 5 short read from file */
-int
-evdns_resolv_conf_parse(int flags, const char *const filename) {
- struct stat st;
- int fd, n, r;
- u8 *resolv;
- char *start;
- int err = 0;
-
- log(EVDNS_LOG_DEBUG, "Parsing resolv.conf file %s", filename);
-
- fd = open(filename, O_RDONLY);
- if (fd < 0) {
- evdns_resolv_set_defaults(flags);
- return 1;
- }
-
- if (fstat(fd, &st)) { err = 2; goto out1; }
- if (!st.st_size) {
- evdns_resolv_set_defaults(flags);
- err = (flags & DNS_OPTION_NAMESERVERS) ? 6 : 0;
- goto out1;
- }
- if (st.st_size > 65535) { err = 3; goto out1; } /* no resolv.conf should be any bigger */
-
- resolv = (u8 *) malloc((size_t)st.st_size + 1);
- if (!resolv) { err = 4; goto out1; }
-
- n = 0;
- while ((r = read(fd, resolv+n, (size_t)st.st_size-n)) > 0) {
- n += r;
- if (n == st.st_size)
- break;
- assert(n < st.st_size);
- }
- if (r < 0) { err = 5; goto out2; }
- resolv[n] = 0; /* we malloced an extra byte; this should be fine. */
-
- start = (char *) resolv;
- for (;;) {
- char *const newline = strchr(start, '\n');
- if (!newline) {
- resolv_conf_parse_line(start, flags);
- break;
- } else {
- *newline = 0;
- resolv_conf_parse_line(start, flags);
- start = newline + 1;
- }
- }
-
- if (!server_head && (flags & DNS_OPTION_NAMESERVERS)) {
- /* no nameservers were configured. */
- evdns_nameserver_ip_add("127.0.0.1");
- err = 6;
- }
- if (flags & DNS_OPTION_SEARCH && (!global_search_state || global_search_state->num_domains == 0)) {
- search_set_from_hostname();
- }
-
-out2:
- free(resolv);
-out1:
- close(fd);
- return err;
-}
-
-#ifdef WIN32
-/* Add multiple nameservers from a space-or-comma-separated list. */
-static int
-evdns_nameserver_ip_add_line(const char *ips) {
- const char *addr;
- char *buf;
- int r;
- while (*ips) {
- while (ISSPACE(*ips) || *ips == ',' || *ips == '\t')
- ++ips;
- addr = ips;
- while (ISDIGIT(*ips) || *ips == '.' || *ips == ':')
- ++ips;
- buf = malloc(ips-addr+1);
- if (!buf) return 4;
- memcpy(buf, addr, ips-addr);
- buf[ips-addr] = '\0';
- r = evdns_nameserver_ip_add(buf);
- free(buf);
- if (r) return r;
- }
- return 0;
-}
-
-typedef DWORD(WINAPI *GetNetworkParams_fn_t)(FIXED_INFO *, DWORD*);
-
-/* Use the windows GetNetworkParams interface in iphlpapi.dll to */
-/* figure out what our nameservers are. */
-static int
-load_nameservers_with_getnetworkparams(void)
-{
- /* Based on MSDN examples and inspection of c-ares code. */
- FIXED_INFO *fixed;
- HMODULE handle = 0;
- ULONG size = sizeof(FIXED_INFO);
- void *buf = NULL;
- int status = 0, r, added_any;
- IP_ADDR_STRING *ns;
- GetNetworkParams_fn_t fn;
-
- if (!(handle = LoadLibrary("iphlpapi.dll"))) {
- log(EVDNS_LOG_WARN, "Could not open iphlpapi.dll");
- status = -1;
- goto done;
- }
- if (!(fn = (GetNetworkParams_fn_t) GetProcAddress(handle, "GetNetworkParams"))) {
- log(EVDNS_LOG_WARN, "Could not get address of function.");
- status = -1;
- goto done;
- }
-
- buf = malloc(size);
- if (!buf) { status = 4; goto done; }
- fixed = buf;
- r = fn(fixed, &size);
- if (r != ERROR_SUCCESS && r != ERROR_BUFFER_OVERFLOW) {
- status = -1;
- goto done;
- }
- if (r != ERROR_SUCCESS) {
- free(buf);
- buf = malloc(size);
- if (!buf) { status = 4; goto done; }
- fixed = buf;
- r = fn(fixed, &size);
- if (r != ERROR_SUCCESS) {
- log(EVDNS_LOG_DEBUG, "fn() failed.");
- status = -1;
- goto done;
- }
- }
-
- assert(fixed);
- added_any = 0;
- ns = &(fixed->DnsServerList);
- while (ns) {
- r = evdns_nameserver_ip_add_line(ns->IpAddress.String);
- if (r) {
- log(EVDNS_LOG_DEBUG,"Could not add nameserver %s to list,error: %d",
- (ns->IpAddress.String),(int)GetLastError());
- status = r;
- goto done;
- } else {
- log(EVDNS_LOG_DEBUG,"Succesfully added %s as nameserver",ns->IpAddress.String);
- }
-
- added_any++;
- ns = ns->Next;
- }
-
- if (!added_any) {
- log(EVDNS_LOG_DEBUG, "No nameservers added.");
- status = -1;
- }
-
- done:
- if (buf)
- free(buf);
- if (handle)
- FreeLibrary(handle);
- return status;
-}
-
-static int
-config_nameserver_from_reg_key(HKEY key, const char *subkey)
-{
- char *buf;
- DWORD bufsz = 0, type = 0;
- int status = 0;
-
- if (RegQueryValueEx(key, subkey, 0, &type, NULL, &bufsz)
- != ERROR_MORE_DATA)
- return -1;
- if (!(buf = malloc(bufsz)))
- return -1;
-
- if (RegQueryValueEx(key, subkey, 0, &type, (LPBYTE)buf, &bufsz)
- == ERROR_SUCCESS && bufsz > 1) {
- status = evdns_nameserver_ip_add_line(buf);
- }
-
- free(buf);
- return status;
-}
-
-#define SERVICES_KEY "System\\CurrentControlSet\\Services\\"
-#define WIN_NS_9X_KEY SERVICES_KEY "VxD\\MSTCP"
-#define WIN_NS_NT_KEY SERVICES_KEY "Tcpip\\Parameters"
-
-static int
-load_nameservers_from_registry(void)
-{
- int found = 0;
- int r;
-#define TRY(k, name) \
- if (!found && config_nameserver_from_reg_key(k,name) == 0) { \
- log(EVDNS_LOG_DEBUG,"Found nameservers in %s/%s",#k,name); \
- found = 1; \
- } else if (!found) { \
- log(EVDNS_LOG_DEBUG,"Didn't find nameservers in %s/%s", \
- #k,#name); \
- }
-
- if (((int)GetVersion()) > 0) { /* NT */
- HKEY nt_key = 0, interfaces_key = 0;
-
- if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0,
- KEY_READ, &nt_key) != ERROR_SUCCESS) {
- log(EVDNS_LOG_DEBUG,"Couldn't open nt key, %d",(int)GetLastError());
- return -1;
- }
- r = RegOpenKeyEx(nt_key, "Interfaces", 0,
- KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS,
- &interfaces_key);
- if (r != ERROR_SUCCESS) {
- log(EVDNS_LOG_DEBUG,"Couldn't open interfaces key, %d",(int)GetLastError());
- return -1;
- }
- TRY(nt_key, "NameServer");
- TRY(nt_key, "DhcpNameServer");
- TRY(interfaces_key, "NameServer");
- TRY(interfaces_key, "DhcpNameServer");
- RegCloseKey(interfaces_key);
- RegCloseKey(nt_key);
- } else {
- HKEY win_key = 0;
- if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_NS_9X_KEY, 0,
- KEY_READ, &win_key) != ERROR_SUCCESS) {
- log(EVDNS_LOG_DEBUG, "Couldn't open registry key, %d", (int)GetLastError());
- return -1;
- }
- TRY(win_key, "NameServer");
- RegCloseKey(win_key);
- }
-
- if (found == 0) {
- log(EVDNS_LOG_WARN,"Didn't find any nameservers.");
- }
-
- return found ? 0 : -1;
-#undef TRY
-}
-
-static int
-evdns_config_windows_nameservers(void)
-{
- if (load_nameservers_with_getnetworkparams() == 0)
- return 0;
- return load_nameservers_from_registry();
-}
-#endif
-
-int
-evdns_init(void)
-{
- int res = 0;
-#ifdef WIN32
- res = evdns_config_windows_nameservers();
-#else
- res = evdns_resolv_conf_parse(DNS_OPTIONS_ALL, "/etc/resolv.conf");
-#endif
-
- return (res);
-}
-
-const char *
-evdns_err_to_string(int err)
-{
- switch (err) {
- case DNS_ERR_NONE: return "no error";
- case DNS_ERR_FORMAT: return "misformatted query";
- case DNS_ERR_SERVERFAILED: return "server failed";
- case DNS_ERR_NOTEXIST: return "name does not exist";
- case DNS_ERR_NOTIMPL: return "query not implemented";
- case DNS_ERR_REFUSED: return "refused";
-
- case DNS_ERR_TRUNCATED: return "reply truncated or ill-formed";
- case DNS_ERR_UNKNOWN: return "unknown";
- case DNS_ERR_TIMEOUT: return "request timed out";
- case DNS_ERR_SHUTDOWN: return "dns subsystem shut down";
- default: return "[Unknown error code]";
- }
-}
-
-void
-evdns_shutdown(int fail_requests)
-{
- struct nameserver *server, *server_next;
- struct search_domain *dom, *dom_next;
-
- while (req_head) {
- if (fail_requests)
- reply_callback(req_head, 0, DNS_ERR_SHUTDOWN, NULL);
- request_finished(req_head, &req_head);
- }
- while (req_waiting_head) {
- if (fail_requests)
- reply_callback(req_waiting_head, 0, DNS_ERR_SHUTDOWN, NULL);
- request_finished(req_waiting_head, &req_waiting_head);
- }
- global_requests_inflight = global_requests_waiting = 0;
-
- for (server = server_head; server; server = server_next) {
- server_next = server->next;
- if (server->socket >= 0)
- CLOSE_SOCKET(server->socket);
- (void) event_del(&server->event);
- if (server->state == 0)
- (void) event_del(&server->timeout_event);
- free(server);
- if (server_next == server_head)
- break;
- }
- server_head = NULL;
- global_good_nameservers = 0;
-
- if (global_search_state) {
- for (dom = global_search_state->head; dom; dom = dom_next) {
- dom_next = dom->next;
- free(dom);
- }
- free(global_search_state);
- global_search_state = NULL;
- }
- evdns_log_fn = NULL;
-}
-
-#ifdef EVDNS_MAIN
-void
-main_callback(int result, char type, int count, int ttl,
- void *addrs, void *orig) {
- char *n = (char*)orig;
- int i;
- for (i = 0; i < count; ++i) {
- if (type == DNS_IPv4_A) {
- printf("%s: %s\n", n, debug_ntoa(((u32*)addrs)[i]));
- } else if (type == DNS_PTR) {
- printf("%s: %s\n", n, ((char**)addrs)[i]);
- }
- }
- if (!count) {
- printf("%s: No answer (%d)\n", n, result);
- }
- fflush(stdout);
-}
-void
-evdns_server_callback(struct evdns_server_request *req, void *data)
-{
- int i, r;
- (void)data;
- /* dummy; give 192.168.11.11 as an answer for all A questions,
- * give foo.bar.example.com as an answer for all PTR questions. */
- for (i = 0; i < req->nquestions; ++i) {
- u32 ans = htonl(0xc0a80b0bUL);
- if (req->questions[i]->type == EVDNS_TYPE_A &&
- req->questions[i]->dns_question_class == EVDNS_CLASS_INET) {
- printf(" -- replying for %s (A)\n", req->questions[i]->name);
- r = evdns_server_request_add_a_reply(req, req->questions[i]->name,
- 1, &ans, 10);
- if (r<0)
- printf("eeep, didn't work.\n");
- } else if (req->questions[i]->type == EVDNS_TYPE_PTR &&
- req->questions[i]->dns_question_class == EVDNS_CLASS_INET) {
- 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);
- } else {
- printf(" -- skipping %s [%d %d]\n", req->questions[i]->name,
- req->questions[i]->type, req->questions[i]->dns_question_class);
- }
- }
-
- r = evdns_request_respond(req, 0);
- if (r<0)
- printf("eeek, couldn't send reply.\n");
-}
-
-void
-logfn(int is_warn, const char *msg) {
- (void) is_warn;
- fprintf(stderr, "%s\n", msg);
-}
-int
-main(int c, char **v) {
- int idx;
- int reverse = 0, verbose = 1, servertest = 0;
- if (c<2) {
- fprintf(stderr, "syntax: %s [-x] [-v] hostname\n", v[0]);
- fprintf(stderr, "syntax: %s [-servertest]\n", v[0]);
- return 1;
- }
- idx = 1;
- while (idx < c && v[idx][0] == '-') {
- if (!strcmp(v[idx], "-x"))
- reverse = 1;
- else if (!strcmp(v[idx], "-v"))
- verbose = 1;
- else if (!strcmp(v[idx], "-servertest"))
- servertest = 1;
- else
- fprintf(stderr, "Unknown option %s\n", v[idx]);
- ++idx;
- }
- event_init();
- if (verbose)
- evdns_set_log_fn(logfn);
- evdns_resolv_conf_parse(DNS_OPTION_NAMESERVERS, "/etc/resolv.conf");
- if (servertest) {
- int sock;
- struct sockaddr_in my_addr;
- sock = socket(PF_INET, SOCK_DGRAM, 0);
- evutil_make_socket_nonblocking(sock);
- my_addr.sin_family = AF_INET;
- my_addr.sin_port = htons(10053);
- my_addr.sin_addr.s_addr = INADDR_ANY;
- if (bind(sock, (struct sockaddr*)&my_addr, sizeof(my_addr))<0) {
- perror("bind");
- exit(1);
- }
- evdns_add_server_port(sock, 0, evdns_server_callback, NULL);
- }
- for (; idx < c; ++idx) {
- if (reverse) {
- struct in_addr addr;
- if (!inet_aton(v[idx], &addr)) {
- fprintf(stderr, "Skipping non-IP %s\n", v[idx]);
- continue;
- }
- fprintf(stderr, "resolving %s...\n",v[idx]);
- evdns_resolve_reverse(&addr, 0, main_callback, v[idx]);
- } else {
- fprintf(stderr, "resolving (fwd) %s...\n",v[idx]);
- evdns_resolve_ipv4(v[idx], 0, main_callback, v[idx]);
- }
- }
- fflush(stdout);
- event_dispatch();
- return 0;
-}
-#endif
diff --git a/extra/libevent/evdns.h b/extra/libevent/evdns.h
deleted file mode 100644
index 0ad22712962..00000000000
--- a/extra/libevent/evdns.h
+++ /dev/null
@@ -1,528 +0,0 @@
-/*
- * 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 BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * The original DNS code is due to Adam Langley with heavy
- * modifications by Nick Mathewson. Adam put his DNS software in the
- * public domain. You can find his original copyright below. Please,
- * aware that the code as part of libevent is governed by the 3-clause
- * BSD license above.
- *
- * This software is Public Domain. To view a copy of the public domain dedication,
- * visit http://creativecommons.org/licenses/publicdomain/ or send a letter to
- * Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.
- *
- * I ask and expect, but do not require, that all derivative works contain an
- * attribution similar to:
- * Parts developed by Adam Langley <agl@imperialviolet.org>
- *
- * You may wish to replace the word "Parts" with something else depending on
- * the amount of original code.
- *
- * (Derivative works does not include programs which link against, run or include
- * the source verbatim in their source distributions)
- */
-
-/** @file evdns.h
- *
- * Welcome, gentle reader
- *
- * 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.
- *
- * 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).
- *
- * 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.
- *
- * 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:
- *
- * 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.
- * 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.
- * 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.
- *
- * The library keeps track of the state of nameservers and will avoid
- * them when they go down. Otherwise it will round robin between them.
- *
- * 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);
- *
- * 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.
- *
- * Searching:
- *
- * 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.
- *
- * 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.
- *
- * To disable searching:
- * 1. Never set it up. If you never call evdns_resolv_conf_parse or
- * evdns_search_add then no searching will occur.
- *
- * 2. If you do call evdns_resolv_conf_parse then don't pass
- * DNS_OPTION_SEARCH (or DNS_OPTIONS_ALL, which implies it).
- *
- * 3. When calling evdns_resolve, pass the DNS_QUERY_NO_SEARCH flag.
- *
- * 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.
- *
- * The ndots setting can either be set from a resolv.conf, or by calling
- * evdns_search_ndots_set.
- *
- * For example, with ndots set to 1 (the default) and a search domain list of
- * ["myhome.net"]:
- * Query: www
- * Order: www.myhome.net, www.
- *
- * Query: www.abc
- * Order: www.abc., www.abc.myhome.net
- *
- * 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.
- *
- * 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.
- *
- * 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.
- */
-
-#ifndef EVENTDNS_H
-#define EVENTDNS_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* For integer types. */
-#include <evutil.h>
-
-/** Error codes 0-5 are as described in RFC 1035. */
-#define DNS_ERR_NONE 0
-/** The name server was unable to interpret the query */
-#define DNS_ERR_FORMAT 1
-/** The name server was unable to process this query due to a problem with the
- * name server */
-#define DNS_ERR_SERVERFAILED 2
-/** The domain name does not exist */
-#define DNS_ERR_NOTEXIST 3
-/** The name server does not support the requested kind of query */
-#define DNS_ERR_NOTIMPL 4
-/** The name server refuses to reform the specified operation for policy
- * reasons */
-#define DNS_ERR_REFUSED 5
-/** The reply was truncated or ill-formated */
-#define DNS_ERR_TRUNCATED 65
-/** An unknown error occurred */
-#define DNS_ERR_UNKNOWN 66
-/** Communication with the server timed out */
-#define DNS_ERR_TIMEOUT 67
-/** The request was canceled because the DNS subsystem was shut down. */
-#define DNS_ERR_SHUTDOWN 68
-
-#define DNS_IPv4_A 1
-#define DNS_PTR 2
-#define DNS_IPv6_AAAA 3
-
-#define DNS_QUERY_NO_SEARCH 1
-
-#define DNS_OPTION_SEARCH 1
-#define DNS_OPTION_NAMESERVERS 2
-#define DNS_OPTION_MISC 4
-#define DNS_OPTIONS_ALL 7
-
-/**
- * The callback that contains the results from a lookup.
- * - type is either DNS_IPv4_A or DNS_PTR or DNS_IPv6_AAAA
- * - count contains the number of addresses of form type
- * - ttl is the number of seconds the resolution may be cached for.
- * - addresses needs to be cast according to type
- */
-typedef void (*evdns_callback_type) (int result, char type, int count, int ttl, void *addresses, void *arg);
-
-/**
- Initialize the asynchronous DNS library.
-
- This function initializes support for non-blocking name resolution by
- calling evdns_resolv_conf_parse() on UNIX and
- evdns_config_windows_nameservers() on Windows.
-
- @return 0 if successful, or -1 if an error occurred
- @see evdns_shutdown()
- */
-int evdns_init(void);
-
-
-/**
- Shut down the asynchronous DNS resolver and terminate all active requests.
-
- If the 'fail_requests' option is enabled, all active requests will return
- an empty result with the error flag set to DNS_ERR_SHUTDOWN. Otherwise,
- the requests will be silently discarded.
-
- @param fail_requests if zero, active requests will be aborted; if non-zero,
- active requests will return DNS_ERR_SHUTDOWN.
- @see evdns_init()
- */
-void evdns_shutdown(int fail_requests);
-
-
-/**
- Convert a DNS error code to a string.
-
- @param err the DNS error code
- @return a string containing an explanation of the error code
-*/
-const char *evdns_err_to_string(int err);
-
-
-/**
- Add a nameserver.
-
- The address should be an IPv4 address in network byte order.
- The type of address is chosen so that it matches in_addr.s_addr.
-
- @param address an IP address in network byte order
- @return 0 if successful, or -1 if an error occurred
- @see evdns_nameserver_ip_add()
- */
-int evdns_nameserver_add(unsigned long int address);
-
-
-/**
- Get the number of configured nameservers.
-
- This returns 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.
-
- @return the number of configured nameservers
- @see evdns_nameserver_add()
- */
-int evdns_count_nameservers(void);
-
-
-/**
- Remove all configured nameservers, and suspend all pending resolves.
-
- Resolves will not necessarily be re-attempted until evdns_resume() is called.
-
- @return 0 if successful, or -1 if an error occurred
- @see evdns_resume()
- */
-int evdns_clear_nameservers_and_suspend(void);
-
-
-/**
- Resume normal operation and continue any suspended resolve requests.
-
- Re-attempt resolves left in limbo after an earlier call to
- evdns_clear_nameservers_and_suspend().
-
- @return 0 if successful, or -1 if an error occurred
- @see evdns_clear_nameservers_and_suspend()
- */
-int evdns_resume(void);
-
-
-/**
- Add a nameserver.
-
- This wraps the evdns_nameserver_add() function by parsing a string as an IP
- address and adds it as a nameserver.
-
- @return 0 if successful, or -1 if an error occurred
- @see evdns_nameserver_add()
- */
-int evdns_nameserver_ip_add(const char *ip_as_string);
-
-
-/**
- Lookup an A record for a given name.
-
- @param name a DNS hostname
- @param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query.
- @param callback a callback function to invoke when the request is completed
- @param ptr an argument to pass to the callback function
- @return 0 if successful, or -1 if an error occurred
- @see evdns_resolve_ipv6(), evdns_resolve_reverse(), evdns_resolve_reverse_ipv6()
- */
-int evdns_resolve_ipv4(const char *name, int flags, evdns_callback_type callback, void *ptr);
-
-
-/**
- Lookup an AAAA record for a given name.
-
- @param name a DNS hostname
- @param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query.
- @param callback a callback function to invoke when the request is completed
- @param ptr an argument to pass to the callback function
- @return 0 if successful, or -1 if an error occurred
- @see evdns_resolve_ipv4(), evdns_resolve_reverse(), evdns_resolve_reverse_ipv6()
- */
-int evdns_resolve_ipv6(const char *name, int flags, evdns_callback_type callback, void *ptr);
-
-struct in_addr;
-struct in6_addr;
-
-/**
- Lookup a PTR record for a given IP address.
-
- @param in an IPv4 address
- @param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query.
- @param callback a callback function to invoke when the request is completed
- @param ptr an argument to pass to the callback function
- @return 0 if successful, or -1 if an error occurred
- @see evdns_resolve_reverse_ipv6()
- */
-int evdns_resolve_reverse(struct in_addr *in, int flags, evdns_callback_type callback, void *ptr);
-
-
-/**
- Lookup a PTR record for a given IPv6 address.
-
- @param in an IPv6 address
- @param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query.
- @param callback a callback function to invoke when the request is completed
- @param ptr an argument to pass to the callback function
- @return 0 if successful, or -1 if an error occurred
- @see evdns_resolve_reverse_ipv6()
- */
-int evdns_resolve_reverse_ipv6(struct in6_addr *in, int flags, evdns_callback_type callback, void *ptr);
-
-
-/**
- Set the value of a configuration option.
-
- The currently available configuration options are:
-
- ndots, timeout, max-timeouts, max-inflight, and attempts
-
- @param option the name of the configuration option to be modified
- @param val the value to be set
- @param flags either 0 | DNS_OPTION_SEARCH | DNS_OPTION_MISC
- @return 0 if successful, or -1 if an error occurred
- */
-int evdns_set_option(const char *option, const char *val, int flags);
-
-
-/**
- Parse a resolv.conf file.
-
- The 'flags' parameter determines what information is parsed from the
- resolv.conf file. See the man page for resolv.conf for the format of this
- file.
-
- The following directives are not parsed from the file: sortlist, rotate,
- no-check-names, inet6, debug.
-
- If this function encounters an error, the possible return values are: 1 =
- failed to open file, 2 = failed to stat file, 3 = file too large, 4 = out of
- memory, 5 = short read from file, 6 = no nameservers listed in the file
-
- @param flags any of DNS_OPTION_NAMESERVERS|DNS_OPTION_SEARCH|DNS_OPTION_MISC|
- DNS_OPTIONS_ALL
- @param filename the path to the resolv.conf file
- @return 0 if successful, or various positive error codes if an error
- occurred (see above)
- @see resolv.conf(3), evdns_config_windows_nameservers()
- */
-int evdns_resolv_conf_parse(int flags, const char *const filename);
-
-
-/**
- Obtain nameserver information using the Windows API.
-
- 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.
-
- @return 0 if successful, or -1 if an error occurred
- @see evdns_resolv_conf_parse()
- */
-#ifdef MS_WINDOWS
-int evdns_config_windows_nameservers(void);
-#endif
-
-
-/**
- Clear the list of search domains.
- */
-void evdns_search_clear(void);
-
-
-/**
- Add a domain to the list of search domains
-
- @param domain the domain to be added to the search list
- */
-void evdns_search_add(const char *domain);
-
-
-/**
- Set the 'ndots' parameter for searches.
-
- Sets the number of dots which, when found in a name, causes
- the first query to be without any search domain.
-
- @param ndots the new ndots parameter
- */
-void evdns_search_ndots_set(const int ndots);
-
-/**
- A callback that is invoked when a log message is generated
-
- @param is_warning indicates if the log message is a 'warning'
- @param msg the content of the log message
- */
-typedef void (*evdns_debug_log_fn_type)(int is_warning, const char *msg);
-
-
-/**
- Set the callback function to handle log messages.
-
- @param fn the callback to be invoked when a log message is generated
- */
-void evdns_set_log_fn(evdns_debug_log_fn_type fn);
-
-/**
- Set a callback that will be invoked to generate transaction IDs. By
- default, we pick transaction IDs based on the current clock time.
-
- @param fn the new callback, or NULL to use the default.
- */
-void evdns_set_transaction_id_fn(ev_uint16_t (*fn)(void));
-
-#define DNS_NO_SEARCH 1
-
-/*
- * Structures and functions used to implement a DNS server.
- */
-
-struct evdns_server_request {
- int flags;
- int nquestions;
- struct evdns_server_question **questions;
-};
-struct evdns_server_question {
- int type;
-#ifdef __cplusplus
- int dns_question_class;
-#else
- /* You should refer to this field as "dns_question_class". The
- * name "class" works in C for backward compatibility, and will be
- * removed in a future version. (1.5 or later). */
- int class;
-#define dns_question_class class
-#endif
- char name[1];
-};
-typedef void (*evdns_request_callback_fn_type)(struct evdns_server_request *, void *);
-#define EVDNS_ANSWER_SECTION 0
-#define EVDNS_AUTHORITY_SECTION 1
-#define EVDNS_ADDITIONAL_SECTION 2
-
-#define EVDNS_TYPE_A 1
-#define EVDNS_TYPE_NS 2
-#define EVDNS_TYPE_CNAME 5
-#define EVDNS_TYPE_SOA 6
-#define EVDNS_TYPE_PTR 12
-#define EVDNS_TYPE_MX 15
-#define EVDNS_TYPE_TXT 16
-#define EVDNS_TYPE_AAAA 28
-
-#define EVDNS_QTYPE_AXFR 252
-#define EVDNS_QTYPE_ALL 255
-
-#define EVDNS_CLASS_INET 1
-
-struct evdns_server_port *evdns_add_server_port(int socket, int is_tcp, evdns_request_callback_fn_type callback, void *user_data);
-void evdns_close_server_port(struct evdns_server_port *port);
-
-int evdns_server_request_add_reply(struct evdns_server_request *req, int section, const char *name, int type, int dns_class, int ttl, int datalen, int is_name, const char *data);
-int evdns_server_request_add_a_reply(struct evdns_server_request *req, const char *name, int n, void *addrs, int ttl);
-int evdns_server_request_add_aaaa_reply(struct evdns_server_request *req, const char *name, int n, void *addrs, int ttl);
-int evdns_server_request_add_ptr_reply(struct evdns_server_request *req, struct in_addr *in, const char *inaddr_name, const char *hostname, int ttl);
-int evdns_server_request_add_cname_reply(struct evdns_server_request *req, const char *name, const char *cname, int ttl);
-
-int evdns_server_request_respond(struct evdns_server_request *req, int err);
-int evdns_server_request_drop(struct evdns_server_request *req);
-struct sockaddr;
-int evdns_server_request_get_requesting_addr(struct evdns_server_request *_req, struct sockaddr *sa, int addr_len);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* !EVENTDNS_H */
diff --git a/extra/libevent/event-internal.h b/extra/libevent/event-internal.h
deleted file mode 100644
index 59a089ddec4..00000000000
--- a/extra/libevent/event-internal.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (c) 2000-2004 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 BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#ifndef _EVENT_INTERNAL_H_
-#define _EVENT_INTERNAL_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "config.h"
-#include "min_heap.h"
-#include "evsignal.h"
-
-struct eventop {
- const char *name;
- void *(*init)(struct event_base *);
- int (*add)(void *, struct event *);
- int (*del)(void *, struct event *);
- int (*dispatch)(struct event_base *, void *, struct timeval *);
- void (*dealloc)(struct event_base *, void *);
- /* set if we need to reinitialize the event base */
- int need_reinit;
-};
-
-struct event_base {
- const struct eventop *evsel;
- void *evbase;
- int event_count; /* counts number of total events */
- int event_count_active; /* counts number of active events */
-
- int event_gotterm; /* Set to terminate loop */
- int event_break; /* Set to terminate loop immediately */
-
- /* active event management */
- struct event_list **activequeues;
- int nactivequeues;
-
- /* signal handling info */
- struct evsignal_info sig;
-
- struct event_list eventqueue;
- struct timeval event_tv;
-
- struct min_heap timeheap;
-};
-
-/* Internal use only: Functions that might be missing from <sys/queue.h> */
-/* These following macros are copied from BSD sys/queue.h
- Copyright (c) 1991, 1993, The Regents of the University of California.
- All rights reserved.
-*/
-#ifndef TAILQ_EMPTY
-#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
-#define TAILQ_FIRST(head) ((head)->tqh_first)
-#define TAILQ_END(head) NULL
-#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
-#endif /* TAILQ_EMPTY */
-#ifndef HAVE_TAILQFOREACH
-#define TAILQ_FOREACH(var, head, field) \
- for((var) = TAILQ_FIRST(head); \
- (var) != TAILQ_END(head); \
- (var) = TAILQ_NEXT(var, field))
-#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
- (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
- (elm)->field.tqe_next = (listelm); \
- *(listelm)->field.tqe_prev = (elm); \
- (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
-} while (0)
-#endif /* TAILQ_FOREACH */
-
-int _evsignal_set_handler(struct event_base *base, int evsignal,
- void (*fn)(int));
-int _evsignal_restore_handler(struct event_base *base, int evsignal);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _EVENT_INTERNAL_H_ */
diff --git a/extra/libevent/event.c b/extra/libevent/event.c
deleted file mode 100644
index 07498c709c8..00000000000
--- a/extra/libevent/event.c
+++ /dev/null
@@ -1,989 +0,0 @@
-/*
- * Copyright (c) 2000-2004 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 BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef WIN32
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#undef WIN32_LEAN_AND_MEAN
-#include "misc.h"
-#endif
-#include <sys/types.h>
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#else
-#include <sys/_time.h>
-#endif
-#include <sys/queue.h>
-#include <stdio.h>
-#include <stdlib.h>
-#ifndef WIN32
-#include <unistd.h>
-#endif
-#include <errno.h>
-#include <signal.h>
-#include <string.h>
-#include <assert.h>
-#include <time.h>
-
-#include "event.h"
-#include "event-internal.h"
-#include "evutil.h"
-#include "log.h"
-
-#ifdef HAVE_EVENT_PORTS
-extern const struct eventop evportops;
-#endif
-#ifdef HAVE_SELECT
-extern const struct eventop selectops;
-#endif
-#ifdef HAVE_POLL
-extern const struct eventop pollops;
-#endif
-#ifdef HAVE_EPOLL
-extern const struct eventop epollops;
-#endif
-#ifdef HAVE_WORKING_KQUEUE
-extern const struct eventop kqops;
-#endif
-#ifdef HAVE_DEVPOLL
-extern const struct eventop devpollops;
-#endif
-#ifdef WIN32
-extern const struct eventop win32ops;
-#endif
-
-/* In order of preference */
-const struct eventop *eventops[] = {
-#ifdef HAVE_EVENT_PORTS
- &evportops,
-#endif
-#ifdef HAVE_WORKING_KQUEUE
- &kqops,
-#endif
-#ifdef HAVE_EPOLL
- &epollops,
-#endif
-#ifdef HAVE_DEVPOLL
- &devpollops,
-#endif
-#ifdef HAVE_POLL
- &pollops,
-#endif
-#ifdef HAVE_SELECT
- &selectops,
-#endif
-#ifdef WIN32
- &win32ops,
-#endif
- NULL
-};
-
-/* Global state */
-struct event_base *current_base = NULL;
-extern struct event_base *evsignal_base;
-static int use_monotonic;
-
-/* Handle signals - This is a deprecated interface */
-int (*event_sigcb)(void); /* Signal callback when gotsig is set */
-volatile sig_atomic_t event_gotsig; /* Set in signal handler */
-
-/* Prototypes */
-static void event_queue_insert(struct event_base *, struct event *, int);
-static void event_queue_remove(struct event_base *, struct event *, int);
-static int event_haveevents(struct event_base *);
-
-static void event_process_active(struct event_base *);
-
-static int timeout_next(struct event_base *, struct timeval **);
-static void timeout_process(struct event_base *);
-static void timeout_correct(struct event_base *, struct timeval *);
-
-static void
-detect_monotonic(void)
-{
-#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
- struct timespec ts;
-
- if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
- use_monotonic = 1;
-#endif
-}
-
-static int
-gettime(struct timeval *tp)
-{
-#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
- struct timespec ts;
-
- if (use_monotonic) {
- if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
- return (-1);
-
- tp->tv_sec = ts.tv_sec;
- tp->tv_usec = ts.tv_nsec / 1000;
- return (0);
- }
-#endif
-
- return (gettimeofday(tp, NULL));
-}
-
-struct event_base *
-event_init(void)
-{
- struct event_base *base = event_base_new();
-
- if (base != NULL)
- current_base = base;
-
- return (base);
-}
-
-struct event_base *
-event_base_new(void)
-{
- int i;
- struct event_base *base;
-
- if ((base = calloc(1, sizeof(struct event_base))) == NULL)
- event_err(1, "%s: calloc", __func__);
-
- event_sigcb = NULL;
- event_gotsig = 0;
-
- detect_monotonic();
- gettime(&base->event_tv);
-
- min_heap_ctor(&base->timeheap);
- TAILQ_INIT(&base->eventqueue);
- TAILQ_INIT(&base->sig.signalqueue);
- base->sig.ev_signal_pair[0] = -1;
- base->sig.ev_signal_pair[1] = -1;
-
- base->evbase = NULL;
- for (i = 0; eventops[i] && !base->evbase; i++) {
- base->evsel = eventops[i];
-
- base->evbase = base->evsel->init(base);
- }
-
- if (base->evbase == NULL)
- event_errx(1, "%s: no event mechanism available", __func__);
-
- if (getenv("EVENT_SHOW_METHOD"))
- event_msgx("libevent using: %s\n",
- base->evsel->name);
-
- /* allocate a single active event queue */
- event_base_priority_init(base, 1);
-
- return (base);
-}
-
-void
-event_base_free(struct event_base *base)
-{
- int i, n_deleted=0;
- struct event *ev;
-
- if (base == NULL && current_base)
- base = current_base;
- if (base == current_base)
- current_base = NULL;
-
- /* XXX(niels) - check for internal events first */
- assert(base);
- /* Delete all non-internal events. */
- for (ev = TAILQ_FIRST(&base->eventqueue); ev; ) {
- struct event *next = TAILQ_NEXT(ev, ev_next);
- if (!(ev->ev_flags & EVLIST_INTERNAL)) {
- event_del(ev);
- ++n_deleted;
- }
- ev = next;
- }
- while ((ev = min_heap_top(&base->timeheap)) != NULL) {
- event_del(ev);
- ++n_deleted;
- }
-
- if (n_deleted)
- event_debug(("%s: %d events were still set in base",
- __func__, n_deleted));
-
- if (base->evsel->dealloc != NULL)
- base->evsel->dealloc(base, base->evbase);
-
- for (i = 0; i < base->nactivequeues; ++i)
- assert(TAILQ_EMPTY(base->activequeues[i]));
-
- assert(min_heap_empty(&base->timeheap));
- min_heap_dtor(&base->timeheap);
-
- for (i = 0; i < base->nactivequeues; ++i)
- free(base->activequeues[i]);
- free(base->activequeues);
-
- assert(TAILQ_EMPTY(&base->eventqueue));
-
- free(base);
-}
-
-/* reinitialized the event base after a fork */
-int
-event_reinit(struct event_base *base)
-{
- const struct eventop *evsel = base->evsel;
- void *evbase = base->evbase;
- int res = 0;
- struct event *ev;
-
- /* check if this event mechanism requires reinit */
- if (!evsel->need_reinit)
- return (0);
-
- if (base->evsel->dealloc != NULL)
- base->evsel->dealloc(base, base->evbase);
- base->evbase = evsel->init(base);
- if (base->evbase == NULL)
- event_errx(1, "%s: could not reinitialize event mechanism",
- __func__);
-
- TAILQ_FOREACH(ev, &base->eventqueue, ev_next) {
- if (evsel->add(evbase, ev) == -1)
- res = -1;
- }
-
- return (res);
-}
-
-int
-event_priority_init(int npriorities)
-{
- return event_base_priority_init(current_base, npriorities);
-}
-
-int
-event_base_priority_init(struct event_base *base, int npriorities)
-{
- int i;
-
- if (base->event_count_active)
- return (-1);
-
- if (base->nactivequeues && npriorities != base->nactivequeues) {
- for (i = 0; i < base->nactivequeues; ++i) {
- free(base->activequeues[i]);
- }
- free(base->activequeues);
- }
-
- /* Allocate our priority queues */
- base->nactivequeues = npriorities;
- base->activequeues = (struct event_list **)calloc(base->nactivequeues,
- npriorities * sizeof(struct event_list *));
- if (base->activequeues == NULL)
- event_err(1, "%s: calloc", __func__);
-
- for (i = 0; i < base->nactivequeues; ++i) {
- base->activequeues[i] = malloc(sizeof(struct event_list));
- if (base->activequeues[i] == NULL)
- event_err(1, "%s: malloc", __func__);
- TAILQ_INIT(base->activequeues[i]);
- }
-
- return (0);
-}
-
-int
-event_haveevents(struct event_base *base)
-{
- return (base->event_count > 0);
-}
-
-/*
- * Active events are stored in priority queues. Lower priorities are always
- * process before higher priorities. Low priority events can starve high
- * priority ones.
- */
-
-static void
-event_process_active(struct event_base *base)
-{
- struct event *ev;
- struct event_list *activeq = NULL;
- int i;
- short ncalls;
-
- for (i = 0; i < base->nactivequeues; ++i) {
- if (TAILQ_FIRST(base->activequeues[i]) != NULL) {
- activeq = base->activequeues[i];
- break;
- }
- }
-
- assert(activeq != NULL);
-
- for (ev = TAILQ_FIRST(activeq); ev; ev = TAILQ_FIRST(activeq)) {
- if (ev->ev_events & EV_PERSIST)
- event_queue_remove(base, ev, EVLIST_ACTIVE);
- else
- event_del(ev);
-
- /* Allows deletes to work */
- ncalls = ev->ev_ncalls;
- ev->ev_pncalls = &ncalls;
- while (ncalls) {
- ncalls--;
- ev->ev_ncalls = ncalls;
- (*ev->ev_callback)((int)ev->ev_fd, ev->ev_res, ev->ev_arg);
- if (event_gotsig || base->event_break)
- return;
- }
- }
-}
-
-/*
- * Wait continously for events. We exit only if no events are left.
- */
-
-int
-event_dispatch(void)
-{
- return (event_loop(0));
-}
-
-int
-event_base_dispatch(struct event_base *event_base)
-{
- return (event_base_loop(event_base, 0));
-}
-
-const char *
-event_base_get_method(struct event_base *base)
-{
- assert(base);
- return (base->evsel->name);
-}
-
-static void
-event_loopexit_cb(int fd __attribute__((unused)),
- short what __attribute__((unused)), void *arg)
-{
- struct event_base *base = arg;
- base->event_gotterm = 1;
-}
-
-/* not thread safe */
-int
-event_loopexit(struct timeval *tv)
-{
- return (event_once(-1, EV_TIMEOUT, &event_loopexit_cb,
- current_base, tv));
-}
-
-int
-event_base_loopexit(struct event_base *event_base, struct timeval *tv)
-{
- return (event_base_once(event_base, -1, EV_TIMEOUT, event_loopexit_cb,
- event_base, tv));
-}
-
-/* not thread safe */
-int
-event_loopbreak(void)
-{
- return (event_base_loopbreak(current_base));
-}
-
-int
-event_base_loopbreak(struct event_base *event_base)
-{
- if (event_base == NULL)
- return (-1);
-
- event_base->event_break = 1;
- return (0);
-}
-
-
-
-/* not thread safe */
-
-int
-event_loop(int flags)
-{
- return event_base_loop(current_base, flags);
-}
-
-int
-event_base_loop(struct event_base *base, int flags)
-{
- const struct eventop *evsel = base->evsel;
- void *evbase = base->evbase;
- struct timeval tv;
- struct timeval *tv_p;
- int res, done;
-
- if(!TAILQ_EMPTY(&base->sig.signalqueue))
- evsignal_base = base;
- done = 0;
- while (!done) {
- /* Terminate the loop if we have been asked to */
- if (base->event_gotterm) {
- base->event_gotterm = 0;
- break;
- }
-
- if (base->event_break) {
- base->event_break = 0;
- break;
- }
-
- /* You cannot use this interface for multi-threaded apps */
- while (event_gotsig) {
- event_gotsig = 0;
- if (event_sigcb) {
- res = (*event_sigcb)();
- if (res == -1) {
- errno = EINTR;
- return (-1);
- }
- }
- }
-
- timeout_correct(base, &tv);
-
- tv_p = &tv;
- if (!base->event_count_active && !(flags & EVLOOP_NONBLOCK)) {
- timeout_next(base, &tv_p);
- } else {
- /*
- * if we have active events, we just poll new events
- * without waiting.
- */
- evutil_timerclear(&tv);
- }
-
- /* If we have no events, we just exit */
- if (!event_haveevents(base)) {
- event_debug(("%s: no events registered.", __func__));
- return (1);
- }
-
- res = evsel->dispatch(base, evbase, tv_p);
-
- if (res == -1)
- return (-1);
-
- timeout_process(base);
-
- if (base->event_count_active) {
- event_process_active(base);
- if (!base->event_count_active && (flags & EVLOOP_ONCE))
- done = 1;
- } else if (flags & EVLOOP_NONBLOCK)
- done = 1;
- }
-
- event_debug(("%s: asked to terminate loop.", __func__));
- return (0);
-}
-
-/* Sets up an event for processing once */
-
-struct event_once {
- struct event ev;
-
- void (*cb)(int, short, void *);
- void *arg;
-};
-
-/* One-time callback, it deletes itself */
-
-static void
-event_once_cb(int fd, short events, void *arg)
-{
- struct event_once *eonce = arg;
-
- (*eonce->cb)(fd, events, eonce->arg);
- free(eonce);
-}
-
-/* not threadsafe, event scheduled once. */
-int
-event_once(int fd, short events,
- void (*callback)(int, short, void *), void *arg, struct timeval *tv)
-{
- return event_base_once(current_base, fd, events, callback, arg, tv);
-}
-
-/* Schedules an event once */
-int
-event_base_once(struct event_base *base, int fd, short events,
- void (*callback)(int, short, void *), void *arg, struct timeval *tv)
-{
- struct event_once *eonce;
- struct timeval etv;
- int res;
-
- /* We cannot support signals that just fire once */
- if (events & EV_SIGNAL)
- return (-1);
-
- if ((eonce = calloc(1, sizeof(struct event_once))) == NULL)
- return (-1);
-
- eonce->cb = callback;
- eonce->arg = arg;
-
- if (events == EV_TIMEOUT) {
- if (tv == NULL) {
- evutil_timerclear(&etv);
- tv = &etv;
- }
-
- evtimer_set(&eonce->ev, event_once_cb, eonce);
- } else if (events & (EV_READ|EV_WRITE)) {
- events &= EV_READ|EV_WRITE;
-
- event_set(&eonce->ev, fd, events, event_once_cb, eonce);
- } else {
- /* Bad event combination */
- free(eonce);
- return (-1);
- }
-
- res = event_base_set(base, &eonce->ev);
- if (res == 0)
- res = event_add(&eonce->ev, tv);
- if (res != 0) {
- free(eonce);
- return (res);
- }
-
- return (0);
-}
-
-void
-event_set(struct event *ev, int fd, short events,
- void (*callback)(int, short, void *), void *arg)
-{
- /* Take the current base - caller needs to set the real base later */
- ev->ev_base = current_base;
-
- ev->ev_callback = callback;
- ev->ev_arg = arg;
- ev->ev_fd = fd;
- ev->ev_events = events;
- ev->ev_res = 0;
- ev->ev_flags = EVLIST_INIT;
- ev->ev_ncalls = 0;
- ev->ev_pncalls = NULL;
-
- min_heap_elem_init(ev);
-
- /* by default, we put new events into the middle priority */
- if(current_base)
- ev->ev_pri = current_base->nactivequeues/2;
-}
-
-int
-event_base_set(struct event_base *base, struct event *ev)
-{
- /* Only innocent events may be assigned to a different base */
- if (ev->ev_flags != EVLIST_INIT)
- return (-1);
-
- ev->ev_base = base;
- ev->ev_pri = base->nactivequeues/2;
-
- return (0);
-}
-
-/*
- * Set's the priority of an event - if an event is already scheduled
- * changing the priority is going to fail.
- */
-
-int
-event_priority_set(struct event *ev, int pri)
-{
- if (ev->ev_flags & EVLIST_ACTIVE)
- return (-1);
- if (pri < 0 || pri >= ev->ev_base->nactivequeues)
- return (-1);
-
- ev->ev_pri = pri;
-
- return (0);
-}
-
-/*
- * Checks if a specific event is pending or scheduled.
- */
-
-int
-event_pending(struct event *ev, short event, struct timeval *tv)
-{
- struct timeval now, res;
- int flags = 0;
-
- if (ev->ev_flags & EVLIST_INSERTED)
- flags |= (ev->ev_events & (EV_READ|EV_WRITE));
- if (ev->ev_flags & EVLIST_ACTIVE)
- flags |= ev->ev_res;
- if (ev->ev_flags & EVLIST_TIMEOUT)
- flags |= EV_TIMEOUT;
- if (ev->ev_flags & EVLIST_SIGNAL)
- flags |= EV_SIGNAL;
-
- event &= (EV_TIMEOUT|EV_READ|EV_WRITE|EV_SIGNAL);
-
- /* See if there is a timeout that we should report */
- if (tv != NULL && (flags & event & EV_TIMEOUT)) {
- gettime(&now);
- evutil_timersub(&ev->ev_timeout, &now, &res);
- /* correctly remap to real time */
- gettimeofday(&now, NULL);
- evutil_timeradd(&now, &res, tv);
- }
-
- return (flags & event);
-}
-
-int
-event_add(struct event *ev, struct timeval *tv)
-{
- struct event_base *base = ev->ev_base;
- const struct eventop *evsel = base->evsel;
- void *evbase = base->evbase;
-
- event_debug((
- "event_add: event: %p, %s%s%scall %p",
- ev,
- ev->ev_events & EV_READ ? "EV_READ " : " ",
- ev->ev_events & EV_WRITE ? "EV_WRITE " : " ",
- tv ? "EV_TIMEOUT " : " ",
- ev->ev_callback));
-
- assert(!(ev->ev_flags & ~EVLIST_ALL));
-
- if (tv != NULL) {
- struct timeval now;
-
- if (ev->ev_flags & EVLIST_TIMEOUT)
- event_queue_remove(base, ev, EVLIST_TIMEOUT);
- else if (min_heap_reserve(&base->timeheap,
- 1 + min_heap_size(&base->timeheap)) == -1)
- return (-1); /* ENOMEM == errno */
-
- /* Check if it is active due to a timeout. Rescheduling
- * this timeout before the callback can be executed
- * removes it from the active list. */
- if ((ev->ev_flags & EVLIST_ACTIVE) &&
- (ev->ev_res & EV_TIMEOUT)) {
- /* See if we are just active executing this
- * event in a loop
- */
- if (ev->ev_ncalls && ev->ev_pncalls) {
- /* Abort loop */
- *ev->ev_pncalls = 0;
- }
-
- event_queue_remove(base, ev, EVLIST_ACTIVE);
- }
-
- gettime(&now);
- evutil_timeradd(&now, tv, &ev->ev_timeout);
-
- event_debug((
- "event_add: timeout in %d seconds, call %p",
- tv->tv_sec, ev->ev_callback));
-
- event_queue_insert(base, ev, EVLIST_TIMEOUT);
- }
-
- if ((ev->ev_events & (EV_READ|EV_WRITE)) &&
- !(ev->ev_flags & (EVLIST_INSERTED|EVLIST_ACTIVE))) {
- int res = evsel->add(evbase, ev);
- if (res != -1)
- event_queue_insert(base, ev, EVLIST_INSERTED);
-
- return (res);
- } else if ((ev->ev_events & EV_SIGNAL) &&
- !(ev->ev_flags & EVLIST_SIGNAL)) {
- int res = evsel->add(evbase, ev);
- if (res != -1)
- event_queue_insert(base, ev, EVLIST_SIGNAL);
-
- return (res);
- }
-
- return (0);
-}
-
-int
-event_del(struct event *ev)
-{
- struct event_base *base;
- const struct eventop *evsel;
- void *evbase;
-
- event_debug(("event_del: %p, callback %p",
- ev, ev->ev_callback));
-
- /* An event without a base has not been added */
- if (ev->ev_base == NULL)
- return (-1);
-
- base = ev->ev_base;
- evsel = base->evsel;
- evbase = base->evbase;
-
- assert(!(ev->ev_flags & ~EVLIST_ALL));
-
- /* See if we are just active executing this event in a loop */
- if (ev->ev_ncalls && ev->ev_pncalls) {
- /* Abort loop */
- *ev->ev_pncalls = 0;
- }
-
- if (ev->ev_flags & EVLIST_TIMEOUT)
- event_queue_remove(base, ev, EVLIST_TIMEOUT);
-
- if (ev->ev_flags & EVLIST_ACTIVE)
- event_queue_remove(base, ev, EVLIST_ACTIVE);
-
- if (ev->ev_flags & EVLIST_INSERTED) {
- event_queue_remove(base, ev, EVLIST_INSERTED);
- return (evsel->del(evbase, ev));
- } else if (ev->ev_flags & EVLIST_SIGNAL) {
- event_queue_remove(base, ev, EVLIST_SIGNAL);
- return (evsel->del(evbase, ev));
- }
-
- return (0);
-}
-
-void
-event_active(struct event *ev, int res, short ncalls)
-{
- /* We get different kinds of events, add them together */
- if (ev->ev_flags & EVLIST_ACTIVE) {
- ev->ev_res |= res;
- return;
- }
-
- ev->ev_res = res;
- ev->ev_ncalls = ncalls;
- ev->ev_pncalls = NULL;
- event_queue_insert(ev->ev_base, ev, EVLIST_ACTIVE);
-}
-
-static int
-timeout_next(struct event_base *base, struct timeval **tv_p)
-{
- struct timeval now;
- struct event *ev;
- struct timeval *tv = *tv_p;
-
- if ((ev = min_heap_top(&base->timeheap)) == NULL) {
- /* if no time-based events are active wait for I/O */
- *tv_p = NULL;
- return (0);
- }
-
- if (gettime(&now) == -1)
- return (-1);
-
- if (evutil_timercmp(&ev->ev_timeout, &now, <=)) {
- evutil_timerclear(tv);
- return (0);
- }
-
- evutil_timersub(&ev->ev_timeout, &now, tv);
-
- assert(tv->tv_sec >= 0);
- assert(tv->tv_usec >= 0);
-
- event_debug(("timeout_next: in %d seconds", tv->tv_sec));
- return (0);
-}
-
-/*
- * Determines if the time is running backwards by comparing the current
- * time against the last time we checked. Not needed when using clock
- * monotonic.
- */
-
-static void
-timeout_correct(struct event_base *base, struct timeval *tv)
-{
- struct event **pev;
- unsigned int size;
- struct timeval off;
-
- if (use_monotonic)
- return;
-
- /* Check if time is running backwards */
- gettime(tv);
- if (evutil_timercmp(tv, &base->event_tv, >=)) {
- base->event_tv = *tv;
- return;
- }
-
- event_debug(("%s: time is running backwards, corrected",
- __func__));
- evutil_timersub(&base->event_tv, tv, &off);
-
- /*
- * We can modify the key element of the node without destroying
- * the key, beause we apply it to all in the right order.
- */
- pev = base->timeheap.p;
- size = base->timeheap.n;
- for (; size-- > 0; ++pev) {
- struct timeval *ev_tv = &(**pev).ev_timeout;
- evutil_timersub(ev_tv, &off, ev_tv);
- }
-}
-
-void
-timeout_process(struct event_base *base)
-{
- struct timeval now;
- struct event *ev;
-
- if (min_heap_empty(&base->timeheap))
- return;
-
- gettime(&now);
-
- while ((ev = min_heap_top(&base->timeheap))) {
- if (evutil_timercmp(&ev->ev_timeout, &now, >))
- break;
-
- /* delete this event from the I/O queues */
- event_del(ev);
-
- event_debug(("timeout_process: call %p",
- ev->ev_callback));
- event_active(ev, EV_TIMEOUT, 1);
- }
-}
-
-void
-event_queue_remove(struct event_base *base, struct event *ev, int queue)
-{
- if (!(ev->ev_flags & queue))
- event_errx(1, "%s: %p(fd %d) not on queue %x", __func__,
- ev, ev->ev_fd, queue);
-
- if (~ev->ev_flags & EVLIST_INTERNAL)
- base->event_count--;
-
- ev->ev_flags &= ~queue;
- switch (queue) {
- case EVLIST_ACTIVE:
- base->event_count_active--;
- TAILQ_REMOVE(base->activequeues[ev->ev_pri],
- ev, ev_active_next);
- break;
- case EVLIST_SIGNAL:
- TAILQ_REMOVE(&base->sig.signalqueue, ev, ev_signal_next);
- break;
- case EVLIST_TIMEOUT:
- min_heap_erase(&base->timeheap, ev);
- break;
- case EVLIST_INSERTED:
- TAILQ_REMOVE(&base->eventqueue, ev, ev_next);
- break;
- default:
- event_errx(1, "%s: unknown queue %x", __func__, queue);
- }
-}
-
-void
-event_queue_insert(struct event_base *base, struct event *ev, int queue)
-{
- if (ev->ev_flags & queue) {
- /* Double insertion is possible for active events */
- if (queue & EVLIST_ACTIVE)
- return;
-
- event_errx(1, "%s: %p(fd %d) already on queue %x", __func__,
- ev, ev->ev_fd, queue);
- }
-
- if (~ev->ev_flags & EVLIST_INTERNAL)
- base->event_count++;
-
- ev->ev_flags |= queue;
- switch (queue) {
- case EVLIST_ACTIVE:
- base->event_count_active++;
- TAILQ_INSERT_TAIL(base->activequeues[ev->ev_pri],
- ev,ev_active_next);
- break;
- case EVLIST_SIGNAL:
- TAILQ_INSERT_TAIL(&base->sig.signalqueue, ev, ev_signal_next);
- break;
- case EVLIST_TIMEOUT: {
- min_heap_push(&base->timeheap, ev);
- break;
- }
- case EVLIST_INSERTED:
- TAILQ_INSERT_TAIL(&base->eventqueue, ev, ev_next);
- break;
- default:
- event_errx(1, "%s: unknown queue %x", __func__, queue);
- }
-}
-
-/* Functions for debugging */
-
-const char *
-event_get_version(void)
-{
- return (VERSION);
-}
-
-/*
- * No thread-safe interface needed - the information should be the same
- * for all threads.
- */
-
-const char *
-event_get_method(void)
-{
- return (current_base->evsel->name);
-}
diff --git a/extra/libevent/event.h b/extra/libevent/event.h
deleted file mode 100644
index 078c940770e..00000000000
--- a/extra/libevent/event.h
+++ /dev/null
@@ -1,1129 +0,0 @@
-/*
- * Copyright (c) 2000-2007 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 BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#ifndef _EVENT_H_
-#define _EVENT_H_
-
-/** @mainpage
-
- @section intro Introduction
-
- libevent is an event notification library for developing scalable network
- servers. The libevent API provides a mechanism to execute a callback
- function when a specific event occurs on a file descriptor or after a
- timeout has been reached. Furthermore, libevent also support callbacks due
- to signals or regular timeouts.
-
- libevent is meant to replace the event loop found in event driven network
- servers. An application just needs to call event_dispatch() and then add or
- remove events dynamically without having to change the event loop.
-
- Currently, libevent supports /dev/poll, kqueue(2), select(2), poll(2) and
- epoll(4). It also has experimental support for real-time signals. The
- internal event mechanism is completely independent of the exposed event API,
- and a simple update of libevent can provide new functionality without having
- to redesign the applications. As a result, Libevent allows for portable
- application development and provides the most scalable event notification
- mechanism available on an operating system. Libevent can also be used for
- multi-threaded aplications; see Steven Grimm's explanation. Libevent should
- compile on Linux, *BSD, Mac OS X, Solaris and Windows.
-
- @section usage Standard usage
-
- Every program that uses libevent must include the <event.h> header, and pass
- the -levent flag to the linker. Before using any of the functions in the
- library, you must call event_init() or event_base_new() to perform one-time
- initialization of the libevent library.
-
- @section event Event notification
-
- For each file descriptor that you wish to monitor, you must declare an event
- structure and call event_set() to initialize the members of the structure.
- To enable notification, you add the structure to the list of monitored
- events by calling event_add(). The event structure must remain allocated as
- long as it is active, so it should be allocated on the heap. Finally, you
- call event_dispatch() to loop and dispatch events.
-
- @section bufferevent I/O Buffers
-
- libevent provides an abstraction on top of the regular event callbacks. This
- abstraction is called a 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 I/O, but instead is reading
- from input and writing to output buffers.
-
- Once initialized via bufferevent_new(), the bufferevent structure can be
- used repeatedly with bufferevent_enable() and bufferevent_disable().
- Instead of reading and writing directly to a socket, you would call
- bufferevent_read() and bufferevent_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 0 by
- default.
-
- @section timers Timers
-
- libevent can also be used to create timers that invoke a callback after a
- certain amount of time has expired. The evtimer_set() function prepares an
- event struct to be used as a timer. To activate the timer, call
- evtimer_add(). Timers can be deactivated by calling evtimer_del().
-
- @section timeouts Timeouts
-
- In addition to simple timers, libevent can assign timeout events to file
- descriptors that are triggered whenever a certain amount of time has passed
- with no activity on a file descriptor. The timeout_set() function
- initializes an event struct for use as a timeout. Once initialized, the
- event must be activated by using timeout_add(). To cancel the timeout, call
- timeout_del().
-
- @section evdns Asynchronous DNS resolution
-
- libevent provides an asynchronous DNS resolver that should be used instead
- of the standard DNS resolver functions. These functions can be imported by
- including the <evdns.h> header in your program. Before using any of the
- resolver functions, you must call evdns_init() to initialize the library. To
- convert a hostname to an IP address, you call the evdns_resolve_ipv4()
- function. To perform a reverse lookup, you would call the
- evdns_resolve_reverse() function. All of these functions use callbacks to
- avoid blocking while the lookup is performed.
-
- @section evhttp Event-driven HTTP servers
-
- libevent provides a very simple event-driven HTTP server that can be
- embedded in your program and used to service HTTP requests.
-
- To use this capability, you need to include the <evhttp.h> header in your
- program. You create the server by calling evhttp_new(). Add addresses and
- ports to listen on with evhttp_bind_socket(). You then register one or more
- callbacks to handle incoming requests. Each URI can be assigned a callback
- via the evhttp_set_cb() function. A generic callback function can also be
- registered via evhttp_set_gencb(); this callback will be invoked if no other
- callbacks have been registered for a given URI.
-
- @section evrpc A framework for RPC servers and clients
-
- libevents provides a framework for creating RPC servers and clients. It
- takes care of marshaling and unmarshaling all data structures.
-
- @section api API Reference
-
- To browse the complete documentation of the libevent API, click on any of
- the following links.
-
- event.h
- The primary libevent header
-
- evdns.h
- Asynchronous DNS resolution
-
- evhttp.h
- An embedded libevent-based HTTP server
-
- evrpc.h
- A framework for creating RPC servers and clients
-
- */
-
-/** @file event.h
-
- A library for writing event-driven network servers
-
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <my_attribute.h>
-
-#include <event-config.h>
-#ifdef _EVENT_HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef _EVENT_HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#ifdef _EVENT_HAVE_STDINT_H
-#include <stdint.h>
-#endif
-#include <stdarg.h>
-
-/* For int types. */
-#include <evutil.h>
-
-#ifdef WIN32
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#undef WIN32_LEAN_AND_MEAN
-typedef unsigned char u_char;
-typedef unsigned short u_short;
-#endif
-
-#define EVLIST_TIMEOUT 0x01
-#define EVLIST_INSERTED 0x02
-#define EVLIST_SIGNAL 0x04
-#define EVLIST_ACTIVE 0x08
-#define EVLIST_INTERNAL 0x10
-#define EVLIST_INIT 0x80
-
-/* EVLIST_X_ Private space: 0x1000-0xf000 */
-#define EVLIST_ALL (0xf000 | 0x9f)
-
-#define EV_TIMEOUT 0x01
-#define EV_READ 0x02
-#define EV_WRITE 0x04
-#define EV_SIGNAL 0x08
-#define EV_PERSIST 0x10 /* Persistant event */
-
-/* Fix so that ppl dont have to run with <sys/queue.h> */
-#ifndef TAILQ_ENTRY
-#define _EVENT_DEFINED_TQENTRY
-#define TAILQ_ENTRY(type) \
-struct { \
- struct type *tqe_next; /* next element */ \
- struct type **tqe_prev; /* address of previous next element */ \
-}
-#endif /* !TAILQ_ENTRY */
-
-struct event_base;
-struct event {
- TAILQ_ENTRY (event) ev_next;
- TAILQ_ENTRY (event) ev_active_next;
- TAILQ_ENTRY (event) ev_signal_next;
- unsigned int min_heap_idx; /* for managing timeouts */
-
- struct event_base *ev_base;
-
- int ev_fd;
- short ev_events;
- short ev_ncalls;
- short *ev_pncalls; /* Allows deletes in callback */
-
- struct timeval ev_timeout;
-
- int ev_pri; /* smaller numbers are higher priority */
-
- void (*ev_callback)(int, short, void *arg);
- void *ev_arg;
-
- int ev_res; /* result passed to event callback */
- int ev_flags;
-};
-
-#define EVENT_SIGNAL(ev) (int)(ev)->ev_fd
-#define EVENT_FD(ev) (int)(ev)->ev_fd
-
-/*
- * Key-Value pairs. Can be used for HTTP headers but also for
- * query argument parsing.
- */
-struct evkeyval {
- TAILQ_ENTRY(evkeyval) next;
-
- char *key;
- char *value;
-};
-
-#ifdef _EVENT_DEFINED_TQENTRY
-#undef TAILQ_ENTRY
-struct event_list;
-struct evkeyvalq;
-#undef _EVENT_DEFINED_TQENTRY
-#else
-TAILQ_HEAD (event_list, event);
-TAILQ_HEAD (evkeyvalq, evkeyval);
-#endif /* _EVENT_DEFINED_TQENTRY */
-
-/**
- Initialize the event API.
-
- Use event_base_new() to initialize a new event base, but does not set
- the current_base global. If using only event_base_new(), each event
- added must have an event base set with event_base_set()
-
- @see event_base_set(), event_base_free(), event_init()
- */
-struct event_base *event_base_new(void);
-
-/**
- Initialize the event API.
-
- The event API needs to be initialized with event_init() before it can be
- used. Sets the current_base global representing the default base for
- events that have no base associated with them.
-
- @see event_base_set(), event_base_new()
- */
-struct event_base *event_init(void);
-
-/**
- Reinitialized the event base after a fork
-
- Some event mechanisms do not survive across fork. The event base needs
- to be reinitialized with the event_reinit() function.
-
- @param base the event base that needs to be re-initialized
- @return 0 if successful, or -1 if some events could not be re-added.
- @see event_base_new(), event_init()
-*/
-int event_reinit(struct event_base *base);
-
-/**
- Loop to process events.
-
- In order to process events, an application needs to call
- event_dispatch(). This function only returns on error, and should
- replace the event core of the application program.
-
- @see event_base_dispatch()
- */
-int event_dispatch(void);
-
-
-/**
- Threadsafe event dispatching loop.
-
- @param eb the event_base structure returned by event_init()
- @see event_init(), event_dispatch()
- */
-int event_base_dispatch(struct event_base *);
-
-
-/**
- Get the kernel event notification mechanism used by libevent.
-
- @param eb the event_base structure returned by event_base_new()
- @return a string identifying the kernel event mechanism (kqueue, epoll, etc.)
- */
-const char *event_base_get_method(struct event_base *);
-
-
-/**
- Deallocate all memory associated with an event_base, and free the base.
-
- Note that this function will not close any fds or free any memory passed
- to event_set as the argument to callback.
-
- @param eb an event_base to be freed
- */
-void event_base_free(struct event_base *);
-
-
-#define _EVENT_LOG_DEBUG 0
-#define _EVENT_LOG_MSG 1
-#define _EVENT_LOG_WARN 2
-#define _EVENT_LOG_ERR 3
-typedef void (*event_log_cb)(int severity, const char *msg);
-/**
- Redirect libevent's log messages.
-
- @param cb a function taking two arguments: an integer severity between
- _EVENT_LOG_DEBUG and _EVENT_LOG_ERR, and a string. If cb is NULL,
- then the default log is used.
- */
-void event_set_log_callback(event_log_cb cb);
-
-/**
- Associate a different event base with an event.
-
- @param eb the event base
- @param ev the event
- */
-int event_base_set(struct event_base *, struct event *);
-
-/**
- event_loop() flags
- */
-/*@{*/
-#define EVLOOP_ONCE 0x01 /**< Block at most once. */
-#define EVLOOP_NONBLOCK 0x02 /**< Do not block. */
-/*@}*/
-
-/**
- Handle events.
-
- This is a more flexible version of event_dispatch().
-
- @param flags any combination of EVLOOP_ONCE | EVLOOP_NONBLOCK
- @return 0 if successful, -1 if an error occurred, or 1 if no events were
- registered.
- @see event_loopexit(), event_base_loop()
-*/
-int event_loop(int);
-
-/**
- Handle events (threadsafe version).
-
- This is a more flexible version of event_base_dispatch().
-
- @param eb the event_base structure returned by event_init()
- @param flags any combination of EVLOOP_ONCE | EVLOOP_NONBLOCK
- @return 0 if successful, -1 if an error occurred, or 1 if no events were
- registered.
- @see event_loopexit(), event_base_loop()
- */
-int event_base_loop(struct event_base *, int);
-
-/**
- Exit the event loop after the specified time.
-
- The next 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 event_loop() will proceed normally.
-
- @param tv the amount of time after which the loop should terminate.
- @return 0 if successful, or -1 if an error occurred
- @see event_loop(), event_base_loop(), event_base_loopexit()
- */
-int event_loopexit(struct timeval *);
-
-
-/**
- Exit the event loop after the specified time (threadsafe variant).
-
- The next event_base_loop() iteration after the given timer expires will
- complete normally (handling all queued events) then exit without
- blocking for events again.
-
- Subsequent invocations of event_base_loop() will proceed normally.
-
- @param eb the event_base structure returned by event_init()
- @param tv the amount of time after which the loop should terminate.
- @return 0 if successful, or -1 if an error occurred
- @see event_loopexit()
- */
-int event_base_loopexit(struct event_base *, struct timeval *);
-
-/**
- Abort the active event_loop() immediately.
-
- event_loop() will abort the loop after the next event is completed;
- event_loopbreak() is typically invoked from this event's callback.
- This behavior is analogous to the "break;" statement.
-
- Subsequent invocations of event_loop() will proceed normally.
-
- @return 0 if successful, or -1 if an error occurred
- @see event_base_loopbreak(), event_loopexit()
- */
-int event_loopbreak(void);
-
-/**
- Abort the active event_base_loop() immediately.
-
- event_base_loop() will abort the loop after the next event is completed;
- event_base_loopbreak() is typically invoked from this event's callback.
- This behavior is analogous to the "break;" statement.
-
- Subsequent invocations of event_loop() will proceed normally.
-
- @param eb the event_base structure returned by event_init()
- @return 0 if successful, or -1 if an error occurred
- @see event_base_loopexit
- */
-int event_base_loopbreak(struct event_base *);
-
-
-/**
- Add a timer event.
-
- @param ev the event struct
- @param tv timeval struct
- */
-#define evtimer_add(ev, tv) event_add(ev, tv)
-
-
-/**
- Define a timer event.
-
- @param ev event struct to be modified
- @param cb callback function
- @param arg argument that will be passed to the callback function
- */
-#define evtimer_set(ev, cb, arg) event_set(ev, -1, 0, cb, arg)
-
-
-/**
- * Delete a timer event.
- *
- * @param ev the event struct to be disabled
- */
-#define evtimer_del(ev) event_del(ev)
-#define evtimer_pending(ev, tv) event_pending(ev, EV_TIMEOUT, tv)
-#define evtimer_initialized(ev) ((ev)->ev_flags & EVLIST_INIT)
-
-/**
- * Add a timeout event.
- *
- * @param ev the event struct to be disabled
- * @param tv the timeout value, in seconds
- */
-#define timeout_add(ev, tv) event_add(ev, tv)
-
-
-/**
- * Define a timeout event.
- *
- * @param ev the event struct to be defined
- * @param cb the callback to be invoked when the timeout expires
- * @param arg the argument to be passed to the callback
- */
-#define timeout_set(ev, cb, arg) event_set(ev, -1, 0, cb, arg)
-
-
-/**
- * Disable a timeout event.
- *
- * @param ev the timeout event to be disabled
- */
-#define timeout_del(ev) event_del(ev)
-
-#define timeout_pending(ev, tv) event_pending(ev, EV_TIMEOUT, tv)
-#define timeout_initialized(ev) ((ev)->ev_flags & EVLIST_INIT)
-
-#define signal_add(ev, tv) event_add(ev, tv)
-#define signal_set(ev, x, cb, arg) \
- event_set(ev, x, EV_SIGNAL|EV_PERSIST, cb, arg)
-#define signal_del(ev) event_del(ev)
-#define signal_pending(ev, tv) event_pending(ev, EV_SIGNAL, tv)
-#define signal_initialized(ev) ((ev)->ev_flags & EVLIST_INIT)
-
-/**
- Prepare an event structure to be added.
-
- The function event_set() prepares the event structure ev to be used in
- future calls to event_add() and event_del(). The event will be prepared to
- call the function specified by the fn argument with an int argument
- indicating the file descriptor, a short argument indicating the type of
- event, and a void * argument given in the arg argument. The fd indicates
- the file descriptor that should be monitored for events. The events can be
- either EV_READ, EV_WRITE, or both. Indicating that an application can read
- or write from the file descriptor respectively without blocking.
-
- The function fn will be called with the file descriptor that triggered the
- event and the type of event which will be either EV_TIMEOUT, EV_SIGNAL,
- EV_READ, or EV_WRITE. The additional flag EV_PERSIST makes an event_add()
- persistent until event_del() has been called.
-
- @param ev an event struct to be modified
- @param fd the file descriptor to be monitored
- @param event desired events to monitor; can be EV_READ and/or EV_WRITE
- @param fn callback function to be invoked when the event occurs
- @param arg an argument to be passed to the callback function
-
- @see event_add(), event_del(), event_once()
-
- */
-void event_set(struct event *, int, short, void (*)(int, short, void *), void *);
-
-/**
- Schedule a one-time event to occur.
-
- The function event_once() is similar to event_set(). However, it schedules
- a callback to be called exactly once and does not require the caller to
- prepare an event structure.
-
- @param fd a file descriptor to monitor
- @param events event(s) to monitor; can be any of EV_TIMEOUT | EV_READ |
- EV_WRITE
- @param callback callback function to be invoked when the event occurs
- @param arg an argument to be passed to the callback function
- @param timeout the maximum amount of time to wait for the event, or NULL
- to wait forever
- @return 0 if successful, or -1 if an error occurred
- @see event_set()
-
- */
-int event_once(int, short, void (*)(int, short, void *), void *, struct timeval *);
-
-
-/**
- Schedule a one-time event (threadsafe variant)
-
- The function event_base_once() is similar to event_set(). However, it
- schedules a callback to be called exactly once and does not require the
- caller to prepare an event structure.
-
- @param base an event_base returned by event_init()
- @param fd a file descriptor to monitor
- @param events event(s) to monitor; can be any of EV_TIMEOUT | EV_READ |
- EV_WRITE
- @param callback callback function to be invoked when the event occurs
- @param arg an argument to be passed to the callback function
- @param timeout the maximum amount of time to wait for the event, or NULL
- to wait forever
- @return 0 if successful, or -1 if an error occurred
- @see event_once()
- */
-int event_base_once(struct event_base *, int, short, void (*)(int, short, void *), void *, struct timeval *);
-
-
-/**
- Add an event to the set of monitored events.
-
- The function event_add() schedules the execution of the ev event when the
- event specified in event_set() occurs or in at least the time specified in
- the tv. If tv is NULL, no timeout occurs and the function will only be
- called if a matching event occurs on the file descriptor. The event in the
- ev argument must be already initialized by event_set() and may not be used
- in calls to event_set() until it has timed out or been removed with
- event_del(). If the event in the ev argument already has a scheduled
- timeout, the old timeout will be replaced by the new one.
-
- @param ev an event struct initialized via event_set()
- @param timeout the maximum amount of time to wait for the event, or NULL
- to wait forever
- @return 0 if successful, or -1 if an error occurred
- @see event_del(), event_set()
- */
-int event_add(struct event *, struct timeval *);
-
-
-/**
- Remove an event from the set of monitored events.
-
- The function event_del() will cancel the event in the argument ev. If the
- event has already executed or has never been added the call will have no
- effect.
-
- @param ev an event struct to be removed from the working set
- @return 0 if successful, or -1 if an error occurred
- @see event_add()
- */
-int event_del(struct event *);
-
-void event_active(struct event *, int, short);
-
-
-/**
- Checks if a specific event is pending or scheduled.
-
- @param ev an event struct previously passed to event_add()
- @param event the requested event type; any of EV_TIMEOUT|EV_READ|
- EV_WRITE|EV_SIGNAL
- @param tv an alternate timeout (FIXME - is this true?)
-
- @return 1 if the event is pending, or 0 if the event has not occurred
-
- */
-int event_pending(struct event *, short, struct timeval *);
-
-
-/**
- Test if an event structure has been initialized.
-
- The event_initialized() macro can be used to check if an event has been
- initialized.
-
- @param ev an event structure to be tested
- @return 1 if the structure has been initialized, or 0 if it has not been
- initialized
- */
-#ifdef WIN32
-#define event_initialized(ev) ((ev)->ev_flags & EVLIST_INIT && (ev)->ev_fd != (int)INVALID_HANDLE_VALUE)
-#else
-#define event_initialized(ev) ((ev)->ev_flags & EVLIST_INIT)
-#endif
-
-
-/**
- Get the libevent version number.
-
- @return a string containing the version number of libevent
- */
-const char *event_get_version(void);
-
-
-/**
- Get the kernel event notification mechanism used by libevent.
-
- @return a string identifying the kernel event mechanism (kqueue, epoll, etc.)
- */
-const char *event_get_method(void);
-
-
-/**
- Set the number of different event priorities.
-
- By default libevent schedules all active events with the same priority.
- However, some time it is desirable to process some events with a higher
- priority than others. For that reason, libevent supports strict priority
- queues. Active events with a lower priority are always processed before
- events with a higher priority.
-
- The number of different priorities can be set initially with the
- event_priority_init() function. This function should be called before the
- first call to event_dispatch(). The event_priority_set() function can be
- used to assign a priority to an event. By default, libevent assigns the
- middle priority to all events unless their priority is explicitly set.
-
- @param npriorities the maximum number of priorities
- @return 0 if successful, or -1 if an error occurred
- @see event_base_priority_init(), event_priority_set()
-
- */
-int event_priority_init(int);
-
-
-/**
- Set the number of different event priorities (threadsafe variant).
-
- See the description of event_priority_init() for more information.
-
- @param eb the event_base structure returned by event_init()
- @param npriorities the maximum number of priorities
- @return 0 if successful, or -1 if an error occurred
- @see event_priority_init(), event_priority_set()
- */
-int event_base_priority_init(struct event_base *, int);
-
-
-/**
- Assign a priority to an event.
-
- @param ev an event struct
- @param priority the new priority to be assigned
- @return 0 if successful, or -1 if an error occurred
- @see event_priority_init()
- */
-int event_priority_set(struct event *, int);
-
-
-/* These functions deal with buffering input and output */
-
-struct evbuffer {
- u_char *buffer;
- u_char *orig_buffer;
-
- size_t misalign;
- size_t totallen;
- size_t off;
-
- void (*cb)(struct evbuffer *, size_t, size_t, void *);
- void *cbarg;
-};
-
-/* Just for error reporting - use other constants otherwise */
-#define EVBUFFER_READ 0x01
-#define EVBUFFER_WRITE 0x02
-#define EVBUFFER_EOF 0x10
-#define EVBUFFER_ERROR 0x20
-#define EVBUFFER_TIMEOUT 0x40
-
-struct bufferevent;
-typedef void (*evbuffercb)(struct bufferevent *, void *);
-typedef void (*everrorcb)(struct bufferevent *, short what, void *);
-
-struct event_watermark {
- size_t low;
- size_t high;
-};
-
-struct bufferevent {
- struct event ev_read;
- struct event ev_write;
-
- struct evbuffer *input;
- struct evbuffer *output;
-
- struct event_watermark wm_read;
- struct event_watermark wm_write;
-
- evbuffercb readcb;
- evbuffercb writecb;
- everrorcb errorcb;
- void *cbarg;
-
- int timeout_read; /* in seconds */
- int timeout_write; /* in seconds */
-
- short enabled; /* events that are currently enabled */
-};
-
-
-/**
- Create a new bufferevent.
-
- libevent provides an abstraction on top of the regular event callbacks.
- This abstraction is called a 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 I/O, but
- instead is reading from input and writing to output buffers.
-
- Once initialized, the bufferevent structure can be used repeatedly with
- bufferevent_enable() and bufferevent_disable().
-
- 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 0 by
- default.
-
- If multiple bases are in use, bufferevent_base_set() must be called before
- enabling the bufferevent for the first time.
-
- @param fd the file descriptor from which data is read and written to.
- This file descriptor is not allowed to be a pipe(2).
- @param readcb callback to invoke when there is data to be read, or NULL if
- no callback is desired
- @param writecb callback to invoke when the file descriptor is ready for
- writing, or NULL if no callback is desired
- @param errorcb callback to invoke when there is an error on the file
- descriptor
- @param cbarg an argument that will be supplied to each of the callbacks
- (readcb, writecb, and errorcb)
- @return a pointer to a newly allocated bufferevent struct, or NULL if an
- error occurred
- @see bufferevent_base_set(), bufferevent_free()
- */
-struct bufferevent *bufferevent_new(int fd,
- evbuffercb readcb, evbuffercb writecb, everrorcb errorcb, void *cbarg);
-
-
-/**
- Assign a bufferevent to a specific event_base.
-
- @param base an event_base returned by event_init()
- @param bufev a bufferevent struct returned by bufferevent_new()
- @return 0 if successful, or -1 if an error occurred
- @see bufferevent_new()
- */
-int bufferevent_base_set(struct event_base *base, struct bufferevent *bufev);
-
-
-/**
- Assign a priority to a bufferevent.
-
- @param bufev a bufferevent struct
- @param pri the priority to be assigned
- @return 0 if successful, or -1 if an error occurred
- */
-int bufferevent_priority_set(struct bufferevent *bufev, int pri);
-
-
-/**
- Deallocate the storage associated with a bufferevent structure.
-
- @param bufev the bufferevent structure to be freed.
- */
-void bufferevent_free(struct bufferevent *bufev);
-
-
-/**
- Write data to a bufferevent buffer.
-
- The 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.
-
- @param bufev the bufferevent to be written to
- @param data a pointer to the data to be written
- @param size the length of the data, in bytes
- @return 0 if successful, or -1 if an error occurred
- @see bufferevent_write_buffer()
- */
-int bufferevent_write(struct bufferevent *bufev,
- const void *data, size_t size);
-
-
-/**
- Write data from an evbuffer to a bufferevent buffer. The evbuffer is
- being drained as a result.
-
- @param bufev the bufferevent to be written to
- @param buf the evbuffer to be written
- @return 0 if successful, or -1 if an error occurred
- @see bufferevent_write()
- */
-int bufferevent_write_buffer(struct bufferevent *bufev, struct evbuffer *buf);
-
-
-/**
- Read data from a bufferevent buffer.
-
- The bufferevent_read() function is used to read data from the input buffer.
-
- @param bufev the bufferevent to be read from
- @param data pointer to a buffer that will store the data
- @param size the size of the data buffer, in bytes
- @return the amount of data read, in bytes.
- */
-size_t bufferevent_read(struct bufferevent *bufev, void *data, size_t size);
-
-/**
- Enable a bufferevent.
-
- @param bufev the bufferevent to be enabled
- @param event any combination of EV_READ | EV_WRITE.
- @return 0 if successful, or -1 if an error occurred
- @see bufferevent_disable()
- */
-int bufferevent_enable(struct bufferevent *bufev, short event);
-
-
-/**
- Disable a bufferevent.
-
- @param bufev the bufferevent to be disabled
- @param event any combination of EV_READ | EV_WRITE.
- @return 0 if successful, or -1 if an error occurred
- @see bufferevent_enable()
- */
-int bufferevent_disable(struct bufferevent *bufev, short event);
-
-
-/**
- Set the read and write timeout for a buffered event.
-
- @param bufev the bufferevent to be modified
- @param timeout_read the read timeout
- @param timeout_write the write timeout
- */
-void bufferevent_settimeout(struct bufferevent *bufev,
- int timeout_read, int timeout_write);
-
-
-#define EVBUFFER_LENGTH(x) (x)->off
-#define EVBUFFER_DATA(x) (x)->buffer
-#define EVBUFFER_INPUT(x) (x)->input
-#define EVBUFFER_OUTPUT(x) (x)->output
-
-
-/**
- Allocate storage for a new evbuffer.
-
- @return a pointer to a newly allocated evbuffer struct, or NULL if an error
- occurred
- */
-struct evbuffer *evbuffer_new(void);
-
-
-/**
- Deallocate storage for an evbuffer.
-
- @param pointer to the evbuffer to be freed
- */
-void evbuffer_free(struct evbuffer *);
-
-
-/**
- Expands the available space in an event buffer.
-
- Expands the available space in the event buffer to at least datlen
-
- @param buf the event buffer to be expanded
- @param datlen the new minimum length requirement
- @return 0 if successful, or -1 if an error occurred
-*/
-int evbuffer_expand(struct evbuffer *, size_t);
-
-
-/**
- Append data to the end of an evbuffer.
-
- @param buf the event buffer to be appended to
- @param data pointer to the beginning of the data buffer
- @param datlen the number of bytes to be copied from the data buffer
- */
-int evbuffer_add(struct evbuffer *, const void *, size_t);
-
-
-
-/**
- Read data from an event buffer and drain the bytes read.
-
- @param buf the event buffer to be read from
- @param data the destination buffer to store the result
- @param datlen the maximum size of the destination buffer
- @return the number of bytes read
- */
-int evbuffer_remove(struct evbuffer *, void *, size_t);
-
-
-/**
- * Read a single line from an event buffer.
- *
- * Reads a line terminated by either '\r\n', '\n\r' or '\r' or '\n'.
- * The returned buffer needs to be freed by the caller.
- *
- * @param buffer the evbuffer to read from
- * @return pointer to a single line, or NULL if an error occurred
- */
-char *evbuffer_readline(struct evbuffer *);
-
-
-/**
- Move data from one evbuffer into another evbuffer.
-
- This is a destructive add. The data from one buffer moves into
- the other buffer. The destination buffer is expanded as needed.
-
- @param outbuf the output buffer
- @param inbuf the input buffer
- @return 0 if successful, or -1 if an error occurred
- */
-int evbuffer_add_buffer(struct evbuffer *, struct evbuffer *);
-
-
-/**
- Append a formatted string to the end of an evbuffer.
-
- @param buf the evbuffer that will be appended to
- @param fmt a format string
- @param ... arguments that will be passed to printf(3)
- @return 0 if successful, or -1 if an error occurred
- */
-int evbuffer_add_printf(struct evbuffer *, const char *fmt, ...)
-#ifdef __GNUC__
- __attribute__((format(printf, 2, 3)))
-#endif
-;
-
-
-/**
- Append a va_list formatted string to the end of an evbuffer.
-
- @param buf the evbuffer that will be appended to
- @param fmt a format string
- @param ap a varargs va_list argument array that will be passed to vprintf(3)
- @return 0 if successful, or -1 if an error occurred
- */
-int evbuffer_add_vprintf(struct evbuffer *, const char *fmt, va_list ap);
-
-
-/**
- Remove a specified number of bytes data from the beginning of an evbuffer.
-
- @param buf the evbuffer to be drained
- @param len the number of bytes to drain from the beginning of the buffer
- @return 0 if successful, or -1 if an error occurred
- */
-void evbuffer_drain(struct evbuffer *, size_t);
-
-
-/**
- Write the contents of an evbuffer to a file descriptor.
-
- The evbuffer will be drained after the bytes have been successfully written.
-
- @param buffer the evbuffer to be written and drained
- @param fd the file descriptor to be written to
- @return the number of bytes written, or -1 if an error occurred
- @see evbuffer_read()
- */
-int evbuffer_write(struct evbuffer *, int);
-
-
-/**
- Read from a file descriptor and store the result in an evbuffer.
-
- @param buf the evbuffer to store the result
- @param fd the file descriptor to read from
- @param howmuch the number of bytes to be read
- @return the number of bytes read, or -1 if an error occurred
- @see evbuffer_write()
- */
-int evbuffer_read(struct evbuffer *, int, int);
-
-
-/**
- Find a string within an evbuffer.
-
- @param buffer the evbuffer to be searched
- @param what the string to be searched for
- @param len the length of the search string
- @return a pointer to the beginning of the search string, or NULL if the search failed.
- */
-u_char *evbuffer_find(struct evbuffer *, const u_char *, size_t);
-
-/**
- Set a callback to invoke when the evbuffer is modified.
-
- @param buffer the evbuffer to be monitored
- @param cb the callback function to invoke when the evbuffer is modified
- @param cbarg an argument to be provided to the callback function
- */
-void evbuffer_setcb(struct evbuffer *, void (*)(struct evbuffer *, size_t, size_t, void *), void *);
-
-/*
- * Marshaling tagged data - We assume that all tags are inserted in their
- * numeric order - so that unknown tags will always be higher than the
- * known ones - and we can just ignore the end of an event buffer.
- */
-
-void evtag_init(void);
-
-void evtag_marshal(struct evbuffer *evbuf, ev_uint32_t tag, const void *data,
- ev_uint32_t len);
-
-/**
- Encode an integer and store it in an evbuffer.
-
- We encode integer's by nibbles; the first nibble contains the number
- of significant nibbles - 1; this allows us to encode up to 64-bit
- integers. This function is byte-order independent.
-
- @param evbuf evbuffer to store the encoded number
- @param number a 32-bit integer
- */
-void encode_int(struct evbuffer *evbuf, ev_uint32_t number);
-
-void evtag_marshal_int(struct evbuffer *evbuf, ev_uint32_t tag,
- ev_uint32_t integer);
-
-void evtag_marshal_string(struct evbuffer *buf, ev_uint32_t tag,
- const char *string);
-
-void evtag_marshal_timeval(struct evbuffer *evbuf, ev_uint32_t tag,
- struct timeval *tv);
-
-int evtag_unmarshal(struct evbuffer *src, ev_uint32_t *ptag,
- struct evbuffer *dst);
-int evtag_peek(struct evbuffer *evbuf, ev_uint32_t *ptag);
-int evtag_peek_length(struct evbuffer *evbuf, ev_uint32_t *plength);
-int evtag_payload_length(struct evbuffer *evbuf, ev_uint32_t *plength);
-int evtag_consume(struct evbuffer *evbuf);
-
-int evtag_unmarshal_int(struct evbuffer *evbuf, ev_uint32_t need_tag,
- ev_uint32_t *pinteger);
-
-int evtag_unmarshal_fixed(struct evbuffer *src, ev_uint32_t need_tag,
- void *data, size_t len);
-
-int evtag_unmarshal_string(struct evbuffer *evbuf, ev_uint32_t need_tag,
- char **pstring);
-
-int evtag_unmarshal_timeval(struct evbuffer *evbuf, ev_uint32_t need_tag,
- struct timeval *ptv);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _EVENT_H_ */
diff --git a/extra/libevent/event_tagging.c b/extra/libevent/event_tagging.c
deleted file mode 100644
index c67ea8a57af..00000000000
--- a/extra/libevent/event_tagging.c
+++ /dev/null
@@ -1,443 +0,0 @@
-/*
- * Copyright (c) 2003, 2004 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 BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-
-#ifdef WIN32
-#define WIN32_LEAN_AND_MEAN
-#include <winsock2.h>
-#include <windows.h>
-#undef WIN32_LEAN_AND_MEAN
-#else
-#include <sys/ioctl.h>
-#endif
-
-#include <sys/queue.h>
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#ifndef WIN32
-#include <syslog.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "event.h"
-#include "evutil.h"
-#include "log.h"
-
-int evtag_decode_int(ev_uint32_t *pnumber, struct evbuffer *evbuf);
-int evtag_encode_tag(struct evbuffer *evbuf, ev_uint32_t tag);
-int evtag_decode_tag(ev_uint32_t *ptag, struct evbuffer *evbuf);
-
-static struct evbuffer *_buf; /* not thread safe */
-
-void
-evtag_init(void)
-{
- if (_buf != NULL)
- return;
-
- if ((_buf = evbuffer_new()) == NULL)
- event_err(1, "%s: malloc", __func__);
-}
-
-/*
- * We encode integer's by nibbles; the first nibble contains the number
- * of significant nibbles - 1; this allows us to encode up to 64-bit
- * integers. This function is byte-order independent.
- */
-
-void
-encode_int(struct evbuffer *evbuf, ev_uint32_t number)
-{
- int off = 1, nibbles = 0;
- ev_uint8_t data[5];
-
- memset(data, 0, sizeof(data));
- while (number) {
- if (off & 0x1)
- data[off/2] = (data[off/2] & 0xf0) | (number & 0x0f);
- else
- data[off/2] = (data[off/2] & 0x0f) |
- ((number & 0x0f) << 4);
- number >>= 4;
- off++;
- }
-
- if (off > 2)
- nibbles = off - 2;
-
- /* Off - 1 is the number of encoded nibbles */
- data[0] = (data[0] & 0x0f) | ((nibbles & 0x0f) << 4);
-
- evbuffer_add(evbuf, data, (off + 1) / 2);
-}
-
-/*
- * Support variable length encoding of tags; we use the high bit in each
- * octet as a continuation signal.
- */
-
-int
-evtag_encode_tag(struct evbuffer *evbuf, ev_uint32_t tag)
-{
- int bytes = 0;
- ev_uint8_t data[5];
-
- memset(data, 0, sizeof(data));
- do {
- ev_uint8_t lower = tag & 0x7f;
- tag >>= 7;
-
- if (tag)
- lower |= 0x80;
-
- data[bytes++] = lower;
- } while (tag);
-
- if (evbuf != NULL)
- evbuffer_add(evbuf, data, bytes);
-
- return (bytes);
-}
-
-static int
-decode_tag_internal(ev_uint32_t *ptag, struct evbuffer *evbuf, int dodrain)
-{
- ev_uint32_t number = 0;
- ev_uint8_t *data = EVBUFFER_DATA(evbuf);
- int len = EVBUFFER_LENGTH(evbuf);
- int count = 0, shift = 0, done = 0;
-
- while (count++ < len) {
- ev_uint8_t lower = *data++;
- number |= (lower & 0x7f) << shift;
- shift += 7;
-
- if (!(lower & 0x80)) {
- done = 1;
- break;
- }
- }
-
- if (!done)
- return (-1);
-
- if (dodrain)
- evbuffer_drain(evbuf, count);
-
- if (ptag != NULL)
- *ptag = number;
-
- return (count);
-}
-
-int
-evtag_decode_tag(ev_uint32_t *ptag, struct evbuffer *evbuf)
-{
- return (decode_tag_internal(ptag, evbuf, 1 /* dodrain */));
-}
-
-/*
- * Marshal a data type, the general format is as follows:
- *
- * tag number: one byte; length: var bytes; payload: var bytes
- */
-
-void
-evtag_marshal(struct evbuffer *evbuf, ev_uint32_t tag,
- const void *data, ev_uint32_t len)
-{
- evtag_encode_tag(evbuf, tag);
- encode_int(evbuf, len);
- evbuffer_add(evbuf, (void *)data, len);
-}
-
-/* Marshaling for integers */
-void
-evtag_marshal_int(struct evbuffer *evbuf, ev_uint32_t tag, ev_uint32_t integer)
-{
- evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf));
- encode_int(_buf, integer);
-
- evtag_encode_tag(evbuf, tag);
- encode_int(evbuf, EVBUFFER_LENGTH(_buf));
- evbuffer_add_buffer(evbuf, _buf);
-}
-
-void
-evtag_marshal_string(struct evbuffer *buf, ev_uint32_t tag, const char *string)
-{
- evtag_marshal(buf, tag, string, strlen(string));
-}
-
-void
-evtag_marshal_timeval(struct evbuffer *evbuf, ev_uint32_t tag, struct timeval *tv)
-{
- evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf));
-
- encode_int(_buf, tv->tv_sec);
- encode_int(_buf, tv->tv_usec);
-
- evtag_marshal(evbuf, tag, EVBUFFER_DATA(_buf),
- EVBUFFER_LENGTH(_buf));
-}
-
-static int
-decode_int_internal(ev_uint32_t *pnumber, struct evbuffer *evbuf, int dodrain)
-{
- ev_uint32_t number = 0;
- ev_uint8_t *data = EVBUFFER_DATA(evbuf);
- int len = EVBUFFER_LENGTH(evbuf);
- int nibbles = 0;
-
- if (!len)
- return (-1);
-
- nibbles = ((data[0] & 0xf0) >> 4) + 1;
- if (nibbles > 8 || (nibbles >> 1) + 1 > len)
- return (-1);
- len = (nibbles >> 1) + 1;
-
- while (nibbles > 0) {
- number <<= 4;
- if (nibbles & 0x1)
- number |= data[nibbles >> 1] & 0x0f;
- else
- number |= (data[nibbles >> 1] & 0xf0) >> 4;
- nibbles--;
- }
-
- if (dodrain)
- evbuffer_drain(evbuf, len);
-
- *pnumber = number;
-
- return (len);
-}
-
-int
-evtag_decode_int(ev_uint32_t *pnumber, struct evbuffer *evbuf)
-{
- return (decode_int_internal(pnumber, evbuf, 1) == -1 ? -1 : 0);
-}
-
-int
-evtag_peek(struct evbuffer *evbuf, ev_uint32_t *ptag)
-{
- return (decode_tag_internal(ptag, evbuf, 0 /* dodrain */));
-}
-
-int
-evtag_peek_length(struct evbuffer *evbuf, ev_uint32_t *plength)
-{
- struct evbuffer tmp;
- int res, len;
-
- len = decode_tag_internal(NULL, evbuf, 0 /* dodrain */);
- if (len == -1)
- return (-1);
-
- tmp = *evbuf;
- tmp.buffer += len;
- tmp.off -= len;
-
- res = decode_int_internal(plength, &tmp, 0);
- if (res == -1)
- return (-1);
-
- *plength += res + len;
-
- return (0);
-}
-
-int
-evtag_payload_length(struct evbuffer *evbuf, ev_uint32_t *plength)
-{
- struct evbuffer tmp;
- int res, len;
-
- len = decode_tag_internal(NULL, evbuf, 0 /* dodrain */);
- if (len == -1)
- return (-1);
-
- tmp = *evbuf;
- tmp.buffer += len;
- tmp.off -= len;
-
- res = decode_int_internal(plength, &tmp, 0);
- if (res == -1)
- return (-1);
-
- return (0);
-}
-
-int
-evtag_consume(struct evbuffer *evbuf)
-{
- ev_uint32_t len;
- if (decode_tag_internal(NULL, evbuf, 1 /* dodrain */) == -1)
- return (-1);
- if (evtag_decode_int(&len, evbuf) == -1)
- return (-1);
- evbuffer_drain(evbuf, len);
-
- return (0);
-}
-
-/* Reads the data type from an event buffer */
-
-int
-evtag_unmarshal(struct evbuffer *src, ev_uint32_t *ptag, struct evbuffer *dst)
-{
- ev_uint32_t len;
- ev_uint32_t integer;
-
- if (decode_tag_internal(ptag, src, 1 /* dodrain */) == -1)
- return (-1);
- if (evtag_decode_int(&integer, src) == -1)
- return (-1);
- len = integer;
-
- if (EVBUFFER_LENGTH(src) < len)
- return (-1);
-
- if (evbuffer_add(dst, EVBUFFER_DATA(src), len) == -1)
- return (-1);
-
- evbuffer_drain(src, len);
-
- return (len);
-}
-
-/* Marshaling for integers */
-
-int
-evtag_unmarshal_int(struct evbuffer *evbuf, ev_uint32_t need_tag,
- ev_uint32_t *pinteger)
-{
- ev_uint32_t tag;
- ev_uint32_t len;
- ev_uint32_t integer;
-
- if (decode_tag_internal(&tag, evbuf, 1 /* dodrain */) == -1)
- return (-1);
- if (need_tag != tag)
- return (-1);
- if (evtag_decode_int(&integer, evbuf) == -1)
- return (-1);
- len = integer;
-
- if (EVBUFFER_LENGTH(evbuf) < len)
- return (-1);
-
- evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf));
- if (evbuffer_add(_buf, EVBUFFER_DATA(evbuf), len) == -1)
- return (-1);
-
- evbuffer_drain(evbuf, len);
-
- return (evtag_decode_int(pinteger, _buf));
-}
-
-/* Unmarshal a fixed length tag */
-
-int
-evtag_unmarshal_fixed(struct evbuffer *src, ev_uint32_t need_tag, void *data,
- size_t len)
-{
- ev_uint32_t tag;
-
- /* Initialize this event buffer so that we can read into it */
- evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf));
-
- /* Now unmarshal a tag and check that it matches the tag we want */
- if (evtag_unmarshal(src, &tag, _buf) == -1 || tag != need_tag)
- return (-1);
-
- if (EVBUFFER_LENGTH(_buf) != len)
- return (-1);
-
- memcpy(data, EVBUFFER_DATA(_buf), len);
- return (0);
-}
-
-int
-evtag_unmarshal_string(struct evbuffer *evbuf, ev_uint32_t need_tag,
- char **pstring)
-{
- ev_uint32_t tag;
-
- evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf));
-
- if (evtag_unmarshal(evbuf, &tag, _buf) == -1 || tag != need_tag)
- return (-1);
-
- *pstring = calloc(EVBUFFER_LENGTH(_buf) + 1, 1);
- if (*pstring == NULL)
- event_err(1, "%s: calloc", __func__);
- evbuffer_remove(_buf, *pstring, EVBUFFER_LENGTH(_buf));
-
- return (0);
-}
-
-int
-evtag_unmarshal_timeval(struct evbuffer *evbuf, ev_uint32_t need_tag,
- struct timeval *ptv)
-{
- ev_uint32_t tag;
- ev_uint32_t integer;
-
- evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf));
- if (evtag_unmarshal(evbuf, &tag, _buf) == -1 || tag != need_tag)
- return (-1);
-
- if (evtag_decode_int(&integer, _buf) == -1)
- return (-1);
- ptv->tv_sec = integer;
- if (evtag_decode_int(&integer, _buf) == -1)
- return (-1);
- ptv->tv_usec = integer;
-
- return (0);
-}
diff --git a/extra/libevent/evhttp.h b/extra/libevent/evhttp.h
deleted file mode 100644
index c20b1a7165e..00000000000
--- a/extra/libevent/evhttp.h
+++ /dev/null
@@ -1,340 +0,0 @@
-/*
- * Copyright (c) 2000-2004 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 BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#ifndef _EVHTTP_H_
-#define _EVHTTP_H_
-
-#include <event.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef WIN32
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <winsock2.h>
-#undef WIN32_LEAN_AND_MEAN
-#endif
-
-/** @file evhttp.h
- *
- * Basic support for HTTP serving.
- *
- * As libevent is a library for dealing with event notification and most
- * interesting applications are networked today, I have often found the
- * need to write HTTP code. The following prototypes and definitions provide
- * an application with a minimal interface for making HTTP requests and for
- * creating a very simple HTTP server.
- */
-
-/* Response codes */
-#define HTTP_OK 200
-#define HTTP_NOCONTENT 204
-#define HTTP_MOVEPERM 301
-#define HTTP_MOVETEMP 302
-#define HTTP_NOTMODIFIED 304
-#define HTTP_BADREQUEST 400
-#define HTTP_NOTFOUND 404
-#define HTTP_SERVUNAVAIL 503
-
-struct evhttp;
-struct evhttp_request;
-struct evkeyvalq;
-
-/** Create a new HTTP server
- *
- * @param base (optional) the event base to receive the HTTP events
- * @return a pointer to a newly initialized evhttp server structure
- */
-struct evhttp *evhttp_new(struct event_base *base);
-
-/**
- * Binds an HTTP server on the specified address and port.
- *
- * Can be called multiple times to bind the same http server
- * to multiple different ports.
- *
- * @param http a pointer to an evhttp object
- * @param address a string containing the IP address to listen(2) on
- * @param port the port number to listen on
- * @return a newly allocated evhttp struct
- * @see evhttp_free()
- */
-int evhttp_bind_socket(struct evhttp *http, const char *address, u_short port);
-
-/**
- * Free the previously created HTTP server.
- *
- * Works only if no requests are currently being served.
- *
- * @param http the evhttp server object to be freed
- * @see evhttp_start()
- */
-void evhttp_free(struct evhttp* http);
-
-/** Set a callback for a specified URI */
-void evhttp_set_cb(struct evhttp *, const char *,
- void (*)(struct evhttp_request *, void *), void *);
-
-/** Removes the callback for a specified URI */
-int evhttp_del_cb(struct evhttp *, const char *);
-
-/** Set a callback for all requests that are not caught by specific callbacks
- */
-void evhttp_set_gencb(struct evhttp *,
- void (*)(struct evhttp_request *, void *), void *);
-
-/**
- * Set the timeout for an HTTP request.
- *
- * @param http an evhttp object
- * @param timeout_in_secs the timeout, in seconds
- */
-void evhttp_set_timeout(struct evhttp *, int timeout_in_secs);
-
-/* Request/Response functionality */
-
-/**
- * Send an HTML error message to the client.
- *
- * @param req a request object
- * @param error the HTTP error code
- * @param reason a brief explanation of the error
- */
-void evhttp_send_error(struct evhttp_request *req, int error,
- const char *reason);
-
-/**
- * Send an HTML reply to the client.
- *
- * @param req a request object
- * @param code the HTTP response code to send
- * @param reason a brief message to send with the response code
- * @param databuf the body of the response
- */
-void evhttp_send_reply(struct evhttp_request *req, int code,
- const char *reason, struct evbuffer *databuf);
-
-/* Low-level response interface, for streaming/chunked replies */
-void evhttp_send_reply_start(struct evhttp_request *, int, const char *);
-void evhttp_send_reply_chunk(struct evhttp_request *, struct evbuffer *);
-void evhttp_send_reply_end(struct evhttp_request *);
-
-/**
- * Start an HTTP server on the specified address and port
- *
- * DEPRECATED: it does not allow an event base to be specified
- *
- * @param address the address to which the HTTP server should be bound
- * @param port the port number on which the HTTP server should listen
- * @return an struct evhttp object
- */
-struct evhttp *evhttp_start(const char *address, u_short port);
-
-/*
- * Interfaces for making requests
- */
-enum evhttp_cmd_type { EVHTTP_REQ_GET, EVHTTP_REQ_POST, EVHTTP_REQ_HEAD };
-
-enum evhttp_request_kind { EVHTTP_REQUEST, EVHTTP_RESPONSE };
-
-/**
- * the request structure that a server receives.
- * WARNING: expect this structure to change. I will try to provide
- * reasonable accessors.
- */
-struct evhttp_request {
-#if defined(TAILQ_ENTRY)
- TAILQ_ENTRY(evhttp_request) next;
-#else
-struct {
- struct evhttp_request *tqe_next;
- struct evhttp_request **tqe_prev;
-} next;
-#endif
-
- /* the connection object that this request belongs to */
- struct evhttp_connection *evcon;
- int flags;
-#define EVHTTP_REQ_OWN_CONNECTION 0x0001
-#define EVHTTP_PROXY_REQUEST 0x0002
-
- struct evkeyvalq *input_headers;
- struct evkeyvalq *output_headers;
-
- /* address of the remote host and the port connection came from */
- char *remote_host;
- u_short remote_port;
-
- enum evhttp_request_kind kind;
- enum evhttp_cmd_type type;
-
- char *uri; /* uri after HTTP request was parsed */
-
- char major; /* HTTP Major number */
- char minor; /* HTTP Minor number */
-
- int got_firstline;
- int response_code; /* HTTP Response code */
- char *response_code_line; /* Readable response */
-
- struct evbuffer *input_buffer; /* read data */
- ev_int64_t ntoread;
- int chunked;
-
- struct evbuffer *output_buffer; /* outgoing post or data */
-
- /* Callback */
- void (*cb)(struct evhttp_request *, void *);
- void *cb_arg;
-
- /*
- * Chunked data callback - call for each completed chunk if
- * specified. If not specified, all the data is delivered via
- * the regular callback.
- */
- void (*chunk_cb)(struct evhttp_request *, void *);
-};
-
-/**
- * Creates a new request object that needs to be filled in with the request
- * parameters. The callback is executed when the request completed or an
- * error occurred.
- */
-struct evhttp_request *evhttp_request_new(
- void (*cb)(struct evhttp_request *, void *), void *arg);
-
-/** enable delivery of chunks to requestor */
-void evhttp_request_set_chunked_cb(struct evhttp_request *,
- void (*cb)(struct evhttp_request *, void *));
-
-/** Frees the request object and removes associated events. */
-void evhttp_request_free(struct evhttp_request *req);
-
-/**
- * A connection object that can be used to for making HTTP requests. The
- * connection object tries to establish the connection when it is given an
- * http request object.
- */
-struct evhttp_connection *evhttp_connection_new(
- const char *address, unsigned short port);
-
-/** Frees an http connection */
-void evhttp_connection_free(struct evhttp_connection *evcon);
-
-/** sets the ip address from which http connections are made */
-void evhttp_connection_set_local_address(struct evhttp_connection *evcon,
- const char *address);
-
-/** Sets the timeout for events related to this connection */
-void evhttp_connection_set_timeout(struct evhttp_connection *evcon,
- int timeout_in_secs);
-
-/** Sets the retry limit for this connection - -1 repeats indefnitely */
-void evhttp_connection_set_retries(struct evhttp_connection *evcon,
- int retry_max);
-
-/** Set a callback for connection close. */
-void evhttp_connection_set_closecb(struct evhttp_connection *evcon,
- void (*)(struct evhttp_connection *, void *), void *);
-
-/**
- * Associates an event base with the connection - can only be called
- * on a freshly created connection object that has not been used yet.
- */
-void evhttp_connection_set_base(struct evhttp_connection *evcon,
- struct event_base *base);
-
-/** Get the remote address and port associated with this connection. */
-void evhttp_connection_get_peer(struct evhttp_connection *evcon,
- char **address, u_short *port);
-
-/** The connection gets ownership of the request */
-int evhttp_make_request(struct evhttp_connection *evcon,
- struct evhttp_request *req,
- enum evhttp_cmd_type type, const char *uri);
-
-const char *evhttp_request_uri(struct evhttp_request *req);
-
-/* Interfaces for dealing with HTTP headers */
-
-const char *evhttp_find_header(const struct evkeyvalq *, const char *);
-int evhttp_remove_header(struct evkeyvalq *, const char *);
-int evhttp_add_header(struct evkeyvalq *, const char *, const char *);
-void evhttp_clear_headers(struct evkeyvalq *);
-
-/* Miscellaneous utility functions */
-
-
-/**
- Helper function to encode a URI.
-
- The returned string must be freed by the caller.
-
- @param uri an unencoded URI
- @return a newly allocated URI-encoded string
- */
-char *evhttp_encode_uri(const char *uri);
-
-
-/**
- Helper function to decode a URI.
-
- The returned string must be freed by the caller.
-
- @param uri an encoded URI
- @return a newly allocated unencoded URI
- */
-char *evhttp_decode_uri(const char *uri);
-
-
-/**
- * Helper function to parse out arguments in a query.
- * The arguments are separated by key and value.
- * URI should already be decoded.
- */
-void evhttp_parse_query(const char *uri, struct evkeyvalq *);
-
-
-/**
- * Escape HTML character entities in a string.
- *
- * Replaces <, >, ", ' and & with &lt;, &gt;, &quot;,
- * &#039; and &amp; correspondingly.
- *
- * The returned string needs to be freed by the caller.
- *
- * @param html an unescaped HTML string
- * @return an escaped HTML string
- */
-char *evhttp_htmlescape(const char *html);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _EVHTTP_H_ */
diff --git a/extra/libevent/evport.c b/extra/libevent/evport.c
deleted file mode 100644
index c3250531d45..00000000000
--- a/extra/libevent/evport.c
+++ /dev/null
@@ -1,517 +0,0 @@
-/*
- * Submitted by David Pacheco (dp.spambait@gmail.com)
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY SUN MICROSYSTEMS, INC. ``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 SUN MICROSYSTEMS, INC. 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.
- */
-
-/*
- * Copyright (c) 2007 Sun Microsystems. All rights reserved.
- * Use is subject to license terms.
- */
-
-/*
- * evport.c: event backend using Solaris 10 event ports. See port_create(3C).
- * This implementation is loosely modeled after the one used for select(2) (in
- * select.c).
- *
- * The outstanding events are tracked in a data structure called evport_data.
- * Each entry in the ed_fds array corresponds to a file descriptor, and contains
- * pointers to the read and write events that correspond to that fd. (That is,
- * when the file is readable, the "read" event should handle it, etc.)
- *
- * evport_add and evport_del update this data structure. evport_dispatch uses it
- * to determine where to callback when an event occurs (which it gets from
- * port_getn).
- *
- * Helper functions are used: grow() grows the file descriptor array as
- * necessary when large fd's come in. reassociate() takes care of maintaining
- * the proper file-descriptor/event-port associations.
- *
- * As in the select(2) implementation, signals are handled by evsignal.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef HAVE_EVENT_PORTS
-
-#include <sys/time.h>
-#include <assert.h>
-#include <sys/queue.h>
-#include <errno.h>
-#include <poll.h>
-#include <port.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-#ifdef CHECK_INVARIANTS
-#include <assert.h>
-#endif
-
-#include "event.h"
-#include "event-internal.h"
-#include "log.h"
-#include "evsignal.h"
-
-
-/*
- * Default value for ed_nevents, which is the maximum file descriptor number we
- * can handle. If an event comes in for a file descriptor F > nevents, we will
- * grow the array of file descriptors, doubling its size.
- */
-#define DEFAULT_NFDS 16
-
-
-/*
- * EVENTS_PER_GETN is the maximum number of events to retrieve from port_getn on
- * any particular call. You can speed things up by increasing this, but it will
- * (obviously) require more memory.
- */
-#define EVENTS_PER_GETN 8
-
-/*
- * Per-file-descriptor information about what events we're subscribed to. These
- * fields are NULL if no event is subscribed to either of them.
- */
-
-struct fd_info {
- struct event* fdi_revt; /* the event responsible for the "read" */
- struct event* fdi_wevt; /* the event responsible for the "write" */
-};
-
-#define FDI_HAS_READ(fdi) ((fdi)->fdi_revt != NULL)
-#define FDI_HAS_WRITE(fdi) ((fdi)->fdi_wevt != NULL)
-#define FDI_HAS_EVENTS(fdi) (FDI_HAS_READ(fdi) || FDI_HAS_WRITE(fdi))
-#define FDI_TO_SYSEVENTS(fdi) (FDI_HAS_READ(fdi) ? POLLIN : 0) | \
- (FDI_HAS_WRITE(fdi) ? POLLOUT : 0)
-
-struct evport_data {
- int ed_port; /* event port for system events */
- int ed_nevents; /* number of allocated fdi's */
- struct fd_info *ed_fds; /* allocated fdi table */
- /* fdi's that we need to reassoc */
- int ed_pending[EVENTS_PER_GETN]; /* fd's with pending events */
-};
-
-static void* evport_init (struct event_base *);
-static int evport_add (void *, struct event *);
-static int evport_del (void *, struct event *);
-static int evport_dispatch (struct event_base *, void *, struct timeval *);
-static void evport_dealloc (struct event_base *, void *);
-
-const struct eventop evportops = {
- "event ports",
- evport_init,
- evport_add,
- evport_del,
- evport_dispatch,
- evport_dealloc,
- 1 /* need reinit */
-};
-
-/*
- * Initialize the event port implementation.
- */
-
-static void*
-evport_init(struct event_base *base)
-{
- struct evport_data *evpd;
- int i;
- /*
- * Disable event ports when this environment variable is set
- */
- if (getenv("EVENT_NOEVPORT"))
- return (NULL);
-
- if (!(evpd = calloc(1, sizeof(struct evport_data))))
- return (NULL);
-
- if ((evpd->ed_port = port_create()) == -1) {
- free(evpd);
- return (NULL);
- }
-
- /*
- * Initialize file descriptor structure
- */
- evpd->ed_fds = calloc(DEFAULT_NFDS, sizeof(struct fd_info));
- if (evpd->ed_fds == NULL) {
- close(evpd->ed_port);
- free(evpd);
- return (NULL);
- }
- evpd->ed_nevents = DEFAULT_NFDS;
- for (i = 0; i < EVENTS_PER_GETN; i++)
- evpd->ed_pending[i] = -1;
-
- evsignal_init(base);
-
- return (evpd);
-}
-
-#ifdef CHECK_INVARIANTS
-/*
- * Checks some basic properties about the evport_data structure. Because it
- * checks all file descriptors, this function can be expensive when the maximum
- * file descriptor ever used is rather large.
- */
-
-static void
-check_evportop(struct evport_data *evpd)
-{
- assert(evpd);
- assert(evpd->ed_nevents > 0);
- assert(evpd->ed_port > 0);
- assert(evpd->ed_fds > 0);
-
- /*
- * Verify the integrity of the fd_info struct as well as the events to
- * which it points (at least, that they're valid references and correct
- * for their position in the structure).
- */
- int i;
- for (i = 0; i < evpd->ed_nevents; ++i) {
- struct event *ev;
- struct fd_info *fdi;
-
- fdi = &evpd->ed_fds[i];
- if ((ev = fdi->fdi_revt) != NULL) {
- assert(ev->ev_fd == i);
- }
- if ((ev = fdi->fdi_wevt) != NULL) {
- assert(ev->ev_fd == i);
- }
- }
-}
-
-/*
- * Verifies very basic integrity of a given port_event.
- */
-static void
-check_event(port_event_t* pevt)
-{
- /*
- * We've only registered for PORT_SOURCE_FD events. The only
- * other thing we can legitimately receive is PORT_SOURCE_ALERT,
- * but since we're not using port_alert either, we can assume
- * PORT_SOURCE_FD.
- */
- assert(pevt->portev_source == PORT_SOURCE_FD);
- assert(pevt->portev_user == NULL);
-}
-
-#else
-#define check_evportop(epop)
-#define check_event(pevt)
-#endif /* CHECK_INVARIANTS */
-
-/*
- * Doubles the size of the allocated file descriptor array.
- */
-static int
-grow(struct evport_data *epdp, int factor)
-{
- struct fd_info *tmp;
- int oldsize = epdp->ed_nevents;
- int newsize = factor * oldsize;
- assert(factor > 1);
-
- check_evportop(epdp);
-
- tmp = realloc(epdp->ed_fds, sizeof(struct fd_info) * newsize);
- if (NULL == tmp)
- return -1;
- epdp->ed_fds = tmp;
- memset((char*) (epdp->ed_fds + oldsize), 0,
- (newsize - oldsize)*sizeof(struct fd_info));
- epdp->ed_nevents = newsize;
-
- check_evportop(epdp);
-
- return 0;
-}
-
-
-/*
- * (Re)associates the given file descriptor with the event port. The OS events
- * are specified (implicitly) from the fd_info struct.
- */
-static int
-reassociate(struct evport_data *epdp, struct fd_info *fdip, int fd)
-{
- int sysevents = FDI_TO_SYSEVENTS(fdip);
-
- if (sysevents != 0) {
- if (port_associate(epdp->ed_port, PORT_SOURCE_FD,
- fd, sysevents, NULL) == -1) {
- event_warn("port_associate");
- return (-1);
- }
- }
-
- check_evportop(epdp);
-
- return (0);
-}
-
-/*
- * Main event loop - polls port_getn for some number of events, and processes
- * them.
- */
-
-static int
-evport_dispatch(struct event_base *base, void *arg, struct timeval *tv)
-{
- int i, res;
- struct evport_data *epdp = arg;
- port_event_t pevtlist[EVENTS_PER_GETN];
-
- /*
- * port_getn will block until it has at least nevents events. It will
- * also return how many it's given us (which may be more than we asked
- * for, as long as it's less than our maximum (EVENTS_PER_GETN)) in
- * nevents.
- */
- int nevents = 1;
-
- /*
- * We have to convert a struct timeval to a struct timespec
- * (only difference is nanoseconds vs. microseconds). If no time-based
- * events are active, we should wait for I/O (and tv == NULL).
- */
- struct timespec ts;
- struct timespec *ts_p = NULL;
- if (tv != NULL) {
- ts.tv_sec = tv->tv_sec;
- ts.tv_nsec = tv->tv_usec * 1000;
- ts_p = &ts;
- }
-
- /*
- * Before doing anything else, we need to reassociate the events we hit
- * last time which need reassociation. See comment at the end of the
- * loop below.
- */
- for (i = 0; i < EVENTS_PER_GETN; ++i) {
- struct fd_info *fdi = NULL;
- if (epdp->ed_pending[i] != -1) {
- fdi = &(epdp->ed_fds[epdp->ed_pending[i]]);
- }
-
- if (fdi != NULL && FDI_HAS_EVENTS(fdi)) {
- int fd = FDI_HAS_READ(fdi) ? fdi->fdi_revt->ev_fd :
- fdi->fdi_wevt->ev_fd;
- reassociate(epdp, fdi, fd);
- epdp->ed_pending[i] = -1;
- }
- }
-
- if ((res = port_getn(epdp->ed_port, pevtlist, EVENTS_PER_GETN,
- (unsigned int *) &nevents, ts_p)) == -1) {
- if (errno == EINTR || errno == EAGAIN) {
- evsignal_process(base);
- return (0);
- } else if (errno == ETIME) {
- if (nevents == 0)
- return (0);
- } else {
- event_warn("port_getn");
- return (-1);
- }
- } else if (base->sig.evsignal_caught) {
- evsignal_process(base);
- }
-
- event_debug(("%s: port_getn reports %d events", __func__, nevents));
-
- for (i = 0; i < nevents; ++i) {
- struct event *ev;
- struct fd_info *fdi;
- port_event_t *pevt = &pevtlist[i];
- int fd = (int) pevt->portev_object;
-
- check_evportop(epdp);
- check_event(pevt);
- epdp->ed_pending[i] = fd;
-
- /*
- * Figure out what kind of event it was
- * (because we have to pass this to the callback)
- */
- res = 0;
- if (pevt->portev_events & POLLIN)
- res |= EV_READ;
- if (pevt->portev_events & POLLOUT)
- res |= EV_WRITE;
-
- assert(epdp->ed_nevents > fd);
- fdi = &(epdp->ed_fds[fd]);
-
- /*
- * We now check for each of the possible events (READ
- * or WRITE). Then, we activate the event (which will
- * cause its callback to be executed).
- */
-
- if ((res & EV_READ) && ((ev = fdi->fdi_revt) != NULL)) {
- event_active(ev, res, 1);
- }
-
- if ((res & EV_WRITE) && ((ev = fdi->fdi_wevt) != NULL)) {
- event_active(ev, res, 1);
- }
- } /* end of all events gotten */
-
- check_evportop(epdp);
-
- return (0);
-}
-
-
-/*
- * Adds the given event (so that you will be notified when it happens via
- * the callback function).
- */
-
-static int
-evport_add(void *arg, struct event *ev)
-{
- struct evport_data *evpd = arg;
- struct fd_info *fdi;
- int factor;
-
- check_evportop(evpd);
-
- /*
- * Delegate, if it's not ours to handle.
- */
- if (ev->ev_events & EV_SIGNAL)
- return (evsignal_add(ev));
-
- /*
- * If necessary, grow the file descriptor info table
- */
-
- factor = 1;
- while (ev->ev_fd >= factor * evpd->ed_nevents)
- factor *= 2;
-
- if (factor > 1) {
- if (-1 == grow(evpd, factor)) {
- return (-1);
- }
- }
-
- fdi = &evpd->ed_fds[ev->ev_fd];
- if (ev->ev_events & EV_READ)
- fdi->fdi_revt = ev;
- if (ev->ev_events & EV_WRITE)
- fdi->fdi_wevt = ev;
-
- return reassociate(evpd, fdi, ev->ev_fd);
-}
-
-/*
- * Removes the given event from the list of events to wait for.
- */
-
-static int
-evport_del(void *arg, struct event *ev)
-{
- struct evport_data *evpd = arg;
- struct fd_info *fdi;
- int i;
- int associated = 1;
-
- check_evportop(evpd);
-
- /*
- * Delegate, if it's not ours to handle
- */
- if (ev->ev_events & EV_SIGNAL) {
- return (evsignal_del(ev));
- }
-
- if (evpd->ed_nevents < ev->ev_fd) {
- return (-1);
- }
-
- for (i = 0; i < EVENTS_PER_GETN; ++i) {
- if (evpd->ed_pending[i] == ev->ev_fd) {
- associated = 0;
- break;
- }
- }
-
- fdi = &evpd->ed_fds[ev->ev_fd];
- if (ev->ev_events & EV_READ)
- fdi->fdi_revt = NULL;
- if (ev->ev_events & EV_WRITE)
- fdi->fdi_wevt = NULL;
-
- if (associated) {
- if (!FDI_HAS_EVENTS(fdi) &&
- port_dissociate(evpd->ed_port, PORT_SOURCE_FD,
- ev->ev_fd) == -1) {
- /*
- * Ignre EBADFD error the fd could have been closed
- * before event_del() was called.
- */
- if (errno != EBADFD) {
- event_warn("port_dissociate");
- return (-1);
- }
- } else {
- if (FDI_HAS_EVENTS(fdi)) {
- return (reassociate(evpd, fdi, ev->ev_fd));
- }
- }
- } else {
- if (fdi->fdi_revt == NULL && fdi->fdi_wevt == NULL) {
- evpd->ed_pending[i] = -1;
- }
- }
- return 0;
-}
-
-
-static void
-evport_dealloc(struct event_base *base, void *arg)
-{
- struct evport_data *evpd = arg;
-
- evsignal_dealloc(base);
-
- close(evpd->ed_port);
-
- if (evpd->ed_fds)
- free(evpd->ed_fds);
- free(evpd);
-}
-
-#endif /* HAVE_EVENT_PORTS */
diff --git a/extra/libevent/evrpc-internal.h b/extra/libevent/evrpc-internal.h
deleted file mode 100644
index c900f959f97..00000000000
--- a/extra/libevent/evrpc-internal.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * 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 BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#ifndef _EVRPC_INTERNAL_H_
-#define _EVRPC_INTERNAL_H_
-
-#include "http-internal.h"
-
-struct evrpc;
-
-#define EVRPC_URI_PREFIX "/.rpc."
-
-struct evrpc_hook {
- TAILQ_ENTRY(evrpc_hook) (next);
-
- /* returns -1; if the rpc should be aborted, is allowed to rewrite */
- int (*process)(struct evhttp_request *, struct evbuffer *, void *);
- void *process_arg;
-};
-
-TAILQ_HEAD(evrpc_hook_list, evrpc_hook);
-
-/*
- * this is shared between the base and the pool, so that we can reuse
- * the hook adding functions; we alias both evrpc_pool and evrpc_base
- * to this common structure.
- */
-struct _evrpc_hooks {
- /* hooks for processing outbound and inbound rpcs */
- struct evrpc_hook_list in_hooks;
- struct evrpc_hook_list out_hooks;
-};
-
-#define input_hooks common.in_hooks
-#define output_hooks common.out_hooks
-
-struct evrpc_base {
- struct _evrpc_hooks common;
-
- /* the HTTP server under which we register our RPC calls */
- struct evhttp* http_server;
-
- /* a list of all RPCs registered with us */
- TAILQ_HEAD(evrpc_list, evrpc) registered_rpcs;
-};
-
-struct evrpc_req_generic;
-void evrpc_reqstate_free(struct evrpc_req_generic* rpc_state);
-
-/* A pool for holding evhttp_connection objects */
-struct evrpc_pool {
- struct _evrpc_hooks common;
-
- struct event_base *base;
-
- struct evconq connections;
-
- int timeout;
-
- TAILQ_HEAD(evrpc_requestq, evrpc_request_wrapper) requests;
-};
-
-
-#endif /* _EVRPC_INTERNAL_H_ */
diff --git a/extra/libevent/evrpc.c b/extra/libevent/evrpc.c
deleted file mode 100644
index bfe3087ef8a..00000000000
--- a/extra/libevent/evrpc.c
+++ /dev/null
@@ -1,658 +0,0 @@
-/*
- * Copyright (c) 2000-2004 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 BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef WIN32
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <winsock2.h>
-#undef WIN32_LEAN_AND_MEAN
-#include "misc.h"
-#endif
-
-#include <sys/types.h>
-#ifndef WIN32
-#include <sys/socket.h>
-#endif
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#include <sys/queue.h>
-#include <stdio.h>
-#include <stdlib.h>
-#ifndef WIN32
-#include <unistd.h>
-#endif
-#include <errno.h>
-#include <signal.h>
-#include <string.h>
-#include <assert.h>
-
-#include "event.h"
-#include "evrpc.h"
-#include "evrpc-internal.h"
-#include "evhttp.h"
-#include "evutil.h"
-#include "log.h"
-
-struct evrpc_base *
-evrpc_init(struct evhttp *http_server)
-{
- struct evrpc_base* base = calloc(1, sizeof(struct evrpc_base));
- if (base == NULL)
- return (NULL);
-
- /* we rely on the tagging sub system */
- evtag_init();
-
- TAILQ_INIT(&base->registered_rpcs);
- TAILQ_INIT(&base->input_hooks);
- TAILQ_INIT(&base->output_hooks);
- base->http_server = http_server;
-
- return (base);
-}
-
-void
-evrpc_free(struct evrpc_base *base)
-{
- struct evrpc *rpc;
- struct evrpc_hook *hook;
-
- while ((rpc = TAILQ_FIRST(&base->registered_rpcs)) != NULL) {
- assert(evrpc_unregister_rpc(base, rpc->uri));
- }
- while ((hook = TAILQ_FIRST(&base->input_hooks)) != NULL) {
- assert(evrpc_remove_hook(base, INPUT, hook));
- }
- while ((hook = TAILQ_FIRST(&base->output_hooks)) != NULL) {
- assert(evrpc_remove_hook(base, OUTPUT, hook));
- }
- free(base);
-}
-
-void *
-evrpc_add_hook(void *vbase,
- enum EVRPC_HOOK_TYPE hook_type,
- int (*cb)(struct evhttp_request *, struct evbuffer *, void *),
- void *cb_arg)
-{
- struct _evrpc_hooks *base = vbase;
- struct evrpc_hook_list *head = NULL;
- struct evrpc_hook *hook = NULL;
- switch (hook_type) {
- case INPUT:
- head = &base->in_hooks;
- break;
- case OUTPUT:
- head = &base->out_hooks;
- break;
- default:
- assert(hook_type == INPUT || hook_type == OUTPUT);
- }
-
- hook = calloc(1, sizeof(struct evrpc_hook));
- assert(hook != NULL);
-
- hook->process = cb;
- hook->process_arg = cb_arg;
- TAILQ_INSERT_TAIL(head, hook, next);
-
- return (hook);
-}
-
-static int
-evrpc_remove_hook_internal(struct evrpc_hook_list *head, void *handle)
-{
- struct evrpc_hook *hook = NULL;
- TAILQ_FOREACH(hook, head, next) {
- if (hook == handle) {
- TAILQ_REMOVE(head, hook, next);
- free(hook);
- return (1);
- }
- }
-
- return (0);
-}
-
-/*
- * remove the hook specified by the handle
- */
-
-int
-evrpc_remove_hook(void *vbase, enum EVRPC_HOOK_TYPE hook_type, void *handle)
-{
- struct _evrpc_hooks *base = vbase;
- struct evrpc_hook_list *head = NULL;
- switch (hook_type) {
- case INPUT:
- head = &base->in_hooks;
- break;
- case OUTPUT:
- head = &base->out_hooks;
- break;
- default:
- assert(hook_type == INPUT || hook_type == OUTPUT);
- }
-
- return (evrpc_remove_hook_internal(head, handle));
-}
-
-static int
-evrpc_process_hooks(struct evrpc_hook_list *head,
- struct evhttp_request *req, struct evbuffer *evbuf)
-{
- struct evrpc_hook *hook;
- TAILQ_FOREACH(hook, head, next) {
- if (hook->process(req, evbuf, hook->process_arg) == -1)
- return (-1);
- }
-
- return (0);
-}
-
-static void evrpc_pool_schedule(struct evrpc_pool *pool);
-static void evrpc_request_cb(struct evhttp_request *, void *);
-void evrpc_request_done(struct evrpc_req_generic*);
-
-/*
- * Registers a new RPC with the HTTP server. The evrpc object is expected
- * to have been filled in via the EVRPC_REGISTER_OBJECT macro which in turn
- * calls this function.
- */
-
-static char *
-evrpc_construct_uri(const char *uri)
-{
- char *constructed_uri;
- int constructed_uri_len;
-
- constructed_uri_len = strlen(EVRPC_URI_PREFIX) + strlen(uri) + 1;
- if ((constructed_uri = malloc(constructed_uri_len)) == NULL)
- event_err(1, "%s: failed to register rpc at %s",
- __func__, uri);
- memcpy(constructed_uri, EVRPC_URI_PREFIX, strlen(EVRPC_URI_PREFIX));
- memcpy(constructed_uri + strlen(EVRPC_URI_PREFIX), uri, strlen(uri));
- constructed_uri[constructed_uri_len - 1] = '\0';
-
- return (constructed_uri);
-}
-
-int
-evrpc_register_rpc(struct evrpc_base *base, struct evrpc *rpc,
- void (*cb)(struct evrpc_req_generic *, void *), void *cb_arg)
-{
- char *constructed_uri = evrpc_construct_uri(rpc->uri);
-
- rpc->base = base;
- rpc->cb = cb;
- rpc->cb_arg = cb_arg;
-
- TAILQ_INSERT_TAIL(&base->registered_rpcs, rpc, next);
-
- evhttp_set_cb(base->http_server,
- constructed_uri,
- evrpc_request_cb,
- rpc);
-
- free(constructed_uri);
-
- return (0);
-}
-
-int
-evrpc_unregister_rpc(struct evrpc_base *base, const char *name)
-{
- char *registered_uri = NULL;
- struct evrpc *rpc;
-
- /* find the right rpc; linear search might be slow */
- TAILQ_FOREACH(rpc, &base->registered_rpcs, next) {
- if (strcmp(rpc->uri, name) == 0)
- break;
- }
- if (rpc == NULL) {
- /* We did not find an RPC with this name */
- return (-1);
- }
- TAILQ_REMOVE(&base->registered_rpcs, rpc, next);
-
- free((char *)rpc->uri);
- free(rpc);
-
- registered_uri = evrpc_construct_uri(name);
-
- /* remove the http server callback */
- assert(evhttp_del_cb(base->http_server, registered_uri) == 0);
-
- free(registered_uri);
- return (0);
-}
-
-static void
-evrpc_request_cb(struct evhttp_request *req, void *arg)
-{
- struct evrpc *rpc = arg;
- struct evrpc_req_generic *rpc_state = NULL;
-
- /* let's verify the outside parameters */
- if (req->type != EVHTTP_REQ_POST ||
- EVBUFFER_LENGTH(req->input_buffer) <= 0)
- goto error;
-
- /*
- * we might want to allow hooks to suspend the processing,
- * but at the moment, we assume that they just act as simple
- * filters.
- */
- if (evrpc_process_hooks(&rpc->base->input_hooks,
- req, req->input_buffer) == -1)
- goto error;
-
- rpc_state = calloc(1, sizeof(struct evrpc_req_generic));
- if (rpc_state == NULL)
- goto error;
-
- /* let's check that we can parse the request */
- rpc_state->request = rpc->request_new();
- if (rpc_state->request == NULL)
- goto error;
-
- rpc_state->rpc = rpc;
-
- if (rpc->request_unmarshal(
- rpc_state->request, req->input_buffer) == -1) {
- /* we failed to parse the request; that's a bummer */
- goto error;
- }
-
- /* at this point, we have a well formed request, prepare the reply */
-
- rpc_state->reply = rpc->reply_new();
- if (rpc_state->reply == NULL)
- goto error;
-
- rpc_state->http_req = req;
- rpc_state->done = evrpc_request_done;
-
- /* give the rpc to the user; they can deal with it */
- rpc->cb(rpc_state, rpc->cb_arg);
-
- return;
-
-error:
- evrpc_reqstate_free(rpc_state);
- evhttp_send_error(req, HTTP_SERVUNAVAIL, "Service Error");
- return;
-}
-
-void
-evrpc_reqstate_free(struct evrpc_req_generic* rpc_state)
-{
- /* clean up all memory */
- if (rpc_state != NULL) {
- struct evrpc *rpc = rpc_state->rpc;
-
- if (rpc_state->request != NULL)
- rpc->request_free(rpc_state->request);
- if (rpc_state->reply != NULL)
- rpc->reply_free(rpc_state->reply);
- free(rpc_state);
- }
-}
-
-void
-evrpc_request_done(struct evrpc_req_generic* rpc_state)
-{
- struct evhttp_request *req = rpc_state->http_req;
- struct evrpc *rpc = rpc_state->rpc;
- struct evbuffer* data = NULL;
-
- if (rpc->reply_complete(rpc_state->reply) == -1) {
- /* the reply was not completely filled in. error out */
- goto error;
- }
-
- if ((data = evbuffer_new()) == NULL) {
- /* out of memory */
- goto error;
- }
-
- /* serialize the reply */
- rpc->reply_marshal(data, rpc_state->reply);
-
- /* do hook based tweaks to the request */
- if (evrpc_process_hooks(&rpc->base->output_hooks,
- req, data) == -1)
- goto error;
-
- /* on success, we are going to transmit marshaled binary data */
- if (evhttp_find_header(req->output_headers, "Content-Type") == NULL) {
- evhttp_add_header(req->output_headers,
- "Content-Type", "application/octet-stream");
- }
-
- evhttp_send_reply(req, HTTP_OK, "OK", data);
-
- evbuffer_free(data);
-
- evrpc_reqstate_free(rpc_state);
-
- return;
-
-error:
- if (data != NULL)
- evbuffer_free(data);
- evrpc_reqstate_free(rpc_state);
- evhttp_send_error(req, HTTP_SERVUNAVAIL, "Service Error");
- return;
-}
-
-/* Client implementation of RPC site */
-
-static int evrpc_schedule_request(struct evhttp_connection *connection,
- struct evrpc_request_wrapper *ctx);
-
-struct evrpc_pool *
-evrpc_pool_new(struct event_base *base)
-{
- struct evrpc_pool *pool = calloc(1, sizeof(struct evrpc_pool));
- if (pool == NULL)
- return (NULL);
-
- TAILQ_INIT(&pool->connections);
- TAILQ_INIT(&pool->requests);
-
- TAILQ_INIT(&pool->input_hooks);
- TAILQ_INIT(&pool->output_hooks);
-
- pool->base = base;
- pool->timeout = -1;
-
- return (pool);
-}
-
-static void
-evrpc_request_wrapper_free(struct evrpc_request_wrapper *request)
-{
- free(request->name);
- free(request);
-}
-
-void
-evrpc_pool_free(struct evrpc_pool *pool)
-{
- struct evhttp_connection *connection;
- struct evrpc_request_wrapper *request;
- struct evrpc_hook *hook;
-
- while ((request = TAILQ_FIRST(&pool->requests)) != NULL) {
- TAILQ_REMOVE(&pool->requests, request, next);
- /* if this gets more complicated we need our own function */
- evrpc_request_wrapper_free(request);
- }
-
- while ((connection = TAILQ_FIRST(&pool->connections)) != NULL) {
- TAILQ_REMOVE(&pool->connections, connection, next);
- evhttp_connection_free(connection);
- }
-
- while ((hook = TAILQ_FIRST(&pool->input_hooks)) != NULL) {
- assert(evrpc_remove_hook(pool, INPUT, hook));
- }
-
- while ((hook = TAILQ_FIRST(&pool->output_hooks)) != NULL) {
- assert(evrpc_remove_hook(pool, OUTPUT, hook));
- }
-
- free(pool);
-}
-
-/*
- * Add a connection to the RPC pool. A request scheduled on the pool
- * may use any available connection.
- */
-
-void
-evrpc_pool_add_connection(struct evrpc_pool *pool,
- struct evhttp_connection *connection) {
- assert(connection->http_server == NULL);
- TAILQ_INSERT_TAIL(&pool->connections, connection, next);
-
- /*
- * associate an event base with this connection
- */
- if (pool->base != NULL)
- evhttp_connection_set_base(connection, pool->base);
-
- /*
- * unless a timeout was specifically set for a connection,
- * the connection inherits the timeout from the pool.
- */
- if (connection->timeout == -1)
- connection->timeout = pool->timeout;
-
- /*
- * if we have any requests pending, schedule them with the new
- * connections.
- */
-
- if (TAILQ_FIRST(&pool->requests) != NULL) {
- struct evrpc_request_wrapper *request =
- TAILQ_FIRST(&pool->requests);
- TAILQ_REMOVE(&pool->requests, request, next);
- evrpc_schedule_request(connection, request);
- }
-}
-
-void
-evrpc_pool_set_timeout(struct evrpc_pool *pool, int timeout_in_secs)
-{
- struct evhttp_connection *evcon;
- TAILQ_FOREACH(evcon, &pool->connections, next) {
- evcon->timeout = timeout_in_secs;
- }
- pool->timeout = timeout_in_secs;
-}
-
-
-static void evrpc_reply_done(struct evhttp_request *, void *);
-static void evrpc_request_timeout(int, short, void *);
-
-/*
- * Finds a connection object associated with the pool that is currently
- * idle and can be used to make a request.
- */
-static struct evhttp_connection *
-evrpc_pool_find_connection(struct evrpc_pool *pool)
-{
- struct evhttp_connection *connection;
- TAILQ_FOREACH(connection, &pool->connections, next) {
- if (TAILQ_FIRST(&connection->requests) == NULL)
- return (connection);
- }
-
- return (NULL);
-}
-
-/*
- * We assume that the ctx is no longer queued on the pool.
- */
-static int
-evrpc_schedule_request(struct evhttp_connection *connection,
- struct evrpc_request_wrapper *ctx)
-{
- struct evhttp_request *req = NULL;
- struct evrpc_pool *pool = ctx->pool;
- struct evrpc_status status;
- char *uri = NULL;
- int res = 0;
-
- if ((req = evhttp_request_new(evrpc_reply_done, ctx)) == NULL)
- goto error;
-
- /* serialize the request data into the output buffer */
- ctx->request_marshal(req->output_buffer, ctx->request);
-
- uri = evrpc_construct_uri(ctx->name);
- if (uri == NULL)
- goto error;
-
- /* we need to know the connection that we might have to abort */
- ctx->evcon = connection;
-
- /* apply hooks to the outgoing request */
- if (evrpc_process_hooks(&pool->output_hooks,
- req, req->output_buffer) == -1)
- goto error;
-
- if (pool->timeout > 0) {
- /*
- * a timeout after which the whole rpc is going to be aborted.
- */
- struct timeval tv;
- evutil_timerclear(&tv);
- tv.tv_sec = pool->timeout;
- evtimer_add(&ctx->ev_timeout, &tv);
- }
-
- /* start the request over the connection */
- res = evhttp_make_request(connection, req, EVHTTP_REQ_POST, uri);
- free(uri);
-
- if (res == -1)
- goto error;
-
- return (0);
-
-error:
- memset(&status, 0, sizeof(status));
- status.error = EVRPC_STATUS_ERR_UNSTARTED;
- (*ctx->cb)(&status, ctx->request, ctx->reply, ctx->cb_arg);
- evrpc_request_wrapper_free(ctx);
- return (-1);
-}
-
-int
-evrpc_make_request(struct evrpc_request_wrapper *ctx)
-{
- struct evrpc_pool *pool = ctx->pool;
-
- /* initialize the event structure for this rpc */
- evtimer_set(&ctx->ev_timeout, evrpc_request_timeout, ctx);
- if (pool->base != NULL)
- event_base_set(pool->base, &ctx->ev_timeout);
-
- /* we better have some available connections on the pool */
- assert(TAILQ_FIRST(&pool->connections) != NULL);
-
- /*
- * if no connection is available, we queue the request on the pool,
- * the next time a connection is empty, the rpc will be send on that.
- */
- TAILQ_INSERT_TAIL(&pool->requests, ctx, next);
-
- evrpc_pool_schedule(pool);
-
- return (0);
-}
-
-static void
-evrpc_reply_done(struct evhttp_request *req, void *arg)
-{
- struct evrpc_request_wrapper *ctx = arg;
- struct evrpc_pool *pool = ctx->pool;
- struct evrpc_status status;
- int res = -1;
-
- /* cancel any timeout we might have scheduled */
- event_del(&ctx->ev_timeout);
-
- memset(&status, 0, sizeof(status));
- status.http_req = req;
-
- /* we need to get the reply now */
- if (req != NULL) {
- /* apply hooks to the incoming request */
- if (evrpc_process_hooks(&pool->input_hooks,
- req, req->input_buffer) == -1) {
- status.error = EVRPC_STATUS_ERR_HOOKABORTED;
- res = -1;
- } else {
- res = ctx->reply_unmarshal(ctx->reply,
- req->input_buffer);
- if (res == -1) {
- status.error = EVRPC_STATUS_ERR_BADPAYLOAD;
- }
- }
- } else {
- status.error = EVRPC_STATUS_ERR_TIMEOUT;
- }
-
- if (res == -1) {
- /* clear everything that we might have written previously */
- ctx->reply_clear(ctx->reply);
- }
-
- (*ctx->cb)(&status, ctx->request, ctx->reply, ctx->cb_arg);
-
- evrpc_request_wrapper_free(ctx);
-
- /* the http layer owns the request structure */
-
- /* see if we can schedule another request */
- evrpc_pool_schedule(pool);
-}
-
-static void
-evrpc_pool_schedule(struct evrpc_pool *pool)
-{
- struct evrpc_request_wrapper *ctx = TAILQ_FIRST(&pool->requests);
- struct evhttp_connection *evcon;
-
- /* if no requests are pending, we have no work */
- if (ctx == NULL)
- return;
-
- if ((evcon = evrpc_pool_find_connection(pool)) != NULL) {
- TAILQ_REMOVE(&pool->requests, ctx, next);
- evrpc_schedule_request(evcon, ctx);
- }
-}
-
-static void
-evrpc_request_timeout(int fd, short what, void *arg)
-{
- struct evrpc_request_wrapper *ctx = arg;
- struct evhttp_connection *evcon = ctx->evcon;
- assert(evcon != NULL);
-
- evhttp_connection_fail(evcon, EVCON_HTTP_TIMEOUT);
-}
diff --git a/extra/libevent/evrpc.h b/extra/libevent/evrpc.h
deleted file mode 100644
index 45f684ac5ac..00000000000
--- a/extra/libevent/evrpc.h
+++ /dev/null
@@ -1,477 +0,0 @@
-/*
- * 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 BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#ifndef _EVRPC_H_
-#define _EVRPC_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/** @file evrpc.h
- *
- * This header files provides basic support for an RPC server and client.
- *
- * To support RPCs in a server, every supported RPC command needs to be
- * defined and registered.
- *
- * EVRPC_HEADER(SendCommand, Request, Reply);
- *
- * SendCommand is the name of the RPC command.
- * Request is the name of a structure generated by event_rpcgen.py.
- * It contains all parameters relating to the SendCommand RPC. The
- * server needs to fill in the Reply structure.
- * Reply is the name of a structure generated by event_rpcgen.py. It
- * contains the answer to the RPC.
- *
- * To register an RPC with an HTTP server, you need to first create an RPC
- * base with:
- *
- * struct evrpc_base *base = evrpc_init(http);
- *
- * A specific RPC can then be registered with
- *
- * EVRPC_REGISTER(base, SendCommand, Request, Reply, FunctionCB, arg);
- *
- * when the server receives an appropriately formatted RPC, the user callback
- * is invokved. The callback needs to fill in the reply structure.
- *
- * void FunctionCB(EVRPC_STRUCT(SendCommand)* rpc, void *arg);
- *
- * To send the reply, call EVRPC_REQUEST_DONE(rpc);
- *
- * See the regression test for an example.
- */
-
-struct evbuffer;
-struct event_base;
-struct evrpc_req_generic;
-
-/* Encapsulates a request */
-struct evrpc {
- TAILQ_ENTRY(evrpc) next;
-
- /* the URI at which the request handler lives */
- const char* uri;
-
- /* creates a new request structure */
- void *(*request_new)(void);
-
- /* frees the request structure */
- void (*request_free)(void *);
-
- /* unmarshals the buffer into the proper request structure */
- int (*request_unmarshal)(void *, struct evbuffer *);
-
- /* creates a new reply structure */
- void *(*reply_new)(void);
-
- /* creates a new reply structure */
- void (*reply_free)(void *);
-
- /* verifies that the reply is valid */
- int (*reply_complete)(void *);
-
- /* marshals the reply into a buffer */
- void (*reply_marshal)(struct evbuffer*, void *);
-
- /* the callback invoked for each received rpc */
- void (*cb)(struct evrpc_req_generic *, void *);
- void *cb_arg;
-
- /* reference for further configuration */
- struct evrpc_base *base;
-};
-
-/** The type of a specific RPC Message
- *
- * @param rpcname the name of the RPC message
- */
-#define EVRPC_STRUCT(rpcname) struct evrpc_req__##rpcname
-
-struct evhttp_request;
-struct evrpc_status;
-
-/* We alias the RPC specific structs to this voided one */
-struct evrpc_req_generic {
- /* the unmarshaled request object */
- void *request;
-
- /* the empty reply object that needs to be filled in */
- void *reply;
-
- /*
- * the static structure for this rpc; that can be used to
- * automatically unmarshal and marshal the http buffers.
- */
- struct evrpc *rpc;
-
- /*
- * the http request structure on which we need to answer.
- */
- struct evhttp_request* http_req;
-
- /*
- * callback to reply and finish answering this rpc
- */
- void (*done)(struct evrpc_req_generic* rpc);
-};
-
-/** Creates the definitions and prototypes for an RPC
- *
- * You need to use EVRPC_HEADER to create structures and function prototypes
- * needed by the server and client implementation. The structures have to be
- * defined in an .rpc file and converted to source code via event_rpcgen.py
- *
- * @param rpcname the name of the RPC
- * @param reqstruct the name of the RPC request structure
- * @param replystruct the name of the RPC reply structure
- * @see EVRPC_GENERATE()
- */
-#define EVRPC_HEADER(rpcname, reqstruct, rplystruct) \
-EVRPC_STRUCT(rpcname) { \
- struct reqstruct* request; \
- struct rplystruct* reply; \
- struct evrpc* rpc; \
- struct evhttp_request* http_req; \
- void (*done)(struct evrpc_status *, \
- struct evrpc* rpc, void *request, void *reply); \
-}; \
-int evrpc_send_request_##rpcname(struct evrpc_pool *, \
- struct reqstruct *, struct rplystruct *, \
- void (*)(struct evrpc_status *, \
- struct reqstruct *, struct rplystruct *, void *cbarg), \
- void *);
-
-/** Generates the code for receiving and sending an RPC message
- *
- * EVRPC_GENERATE is used to create the code corresponding to sending
- * and receiving a particular RPC message
- *
- * @param rpcname the name of the RPC
- * @param reqstruct the name of the RPC request structure
- * @param replystruct the name of the RPC reply structure
- * @see EVRPC_HEADER()
- */
-#define EVRPC_GENERATE(rpcname, reqstruct, rplystruct) \
-int evrpc_send_request_##rpcname(struct evrpc_pool *pool, \
- struct reqstruct *request, struct rplystruct *reply, \
- void (*cb)(struct evrpc_status *, \
- struct reqstruct *, struct rplystruct *, void *cbarg), \
- void *cbarg) { \
- struct evrpc_status status; \
- struct evrpc_request_wrapper *ctx; \
- ctx = (struct evrpc_request_wrapper *) \
- malloc(sizeof(struct evrpc_request_wrapper)); \
- if (ctx == NULL) \
- goto error; \
- ctx->pool = pool; \
- ctx->evcon = NULL; \
- ctx->name = strdup(#rpcname); \
- if (ctx->name == NULL) { \
- free(ctx); \
- goto error; \
- } \
- ctx->cb = (void (*)(struct evrpc_status *, \
- void *, void *, void *))cb; \
- ctx->cb_arg = cbarg; \
- ctx->request = (void *)request; \
- ctx->reply = (void *)reply; \
- ctx->request_marshal = (void (*)(struct evbuffer *, void *))reqstruct##_marshal; \
- ctx->reply_clear = (void (*)(void *))rplystruct##_clear; \
- ctx->reply_unmarshal = (int (*)(void *, struct evbuffer *))rplystruct##_unmarshal; \
- return (evrpc_make_request(ctx)); \
-error: \
- memset(&status, 0, sizeof(status)); \
- status.error = EVRPC_STATUS_ERR_UNSTARTED; \
- (*(cb))(&status, request, reply, cbarg); \
- return (-1); \
-}
-
-/** Provides access to the HTTP request object underlying an RPC
- *
- * Access to the underlying http object; can be used to look at headers or
- * for getting the remote ip address
- *
- * @param rpc_req the rpc request structure provided to the server callback
- * @return an struct evhttp_request object that can be inspected for
- * HTTP headers or sender information.
- */
-#define EVRPC_REQUEST_HTTP(rpc_req) (rpc_req)->http_req
-
-/** Creates the reply to an RPC request
- *
- * EVRPC_REQUEST_DONE is used to answer a request; the reply is expected
- * to have been filled in. The request and reply pointers become invalid
- * after this call has finished.
- *
- * @param rpc_req the rpc request structure provided to the server callback
- */
-#define EVRPC_REQUEST_DONE(rpc_req) do { \
- struct evrpc_req_generic *_req = (struct evrpc_req_generic *)(rpc_req); \
- _req->done(_req); \
-} while (0)
-
-
-/* Takes a request object and fills it in with the right magic */
-#define EVRPC_REGISTER_OBJECT(rpc, name, request, reply) \
- do { \
- (rpc)->uri = strdup(#name); \
- if ((rpc)->uri == NULL) { \
- fprintf(stderr, "failed to register object\n"); \
- exit(1); \
- } \
- (rpc)->request_new = (void *(*)(void))request##_new; \
- (rpc)->request_free = (void (*)(void *))request##_free; \
- (rpc)->request_unmarshal = (int (*)(void *, struct evbuffer *))request##_unmarshal; \
- (rpc)->reply_new = (void *(*)(void))reply##_new; \
- (rpc)->reply_free = (void (*)(void *))reply##_free; \
- (rpc)->reply_complete = (int (*)(void *))reply##_complete; \
- (rpc)->reply_marshal = (void (*)(struct evbuffer*, void *))reply##_marshal; \
- } while (0)
-
-struct evrpc_base;
-struct evhttp;
-
-/* functions to start up the rpc system */
-
-/** Creates a new rpc base from which RPC requests can be received
- *
- * @param server a pointer to an existing HTTP server
- * @return a newly allocated evrpc_base struct
- * @see evrpc_free()
- */
-struct evrpc_base *evrpc_init(struct evhttp *server);
-
-/**
- * Frees the evrpc base
- *
- * For now, you are responsible for making sure that no rpcs are ongoing.
- *
- * @param base the evrpc_base object to be freed
- * @see evrpc_init
- */
-void evrpc_free(struct evrpc_base *base);
-
-/** register RPCs with the HTTP Server
- *
- * registers a new RPC with the HTTP server, each RPC needs to have
- * a unique name under which it can be identified.
- *
- * @param base the evrpc_base structure in which the RPC should be
- * registered.
- * @param name the name of the RPC
- * @param request the name of the RPC request structure
- * @param reply the name of the RPC reply structure
- * @param callback the callback that should be invoked when the RPC
- * is received. The callback has the following prototype
- * void (*callback)(EVRPC_STRUCT(Message)* rpc, void *arg)
- * @param cbarg an additional parameter that can be passed to the callback.
- * The parameter can be used to carry around state.
- */
-#define EVRPC_REGISTER(base, name, request, reply, callback, cbarg) \
- do { \
- struct evrpc* rpc = (struct evrpc *)calloc(1, sizeof(struct evrpc)); \
- EVRPC_REGISTER_OBJECT(rpc, name, request, reply); \
- evrpc_register_rpc(base, rpc, \
- (void (*)(struct evrpc_req_generic*, void *))callback, cbarg); \
- } while (0)
-
-int evrpc_register_rpc(struct evrpc_base *, struct evrpc *,
- void (*)(struct evrpc_req_generic*, void *), void *);
-
-/**
- * Unregisters an already registered RPC
- *
- * @param base the evrpc_base object from which to unregister an RPC
- * @param name the name of the rpc to unregister
- * @return -1 on error or 0 when successful.
- * @see EVRPC_REGISTER()
- */
-#define EVRPC_UNREGISTER(base, name) evrpc_unregister_rpc(base, #name)
-
-int evrpc_unregister_rpc(struct evrpc_base *base, const char *name);
-
-/*
- * Client-side RPC support
- */
-
-struct evrpc_pool;
-struct evhttp_connection;
-
-/**
- * provides information about the completed RPC request.
- */
-struct evrpc_status {
-#define EVRPC_STATUS_ERR_NONE 0
-#define EVRPC_STATUS_ERR_TIMEOUT 1
-#define EVRPC_STATUS_ERR_BADPAYLOAD 2
-#define EVRPC_STATUS_ERR_UNSTARTED 3
-#define EVRPC_STATUS_ERR_HOOKABORTED 4
- int error;
-
- /* for looking at headers or other information */
- struct evhttp_request *http_req;
-};
-
-struct evrpc_request_wrapper {
- TAILQ_ENTRY(evrpc_request_wrapper) next;
-
- /* pool on which this rpc request is being made */
- struct evrpc_pool *pool;
-
- /* connection on which the request is being sent */
- struct evhttp_connection *evcon;
-
- /* event for implementing request timeouts */
- struct event ev_timeout;
-
- /* the name of the rpc */
- char *name;
-
- /* callback */
- void (*cb)(struct evrpc_status*, void *request, void *reply, void *arg);
- void *cb_arg;
-
- void *request;
- void *reply;
-
- /* unmarshals the buffer into the proper request structure */
- void (*request_marshal)(struct evbuffer *, void *);
-
- /* removes all stored state in the reply */
- void (*reply_clear)(void *);
-
- /* marshals the reply into a buffer */
- int (*reply_unmarshal)(void *, struct evbuffer*);
-};
-
-/** launches an RPC and sends it to the server
- *
- * EVRPC_MAKE_REQUEST() is used by the client to send an RPC to the server.
- *
- * @param name the name of the RPC
- * @param pool the evrpc_pool that contains the connection objects over which
- * the request should be sent.
- * @param request a pointer to the RPC request structure - it contains the
- * data to be sent to the server.
- * @param reply a pointer to the RPC reply structure. It is going to be filled
- * if the request was answered successfully
- * @param cb the callback to invoke when the RPC request has been answered
- * @param cbarg an additional argument to be passed to the client
- * @return 0 on success, -1 on failure
- */
-#define EVRPC_MAKE_REQUEST(name, pool, request, reply, cb, cbarg) \
- evrpc_send_request_##name(pool, request, reply, cb, cbarg)
-
-int evrpc_make_request(struct evrpc_request_wrapper *);
-
-/** creates an rpc connection pool
- *
- * a pool has a number of connections associated with it.
- * rpc requests are always made via a pool.
- *
- * @param base a pointer to an struct event_based object; can be left NULL
- * in singled-threaded applications
- * @return a newly allocated struct evrpc_pool object
- * @see evrpc_pool_free()
- */
-struct evrpc_pool *evrpc_pool_new(struct event_base *base);
-/** frees an rpc connection pool
- *
- * @param pool a pointer to an evrpc_pool allocated via evrpc_pool_new()
- * @see evrpc_pool_new()
- */
-void evrpc_pool_free(struct evrpc_pool *pool);
-/*
- * adds a connection over which rpc can be dispatched. the connection
- * object must have been newly created.
- */
-void evrpc_pool_add_connection(struct evrpc_pool *,
- struct evhttp_connection *);
-
-/**
- * Sets the timeout in secs after which a request has to complete. The
- * RPC is completely aborted if it does not complete by then. Setting
- * the timeout to 0 means that it never timeouts and can be used to
- * implement callback type RPCs.
- *
- * Any connection already in the pool will be updated with the new
- * timeout. Connections added to the pool after set_timeout has be
- * called receive the pool timeout only if no timeout has been set
- * for the connection itself.
- *
- * @param pool a pointer to a struct evrpc_pool object
- * @param timeout_in_secs the number of seconds after which a request should
- * timeout and a failure be returned to the callback.
- */
-void evrpc_pool_set_timeout(struct evrpc_pool *pool, int timeout_in_secs);
-
-/**
- * Hooks for changing the input and output of RPCs; this can be used to
- * implement compression, authentication, encryption, ...
- */
-
-enum EVRPC_HOOK_TYPE {
- INPUT, /**< apply the function to an input hook */
- OUTPUT /**< apply the function to an output hook */
-};
-
-/** adds a processing hook to either an rpc base or rpc pool
- *
- * If a hook returns -1, the processing is aborted.
- *
- * The add functions return handles that can be used for removing hooks.
- *
- * @param vbase a pointer to either struct evrpc_base or struct evrpc_pool
- * @param hook_type either INPUT or OUTPUT
- * @param cb the callback to call when the hook is activated
- * @param cb_arg an additional argument for the callback
- * @return a handle to the hook so it can be removed later
- * @see evrpc_remove_hook()
- */
-void *evrpc_add_hook(void *vbase,
- enum EVRPC_HOOK_TYPE hook_type,
- int (*cb)(struct evhttp_request *, struct evbuffer *, void *),
- void *cb_arg);
-
-/** removes a previously added hook
- *
- * @param vbase a pointer to either struct evrpc_base or struct evrpc_pool
- * @param hook_type either INPUT or OUTPUT
- * @param handle a handle returned by evrpc_add_hook()
- * @return 1 on success or 0 on failure
- * @see evrpc_add_hook()
- */
-int evrpc_remove_hook(void *vbase,
- enum EVRPC_HOOK_TYPE hook_type,
- void *handle);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _EVRPC_H_ */
diff --git a/extra/libevent/evsignal.h b/extra/libevent/evsignal.h
deleted file mode 100644
index 0d1e83140bd..00000000000
--- a/extra/libevent/evsignal.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2000-2002 Niels Provos <provos@citi.umich.edu>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#ifndef _EVSIGNAL_H_
-#define _EVSIGNAL_H_
-
-typedef void (*ev_sighandler_t)(int);
-
-struct evsignal_info {
- struct event_list signalqueue;
- struct event ev_signal;
- int ev_signal_pair[2];
- int ev_signal_added;
- volatile sig_atomic_t evsignal_caught;
- sig_atomic_t evsigcaught[NSIG];
-#ifdef HAVE_SIGACTION
- struct sigaction **sh_old;
-#else
- ev_sighandler_t **sh_old;
-#endif
- int sh_old_max;
-};
-void evsignal_init(struct event_base *);
-void evsignal_process(struct event_base *);
-int evsignal_add(struct event *);
-int evsignal_del(struct event *);
-void evsignal_dealloc(struct event_base *);
-
-#endif /* _EVSIGNAL_H_ */
diff --git a/extra/libevent/evutil.c b/extra/libevent/evutil.c
deleted file mode 100644
index 1202d354fe4..00000000000
--- a/extra/libevent/evutil.c
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * Copyright (c) 2007 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 BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef WIN32
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#undef WIN32_LEAN_AND_MEAN
-#include <winsock2.h>
-#include "misc.h"
-#endif
-
-#include <sys/types.h>
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#include <errno.h>
-
-#include "evutil.h"
-#include "log.h"
-
-int
-evutil_socketpair(int family, int type, int protocol, int fd[2])
-{
-#ifndef WIN32
- return socketpair(family, type, protocol, fd);
-#else
- /* This code is originally from Tor. Used with permission. */
-
- /* This socketpair does not work when localhost is down. So
- * it's really not the same thing at all. But it's close enough
- * for now, and really, when localhost is down sometimes, we
- * have other problems too.
- */
- int listener = -1;
- int connector = -1;
- int acceptor = -1;
- struct sockaddr_in listen_addr;
- struct sockaddr_in connect_addr;
- int size;
- int saved_errno = -1;
-
- if (protocol
-#ifdef AF_UNIX
- || family != AF_UNIX
-#endif
- ) {
- EVUTIL_SET_SOCKET_ERROR(WSAEAFNOSUPPORT);
- return -1;
- }
- if (!fd) {
- EVUTIL_SET_SOCKET_ERROR(WSAEINVAL);
- return -1;
- }
-
- listener = (int)socket(AF_INET, type, 0);
- if (listener < 0)
- return -1;
- memset(&listen_addr, 0, sizeof(listen_addr));
- listen_addr.sin_family = AF_INET;
- listen_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- listen_addr.sin_port = 0; /* kernel chooses port. */
- if (bind(listener, (struct sockaddr *) &listen_addr, sizeof (listen_addr))
- == -1)
- goto tidy_up_and_fail;
- if (listen(listener, 1) == -1)
- goto tidy_up_and_fail;
-
- connector = (int)socket(AF_INET, type, 0);
- if (connector < 0)
- goto tidy_up_and_fail;
- /* We want to find out the port number to connect to. */
- size = sizeof(connect_addr);
- if (getsockname(listener, (struct sockaddr *) &connect_addr, &size) == -1)
- goto tidy_up_and_fail;
- if (size != sizeof (connect_addr))
- goto abort_tidy_up_and_fail;
- if (connect(connector, (struct sockaddr *) &connect_addr,
- sizeof(connect_addr)) == -1)
- goto tidy_up_and_fail;
-
- size = sizeof(listen_addr);
- acceptor = (int)accept(listener, (struct sockaddr *) &listen_addr, &size);
- if (acceptor < 0)
- goto tidy_up_and_fail;
- if (size != sizeof(listen_addr))
- goto abort_tidy_up_and_fail;
- EVUTIL_CLOSESOCKET(listener);
- /* Now check we are talking to ourself by matching port and host on the
- two sockets. */
- if (getsockname(connector, (struct sockaddr *) &connect_addr, &size) == -1)
- goto tidy_up_and_fail;
- if (size != sizeof (connect_addr)
- || listen_addr.sin_family != connect_addr.sin_family
- || listen_addr.sin_addr.s_addr != connect_addr.sin_addr.s_addr
- || listen_addr.sin_port != connect_addr.sin_port)
- goto abort_tidy_up_and_fail;
- fd[0] = connector;
- fd[1] = acceptor;
-
- return 0;
-
- abort_tidy_up_and_fail:
- saved_errno = WSAECONNABORTED;
- tidy_up_and_fail:
- if (saved_errno < 0)
- saved_errno = WSAGetLastError();
- if (listener != -1)
- EVUTIL_CLOSESOCKET(listener);
- if (connector != -1)
- EVUTIL_CLOSESOCKET(connector);
- if (acceptor != -1)
- EVUTIL_CLOSESOCKET(acceptor);
-
- EVUTIL_SET_SOCKET_ERROR(saved_errno);
- return -1;
-#endif
-}
-
-int
-evutil_make_socket_nonblocking(int fd)
-{
-#ifdef WIN32
- {
- unsigned long nonblocking = 1;
- ioctlsocket(fd, FIONBIO, (unsigned long*) &nonblocking);
- }
-#else
- if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) {
- event_warn("fcntl(O_NONBLOCK)");
- return -1;
-}
-#endif
- return 0;
-}
-
-ev_int64_t
-evutil_strtoll(const char *s, char **endptr, int base)
-{
-#ifdef HAVE_STRTOLL
- return (ev_int64_t)strtoll(s, endptr, base);
-#elif SIZEOF_LONG == 8
- return (ev_int64_t)strtol(s, endptr, base);
-#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 (base != 10)
- return 0;
- r = (ev_int64_t) _atoi64(s);
- while (isspace(*s))
- ++s;
- while (isdigit(*s))
- ++s;
- if (endptr)
- *endptr = (char*) s;
- return r;
-#elif defined(WIN32)
- return (ev_int64_t) _strtoi64(s, endptr, base);
-#else
-#error "I don't know how to parse 64-bit integers."
-#endif
-}
diff --git a/extra/libevent/evutil.h b/extra/libevent/evutil.h
deleted file mode 100644
index 2cfcacb2e0e..00000000000
--- a/extra/libevent/evutil.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (c) 2007 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 BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#ifndef _EVUTIL_H_
-#define _EVUTIL_H_
-
-/** @file evutil.h
-
- Common convenience functions for cross-platform portability and
- related socket manipulations.
-
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <event-config.h>
-#ifdef _EVENT_HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#ifdef _EVENT_HAVE_STDINT_H
-#include <stdint.h>
-#elif defined(_EVENT_HAVE_INTTYPES_H)
-#include <inttypes.h>
-#endif
-#ifdef _EVENT_HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#ifdef _EVENT_HAVE_UINT64_T
-#define ev_uint64_t uint64_t
-#define ev_int64_t int64_t
-#elif defined(WIN32)
-#define ev_uint64_t unsigned __int64
-#define ev_int64_t __int64
-#elif _EVENT_SIZEOF_LONG_LONG == 8
-#define ev_uint64_t unsigned long long
-#define ev_int64_t long long
-#elif _EVENT_SIZEOF_LONG == 8
-#define ev_uint64_t unsigned long
-#define ev_int64_t long
-#else
-#error "No way to define ev_uint64_t"
-#endif
-
-#ifdef _EVENT_HAVE_UINT32_T
-#define ev_uint32_t uint32_t
-#elif defined(WIN32)
-#define ev_uint32_t unsigned int
-#elif _EVENT_SIZEOF_LONG == 4
-#define ev_uint32_t unsigned long
-#elif _EVENT_SIZEOF_INT == 4
-#define ev_uint32_t unsigned int
-#else
-#error "No way to define ev_uint32_t"
-#endif
-
-#ifdef _EVENT_HAVE_UINT16_T
-#define ev_uint16_t uint16_t
-#elif defined(WIN32)
-#define ev_uint16_t unsigned short
-#elif _EVENT_SIZEOF_INT == 2
-#define ev_uint16_t unsigned int
-#elif _EVENT_SIZEOF_SHORT == 2
-#define ev_uint16_t unsigned short
-#else
-#error "No way to define ev_uint16_t"
-#endif
-
-#ifdef _EVENT_HAVE_UINT8_T
-#define ev_uint8_t uint8_t
-#else
-#define ev_uint8_t unsigned char
-#endif
-
-int evutil_socketpair(int d, int type, int protocol, int sv[2]);
-int evutil_make_socket_nonblocking(int sock);
-#ifdef WIN32
-#define EVUTIL_CLOSESOCKET(s) closesocket(s)
-#else
-#define EVUTIL_CLOSESOCKET(s) close(s)
-#endif
-
-#ifdef WIN32
-#define EVUTIL_SOCKET_ERROR() WSAGetLastError()
-#define EVUTIL_SET_SOCKET_ERROR(errcode) \
- do { WSASetLastError(errcode); } while (0)
-#else
-#define EVUTIL_SOCKET_ERROR() (errno)
-#define EVUTIL_SET_SOCKET_ERROR(errcode) \
- do { errno = (errcode); } while (0)
-#endif
-
-/*
- * Manipulation functions for struct timeval
- */
-#ifdef _EVENT_HAVE_TIMERADD
-#define evutil_timeradd(tvp, uvp, vvp) timeradd((tvp), (uvp), (vvp))
-#define evutil_timersub(tvp, uvp, vvp) timersub((tvp), (uvp), (vvp))
-#else
-#define evutil_timeradd(tvp, uvp, vvp) \
- do { \
- (vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec; \
- (vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec; \
- if ((vvp)->tv_usec >= 1000000) { \
- (vvp)->tv_sec++; \
- (vvp)->tv_usec -= 1000000; \
- } \
- } while (0)
-#define evutil_timersub(tvp, uvp, vvp) \
- do { \
- (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \
- (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \
- if ((vvp)->tv_usec < 0) { \
- (vvp)->tv_sec--; \
- (vvp)->tv_usec += 1000000; \
- } \
- } while (0)
-#endif /* !_EVENT_HAVE_HAVE_TIMERADD */
-
-#ifdef _EVENT_HAVE_TIMERCLEAR
-#define evutil_timerclear(tvp) timerclear(tvp)
-#else
-#define evutil_timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0
-#endif
-
-#ifdef _EVENT_HAVE_TIMERCMP
-#define evutil_timercmp(tvp, uvp, cmp) timercmp((tvp), (uvp), cmp)
-#else
-#define evutil_timercmp(tvp, uvp, cmp) \
- (((tvp)->tv_sec == (uvp)->tv_sec) ? \
- ((tvp)->tv_usec cmp (uvp)->tv_usec) : \
- ((tvp)->tv_sec cmp (uvp)->tv_sec))
-#endif
-
-#ifdef _EVENT_HAVE_TIMERISSET
-#define evutil_timerisset(tvp) timerisset(tvp)
-#else
-#define evutil_timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec)
-#endif
-
-
-/* big-int related functions */
-ev_int64_t evutil_strtoll(const char *s, char **endptr, int base);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _EVUTIL_H_ */
diff --git a/extra/libevent/http-internal.h b/extra/libevent/http-internal.h
deleted file mode 100644
index e9a45f124d8..00000000000
--- a/extra/libevent/http-internal.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright 2001 Niels Provos <provos@citi.umich.edu>
- * All rights reserved.
- *
- * This header file contains definitions for dealing with HTTP requests
- * that are internal to libevent. As user of the library, you should not
- * need to know about these.
- */
-
-#ifndef _HTTP_H_
-#define _HTTP_H_
-
-#define HTTP_CONNECT_TIMEOUT 45
-#define HTTP_WRITE_TIMEOUT 50
-#define HTTP_READ_TIMEOUT 50
-
-#define HTTP_PREFIX "http://"
-#define HTTP_DEFAULTPORT 80
-
-enum evhttp_connection_error {
- EVCON_HTTP_TIMEOUT,
- EVCON_HTTP_EOF,
- EVCON_HTTP_INVALID_HEADER
-};
-
-struct evbuffer;
-struct addrinfo;
-struct evhttp_request;
-
-/* A stupid connection object - maybe make this a bufferevent later */
-
-enum evhttp_connection_state {
- EVCON_DISCONNECTED, /* not currently connected not trying either */
- EVCON_CONNECTING, /* tries to currently connect */
- EVCON_CONNECTED /* connection is established */
-};
-
-struct event_base;
-
-struct evhttp_connection {
- /* we use tailq only if they were created for an http server */
- TAILQ_ENTRY(evhttp_connection) (next);
-
- int fd;
- struct event ev;
- struct event close_ev;
- struct evbuffer *input_buffer;
- struct evbuffer *output_buffer;
-
- char *bind_address; /* address to use for binding the src */
-
- char *address; /* address to connect to */
- u_short port;
-
- int flags;
-#define EVHTTP_CON_INCOMING 0x0001 /* only one request on it ever */
-#define EVHTTP_CON_OUTGOING 0x0002 /* multiple requests possible */
-#define EVHTTP_CON_CLOSEDETECT 0x0004 /* detecting if persistent close */
-
- int timeout; /* timeout in seconds for events */
- int retry_cnt; /* retry count */
- int retry_max; /* maximum number of retries */
-
- enum evhttp_connection_state state;
-
- /* for server connections, the http server they are connected with */
- struct evhttp *http_server;
-
- TAILQ_HEAD(evcon_requestq, evhttp_request) requests;
-
- void (*cb)(struct evhttp_connection *, void *);
- void *cb_arg;
-
- void (*closecb)(struct evhttp_connection *, void *);
- void *closecb_arg;
-
- struct event_base *base;
-};
-
-struct evhttp_cb {
- TAILQ_ENTRY(evhttp_cb) next;
-
- char *what;
-
- void (*cb)(struct evhttp_request *req, void *);
- void *cbarg;
-};
-
-/* both the http server as well as the rpc system need to queue connections */
-TAILQ_HEAD(evconq, evhttp_connection);
-
-struct evhttp {
- struct event bind_ev;
-
- TAILQ_HEAD(httpcbq, evhttp_cb) callbacks;
- struct evconq connections;
-
- int timeout;
-
- void (*gencb)(struct evhttp_request *req, void *);
- void *gencbarg;
-
- struct event_base *base;
-};
-
-/* resets the connection; can be reused for more requests */
-void evhttp_connection_reset(struct evhttp_connection *);
-
-/* connects if necessary */
-int evhttp_connection_connect(struct evhttp_connection *);
-
-/* notifies the current request that it failed; resets connection */
-void evhttp_connection_fail(struct evhttp_connection *,
- enum evhttp_connection_error error);
-
-void evhttp_get_request(struct evhttp *, int, struct sockaddr *, socklen_t);
-
-int evhttp_hostportfile(char *, char **, u_short *, char **);
-
-int evhttp_parse_lines(struct evhttp_request *, struct evbuffer*);
-
-void evhttp_start_read(struct evhttp_connection *);
-void evhttp_read_header(int, short, void *);
-void evhttp_make_header(struct evhttp_connection *, struct evhttp_request *);
-
-void evhttp_write_buffer(struct evhttp_connection *,
- void (*)(struct evhttp_connection *, void *), void *);
-
-/* response sending HTML the data in the buffer */
-void evhttp_response_code(struct evhttp_request *, int, const char *);
-void evhttp_send_page(struct evhttp_request *, struct evbuffer *);
-
-#endif /* _HTTP_H */
diff --git a/extra/libevent/http.c b/extra/libevent/http.c
deleted file mode 100644
index d56a34ca122..00000000000
--- a/extra/libevent/http.c
+++ /dev/null
@@ -1,2512 +0,0 @@
-/*
- * Copyright (c) 2002-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 BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#ifdef HAVE_SYS_IOCCOM_H
-#include <sys/ioccom.h>
-#endif
-
-#ifndef WIN32
-#include <sys/resource.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-#endif
-
-#include <sys/queue.h>
-
-#ifndef WIN32
-#include <netinet/in.h>
-#include <netdb.h>
-#endif
-
-#ifdef WIN32
-#include <winsock2.h>
-#endif
-
-#include <assert.h>
-#include <ctype.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#ifndef WIN32
-#include <syslog.h>
-#endif
-#include <signal.h>
-#include <time.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-
-#undef timeout_pending
-#undef timeout_initialized
-
-#include "strlcpy-internal.h"
-#include "event.h"
-#include "evhttp.h"
-#include "evutil.h"
-#include "log.h"
-#include "http-internal.h"
-
-#ifdef WIN32
-#define snprintf _snprintf
-#define strcasecmp _stricmp
-#define strncasecmp _strnicmp
-#define strdup _strdup
-#endif
-
-#ifndef HAVE_GETADDRINFO
-struct addrinfo {
- int ai_family;
- int ai_socktype;
- int ai_protocol;
- size_t ai_addrlen;
- struct sockaddr *ai_addr;
- struct addrinfo *ai_next;
-};
-static int
-fake_getaddrinfo(const char *hostname, struct addrinfo *ai)
-{
- struct hostent *he = NULL;
- struct sockaddr_in *sa;
- if (hostname) {
- he = gethostbyname(hostname);
- if (!he)
- return (-1);
- }
- ai->ai_family = he ? he->h_addrtype : AF_INET;
- ai->ai_socktype = SOCK_STREAM;
- ai->ai_protocol = 0;
- ai->ai_addrlen = sizeof(struct sockaddr_in);
- if (NULL == (ai->ai_addr = malloc(ai->ai_addrlen)))
- return (-1);
- sa = (struct sockaddr_in*)ai->ai_addr;
- memset(sa, 0, ai->ai_addrlen);
- if (he) {
- sa->sin_family = he->h_addrtype;
- memcpy(&sa->sin_addr, he->h_addr_list[0], he->h_length);
- } else {
- sa->sin_family = AF_INET;
- sa->sin_addr.s_addr = INADDR_ANY;
- }
- ai->ai_next = NULL;
- return (0);
-}
-static void
-fake_freeaddrinfo(struct addrinfo *ai)
-{
- free(ai->ai_addr);
-}
-#endif
-
-#ifndef MIN
-#define MIN(a,b) (((a)<(b))?(a):(b))
-#endif
-
-/* wrapper for setting the base from the http server */
-#define EVHTTP_BASE_SET(x, y) do { \
- if ((x)->base != NULL) event_base_set((x)->base, y); \
-} while (0)
-
-extern int debug;
-
-static int socket_connect(int fd, const char *address, unsigned short port);
-static int bind_socket_ai(struct addrinfo *);
-static int bind_socket(const char *, u_short);
-static void name_from_addr(struct sockaddr *, socklen_t, char **, char **);
-static int evhttp_associate_new_request_with_connection(
- struct evhttp_connection *evcon);
-static void evhttp_connection_start_detectclose(
- struct evhttp_connection *evcon);
-static void evhttp_connection_stop_detectclose(
- struct evhttp_connection *evcon);
-static void evhttp_request_dispatch(struct evhttp_connection* evcon);
-
-void evhttp_read(int, short, void *);
-void evhttp_write(int, short, void *);
-
-#ifndef HAVE_STRSEP
-/* strsep replacement for platforms that lack it. Only works if
- * del is one character long. */
-static char *
-strsep(char **s, const char *del)
-{
- char *d, *tok;
- assert(strlen(del) == 1);
- if (!s || !*s)
- return NULL;
- tok = *s;
- d = strstr(tok, del);
- if (d) {
- *d = '\0';
- *s = d + 1;
- } else
- *s = NULL;
- return tok;
-}
-#endif
-
-static const char *
-html_replace(char ch, char *buf)
-{
- switch (ch) {
- case '<':
- return "&lt;";
- case '>':
- return "&gt;";
- case '"':
- return "&quot;";
- case '\'':
- return "&#039;";
- case '&':
- return "&amp;";
- default:
- break;
- }
-
- /* Echo the character back */
- buf[0] = ch;
- buf[1] = '\0';
-
- return buf;
-}
-
-/*
- * Replaces <, >, ", ' and & with &lt;, &gt;, &quot;,
- * &#039; and &amp; correspondingly.
- *
- * The returned string needs to be freed by the caller.
- */
-
-char *
-evhttp_htmlescape(const char *html)
-{
- int i, new_size = 0, old_size = strlen(html);
- char *escaped_html, *p;
- char scratch_space[2];
-
- for (i = 0; i < old_size; ++i)
- new_size += strlen(html_replace(html[i], scratch_space));
-
- p = escaped_html = malloc(new_size + 1);
- if (escaped_html == NULL)
- event_err(1, "%s: malloc(%d)", __func__, new_size + 1);
- for (i = 0; i < old_size; ++i) {
- const char *replaced = html_replace(html[i], scratch_space);
- /* this is length checked */
- strcpy(p, replaced);
- p += strlen(replaced);
- }
-
- *p = '\0';
-
- return (escaped_html);
-}
-
-static const char *
-evhttp_method(enum evhttp_cmd_type type)
-{
- const char *method;
-
- switch (type) {
- case EVHTTP_REQ_GET:
- method = "GET";
- break;
- case EVHTTP_REQ_POST:
- method = "POST";
- break;
- case EVHTTP_REQ_HEAD:
- method = "HEAD";
- break;
- default:
- method = NULL;
- break;
- }
-
- return (method);
-}
-
-static void
-evhttp_add_event(struct event *ev, int timeout, int default_timeout)
-{
- if (timeout != 0) {
- struct timeval tv;
-
- evutil_timerclear(&tv);
- tv.tv_sec = timeout != -1 ? timeout : default_timeout;
- event_add(ev, &tv);
- } else {
- event_add(ev, NULL);
- }
-}
-
-void
-evhttp_write_buffer(struct evhttp_connection *evcon,
- void (*cb)(struct evhttp_connection *, void *), void *arg)
-{
- event_debug(("%s: preparing to write buffer\n", __func__));
-
- /* Set call back */
- evcon->cb = cb;
- evcon->cb_arg = arg;
-
- /* check if the event is already pending */
- if (event_pending(&evcon->ev, EV_WRITE|EV_TIMEOUT, NULL))
- event_del(&evcon->ev);
-
- event_set(&evcon->ev, evcon->fd, EV_WRITE, evhttp_write, evcon);
- EVHTTP_BASE_SET(evcon, &evcon->ev);
- evhttp_add_event(&evcon->ev, evcon->timeout, HTTP_WRITE_TIMEOUT);
-}
-
-/*
- * Create the headers need for an HTTP request
- */
-static void
-evhttp_make_header_request(struct evhttp_connection *evcon,
- struct evhttp_request *req)
-{
- char line[1024];
- const char *method;
-
- evhttp_remove_header(req->output_headers, "Accept-Encoding");
- evhttp_remove_header(req->output_headers, "Proxy-Connection");
-
- /* Generate request line */
- method = evhttp_method(req->type);
- snprintf(line, sizeof(line), "%s %s HTTP/%d.%d\r\n",
- method, req->uri, req->major, req->minor);
- evbuffer_add(evcon->output_buffer, line, strlen(line));
-
- /* Add the content length on a post request if missing */
- if (req->type == EVHTTP_REQ_POST &&
- evhttp_find_header(req->output_headers, "Content-Length") == NULL){
- char size[12];
- snprintf(size, sizeof(size), "%ld",
- (long)EVBUFFER_LENGTH(req->output_buffer));
- evhttp_add_header(req->output_headers, "Content-Length", size);
- }
-}
-
-static int
-evhttp_is_connection_close(int flags, struct evkeyvalq* headers)
-{
- if (flags & EVHTTP_PROXY_REQUEST) {
- /* proxy connection */
- const char *connection = evhttp_find_header(headers, "Proxy-Connection");
- return (connection == NULL || strcasecmp(connection, "keep-alive") != 0);
- } else {
- const char *connection = evhttp_find_header(headers, "Connection");
- return (connection != NULL && strcasecmp(connection, "close") == 0);
- }
-}
-
-static int
-evhttp_is_connection_keepalive(struct evkeyvalq* headers)
-{
- const char *connection = evhttp_find_header(headers, "Connection");
- return (connection != NULL
- && strncasecmp(connection, "keep-alive", 10) == 0);
-}
-
-static void
-evhttp_maybe_add_date_header(struct evkeyvalq *headers)
-{
- if (evhttp_find_header(headers, "Date") == NULL) {
- char date[50];
-#ifndef WIN32
- struct tm cur;
-#endif
- struct tm *cur_p;
- time_t t = time(NULL);
-#ifdef WIN32
- cur_p = gmtime(&t);
-#else
- gmtime_r(&t, &cur);
- cur_p = &cur;
-#endif
- if (strftime(date, sizeof(date),
- "%a, %d %b %Y %H:%M:%S GMT", cur_p) != 0) {
- evhttp_add_header(headers, "Date", date);
- }
- }
-}
-
-static void
-evhttp_maybe_add_content_length_header(struct evkeyvalq *headers,
- long content_length)
-{
- if (evhttp_find_header(headers, "Transfer-Encoding") == NULL &&
- evhttp_find_header(headers, "Content-Length") == NULL) {
- char len[12];
- snprintf(len, sizeof(len), "%ld", content_length);
- evhttp_add_header(headers, "Content-Length", len);
- }
-}
-
-/*
- * Create the headers needed for an HTTP reply
- */
-
-static void
-evhttp_make_header_response(struct evhttp_connection *evcon,
- struct evhttp_request *req)
-{
- char line[1024];
- snprintf(line, sizeof(line), "HTTP/%d.%d %d %s\r\n",
- req->major, req->minor, req->response_code,
- req->response_code_line);
- evbuffer_add(evcon->output_buffer, line, strlen(line));
-
- if (req->major == 1 && req->minor == 1)
- evhttp_maybe_add_date_header(req->output_headers);
-
- if (req->major == 1 &&
- (req->minor == 1 ||
- evhttp_is_connection_keepalive(req->input_headers))) {
- /*
- * we need to add the content length if the user did
- * not give it, this is required for persistent
- * connections to work.
- */
- evhttp_maybe_add_content_length_header(req->output_headers,
- (long)EVBUFFER_LENGTH(req->output_buffer));
- }
-
- /* Potentially add headers for unidentified content. */
- if (EVBUFFER_LENGTH(req->output_buffer)) {
- if (evhttp_find_header(req->output_headers,
- "Content-Type") == NULL) {
- evhttp_add_header(req->output_headers,
- "Content-Type", "text/html; charset=ISO-8859-1");
- }
- }
-
- /* if the request asked for a close, we send a close, too */
- if (evhttp_is_connection_close(req->flags, req->input_headers)) {
- evhttp_remove_header(req->output_headers, "Connection");
- if (!(req->flags & EVHTTP_PROXY_REQUEST))
- evhttp_add_header(req->output_headers, "Connection", "close");
- evhttp_remove_header(req->output_headers, "Proxy-Connection");
- }
-}
-
-void
-evhttp_make_header(struct evhttp_connection *evcon, struct evhttp_request *req)
-{
- char line[1024];
- struct evkeyval *header;
-
- /*
- * Depending if this is a HTTP request or response, we might need to
- * add some new headers or remove existing headers.
- */
- if (req->kind == EVHTTP_REQUEST) {
- evhttp_make_header_request(evcon, req);
- } else {
- evhttp_make_header_response(evcon, req);
- }
-
- TAILQ_FOREACH(header, req->output_headers, next) {
- snprintf(line, sizeof(line), "%s: %s\r\n",
- header->key, header->value);
- evbuffer_add(evcon->output_buffer, line, strlen(line));
- }
- evbuffer_add(evcon->output_buffer, "\r\n", 2);
-
- if (EVBUFFER_LENGTH(req->output_buffer) > 0) {
- /*
- * For a request, we add the POST data, for a reply, this
- * is the regular data.
- */
- evbuffer_add_buffer(evcon->output_buffer, req->output_buffer);
- }
-}
-
-/* Separated host, port and file from URI */
-
-int
-evhttp_hostportfile(char *url, char **phost, u_short *pport, char **pfile)
-{
- /* XXX not threadsafe. */
- static char host[1024];
- static char file[1024];
- char *p;
- const char *p2;
- int len;
- u_short port;
-
- len = strlen(HTTP_PREFIX);
- if (strncasecmp(url, HTTP_PREFIX, len))
- return (-1);
-
- url += len;
-
- /* We might overrun */
- if (strlcpy(host, url, sizeof (host)) >= sizeof(host))
- return (-1);
-
- p = strchr(host, '/');
- if (p != NULL) {
- *p = '\0';
- p2 = p + 1;
- } else
- p2 = NULL;
-
- if (pfile != NULL) {
- /* Generate request file */
- if (p2 == NULL)
- p2 = "";
- snprintf(file, sizeof(file), "/%s", p2);
- }
-
- p = strchr(host, ':');
- if (p != NULL) {
- *p = '\0';
- port = atoi(p + 1);
-
- if (port == 0)
- return (-1);
- } else
- port = HTTP_DEFAULTPORT;
-
- if (phost != NULL)
- *phost = host;
- if (pport != NULL)
- *pport = port;
- if (pfile != NULL)
- *pfile = file;
-
- return (0);
-}
-
-static int
-evhttp_connection_incoming_fail(struct evhttp_request *req,
- enum evhttp_connection_error error)
-{
- switch (error) {
- case EVCON_HTTP_TIMEOUT:
- case EVCON_HTTP_EOF:
- /*
- * these are cases in which we probably should just
- * close the connection and not send a reply. this
- * case may happen when a browser keeps a persistent
- * connection open and we timeout on the read.
- */
- return (-1);
- case EVCON_HTTP_INVALID_HEADER:
- default: /* xxx: probably should just error on default */
- /* the callback looks at the uri to determine errors */
- if (req->uri) {
- free(req->uri);
- req->uri = NULL;
- }
-
- /*
- * the callback needs to send a reply, once the reply has
- * been send, the connection should get freed.
- */
- (*req->cb)(req, req->cb_arg);
- }
-
- return (0);
-}
-
-void
-evhttp_connection_fail(struct evhttp_connection *evcon,
- enum evhttp_connection_error error)
-{
- struct evhttp_request* req = TAILQ_FIRST(&evcon->requests);
- void (*cb)(struct evhttp_request *, void *);
- void *cb_arg;
- assert(req != NULL);
-
- if (evcon->flags & EVHTTP_CON_INCOMING) {
- /*
- * for incoming requests, there are two different
- * failure cases. it's either a network level error
- * or an http layer error. for problems on the network
- * layer like timeouts we just drop the connections.
- * For HTTP problems, we might have to send back a
- * reply before the connection can be freed.
- */
- if (evhttp_connection_incoming_fail(req, error) == -1)
- evhttp_connection_free(evcon);
- return;
- }
-
- /* save the callback for later; the cb might free our object */
- cb = req->cb;
- cb_arg = req->cb_arg;
-
- TAILQ_REMOVE(&evcon->requests, req, next);
- evhttp_request_free(req);
-
- /* xxx: maybe we should fail all requests??? */
-
- /* reset the connection */
- evhttp_connection_reset(evcon);
-
- /* We are trying the next request that was queued on us */
- if (TAILQ_FIRST(&evcon->requests) != NULL)
- evhttp_connection_connect(evcon);
-
- /* inform the user */
- if (cb != NULL)
- (*cb)(NULL, cb_arg);
-}
-
-void
-evhttp_write(int fd, short what, void *arg)
-{
- struct evhttp_connection *evcon = arg;
- int n;
-
- if (what == EV_TIMEOUT) {
- evhttp_connection_fail(evcon, EVCON_HTTP_TIMEOUT);
- return;
- }
-
- n = evbuffer_write(evcon->output_buffer, fd);
- if (n == -1) {
- event_debug(("%s: evbuffer_write", __func__));
- evhttp_connection_fail(evcon, EVCON_HTTP_EOF);
- return;
- }
-
- if (n == 0) {
- event_debug(("%s: write nothing", __func__));
- evhttp_connection_fail(evcon, EVCON_HTTP_EOF);
- return;
- }
-
- if (EVBUFFER_LENGTH(evcon->output_buffer) != 0) {
- evhttp_add_event(&evcon->ev,
- evcon->timeout, HTTP_WRITE_TIMEOUT);
- return;
- }
-
- /* Activate our call back */
- if (evcon->cb != NULL)
- (*evcon->cb)(evcon, evcon->cb_arg);
-}
-
-static void
-evhttp_connection_done(struct evhttp_connection *evcon)
-{
- struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
- int con_outgoing = evcon->flags & EVHTTP_CON_OUTGOING;
-
- /*
- * if this is an incoming connection, we need to leave the request
- * on the connection, so that we can reply to it.
- */
- if (con_outgoing) {
- int need_close;
- TAILQ_REMOVE(&evcon->requests, req, next);
- req->evcon = NULL;
-
- need_close =
- evhttp_is_connection_close(req->flags, req->input_headers) ||
- evhttp_is_connection_close(req->flags, req->output_headers);
-
- /* check if we got asked to close the connection */
- if (need_close)
- evhttp_connection_reset(evcon);
-
- if (TAILQ_FIRST(&evcon->requests) != NULL) {
- /*
- * We have more requests; reset the connection
- * and deal with the next request. xxx: no
- * persistent connection right now
- */
- if (evcon->state != EVCON_CONNECTED)
- evhttp_connection_connect(evcon);
- else
- evhttp_request_dispatch(evcon);
- } else if (!need_close) {
- /*
- * The connection is going to be persistent, but we
- * need to detect if the other side closes it.
- */
- evhttp_connection_start_detectclose(evcon);
- }
- }
-
- /* notify the user of the request */
- (*req->cb)(req, req->cb_arg);
-
- /* if this was an outgoing request, we own and it's done. so free it */
- if (con_outgoing) {
- evhttp_request_free(req);
- }
-}
-
-/*
- * Handles reading from a chunked request.
- * return 1: all data has been read
- * return 0: more data is expected
- * return -1: data is corrupted
- */
-
-static int
-evhttp_handle_chunked_read(struct evhttp_request *req, struct evbuffer *buf)
-{
- int len;
-
- while ((len = EVBUFFER_LENGTH(buf)) > 0) {
- if (req->ntoread < 0) {
- /* Read chunk size */
- char *p = evbuffer_readline(buf);
- char *endp;
- int error;
- if (p == NULL)
- break;
- /* the last chunk is on a new line? */
- if (strlen(p) == 0) {
- free(p);
- continue;
- }
- req->ntoread = evutil_strtoll(p, &endp, 16);
- error = *p == '\0' || (*endp != '\0' && *endp != ' ');
- free(p);
- if (error) {
- /* could not get chunk size */
- return (-1);
- }
- if (req->ntoread == 0) {
- /* Last chunk */
- return (1);
- }
- continue;
- }
-
- /* don't have enough to complete a chunk; wait for more */
- if (len < req->ntoread)
- return (0);
-
- /* Completed chunk */
- evbuffer_add(req->input_buffer,
- EVBUFFER_DATA(buf), req->ntoread);
- evbuffer_drain(buf, req->ntoread);
- req->ntoread = -1;
- if (req->chunk_cb != NULL) {
- (*req->chunk_cb)(req, req->cb_arg);
- evbuffer_drain(req->input_buffer,
- EVBUFFER_LENGTH(req->input_buffer));
- }
- }
-
- return (0);
-}
-
-static void
-evhttp_read_body(struct evhttp_connection *evcon, struct evhttp_request *req)
-{
- struct evbuffer *buf = evcon->input_buffer;
-
- if (req->chunked) {
- int res = evhttp_handle_chunked_read(req, buf);
- if (res == 1) {
- /* finished last chunk */
- evhttp_connection_done(evcon);
- return;
- } else if (res == -1) {
- /* corrupted data */
- evhttp_connection_fail(evcon,
- EVCON_HTTP_INVALID_HEADER);
- return;
- }
- } else if (req->ntoread < 0) {
- /* Read until connection close. */
- evbuffer_add_buffer(req->input_buffer, buf);
- } else if (EVBUFFER_LENGTH(buf) >= req->ntoread) {
- /* Completed content length */
- evbuffer_add(req->input_buffer, EVBUFFER_DATA(buf),
- req->ntoread);
- evbuffer_drain(buf, req->ntoread);
- req->ntoread = 0;
- evhttp_connection_done(evcon);
- return;
- }
- /* Read more! */
- event_set(&evcon->ev, evcon->fd, EV_READ, evhttp_read, evcon);
- EVHTTP_BASE_SET(evcon, &evcon->ev);
- evhttp_add_event(&evcon->ev, evcon->timeout, HTTP_READ_TIMEOUT);
-}
-
-/*
- * Reads data into a buffer structure until no more data
- * can be read on the file descriptor or we have read all
- * the data that we wanted to read.
- * Execute callback when done.
- */
-
-void
-evhttp_read(int fd, short what, void *arg)
-{
- struct evhttp_connection *evcon = arg;
- struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
- struct evbuffer *buf = evcon->input_buffer;
- int n, len;
-
- if (what == EV_TIMEOUT) {
- evhttp_connection_fail(evcon, EVCON_HTTP_TIMEOUT);
- return;
- }
- n = evbuffer_read(buf, fd, -1);
- len = EVBUFFER_LENGTH(buf);
- event_debug(("%s: got %d on %d\n", __func__, n, fd));
-
- if (n == -1) {
- event_debug(("%s: evbuffer_read", __func__));
- evhttp_connection_fail(evcon, EVCON_HTTP_EOF);
- return;
- } else if (n == 0) {
- /* Connection closed */
- evhttp_connection_done(evcon);
- return;
- }
- evhttp_read_body(evcon, req);
-}
-
-static void
-evhttp_write_connectioncb(struct evhttp_connection *evcon, void *arg)
-{
- /* This is after writing the request to the server */
- struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
- assert(req != NULL);
-
- /* We are done writing our header and are now expecting the response */
- req->kind = EVHTTP_RESPONSE;
-
- evhttp_start_read(evcon);
-}
-
-/*
- * Clean up a connection object
- */
-
-void
-evhttp_connection_free(struct evhttp_connection *evcon)
-{
- struct evhttp_request *req;
-
- /* notify interested parties that this connection is going down */
- if (evcon->fd != -1) {
- if (evcon->state == EVCON_CONNECTED && evcon->closecb != NULL)
- (*evcon->closecb)(evcon, evcon->closecb_arg);
- }
-
- /* remove all requests that might be queued on this connection */
- while ((req = TAILQ_FIRST(&evcon->requests)) != NULL) {
- TAILQ_REMOVE(&evcon->requests, req, next);
- evhttp_request_free(req);
- }
-
- if (evcon->http_server != NULL) {
- struct evhttp *http = evcon->http_server;
- TAILQ_REMOVE(&http->connections, evcon, next);
- }
-
- if (event_initialized(&evcon->close_ev))
- event_del(&evcon->close_ev);
-
- if (event_initialized(&evcon->ev))
- event_del(&evcon->ev);
-
- if (evcon->fd != -1)
- EVUTIL_CLOSESOCKET(evcon->fd);
-
- if (evcon->bind_address != NULL)
- free(evcon->bind_address);
-
- if (evcon->address != NULL)
- free(evcon->address);
-
- if (evcon->input_buffer != NULL)
- evbuffer_free(evcon->input_buffer);
-
- if (evcon->output_buffer != NULL)
- evbuffer_free(evcon->output_buffer);
-
- free(evcon);
-}
-
-void
-evhttp_connection_set_local_address(struct evhttp_connection *evcon,
- const char *address)
-{
- assert(evcon->state == EVCON_DISCONNECTED);
- if (evcon->bind_address)
- free(evcon->bind_address);
- if ((evcon->bind_address = strdup(address)) == NULL)
- event_err(1, "%s: strdup", __func__);
-}
-
-
-static void
-evhttp_request_dispatch(struct evhttp_connection* evcon)
-{
- struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
-
- /* this should not usually happy but it's possible */
- if (req == NULL)
- return;
-
- /* delete possible close detection events */
- evhttp_connection_stop_detectclose(evcon);
-
- /* we assume that the connection is connected already */
- assert(evcon->state == EVCON_CONNECTED);
-
- /* Create the header from the store arguments */
- evhttp_make_header(evcon, req);
-
- evhttp_write_buffer(evcon, evhttp_write_connectioncb, NULL);
-}
-
-/* Reset our connection state */
-void
-evhttp_connection_reset(struct evhttp_connection *evcon)
-{
- if (event_initialized(&evcon->ev))
- event_del(&evcon->ev);
-
- if (evcon->fd != -1) {
- /* inform interested parties about connection close */
- if (evcon->state == EVCON_CONNECTED && evcon->closecb != NULL)
- (*evcon->closecb)(evcon, evcon->closecb_arg);
-
- EVUTIL_CLOSESOCKET(evcon->fd);
- evcon->fd = -1;
- }
- evcon->state = EVCON_DISCONNECTED;
-
- /* remove unneeded flags */
- evcon->flags &= ~EVHTTP_CON_CLOSEDETECT;
-}
-
-static void
-evhttp_detect_close_cb(int fd, short what, void *arg)
-{
- struct evhttp_connection *evcon = arg;
- evhttp_connection_reset(evcon);
-}
-
-static void
-evhttp_connection_start_detectclose(struct evhttp_connection *evcon)
-{
- evcon->flags |= EVHTTP_CON_CLOSEDETECT;
-
- if (event_initialized(&evcon->close_ev))
- event_del(&evcon->close_ev);
- event_set(&evcon->close_ev, evcon->fd, EV_READ,
- evhttp_detect_close_cb, evcon);
- EVHTTP_BASE_SET(evcon, &evcon->close_ev);
- event_add(&evcon->close_ev, NULL);
-}
-
-static void
-evhttp_connection_stop_detectclose(struct evhttp_connection *evcon)
-{
- evcon->flags &= ~EVHTTP_CON_CLOSEDETECT;
- event_del(&evcon->close_ev);
-}
-
-static void
-evhttp_connection_retry(int fd, short what, void *arg)
-{
- struct evhttp_connection *evcon = arg;
-
- evcon->state = EVCON_DISCONNECTED;
- evhttp_connection_connect(evcon);
-}
-
-/*
- * Call back for asynchronous connection attempt.
- */
-
-static void
-evhttp_connectioncb(int fd, short what, void *arg)
-{
- struct evhttp_connection *evcon = arg;
- int error;
- socklen_t errsz = sizeof(error);
-
- if (what == EV_TIMEOUT) {
- event_debug(("%s: connection timeout for \"%s:%d\" on %d",
- __func__, evcon->address, evcon->port, evcon->fd));
- goto cleanup;
- }
-
- /* Check if the connection completed */
- if (getsockopt(evcon->fd, SOL_SOCKET, SO_ERROR, (void*)&error,
- &errsz) == -1) {
- event_debug(("%s: getsockopt for \"%s:%d\" on %d",
- __func__, evcon->address, evcon->port, evcon->fd));
- goto cleanup;
- }
-
- if (error) {
- event_debug(("%s: connect failed for \"%s:%d\" on %d: %s",
- __func__, evcon->address, evcon->port, evcon->fd,
- strerror(error)));
- goto cleanup;
- }
-
- /* We are connected to the server now */
- event_debug(("%s: connected to \"%s:%d\" on %d\n",
- __func__, evcon->address, evcon->port, evcon->fd));
-
- /* Reset the retry count as we were successful in connecting */
- evcon->retry_cnt = 0;
- evcon->state = EVCON_CONNECTED;
-
- /* try to start requests that have queued up on this connection */
- evhttp_request_dispatch(evcon);
- return;
-
- cleanup:
- if (evcon->retry_max < 0 || evcon->retry_cnt < evcon->retry_max) {
- evtimer_set(&evcon->ev, evhttp_connection_retry, evcon);
- EVHTTP_BASE_SET(evcon, &evcon->ev);
- evhttp_add_event(&evcon->ev, MIN(3600, 2 << evcon->retry_cnt),
- HTTP_CONNECT_TIMEOUT);
- evcon->retry_cnt++;
- return;
- }
- evhttp_connection_reset(evcon);
-
- /* for now, we just signal all requests by executing their callbacks */
- while (TAILQ_FIRST(&evcon->requests) != NULL) {
- struct evhttp_request *request = TAILQ_FIRST(&evcon->requests);
- TAILQ_REMOVE(&evcon->requests, request, next);
- request->evcon = NULL;
-
- /* we might want to set an error here */
- request->cb(request, request->cb_arg);
- evhttp_request_free(request);
- }
-}
-
-/*
- * Check if we got a valid response code.
- */
-
-static int
-evhttp_valid_response_code(int code)
-{
- if (code == 0)
- return (0);
-
- return (1);
-}
-
-/* Parses the status line of a web server */
-
-static int
-evhttp_parse_response_line(struct evhttp_request *req, char *line)
-{
- char *protocol;
- char *number;
- char *readable;
-
- protocol = strsep(&line, " ");
- if (line == NULL)
- return (-1);
- number = strsep(&line, " ");
- if (line == NULL)
- return (-1);
- readable = line;
-
- if (strcmp(protocol, "HTTP/1.0") == 0) {
- req->major = 1;
- req->minor = 0;
- } else if (strcmp(protocol, "HTTP/1.1") == 0) {
- req->major = 1;
- req->minor = 1;
- } else {
- event_debug(("%s: bad protocol \"%s\"",
- __func__, protocol));
- return (-1);
- }
-
- req->response_code = atoi(number);
- if (!evhttp_valid_response_code(req->response_code)) {
- event_debug(("%s: bad response code \"%s\"",
- __func__, number));
- return (-1);
- }
-
- if ((req->response_code_line = strdup(readable)) == NULL)
- event_err(1, "%s: strdup", __func__);
-
- return (0);
-}
-
-/* Parse the first line of a HTTP request */
-
-static int
-evhttp_parse_request_line(struct evhttp_request *req, char *line)
-{
- char *method;
- char *uri;
- char *version;
-
- /* Parse the request line */
- method = strsep(&line, " ");
- if (line == NULL)
- return (-1);
- uri = strsep(&line, " ");
- if (line == NULL)
- return (-1);
- version = strsep(&line, " ");
- if (line != NULL)
- return (-1);
-
- /* 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 {
- event_debug(("%s: bad method %s on request %p from %s",
- __func__, method, req, req->remote_host));
- return (-1);
- }
-
- if (strcmp(version, "HTTP/1.0") == 0) {
- req->major = 1;
- req->minor = 0;
- } else if (strcmp(version, "HTTP/1.1") == 0) {
- req->major = 1;
- req->minor = 1;
- } else {
- event_debug(("%s: bad version %s on request %p from %s",
- __func__, version, req, req->remote_host));
- return (-1);
- }
-
- if ((req->uri = strdup(uri)) == NULL) {
- event_debug(("%s: evhttp_decode_uri", __func__));
- return (-1);
- }
-
- /* determine if it's a proxy request */
- if (strlen(req->uri) > 0 && req->uri[0] != '/')
- req->flags |= EVHTTP_PROXY_REQUEST;
-
- return (0);
-}
-
-const char *
-evhttp_find_header(const struct evkeyvalq *headers, const char *key)
-{
- struct evkeyval *header;
-
- TAILQ_FOREACH(header, headers, next) {
- if (strcasecmp(header->key, key) == 0)
- return (header->value);
- }
-
- return (NULL);
-}
-
-void
-evhttp_clear_headers(struct evkeyvalq *headers)
-{
- struct evkeyval *header;
-
- for (header = TAILQ_FIRST(headers);
- header != NULL;
- header = TAILQ_FIRST(headers)) {
- TAILQ_REMOVE(headers, header, next);
- free(header->key);
- free(header->value);
- free(header);
- }
-}
-
-/*
- * Returns 0, if the header was successfully removed.
- * Returns -1, if the header could not be found.
- */
-
-int
-evhttp_remove_header(struct evkeyvalq *headers, const char *key)
-{
- struct evkeyval *header;
-
- TAILQ_FOREACH(header, headers, next) {
- if (strcasecmp(header->key, key) == 0)
- break;
- }
-
- if (header == NULL)
- return (-1);
-
- /* Free and remove the header that we found */
- TAILQ_REMOVE(headers, header, next);
- free(header->key);
- free(header->value);
- free(header);
-
- return (0);
-}
-
-int
-evhttp_add_header(struct evkeyvalq *headers,
- const char *key, const char *value)
-{
- struct evkeyval *header = NULL;
-
- event_debug(("%s: key: %s val: %s\n", __func__, key, value));
-
- if (strchr(value, '\r') != NULL || strchr(value, '\n') != NULL ||
- strchr(key, '\r') != NULL || strchr(key, '\n') != NULL) {
- /* drop illegal headers */
- event_debug(("%s: dropping illegal header\n", __func__));
- return (-1);
- }
-
- header = calloc(1, sizeof(struct evkeyval));
- if (header == NULL) {
- event_warn("%s: calloc", __func__);
- return (-1);
- }
- if ((header->key = strdup(key)) == NULL) {
- free(header);
- event_warn("%s: strdup", __func__);
- return (-1);
- }
- if ((header->value = strdup(value)) == NULL) {
- free(header->key);
- free(header);
- event_warn("%s: strdup", __func__);
- return (-1);
- }
-
- TAILQ_INSERT_TAIL(headers, header, next);
-
- return (0);
-}
-
-/*
- * Parses header lines from a request or a response into the specified
- * request object given an event buffer.
- *
- * Returns
- * -1 on error
- * 0 when we need to read more headers
- * 1 when all headers have been read.
- */
-
-int
-evhttp_parse_lines(struct evhttp_request *req, struct evbuffer* buffer)
-{
- char *line;
- int done = 0;
-
- struct evkeyvalq* headers = req->input_headers;
- while ((line = evbuffer_readline(buffer)) != NULL) {
- char *skey, *svalue;
-
- if (*line == '\0') { /* Last header - Done */
- done = 1;
- free (line);
- break;
- }
-
- /* Processing of header lines */
- if (req->got_firstline == 0) {
- switch (req->kind) {
- case EVHTTP_REQUEST:
- if (evhttp_parse_request_line(req, line) == -1)
- goto error;
- break;
- case EVHTTP_RESPONSE:
- if (evhttp_parse_response_line(req, line) == -1)
- goto error;
- break;
- default:
- goto error;
- }
- req->got_firstline = 1;
- } else {
- /* Regular header */
- svalue = line;
- skey = strsep(&svalue, ":");
- if (svalue == NULL)
- goto error;
-
- svalue += strspn(svalue, " ");
-
- if (evhttp_add_header(headers, skey, svalue) == -1)
- goto error;
- }
-
- free (line);
- }
-
- return (done);
-
- error:
- free (line);
- return (-1);
-}
-
-static int
-evhttp_get_body_length(struct evhttp_request *req)
-{
- struct evkeyvalq *headers = req->input_headers;
- const char *content_length;
- const char *connection;
-
- content_length = evhttp_find_header(headers, "Content-Length");
- connection = evhttp_find_header(headers, "Connection");
-
- if (content_length == NULL && connection == NULL)
- req->ntoread = -1;
- else if (content_length == NULL &&
- strcasecmp(connection, "Close") != 0) {
- /* Bad combination, we don't know when it will end */
- event_warnx("%s: we got no content length, but the "
- "server wants to keep the connection open: %s.",
- __func__, connection);
- return (-1);
- } else if (content_length == NULL) {
- req->ntoread = -1;
- } else {
- char *endp;
- req->ntoread = evutil_strtoll(content_length, &endp, 10);
- if (*content_length == '\0' || *endp != '\0') {
- event_warnx("%s: illegal content length: %s",
- __func__, content_length);
- return (-1);
- }
- }
-
- event_debug(("%s: bytes to read: %d (in buffer %d)\n",
- __func__, req->ntoread,
- EVBUFFER_LENGTH(req->evcon->input_buffer)));
-
- return (0);
-}
-
-static void
-evhttp_get_body(struct evhttp_connection *evcon, struct evhttp_request *req)
-{
- const char *xfer_enc;
-
- /* If this is a request without a body, then we are done */
- if (req->kind == EVHTTP_REQUEST && req->type != EVHTTP_REQ_POST) {
- evhttp_connection_done(evcon);
- return;
- }
- xfer_enc = evhttp_find_header(req->input_headers, "Transfer-Encoding");
- if (xfer_enc != NULL && strcasecmp(xfer_enc, "chunked") == 0) {
- req->chunked = 1;
- req->ntoread = -1;
- } else {
- if (evhttp_get_body_length(req) == -1) {
- evhttp_connection_fail(evcon,
- EVCON_HTTP_INVALID_HEADER);
- return;
- }
- }
- evhttp_read_body(evcon, req);
-}
-
-void
-evhttp_read_header(int fd, short what, void *arg)
-{
- struct evhttp_connection *evcon = arg;
- struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
- int n, res;
-
- if (what == EV_TIMEOUT) {
- event_debug(("%s: timeout on %d\n", __func__, fd));
- evhttp_connection_fail(evcon, EVCON_HTTP_TIMEOUT);
- return;
- }
-
- n = evbuffer_read(evcon->input_buffer, fd, -1);
- if (n == 0) {
- event_debug(("%s: no more data on %d", __func__, fd));
- evhttp_connection_fail(evcon, EVCON_HTTP_EOF);
- return;
- }
- if (n == -1) {
- event_debug(("%s: bad read on %d", __func__, fd));
- evhttp_connection_fail(evcon, EVCON_HTTP_EOF);
- return;
- }
-
- res = evhttp_parse_lines(req, evcon->input_buffer);
- if (res == -1) {
- /* Error while reading, terminate */
- event_debug(("%s: bad header lines on %d\n", __func__, fd));
- evhttp_connection_fail(evcon, EVCON_HTTP_INVALID_HEADER);
- return;
- } else if (res == 0) {
- /* Need more header lines */
- evhttp_add_event(&evcon->ev,
- evcon->timeout, HTTP_READ_TIMEOUT);
- return;
- }
-
- /* Done reading headers, do the real work */
- switch (req->kind) {
- case EVHTTP_REQUEST:
- event_debug(("%s: checking for post data on %d\n",
- __func__, fd));
- evhttp_get_body(evcon, req);
- break;
-
- case EVHTTP_RESPONSE:
- if (req->response_code == HTTP_NOCONTENT ||
- req->response_code == HTTP_NOTMODIFIED ||
- (req->response_code >= 100 && req->response_code < 200)) {
- event_debug(("%s: skipping body for code %d\n",
- __func__, req->response_code));
- evhttp_connection_done(evcon);
- } else {
- event_debug(("%s: start of read body for %s on %d\n",
- __func__, req->remote_host, fd));
- evhttp_get_body(evcon, req);
- }
- break;
-
- default:
- event_warnx("%s: bad header on %d", __func__, fd);
- evhttp_connection_fail(evcon, EVCON_HTTP_INVALID_HEADER);
- break;
- }
-}
-
-/*
- * Creates a TCP connection to the specified port and executes a callback
- * when finished. Failure or sucess is indicate by the passed connection
- * object.
- *
- * Although this interface accepts a hostname, it is intended to take
- * only numeric hostnames so that non-blocking DNS resolution can
- * happen elsewhere.
- */
-
-struct evhttp_connection *
-evhttp_connection_new(const char *address, unsigned short port)
-{
- struct evhttp_connection *evcon = NULL;
-
- event_debug(("Attempting connection to %s:%d\n", address, port));
-
- if ((evcon = calloc(1, sizeof(struct evhttp_connection))) == NULL) {
- event_warn("%s: calloc failed", __func__);
- goto error;
- }
-
- evcon->fd = -1;
- evcon->port = port;
-
- evcon->timeout = -1;
- evcon->retry_cnt = evcon->retry_max = 0;
-
- if ((evcon->address = strdup(address)) == NULL) {
- event_warn("%s: strdup failed", __func__);
- goto error;
- }
-
- if ((evcon->input_buffer = evbuffer_new()) == NULL) {
- event_warn("%s: evbuffer_new failed", __func__);
- goto error;
- }
-
- if ((evcon->output_buffer = evbuffer_new()) == NULL) {
- event_warn("%s: evbuffer_new failed", __func__);
- goto error;
- }
-
- evcon->state = EVCON_DISCONNECTED;
- TAILQ_INIT(&evcon->requests);
-
- return (evcon);
-
- error:
- if (evcon != NULL)
- evhttp_connection_free(evcon);
- return (NULL);
-}
-
-void evhttp_connection_set_base(struct evhttp_connection *evcon,
- struct event_base *base)
-{
- assert(evcon->base == NULL);
- assert(evcon->state == EVCON_DISCONNECTED);
- evcon->base = base;
-}
-
-void
-evhttp_connection_set_timeout(struct evhttp_connection *evcon,
- int timeout_in_secs)
-{
- evcon->timeout = timeout_in_secs;
-}
-
-void
-evhttp_connection_set_retries(struct evhttp_connection *evcon,
- int retry_max)
-{
- evcon->retry_max = retry_max;
-}
-
-void
-evhttp_connection_set_closecb(struct evhttp_connection *evcon,
- void (*cb)(struct evhttp_connection *, void *), void *cbarg)
-{
- evcon->closecb = cb;
- evcon->closecb_arg = cbarg;
-}
-
-void
-evhttp_connection_get_peer(struct evhttp_connection *evcon,
- char **address, u_short *port)
-{
- *address = evcon->address;
- *port = evcon->port;
-}
-
-int
-evhttp_connection_connect(struct evhttp_connection *evcon)
-{
- if (evcon->state == EVCON_CONNECTING)
- return (0);
-
- evhttp_connection_reset(evcon);
-
- assert(!(evcon->flags & EVHTTP_CON_INCOMING));
- evcon->flags |= EVHTTP_CON_OUTGOING;
-
- evcon->fd = bind_socket(evcon->bind_address, 0);
- if (evcon->fd == -1) {
- event_debug(("%s: failed to bind to \"%s\"",
- __func__, evcon->bind_address));
- return (-1);
- }
-
- if (socket_connect(evcon->fd, evcon->address, evcon->port) == -1) {
- EVUTIL_CLOSESOCKET(evcon->fd); evcon->fd = -1;
- return (-1);
- }
-
- /* Set up a callback for successful connection setup */
- event_set(&evcon->ev, evcon->fd, EV_WRITE, evhttp_connectioncb, evcon);
- EVHTTP_BASE_SET(evcon, &evcon->ev);
- evhttp_add_event(&evcon->ev, evcon->timeout, HTTP_CONNECT_TIMEOUT);
-
- evcon->state = EVCON_CONNECTING;
-
- return (0);
-}
-
-/*
- * Starts an HTTP request on the provided evhttp_connection object.
- * If the connection object is not connected to the web server already,
- * this will start the connection.
- */
-
-int
-evhttp_make_request(struct evhttp_connection *evcon,
- struct evhttp_request *req,
- enum evhttp_cmd_type type, const char *uri)
-{
- /* We are making a request */
- req->kind = EVHTTP_REQUEST;
- req->type = type;
- if (req->uri != NULL)
- free(req->uri);
- if ((req->uri = strdup(uri)) == NULL)
- event_err(1, "%s: strdup", __func__);
-
- /* Set the protocol version if it is not supplied */
- if (!req->major && !req->minor) {
- req->major = 1;
- req->minor = 1;
- }
-
- assert(req->evcon == NULL);
- req->evcon = evcon;
- 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 (evcon->state != EVCON_CONNECTED)
- return (evhttp_connection_connect(evcon));
-
- /*
- * If it's connected already and we are the first in the queue,
- * then we can dispatch this request immediately. Otherwise, it
- * will be dispatched once the pending requests are completed.
- */
- if (TAILQ_FIRST(&evcon->requests) == req)
- evhttp_request_dispatch(evcon);
-
- return (0);
-}
-
-/*
- * Reads data from file descriptor into request structure
- * Request structure needs to be set up correctly.
- */
-
-void
-evhttp_start_read(struct evhttp_connection *evcon)
-{
- /* Set up an event to read the headers */
- if (event_initialized(&evcon->ev))
- event_del(&evcon->ev);
- event_set(&evcon->ev, evcon->fd, EV_READ, evhttp_read_header, evcon);
- EVHTTP_BASE_SET(evcon, &evcon->ev);
-
- evhttp_add_event(&evcon->ev, evcon->timeout, HTTP_READ_TIMEOUT);
-}
-
-static void
-evhttp_send_done(struct evhttp_connection *evcon, void *arg)
-{
- int need_close;
- struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
- TAILQ_REMOVE(&evcon->requests, req, next);
-
- /* delete possible close detection events */
- evhttp_connection_stop_detectclose(evcon);
-
- need_close =
- (req->minor == 0 &&
- !evhttp_is_connection_keepalive(req->input_headers))||
- evhttp_is_connection_close(req->flags, req->input_headers) ||
- evhttp_is_connection_close(req->flags, req->output_headers);
-
- assert(req->flags & EVHTTP_REQ_OWN_CONNECTION);
- evhttp_request_free(req);
-
- if (need_close) {
- evhttp_connection_free(evcon);
- return;
- }
-
- /* we have a persistent connection; try to accept another request. */
- if (evhttp_associate_new_request_with_connection(evcon) == -1)
- evhttp_connection_free(evcon);
-}
-
-/*
- * Returns an error page.
- */
-
-void
-evhttp_send_error(struct evhttp_request *req, int error, const char *reason)
-{
-#define ERR_FORMAT "<HTML><HEAD>\n" \
- "<TITLE>%d %s</TITLE>\n" \
- "</HEAD><BODY>\n" \
- "<H1>Method Not Implemented</H1>\n" \
- "Invalid method in request<P>\n" \
- "</BODY></HTML>\n"
-
- struct evbuffer *buf = evbuffer_new();
-
- /* close the connection on error */
- evhttp_add_header(req->output_headers, "Connection", "close");
-
- evhttp_response_code(req, error, reason);
-
- evbuffer_add_printf(buf, ERR_FORMAT, error, reason);
-
- evhttp_send_page(req, buf);
-
- evbuffer_free(buf);
-#undef ERR_FORMAT
-}
-
-/* Requires that headers and response code are already set up */
-
-static inline void
-evhttp_send(struct evhttp_request *req, struct evbuffer *databuf)
-{
- struct evhttp_connection *evcon = req->evcon;
-
- assert(TAILQ_FIRST(&evcon->requests) == req);
-
- /* xxx: not sure if we really should expose the data buffer this way */
- if (databuf != NULL)
- evbuffer_add_buffer(req->output_buffer, databuf);
-
- /* Adds headers to the response */
- evhttp_make_header(evcon, req);
-
- evhttp_write_buffer(evcon, evhttp_send_done, NULL);
-}
-
-void
-evhttp_send_reply(struct evhttp_request *req, int code, const char *reason,
- struct evbuffer *databuf)
-{
- /* set up to watch for client close */
- evhttp_connection_start_detectclose(req->evcon);
- evhttp_response_code(req, code, reason);
-
- evhttp_send(req, databuf);
-}
-
-void
-evhttp_send_reply_start(struct evhttp_request *req, int code,
- const char *reason)
-{
- /* set up to watch for client close */
- evhttp_connection_start_detectclose(req->evcon);
- evhttp_response_code(req, code, reason);
- if (req->major == 1 && req->minor == 1) {
- /* use chunked encoding for HTTP/1.1 */
- evhttp_add_header(req->output_headers, "Transfer-Encoding",
- "chunked");
- req->chunked = 1;
- }
- evhttp_make_header(req->evcon, req);
- evhttp_write_buffer(req->evcon, NULL, NULL);
-}
-
-void
-evhttp_send_reply_chunk(struct evhttp_request *req, struct evbuffer *databuf)
-{
- if (req->chunked) {
- evbuffer_add_printf(req->evcon->output_buffer, "%x\r\n",
- (unsigned)EVBUFFER_LENGTH(databuf));
- }
- evbuffer_add_buffer(req->evcon->output_buffer, databuf);
- if (req->chunked) {
- evbuffer_add(req->evcon->output_buffer, "\r\n", 2);
- }
- evhttp_write_buffer(req->evcon, NULL, NULL);
-}
-
-void
-evhttp_send_reply_end(struct evhttp_request *req)
-{
- struct evhttp_connection *evcon = req->evcon;
-
- if (req->chunked) {
- evbuffer_add(req->evcon->output_buffer, "0\r\n\r\n", 5);
- evhttp_write_buffer(req->evcon, evhttp_send_done, NULL);
- req->chunked = 0;
- } else if (!event_pending(&evcon->ev, EV_WRITE|EV_TIMEOUT, NULL)) {
- /* let the connection know that we are done with the request */
- evhttp_send_done(evcon, NULL);
- } else {
- /* make the callback execute after all data has been written */
- evcon->cb = evhttp_send_done;
- evcon->cb_arg = NULL;
- }
-}
-
-void
-evhttp_response_code(struct evhttp_request *req, int code, const char *reason)
-{
- req->kind = EVHTTP_RESPONSE;
- req->response_code = code;
- if (req->response_code_line != NULL)
- free(req->response_code_line);
- req->response_code_line = strdup(reason);
-}
-
-void
-evhttp_send_page(struct evhttp_request *req, struct evbuffer *databuf)
-{
- if (!req->major || !req->minor) {
- req->major = 1;
- req->minor = 1;
- }
-
- if (req->kind != EVHTTP_RESPONSE)
- evhttp_response_code(req, 200, "OK");
-
- evhttp_clear_headers(req->output_headers);
- evhttp_add_header(req->output_headers, "Content-Type", "text/html");
- evhttp_add_header(req->output_headers, "Connection", "close");
-
- evhttp_send(req, databuf);
-}
-
-static const char uri_chars[256] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0,
- /* 64 */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0,
- /* 128 */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* 192 */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-};
-
-/*
- * Helper functions to encode/decode a URI.
- * The returned string must be freed by the caller.
- */
-char *
-evhttp_encode_uri(const char *uri)
-{
- struct evbuffer *buf = evbuffer_new();
- char *p;
-
- for (p = (char *)uri; *p != '\0'; p++) {
- if (uri_chars[(u_char)(*p)]) {
- evbuffer_add(buf, p, 1);
- } else {
- evbuffer_add_printf(buf, "%%%02X", (u_char)(*p));
- }
- }
- evbuffer_add(buf, "", 1);
- p = strdup((char *)EVBUFFER_DATA(buf));
- evbuffer_free(buf);
-
- return (p);
-}
-
-char *
-evhttp_decode_uri(const char *uri)
-{
- char c, *ret;
- int i, j, in_query = 0;
-
- ret = malloc(strlen(uri) + 1);
- if (ret == NULL)
- event_err(1, "%s: malloc(%lu)", __func__,
- (unsigned long)(strlen(uri) + 1));
-
- for (i = j = 0; uri[i] != '\0'; i++) {
- c = uri[i];
- if (c == '?') {
- in_query = 1;
- } else if (c == '+' && in_query) {
- c = ' ';
- } else if (c == '%' && isxdigit((unsigned char)uri[i+1]) &&
- isxdigit((unsigned char)uri[i+2])) {
- char tmp[] = { uri[i+1], uri[i+2], '\0' };
- c = (char)strtol(tmp, NULL, 16);
- i += 2;
- }
- ret[j++] = c;
- }
- ret[j] = '\0';
-
- return (ret);
-}
-
-/*
- * Helper function to parse out arguments in a query.
- * The arguments are separated by key and value.
- * URI should already be decoded.
- */
-
-void
-evhttp_parse_query(const char *uri, struct evkeyvalq *headers)
-{
- char *line;
- char *argument;
- char *p;
-
- TAILQ_INIT(headers);
-
- /* No arguments - we are done */
- if (strchr(uri, '?') == NULL)
- return;
-
- if ((line = strdup(uri)) == NULL)
- event_err(1, "%s: strdup", __func__);
-
-
- argument = line;
-
- /* We already know that there has to be a ? */
- strsep(&argument, "?");
-
- p = argument;
- while (p != NULL && *p != '\0') {
- char *key, *value;
- argument = strsep(&p, "&");
-
- value = argument;
- key = strsep(&value, "=");
- if (value == NULL)
- goto error;
-
- value = evhttp_decode_uri(value);
- event_debug(("Query Param: %s -> %s\n", key, value));
- evhttp_add_header(headers, key, value);
- free(value);
- }
-
- error:
- free(line);
-}
-
-static struct evhttp_cb *
-evhttp_dispatch_callback(struct httpcbq *callbacks, struct evhttp_request *req)
-{
- struct evhttp_cb *cb;
- size_t offset = 0;
-
- /* Test for different URLs */
- char *p = strchr(req->uri, '?');
- if (p != NULL)
- offset = (size_t)(p - req->uri);
-
- TAILQ_FOREACH(cb, callbacks, next) {
- int res = 0;
- if (p == NULL) {
- res = strcmp(cb->what, req->uri) == 0;
- } else {
- res = ((strncmp(cb->what, req->uri, offset) == 0) &&
- (cb->what[offset] == '\0'));
- }
-
- if (res)
- return (cb);
- }
-
- return (NULL);
-}
-
-static void
-evhttp_handle_request(struct evhttp_request *req, void *arg)
-{
- struct evhttp *http = arg;
- struct evhttp_cb *cb = NULL;
-
- if (req->uri == NULL) {
- evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request");
- return;
- }
-
- if ((cb = evhttp_dispatch_callback(&http->callbacks, req)) != NULL) {
- (*cb->cb)(req, cb->cbarg);
- return;
- }
-
- /* Generic call back */
- if (http->gencb) {
- (*http->gencb)(req, http->gencbarg);
- return;
- } else {
- /* We need to send a 404 here */
-#define ERR_FORMAT "<html><head>" \
- "<title>404 Not Found</title>" \
- "</head><body>" \
- "<h1>Not Found</h1>" \
- "<p>The requested URL %s was not found on this server.</p>"\
- "</body></html>\n"
-
- char *escaped_html = evhttp_htmlescape(req->uri);
- struct evbuffer *buf = evbuffer_new();
-
- evhttp_response_code(req, HTTP_NOTFOUND, "Not Found");
-
- evbuffer_add_printf(buf, ERR_FORMAT, escaped_html);
-
- free(escaped_html);
-
- evhttp_send_page(req, buf);
-
- evbuffer_free(buf);
-#undef ERR_FORMAT
- }
-}
-
-static void
-accept_socket(int fd, short what, void *arg)
-{
- struct evhttp *http = arg;
- struct sockaddr_storage ss;
- socklen_t addrlen = sizeof(ss);
- int nfd;
-
- if ((nfd = accept(fd, (struct sockaddr *)&ss, &addrlen)) == -1) {
- event_warn("%s: bad accept", __func__);
- return;
- }
- if (evutil_make_socket_nonblocking(nfd) < 0)
- return;
-
- evhttp_get_request(http, nfd, (struct sockaddr *)&ss, addrlen);
-}
-
-int
-evhttp_bind_socket(struct evhttp *http, const char *address, u_short port)
-{
- struct event *ev = &http->bind_ev;
- int fd;
-
- if ((fd = bind_socket(address, port)) == -1)
- return (-1);
-
- if (listen(fd, 10) == -1) {
- event_warn("%s: listen", __func__);
- EVUTIL_CLOSESOCKET(fd);
- return (-1);
- }
-
- /* Schedule the socket for accepting */
- event_set(ev, fd, EV_READ | EV_PERSIST, accept_socket, http);
- EVHTTP_BASE_SET(http, ev);
- event_add(ev, NULL);
-
- event_debug(("Bound to port %d - Awaiting connections ... ", port));
-
- return (0);
-}
-
-static struct evhttp*
-evhttp_new_object(void)
-{
- struct evhttp *http = NULL;
-
- if ((http = calloc(1, sizeof(struct evhttp))) == NULL) {
- event_warn("%s: calloc", __func__);
- return (NULL);
- }
-
- http->timeout = -1;
-
- TAILQ_INIT(&http->callbacks);
- TAILQ_INIT(&http->connections);
-
- return (http);
-}
-
-struct evhttp *
-evhttp_new(struct event_base *base)
-{
- struct evhttp *http = evhttp_new_object();
-
- http->base = base;
-
- return (http);
-}
-
-/*
- * Start a web server on the specified address and port.
- */
-
-struct evhttp *
-evhttp_start(const char *address, u_short port)
-{
- struct evhttp *http = evhttp_new_object();
-
- if (evhttp_bind_socket(http, address, port) == -1) {
- free(http);
- return (NULL);
- }
-
- return (http);
-}
-
-void
-evhttp_free(struct evhttp* http)
-{
- struct evhttp_cb *http_cb;
- struct evhttp_connection *evcon;
- int fd = http->bind_ev.ev_fd;
-
- /* Remove the accepting part */
- event_del(&http->bind_ev);
- EVUTIL_CLOSESOCKET(fd);
-
- while ((evcon = TAILQ_FIRST(&http->connections)) != NULL) {
- /* evhttp_connection_free removes the connection */
- evhttp_connection_free(evcon);
- }
-
- while ((http_cb = TAILQ_FIRST(&http->callbacks)) != NULL) {
- TAILQ_REMOVE(&http->callbacks, http_cb, next);
- free(http_cb->what);
- free(http_cb);
- }
-
- free(http);
-}
-
-void
-evhttp_set_timeout(struct evhttp* http, int timeout_in_secs)
-{
- http->timeout = timeout_in_secs;
-}
-
-void
-evhttp_set_cb(struct evhttp *http, const char *uri,
- void (*cb)(struct evhttp_request *, void *), void *cbarg)
-{
- struct evhttp_cb *http_cb;
-
- if ((http_cb = calloc(1, sizeof(struct evhttp_cb))) == NULL)
- event_err(1, "%s: calloc", __func__);
-
- http_cb->what = strdup(uri);
- http_cb->cb = cb;
- http_cb->cbarg = cbarg;
-
- TAILQ_INSERT_TAIL(&http->callbacks, http_cb, next);
-}
-
-int
-evhttp_del_cb(struct evhttp *http, const char *uri)
-{
- struct evhttp_cb *http_cb;
-
- TAILQ_FOREACH(http_cb, &http->callbacks, next) {
- if (strcmp(http_cb->what, uri) == 0)
- break;
- }
- if (http_cb == NULL)
- return (-1);
-
- TAILQ_REMOVE(&http->callbacks, http_cb, next);
- free(http_cb->what);
- free(http_cb);
-
- return (0);
-}
-
-void
-evhttp_set_gencb(struct evhttp *http,
- void (*cb)(struct evhttp_request *, void *), void *cbarg)
-{
- http->gencb = cb;
- http->gencbarg = cbarg;
-}
-
-/*
- * Request related functions
- */
-
-struct evhttp_request *
-evhttp_request_new(void (*cb)(struct evhttp_request *, void *), void *arg)
-{
- struct evhttp_request *req = NULL;
-
- /* Allocate request structure */
- if ((req = calloc(1, sizeof(struct evhttp_request))) == NULL) {
- event_warn("%s: calloc", __func__);
- goto error;
- }
-
- req->kind = EVHTTP_RESPONSE;
- req->input_headers = calloc(1, sizeof(struct evkeyvalq));
- if (req->input_headers == NULL) {
- event_warn("%s: calloc", __func__);
- goto error;
- }
- TAILQ_INIT(req->input_headers);
-
- req->output_headers = calloc(1, sizeof(struct evkeyvalq));
- if (req->output_headers == NULL) {
- event_warn("%s: calloc", __func__);
- goto error;
- }
- TAILQ_INIT(req->output_headers);
-
- if ((req->input_buffer = evbuffer_new()) == NULL) {
- event_warn("%s: evbuffer_new", __func__);
- goto error;
- }
-
- if ((req->output_buffer = evbuffer_new()) == NULL) {
- event_warn("%s: evbuffer_new", __func__);
- goto error;
- }
-
- req->cb = cb;
- req->cb_arg = arg;
-
- return (req);
-
- error:
- if (req != NULL)
- evhttp_request_free(req);
- return (NULL);
-}
-
-void
-evhttp_request_free(struct evhttp_request *req)
-{
- if (req->remote_host != NULL)
- free(req->remote_host);
- if (req->uri != NULL)
- free(req->uri);
- if (req->response_code_line != NULL)
- free(req->response_code_line);
-
- evhttp_clear_headers(req->input_headers);
- free(req->input_headers);
-
- evhttp_clear_headers(req->output_headers);
- free(req->output_headers);
-
- if (req->input_buffer != NULL)
- evbuffer_free(req->input_buffer);
-
- if (req->output_buffer != NULL)
- evbuffer_free(req->output_buffer);
-
- free(req);
-}
-
-void
-evhttp_request_set_chunked_cb(struct evhttp_request *req,
- void (*cb)(struct evhttp_request *, void *))
-{
- req->chunk_cb = cb;
-}
-
-/*
- * Allows for inspection of the request URI
- */
-
-const char *
-evhttp_request_uri(struct evhttp_request *req) {
- if (req->uri == NULL)
- event_debug(("%s: request %p has no uri\n", req));
- return (req->uri);
-}
-
-/*
- * Takes a file descriptor to read a request from.
- * The callback is executed once the whole request has been read.
- */
-
-static struct evhttp_connection*
-evhttp_get_request_connection(
- struct evhttp* http,
- int fd, struct sockaddr *sa, socklen_t salen)
-{
- struct evhttp_connection *evcon;
- char *hostname, *portname;
-
- name_from_addr(sa, salen, &hostname, &portname);
- event_debug(("%s: new request from %s:%s on %d\n",
- __func__, hostname, portname, fd));
-
- /* we need a connection object to put the http request on */
- if ((evcon = evhttp_connection_new(hostname, atoi(portname))) == NULL)
- return (NULL);
-
- /* associate the base if we have one*/
- evhttp_connection_set_base(evcon, http->base);
-
- evcon->flags |= EVHTTP_CON_INCOMING;
- evcon->state = EVCON_CONNECTED;
-
- evcon->fd = fd;
-
- return (evcon);
-}
-
-static int
-evhttp_associate_new_request_with_connection(struct evhttp_connection *evcon)
-{
- struct evhttp *http = evcon->http_server;
- struct evhttp_request *req;
- if ((req = evhttp_request_new(evhttp_handle_request, http)) == NULL)
- return (-1);
-
- req->evcon = evcon; /* the request ends up owning the connection */
- req->flags |= EVHTTP_REQ_OWN_CONNECTION;
-
- TAILQ_INSERT_TAIL(&evcon->requests, req, next);
-
- req->kind = EVHTTP_REQUEST;
-
- if ((req->remote_host = strdup(evcon->address)) == NULL)
- event_err(1, "%s: strdup", __func__);
- req->remote_port = evcon->port;
-
- evhttp_start_read(evcon);
-
- return (0);
-}
-
-void
-evhttp_get_request(struct evhttp *http, int fd,
- struct sockaddr *sa, socklen_t salen)
-{
- struct evhttp_connection *evcon;
-
- evcon = evhttp_get_request_connection(http, fd, sa, salen);
- if (evcon == NULL)
- return;
-
- /* the timeout can be used by the server to close idle connections */
- if (http->timeout != -1)
- evhttp_connection_set_timeout(evcon, http->timeout);
-
- /*
- * if we want to accept more than one request on a connection,
- * we need to know which http server it belongs to.
- */
- evcon->http_server = http;
- TAILQ_INSERT_TAIL(&http->connections, evcon, next);
-
- if (evhttp_associate_new_request_with_connection(evcon) == -1)
- evhttp_connection_free(evcon);
-}
-
-
-/*
- * Network helper functions that we do not want to export to the rest of
- * the world.
- */
-#if 0 /* Unused */
-static struct addrinfo *
-addr_from_name(char *address)
-{
-#ifdef HAVE_GETADDRINFO
- struct addrinfo ai, *aitop;
- int ai_result;
-
- memset(&ai, 0, sizeof(ai));
- ai.ai_family = AF_INET;
- ai.ai_socktype = SOCK_RAW;
- ai.ai_flags = 0;
- if ((ai_result = getaddrinfo(address, NULL, &ai, &aitop)) != 0) {
- if ( ai_result == EAI_SYSTEM )
- event_warn("getaddrinfo");
- else
- event_warnx("getaddrinfo: %s", gai_strerror(ai_result));
- }
-
- return (aitop);
-#else
- assert(0);
- return NULL; /* XXXXX Use gethostbyname, if this function is ever used. */
-#endif
-}
-#endif
-
-static void
-name_from_addr(struct sockaddr *sa, socklen_t salen,
- char **phost, char **pport)
-{
-#ifdef HAVE_GETNAMEINFO
- /* XXXX not threadsafe. */
- static char ntop[NI_MAXHOST];
- static char strport[NI_MAXSERV];
- int ni_result;
-
- if ((ni_result = getnameinfo(sa, salen,
- ntop, sizeof(ntop), strport, sizeof(strport),
- NI_NUMERICHOST|NI_NUMERICSERV)) != 0) {
- if (ni_result == EAI_SYSTEM)
- event_err(1, "getnameinfo failed");
- else
- event_errx(1, "getnameinfo failed: %s", gai_strerror(ni_result));
- }
-
- *phost = ntop;
- *pport = strport;
-#else
- /* XXXX */
-#endif
-}
-
-/* Either connect or bind */
-
-static int
-bind_socket_ai(struct addrinfo *ai)
-{
- int fd, on = 1, r;
- int serrno;
-
- /* Create listen socket */
- fd = socket(AF_INET, SOCK_STREAM, 0);
- if (fd == -1) {
- event_warn("socket");
- return (-1);
- }
-
- if (evutil_make_socket_nonblocking(fd) < 0)
- goto out;
-
-#ifndef WIN32
- if (fcntl(fd, F_SETFD, 1) == -1) {
- event_warn("fcntl(F_SETFD)");
- goto out;
- }
-#endif
-
- setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on));
- setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on));
-
- r = bind(fd, ai->ai_addr, ai->ai_addrlen);
- if (r == -1)
- goto out;
-
- return (fd);
-
- out:
- serrno = EVUTIL_SOCKET_ERROR();
- EVUTIL_CLOSESOCKET(fd);
- EVUTIL_SET_SOCKET_ERROR(serrno);
- return (-1);
-}
-
-static struct addrinfo *
-make_addrinfo(const char *address, u_short port)
-{
- struct addrinfo *aitop = NULL;
-
-#ifdef HAVE_GETADDRINFO
- struct addrinfo ai;
- char strport[NI_MAXSERV];
- int ai_result;
-
- memset(&ai, 0, sizeof(ai));
- ai.ai_family = AF_INET;
- ai.ai_socktype = SOCK_STREAM;
- ai.ai_flags = AI_PASSIVE; /* turn NULL host name into INADDR_ANY */
- snprintf(strport, sizeof(strport), "%d", port);
- if ((ai_result = getaddrinfo(address, strport, &ai, &aitop)) != 0) {
- if ( ai_result == EAI_SYSTEM )
- event_warn("getaddrinfo");
- else
- event_warnx("getaddrinfo: %s", gai_strerror(ai_result));
- return (NULL);
- }
-#else
- static int cur;
- static struct addrinfo ai[2]; /* We will be returning the address of some of this memory so it has to last even after this call. */
- if (++cur == 2) cur = 0; /* allow calling this function twice */
-
- if (fake_getaddrinfo(address, &ai[cur]) < 0) {
- event_warn("fake_getaddrinfo");
- return (NULL);
- }
- aitop = &ai[cur];
- ((struct sockaddr_in *) aitop->ai_addr)->sin_port = htons(port);
-#endif
-
- return (aitop);
-}
-
-static int
-bind_socket(const char *address, u_short port)
-{
- int fd;
- struct addrinfo *aitop = make_addrinfo(address, port);
-
- if (aitop == NULL)
- return (-1);
-
- fd = bind_socket_ai(aitop);
-
-#ifdef HAVE_GETADDRINFO
- freeaddrinfo(aitop);
-#else
- fake_freeaddrinfo(aitop);
-#endif
-
- return (fd);
-}
-
-static int
-socket_connect(int fd, const char *address, unsigned short port)
-{
- struct addrinfo *ai = make_addrinfo(address, port);
- int res = -1;
-
- if (ai == NULL) {
- event_debug(("%s: make_addrinfo: \"%s:%d\"",
- __func__, address, port));
- return (-1);
- }
-
- if (connect(fd, ai->ai_addr, ai->ai_addrlen) == -1) {
-#ifdef WIN32
- int tmp_error = WSAGetLastError();
- if (tmp_error != WSAEWOULDBLOCK && tmp_error != WSAEINVAL &&
- tmp_error != WSAEINPROGRESS) {
- goto out;
- }
-#else
- if (errno != EINPROGRESS) {
- goto out;
- }
-#endif
- }
-
- /* everything is fine */
- res = 0;
-
-out:
-#ifdef HAVE_GETADDRINFO
- freeaddrinfo(ai);
-#else
- fake_freeaddrinfo(ai);
-#endif
-
- return (res);
-}
diff --git a/extra/libevent/kqueue.c b/extra/libevent/kqueue.c
deleted file mode 100644
index 763236e40ac..00000000000
--- a/extra/libevent/kqueue.c
+++ /dev/null
@@ -1,426 +0,0 @@
-/* $OpenBSD: kqueue.c,v 1.5 2002/07/10 14:41:31 art Exp $ */
-
-/*
- * Copyright 2000-2002 Niels Provos <provos@citi.umich.edu>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef HAVE_WORKING_KQUEUE
-
-#include <sys/types.h>
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#else
-#include <sys/_time.h>
-#endif
-#include <sys/queue.h>
-#include <sys/event.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#ifdef HAVE_INTTYPES_H
-#include <inttypes.h>
-#endif
-
-/* Some platforms apparently define the udata field of struct kevent as
- * intptr_t, whereas others define it as void*. There doesn't seem to be an
- * easy way to tell them apart via autoconf, so we need to use OS macros. */
-#if defined(HAVE_INTTYPES_H) && !defined(__OpenBSD__) && !defined(__FreeBSD__) && !defined(__darwin__) && !defined(__APPLE__)
-#define PTR_TO_UDATA(x) ((intptr_t)(x))
-#else
-#define PTR_TO_UDATA(x) (x)
-#endif
-
-#include "event.h"
-#include "event-internal.h"
-#include "log.h"
-#include "event-internal.h"
-
-#define EVLIST_X_KQINKERNEL 0x1000
-
-#define NEVENT 64
-
-struct kqop {
- struct kevent *changes;
- int nchanges;
- struct kevent *events;
- int nevents;
- int kq;
- pid_t pid;
-};
-
-static void *kq_init (struct event_base *);
-static int kq_add (void *, struct event *);
-static int kq_del (void *, struct event *);
-static int kq_dispatch (struct event_base *, void *, struct timeval *);
-static int kq_insert (struct kqop *, struct kevent *);
-static void kq_dealloc (struct event_base *, void *);
-
-const struct eventop kqops = {
- "kqueue",
- kq_init,
- kq_add,
- kq_del,
- kq_dispatch,
- kq_dealloc,
- 1 /* need reinit */
-};
-
-static void *
-kq_init(struct event_base *base __attribute__((unused)))
-{
- int kq;
- struct kqop *kqueueop;
-
- /* Disable kqueue when this environment variable is set */
- if (getenv("EVENT_NOKQUEUE"))
- return (NULL);
-
- if (!(kqueueop = calloc(1, sizeof(struct kqop))))
- return (NULL);
-
- /* Initalize the kernel queue */
-
- if ((kq = kqueue()) == -1) {
- event_warn("kqueue");
- free (kqueueop);
- return (NULL);
- }
-
- kqueueop->kq = kq;
-
- kqueueop->pid = getpid();
-
- /* Initalize fields */
- kqueueop->changes = malloc(NEVENT * sizeof(struct kevent));
- if (kqueueop->changes == NULL) {
- free (kqueueop);
- return (NULL);
- }
- kqueueop->events = malloc(NEVENT * sizeof(struct kevent));
- if (kqueueop->events == NULL) {
- free (kqueueop->changes);
- free (kqueueop);
- return (NULL);
- }
- kqueueop->nevents = NEVENT;
-
- /* Check for Mac OS X kqueue bug. */
- kqueueop->changes[0].ident = -1;
- kqueueop->changes[0].filter = EVFILT_READ;
- kqueueop->changes[0].flags = EV_ADD;
- /*
- * If kqueue works, then kevent will succeed, and it will
- * stick an error in events[0]. If kqueue is broken, then
- * kevent will fail.
- */
- if (kevent(kq,
- kqueueop->changes, 1, kqueueop->events, NEVENT, NULL) != 1 ||
- ((int) kqueueop->events[0].ident) != -1 ||
- kqueueop->events[0].flags != EV_ERROR) {
- event_warn("%s: detected broken kqueue; not using.", __func__);
- free(kqueueop->changes);
- free(kqueueop->events);
- free(kqueueop);
- close(kq);
- return (NULL);
- }
-
- return (kqueueop);
-}
-
-static int
-kq_insert(struct kqop *kqop, struct kevent *kev)
-{
- int nevents = kqop->nevents;
-
- if (kqop->nchanges == nevents) {
- struct kevent *newchange;
- struct kevent *newresult;
-
- nevents *= 2;
-
- newchange = realloc(kqop->changes,
- nevents * sizeof(struct kevent));
- if (newchange == NULL) {
- event_warn("%s: malloc", __func__);
- return (-1);
- }
- kqop->changes = newchange;
-
- newresult = realloc(kqop->events,
- nevents * sizeof(struct kevent));
-
- /*
- * If we fail, we don't have to worry about freeing,
- * the next realloc will pick it up.
- */
- if (newresult == NULL) {
- event_warn("%s: malloc", __func__);
- return (-1);
- }
- kqop->events = newresult;
-
- kqop->nevents = nevents;
- }
-
- memcpy(&kqop->changes[kqop->nchanges++], kev, sizeof(struct kevent));
-
- event_debug(("%s: fd %d %s%s",
- __func__, kev->ident,
- kev->filter == EVFILT_READ ? "EVFILT_READ" : "EVFILT_WRITE",
- kev->flags == EV_DELETE ? " (del)" : ""));
-
- return (0);
-}
-
-static void
-kq_sighandler(int sig __attribute__((unused)))
-{
- /* Do nothing here */
-}
-
-static int
-kq_dispatch(struct event_base *base __attribute__((unused)), void *arg,
- struct timeval *tv)
-{
- struct kqop *kqop = arg;
- struct kevent *changes = kqop->changes;
- struct kevent *events = kqop->events;
- struct event *ev;
- struct timespec ts, *ts_p = NULL;
- int i, res;
-
- if (tv != NULL) {
- TIMEVAL_TO_TIMESPEC(tv, &ts);
- ts_p = &ts;
- }
-
- res = kevent(kqop->kq, changes, kqop->nchanges,
- events, kqop->nevents, ts_p);
- kqop->nchanges = 0;
- if (res == -1) {
- if (errno != EINTR) {
- event_warn("kevent");
- return (-1);
- }
-
- return (0);
- }
-
- event_debug(("%s: kevent reports %d", __func__, res));
-
- for (i = 0; i < res; i++) {
- int which = 0;
-
- if (events[i].flags & EV_ERROR) {
- /*
- * Error messages that can happen, when a delete fails.
- * EBADF happens when the file discriptor has been
- * closed,
- * ENOENT when the file discriptor was closed and
- * then reopened.
- * EINVAL for some reasons not understood; EINVAL
- * should not be returned ever; but FreeBSD does :-\
- * An error is also indicated when a callback deletes
- * an event we are still processing. In that case
- * the data field is set to ENOENT.
- */
- if (events[i].data == EBADF ||
- events[i].data == EINVAL ||
- events[i].data == ENOENT)
- continue;
- errno = events[i].data;
- return (-1);
- }
-
- ev = (struct event *)events[i].udata;
-
- if (events[i].filter == EVFILT_READ) {
- which |= EV_READ;
- } else if (events[i].filter == EVFILT_WRITE) {
- which |= EV_WRITE;
- } else if (events[i].filter == EVFILT_SIGNAL) {
- which |= EV_SIGNAL;
- }
-
- if (!which)
- continue;
-
- if (!(ev->ev_events & EV_PERSIST))
- ev->ev_flags &= ~EVLIST_X_KQINKERNEL;
-
- event_active(ev, which,
- ev->ev_events & EV_SIGNAL ? events[i].data : 1);
- }
-
- return (0);
-}
-
-
-static int
-kq_add(void *arg, struct event *ev)
-{
- struct kqop *kqop = arg;
- struct kevent kev;
-
- if (ev->ev_events & EV_SIGNAL) {
- int nsignal = EVENT_SIGNAL(ev);
- struct timespec timeout = { 0, 0 };
-
- memset(&kev, 0, sizeof(kev));
- kev.ident = nsignal;
- kev.filter = EVFILT_SIGNAL;
- kev.flags = EV_ADD;
- if (!(ev->ev_events & EV_PERSIST))
- kev.flags |= EV_ONESHOT;
- kev.udata = PTR_TO_UDATA(ev);
-
- /* Be ready for the signal if it is sent any time between
- * now and the next call to kq_dispatch. */
- if (kevent(kqop->kq, &kev, 1, NULL, 0, &timeout) == -1)
- return (-1);
-
- if (_evsignal_set_handler(ev->ev_base, nsignal,
- kq_sighandler) == -1)
- return (-1);
-
- ev->ev_flags |= EVLIST_X_KQINKERNEL;
- return (0);
- }
-
- if (ev->ev_events & EV_READ) {
- memset(&kev, 0, sizeof(kev));
- kev.ident = ev->ev_fd;
- kev.filter = EVFILT_READ;
-#ifdef NOTE_EOF
- /* Make it behave like select() and poll() */
- kev.fflags = NOTE_EOF;
-#endif
- kev.flags = EV_ADD;
- if (!(ev->ev_events & EV_PERSIST))
- kev.flags |= EV_ONESHOT;
- kev.udata = PTR_TO_UDATA(ev);
-
- if (kq_insert(kqop, &kev) == -1)
- return (-1);
-
- ev->ev_flags |= EVLIST_X_KQINKERNEL;
- }
-
- if (ev->ev_events & EV_WRITE) {
- memset(&kev, 0, sizeof(kev));
- kev.ident = ev->ev_fd;
- kev.filter = EVFILT_WRITE;
- kev.flags = EV_ADD;
- if (!(ev->ev_events & EV_PERSIST))
- kev.flags |= EV_ONESHOT;
- kev.udata = PTR_TO_UDATA(ev);
-
- if (kq_insert(kqop, &kev) == -1)
- return (-1);
-
- ev->ev_flags |= EVLIST_X_KQINKERNEL;
- }
-
- return (0);
-}
-
-static int
-kq_del(void *arg, struct event *ev)
-{
- struct kqop *kqop = arg;
- struct kevent kev;
-
- if (!(ev->ev_flags & EVLIST_X_KQINKERNEL))
- return (0);
-
- if (ev->ev_events & EV_SIGNAL) {
- int nsignal = EVENT_SIGNAL(ev);
-
- memset(&kev, 0, sizeof(kev));
- kev.ident = nsignal;
- kev.filter = EVFILT_SIGNAL;
- kev.flags = EV_DELETE;
-
- if (kq_insert(kqop, &kev) == -1)
- return (-1);
-
- if (_evsignal_restore_handler(ev->ev_base, nsignal) == -1)
- return (-1);
-
- ev->ev_flags &= ~EVLIST_X_KQINKERNEL;
- return (0);
- }
-
- if (ev->ev_events & EV_READ) {
- memset(&kev, 0, sizeof(kev));
- kev.ident = ev->ev_fd;
- kev.filter = EVFILT_READ;
- kev.flags = EV_DELETE;
-
- if (kq_insert(kqop, &kev) == -1)
- return (-1);
-
- ev->ev_flags &= ~EVLIST_X_KQINKERNEL;
- }
-
- if (ev->ev_events & EV_WRITE) {
- memset(&kev, 0, sizeof(kev));
- kev.ident = ev->ev_fd;
- kev.filter = EVFILT_WRITE;
- kev.flags = EV_DELETE;
-
- if (kq_insert(kqop, &kev) == -1)
- return (-1);
-
- ev->ev_flags &= ~EVLIST_X_KQINKERNEL;
- }
-
- return (0);
-}
-
-static void
-kq_dealloc(struct event_base *base __attribute__((unused)), void *arg)
-{
- struct kqop *kqop = arg;
-
- if (kqop->changes)
- free(kqop->changes);
- if (kqop->events)
- free(kqop->events);
- if (kqop->kq >= 0 && kqop->pid == getpid())
- close(kqop->kq);
- memset(kqop, 0, sizeof(struct kqop));
- free(kqop);
-}
-
-#endif /* HAVE_WORKING_KQUEUE */
diff --git a/extra/libevent/log.c b/extra/libevent/log.c
deleted file mode 100644
index aab47182af5..00000000000
--- a/extra/libevent/log.c
+++ /dev/null
@@ -1,218 +0,0 @@
-/* $OpenBSD: err.c,v 1.2 2002/06/25 15:50:15 mickey Exp $ */
-
-/*
- * log.c
- *
- * Based on err.c, which was adapted from OpenBSD libc *err* *warn* code.
- *
- * Copyright (c) 2005 Nick Mathewson <nickm@freehaven.net>
- *
- * Copyright (c) 2000 Dug Song <dugsong@monkey.org>
- *
- * Copyright (c) 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef WIN32
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#undef WIN32_LEAN_AND_MEAN
-#include "misc.h"
-#endif
-#include <sys/types.h>
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#else
-#include <sys/_time.h>
-#endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <errno.h>
-#include "event.h"
-
-#include "log.h"
-
-static void _warn_helper(int severity, int log_errno, const char *fmt,
- va_list ap);
-static void event_log(int severity, const char *msg);
-
-static int
-event_vsnprintf(char *str, size_t size, const char *format, va_list args)
-{
- int r;
- if (size == 0)
- return -1;
-#ifdef WIN32
- r = _vsnprintf(str, size, format, args);
-#else
- r = vsnprintf(str, size, format, args);
-#endif
- str[size-1] = '\0';
- if (r < 0 || ((size_t)r) >= size) {
- /* different platforms behave differently on overflow;
- * handle both kinds. */
- return -1;
- }
- return r;
-}
-
-static int
-event_snprintf(char *str, size_t size, const char *format, ...)
-{
- va_list ap;
- int r;
- va_start(ap, format);
- r = event_vsnprintf(str, size, format, ap);
- va_end(ap);
- return r;
-}
-
-void
-event_err(int eval, const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- _warn_helper(_EVENT_LOG_ERR, errno, fmt, ap);
- va_end(ap);
- exit(eval);
-}
-
-void
-event_warn(const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- _warn_helper(_EVENT_LOG_WARN, errno, fmt, ap);
- va_end(ap);
-}
-
-void
-event_errx(int eval, const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- _warn_helper(_EVENT_LOG_ERR, -1, fmt, ap);
- va_end(ap);
- exit(eval);
-}
-
-void
-event_warnx(const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- _warn_helper(_EVENT_LOG_WARN, -1, fmt, ap);
- va_end(ap);
-}
-
-void
-event_msgx(const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- _warn_helper(_EVENT_LOG_MSG, -1, fmt, ap);
- va_end(ap);
-}
-
-void
-_event_debugx(const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- _warn_helper(_EVENT_LOG_DEBUG, -1, fmt, ap);
- va_end(ap);
-}
-
-static void
-_warn_helper(int severity, int log_errno, const char *fmt, va_list ap)
-{
- char buf[1024];
- size_t len;
-
- if (fmt != NULL)
- event_vsnprintf(buf, sizeof(buf), fmt, ap);
- else
- buf[0] = '\0';
-
- if (log_errno >= 0) {
- len = strlen(buf);
- if (len < sizeof(buf) - 3) {
- event_snprintf(buf + len, sizeof(buf) - len, ": %s",
- strerror(log_errno));
- }
- }
-
- event_log(severity, buf);
-}
-
-static event_log_cb log_fn = NULL;
-
-void
-event_set_log_callback(event_log_cb cb)
-{
- log_fn = cb;
-}
-
-static void
-event_log(int severity, const char *msg)
-{
- if (log_fn)
- log_fn(severity, msg);
- else {
- const char *severity_str;
- switch (severity) {
- case _EVENT_LOG_DEBUG:
- severity_str = "debug";
- break;
- case _EVENT_LOG_MSG:
- severity_str = "msg";
- break;
- case _EVENT_LOG_WARN:
- severity_str = "warn";
- break;
- case _EVENT_LOG_ERR:
- severity_str = "err";
- break;
- default:
- severity_str = "???";
- break;
- }
- (void)fprintf(stderr, "[%s] %s\n", severity_str, msg);
- }
-}
diff --git a/extra/libevent/log.h b/extra/libevent/log.h
deleted file mode 100644
index 7bc6632b8dd..00000000000
--- a/extra/libevent/log.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2000-2004 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 BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#ifndef _LOG_H_
-#define _LOG_H_
-
-#ifdef __GNUC__
-#define EV_CHECK_FMT(a,b) __attribute__((format(printf, a, b)))
-#else
-#define EV_CHECK_FMT(a,b)
-#endif
-
-void event_err(int eval, const char *fmt, ...) EV_CHECK_FMT(2,3);
-void event_warn(const char *fmt, ...) EV_CHECK_FMT(1,2);
-void event_errx(int eval, const char *fmt, ...) EV_CHECK_FMT(2,3);
-void event_warnx(const char *fmt, ...) EV_CHECK_FMT(1,2);
-void event_msgx(const char *fmt, ...) EV_CHECK_FMT(1,2);
-void _event_debugx(const char *fmt, ...) EV_CHECK_FMT(1,2);
-
-#ifdef USE_DEBUG
-#define event_debug(x) _event_debugx x
-#else
-#define event_debug(x) do {;} while (0)
-#endif
-
-#undef EV_CHECK_FMT
-
-#endif
diff --git a/extra/libevent/min_heap.h b/extra/libevent/min_heap.h
deleted file mode 100644
index 389d6dbed4e..00000000000
--- a/extra/libevent/min_heap.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (c) 2006 Maxim Yegorushkin <maxim.yegorushkin@gmail.com>
- * 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 BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#ifndef _MIN_HEAP_H_
-#define _MIN_HEAP_H_
-
-#include "event.h"
-
-typedef struct min_heap
-{
- struct event** p;
- unsigned n, a;
-} min_heap_t;
-
-static inline void min_heap_ctor(min_heap_t* s);
-static inline void min_heap_dtor(min_heap_t* s);
-static inline void min_heap_elem_init(struct event* e);
-static inline int min_heap_elem_greater(struct event *a, struct event *b);
-static inline int min_heap_empty(min_heap_t* s);
-static inline unsigned min_heap_size(min_heap_t* s);
-static inline struct event* min_heap_top(min_heap_t* s);
-static inline int min_heap_reserve(min_heap_t* s, unsigned n);
-static inline int min_heap_push(min_heap_t* s, struct event* e);
-static inline struct event* min_heap_pop(min_heap_t* s);
-static inline int min_heap_erase(min_heap_t* s, struct event* e);
-static inline void min_heap_shift_up_(min_heap_t* s, unsigned hole_index, struct event* e);
-static inline void min_heap_shift_down_(min_heap_t* s, unsigned hole_index, struct event* e);
-
-int min_heap_elem_greater(struct event *a, struct event *b)
-{
- return timercmp(&a->ev_timeout, &b->ev_timeout, >);
-}
-
-void min_heap_ctor(min_heap_t* s) { s->p = 0; s->n = 0; s->a = 0; }
-void min_heap_dtor(min_heap_t* s) { free(s->p); }
-void min_heap_elem_init(struct event* e) { e->min_heap_idx = -1; }
-int min_heap_empty(min_heap_t* s) { return 0u == s->n; }
-unsigned min_heap_size(min_heap_t* s) { return s->n; }
-struct event* min_heap_top(min_heap_t* s) { return s->n ? *s->p : 0; }
-
-int min_heap_push(min_heap_t* s, struct event* e)
-{
- if(min_heap_reserve(s, s->n + 1))
- return -1;
- min_heap_shift_up_(s, s->n++, e);
- return 0;
-}
-
-struct event* min_heap_pop(min_heap_t* s)
-{
- if(s->n)
- {
- struct event* e = *s->p;
- e->min_heap_idx = -1;
- min_heap_shift_down_(s, 0u, s->p[--s->n]);
- return e;
- }
- return 0;
-}
-
-int min_heap_erase(min_heap_t* s, struct event* e)
-{
- if(((unsigned int)-1) != e->min_heap_idx)
- {
- min_heap_shift_down_(s, e->min_heap_idx, s->p[--s->n]);
- e->min_heap_idx = -1;
- return 0;
- }
- return -1;
-}
-
-int min_heap_reserve(min_heap_t* s, unsigned n)
-{
- if(s->a < n)
- {
- struct event** p;
- unsigned a = s->a ? s->a * 2 : 8;
- if(a < n)
- a = n;
- if(!(p = (struct event**)realloc(s->p, a * sizeof *p)))
- return -1;
- s->p = p;
- s->a = a;
- }
- return 0;
-}
-
-void min_heap_shift_up_(min_heap_t* s, unsigned hole_index, struct event* e)
-{
- unsigned parent = (hole_index - 1) / 2;
- while(hole_index && min_heap_elem_greater(s->p[parent], e))
- {
- (s->p[hole_index] = s->p[parent])->min_heap_idx = hole_index;
- hole_index = parent;
- parent = (hole_index - 1) / 2;
- }
- (s->p[hole_index] = e)->min_heap_idx = hole_index;
-}
-
-void min_heap_shift_down_(min_heap_t* s, unsigned hole_index, struct event* e)
-{
- unsigned min_child = 2 * (hole_index + 1);
- while(min_child <= s->n)
- {
- min_child -= min_child == s->n || min_heap_elem_greater(s->p[min_child], s->p[min_child - 1]);
- if(!(min_heap_elem_greater(e, s->p[min_child])))
- break;
- (s->p[hole_index] = s->p[min_child])->min_heap_idx = hole_index;
- hole_index = min_child;
- min_child = 2 * (hole_index + 1);
- }
- min_heap_shift_up_(s, hole_index, e);
-}
-
-#endif /* _MIN_HEAP_H_ */
diff --git a/extra/libevent/poll.c b/extra/libevent/poll.c
deleted file mode 100644
index 6c99e2ca79b..00000000000
--- a/extra/libevent/poll.c
+++ /dev/null
@@ -1,378 +0,0 @@
-/* $OpenBSD: poll.c,v 1.2 2002/06/25 15:50:15 mickey Exp $ */
-
-/*
- * Copyright 2000-2003 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 BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef HAVE_POLL
-
-#include <sys/types.h>
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#else
-#include <sys/_time.h>
-#endif
-#include <sys/queue.h>
-#include <poll.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#ifdef CHECK_INVARIANTS
-#include <assert.h>
-#endif
-
-#include "event.h"
-#include "event-internal.h"
-#include "evsignal.h"
-#include "log.h"
-
-struct pollop {
- int event_count; /* Highest number alloc */
- int nfds; /* Size of event_* */
- int fd_count; /* Size of idxplus1_by_fd */
- struct pollfd *event_set;
- struct event **event_r_back;
- struct event **event_w_back;
- int *idxplus1_by_fd; /* Index into event_set by fd; we add 1 so
- * that 0 (which is easy to memset) can mean
- * "no entry." */
-};
-
-static void *poll_init (struct event_base *);
-static int poll_add (void *, struct event *);
-static int poll_del (void *, struct event *);
-static int poll_dispatch (struct event_base *, void *, struct timeval *);
-static void poll_dealloc (struct event_base *, void *);
-
-const struct eventop pollops = {
- "poll",
- poll_init,
- poll_add,
- poll_del,
- poll_dispatch,
- poll_dealloc,
- 0
-};
-
-static void *
-poll_init(struct event_base *base)
-{
- struct pollop *pollop;
-
- /* Disable poll when this environment variable is set */
- if (getenv("EVENT_NOPOLL"))
- return (NULL);
-
- if (!(pollop = calloc(1, sizeof(struct pollop))))
- return (NULL);
-
- evsignal_init(base);
-
- return (pollop);
-}
-
-#ifdef CHECK_INVARIANTS
-static void
-poll_check_ok(struct pollop *pop)
-{
- int i, idx;
- struct event *ev;
-
- for (i = 0; i < pop->fd_count; ++i) {
- idx = pop->idxplus1_by_fd[i]-1;
- if (idx < 0)
- continue;
- assert(pop->event_set[idx].fd == i);
- if (pop->event_set[idx].events & POLLIN) {
- ev = pop->event_r_back[idx];
- assert(ev);
- assert(ev->ev_events & EV_READ);
- assert(ev->ev_fd == i);
- }
- if (pop->event_set[idx].events & POLLOUT) {
- ev = pop->event_w_back[idx];
- assert(ev);
- assert(ev->ev_events & EV_WRITE);
- assert(ev->ev_fd == i);
- }
- }
- for (i = 0; i < pop->nfds; ++i) {
- struct pollfd *pfd = &pop->event_set[i];
- assert(pop->idxplus1_by_fd[pfd->fd] == i+1);
- }
-}
-#else
-#define poll_check_ok(pop)
-#endif
-
-static int
-poll_dispatch(struct event_base *base, void *arg, struct timeval *tv)
-{
- int res, i, msec = -1, nfds;
- struct pollop *pop = arg;
-
- poll_check_ok(pop);
-
- if (tv != NULL)
- msec = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000;
-
- nfds = pop->nfds;
- res = poll(pop->event_set, nfds, msec);
-
- if (res == -1) {
- if (errno != EINTR) {
- event_warn("poll");
- return (-1);
- }
-
- evsignal_process(base);
- return (0);
- } else if (base->sig.evsignal_caught) {
- evsignal_process(base);
- }
-
- event_debug(("%s: poll reports %d", __func__, res));
-
- if (res == 0)
- return (0);
-
- for (i = 0; i < nfds; i++) {
- int what = pop->event_set[i].revents;
- struct event *r_ev = NULL, *w_ev = NULL;
- if (!what)
- continue;
-
- res = 0;
-
- /* If the file gets closed notify */
- if (what & (POLLHUP|POLLERR))
- what |= POLLIN|POLLOUT;
- if (what & POLLIN) {
- res |= EV_READ;
- r_ev = pop->event_r_back[i];
- }
- if (what & POLLOUT) {
- res |= EV_WRITE;
- w_ev = pop->event_w_back[i];
- }
- if (res == 0)
- continue;
-
- if (r_ev && (res & r_ev->ev_events)) {
- event_active(r_ev, res & r_ev->ev_events, 1);
- }
- if (w_ev && w_ev != r_ev && (res & w_ev->ev_events)) {
- event_active(w_ev, res & w_ev->ev_events, 1);
- }
- }
-
- return (0);
-}
-
-static int
-poll_add(void *arg, struct event *ev)
-{
- struct pollop *pop = arg;
- struct pollfd *pfd = NULL;
- int i;
-
- if (ev->ev_events & EV_SIGNAL)
- return (evsignal_add(ev));
- if (!(ev->ev_events & (EV_READ|EV_WRITE)))
- return (0);
-
- poll_check_ok(pop);
- if (pop->nfds + 1 >= pop->event_count) {
- struct pollfd *tmp_event_set;
- struct event **tmp_event_r_back;
- struct event **tmp_event_w_back;
- int tmp_event_count;
-
- if (pop->event_count < 32)
- tmp_event_count = 32;
- else
- tmp_event_count = pop->event_count * 2;
-
- /* We need more file descriptors */
- tmp_event_set = realloc(pop->event_set,
- tmp_event_count * sizeof(struct pollfd));
- if (tmp_event_set == NULL) {
- event_warn("realloc");
- return (-1);
- }
- pop->event_set = tmp_event_set;
-
- tmp_event_r_back = realloc(pop->event_r_back,
- tmp_event_count * sizeof(struct event *));
- if (tmp_event_r_back == NULL) {
- /* event_set overallocated; that's okay. */
- event_warn("realloc");
- return (-1);
- }
- pop->event_r_back = tmp_event_r_back;
-
- tmp_event_w_back = realloc(pop->event_w_back,
- tmp_event_count * sizeof(struct event *));
- if (tmp_event_w_back == NULL) {
- /* event_set and event_r_back overallocated; that's
- * okay. */
- event_warn("realloc");
- return (-1);
- }
- pop->event_w_back = tmp_event_w_back;
-
- pop->event_count = tmp_event_count;
- }
- if (ev->ev_fd >= pop->fd_count) {
- int *tmp_idxplus1_by_fd;
- int new_count;
- if (pop->fd_count < 32)
- new_count = 32;
- else
- new_count = pop->fd_count * 2;
- while (new_count <= ev->ev_fd)
- new_count *= 2;
- tmp_idxplus1_by_fd =
- realloc(pop->idxplus1_by_fd, new_count * sizeof(int));
- if (tmp_idxplus1_by_fd == NULL) {
- event_warn("realloc");
- return (-1);
- }
- pop->idxplus1_by_fd = tmp_idxplus1_by_fd;
- memset(pop->idxplus1_by_fd + pop->fd_count,
- 0, sizeof(int)*(new_count - pop->fd_count));
- pop->fd_count = new_count;
- }
-
- i = pop->idxplus1_by_fd[ev->ev_fd] - 1;
- if (i >= 0) {
- pfd = &pop->event_set[i];
- } else {
- i = pop->nfds++;
- pfd = &pop->event_set[i];
- pfd->events = 0;
- pfd->fd = ev->ev_fd;
- pop->event_w_back[i] = pop->event_r_back[i] = NULL;
- pop->idxplus1_by_fd[ev->ev_fd] = i + 1;
- }
-
- pfd->revents = 0;
- if (ev->ev_events & EV_WRITE) {
- pfd->events |= POLLOUT;
- pop->event_w_back[i] = ev;
- }
- if (ev->ev_events & EV_READ) {
- pfd->events |= POLLIN;
- pop->event_r_back[i] = ev;
- }
- poll_check_ok(pop);
-
- return (0);
-}
-
-/*
- * Nothing to be done here.
- */
-
-static int
-poll_del(void *arg, struct event *ev)
-{
- struct pollop *pop = arg;
- struct pollfd *pfd = NULL;
- int i;
-
- if (ev->ev_events & EV_SIGNAL)
- return (evsignal_del(ev));
-
- if (!(ev->ev_events & (EV_READ|EV_WRITE)))
- return (0);
-
- poll_check_ok(pop);
- i = pop->idxplus1_by_fd[ev->ev_fd] - 1;
- if (i < 0)
- return (-1);
-
- /* Do we still want to read or write? */
- pfd = &pop->event_set[i];
- if (ev->ev_events & EV_READ) {
- pfd->events &= ~POLLIN;
- pop->event_r_back[i] = NULL;
- }
- if (ev->ev_events & EV_WRITE) {
- pfd->events &= ~POLLOUT;
- pop->event_w_back[i] = NULL;
- }
- poll_check_ok(pop);
- if (pfd->events)
- /* Another event cares about that fd. */
- return (0);
-
- /* Okay, so we aren't interested in that fd anymore. */
- pop->idxplus1_by_fd[ev->ev_fd] = 0;
-
- --pop->nfds;
- if (i != pop->nfds) {
- /*
- * Shift the last pollfd down into the now-unoccupied
- * position.
- */
- memcpy(&pop->event_set[i], &pop->event_set[pop->nfds],
- sizeof(struct pollfd));
- pop->event_r_back[i] = pop->event_r_back[pop->nfds];
- pop->event_w_back[i] = pop->event_w_back[pop->nfds];
- pop->idxplus1_by_fd[pop->event_set[i].fd] = i + 1;
- }
-
- poll_check_ok(pop);
- return (0);
-}
-
-static void
-poll_dealloc(struct event_base *base, void *arg)
-{
- struct pollop *pop = arg;
-
- evsignal_dealloc(base);
- if (pop->event_set)
- free(pop->event_set);
- if (pop->event_r_back)
- free(pop->event_r_back);
- if (pop->event_w_back)
- free(pop->event_w_back);
- if (pop->idxplus1_by_fd)
- free(pop->idxplus1_by_fd);
-
- memset(pop, 0, sizeof(struct pollop));
- free(pop);
-}
-
-#endif /* HAVE_POLL */
diff --git a/extra/libevent/select.c b/extra/libevent/select.c
deleted file mode 100644
index b8bd1a1c361..00000000000
--- a/extra/libevent/select.c
+++ /dev/null
@@ -1,356 +0,0 @@
-/* $OpenBSD: select.c,v 1.2 2002/06/25 15:50:15 mickey Exp $ */
-
-/*
- * Copyright 2000-2002 Niels Provos <provos@citi.umich.edu>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef HAVE_SELECT
-
-#include <sys/types.h>
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#else
-#include <sys/_time.h>
-#endif
-#ifdef HAVE_SYS_SELECT_H
-#include <sys/select.h>
-#endif
-#include <sys/queue.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#ifdef CHECK_INVARIANTS
-#include <assert.h>
-#endif
-
-#include "event.h"
-#include "event-internal.h"
-#include "evsignal.h"
-#include "log.h"
-
-#ifndef howmany
-#define howmany(x, y) (((x)+((y)-1))/(y))
-#endif
-
-struct selectop {
- int event_fds; /* Highest fd in fd set */
- int event_fdsz;
- fd_set *event_readset_in;
- fd_set *event_writeset_in;
- fd_set *event_readset_out;
- fd_set *event_writeset_out;
- struct event **event_r_by_fd;
- struct event **event_w_by_fd;
-};
-
-static void *select_init (struct event_base *);
-static int select_add (void *, struct event *);
-static int select_del (void *, struct event *);
-static int select_dispatch (struct event_base *, void *, struct timeval *);
-static void select_dealloc (struct event_base *, void *);
-
-const struct eventop selectops = {
- "select",
- select_init,
- select_add,
- select_del,
- select_dispatch,
- select_dealloc,
- 0
-};
-
-static int select_resize(struct selectop *sop, int fdsz);
-
-static void *
-select_init(struct event_base *base)
-{
- struct selectop *sop;
-
- /* Disable select when this environment variable is set */
- if (getenv("EVENT_NOSELECT"))
- return (NULL);
-
- if (!(sop = calloc(1, sizeof(struct selectop))))
- return (NULL);
-
- select_resize(sop, howmany(32 + 1, NFDBITS)*sizeof(fd_mask));
-
- evsignal_init(base);
-
- return (sop);
-}
-
-#ifdef CHECK_INVARIANTS
-static void
-check_selectop(struct selectop *sop)
-{
- int i;
- for (i = 0; i <= sop->event_fds; ++i) {
- if (FD_ISSET(i, sop->event_readset_in)) {
- assert(sop->event_r_by_fd[i]);
- assert(sop->event_r_by_fd[i]->ev_events & EV_READ);
- assert(sop->event_r_by_fd[i]->ev_fd == i);
- } else {
- assert(! sop->event_r_by_fd[i]);
- }
- if (FD_ISSET(i, sop->event_writeset_in)) {
- assert(sop->event_w_by_fd[i]);
- assert(sop->event_w_by_fd[i]->ev_events & EV_WRITE);
- assert(sop->event_w_by_fd[i]->ev_fd == i);
- } else {
- assert(! sop->event_w_by_fd[i]);
- }
- }
-
-}
-#else
-#define check_selectop(sop) do { (void) sop; } while (0)
-#endif
-
-static int
-select_dispatch(struct event_base *base, void *arg, struct timeval *tv)
-{
- int res, i;
- struct selectop *sop = arg;
-
- check_selectop(sop);
-
- memcpy(sop->event_readset_out, sop->event_readset_in,
- sop->event_fdsz);
- memcpy(sop->event_writeset_out, sop->event_writeset_in,
- sop->event_fdsz);
-
- res = select(sop->event_fds + 1, sop->event_readset_out,
- sop->event_writeset_out, NULL, tv);
-
- check_selectop(sop);
-
- if (res == -1) {
- if (errno != EINTR) {
- event_warn("select");
- return (-1);
- }
-
- evsignal_process(base);
- return (0);
- } else if (base->sig.evsignal_caught) {
- evsignal_process(base);
- }
-
- event_debug(("%s: select reports %d", __func__, res));
-
- check_selectop(sop);
- for (i = 0; i <= sop->event_fds; ++i) {
- struct event *r_ev = NULL, *w_ev = NULL;
- res = 0;
- if (FD_ISSET(i, sop->event_readset_out)) {
- r_ev = sop->event_r_by_fd[i];
- res |= EV_READ;
- }
- if (FD_ISSET(i, sop->event_writeset_out)) {
- w_ev = sop->event_w_by_fd[i];
- res |= EV_WRITE;
- }
- if (r_ev && (res & r_ev->ev_events)) {
- event_active(r_ev, res & r_ev->ev_events, 1);
- }
- if (w_ev && w_ev != r_ev && (res & w_ev->ev_events)) {
- event_active(w_ev, res & w_ev->ev_events, 1);
- }
- }
- check_selectop(sop);
-
- return (0);
-}
-
-
-static int
-select_resize(struct selectop *sop, int fdsz)
-{
- int n_events, n_events_old;
-
- fd_set *readset_in = NULL;
- fd_set *writeset_in = NULL;
- fd_set *readset_out = NULL;
- fd_set *writeset_out = NULL;
- struct event **r_by_fd = NULL;
- struct event **w_by_fd = NULL;
-
- n_events = (fdsz/sizeof(fd_mask)) * NFDBITS;
- n_events_old = (sop->event_fdsz/sizeof(fd_mask)) * NFDBITS;
-
- if (sop->event_readset_in)
- check_selectop(sop);
-
- if ((readset_in = realloc(sop->event_readset_in, fdsz)) == NULL)
- goto error;
- sop->event_readset_in = readset_in;
- if ((readset_out = realloc(sop->event_readset_out, fdsz)) == NULL)
- goto error;
- sop->event_readset_out = readset_out;
- if ((writeset_in = realloc(sop->event_writeset_in, fdsz)) == NULL)
- goto error;
- sop->event_writeset_in = writeset_in;
- if ((writeset_out = realloc(sop->event_writeset_out, fdsz)) == NULL)
- goto error;
- sop->event_writeset_out = writeset_out;
- if ((r_by_fd = realloc(sop->event_r_by_fd,
- n_events*sizeof(struct event*))) == NULL)
- goto error;
- sop->event_r_by_fd = r_by_fd;
- if ((w_by_fd = realloc(sop->event_w_by_fd,
- n_events * sizeof(struct event*))) == NULL)
- goto error;
- sop->event_w_by_fd = w_by_fd;
-
- memset((char *)sop->event_readset_in + sop->event_fdsz, 0,
- fdsz - sop->event_fdsz);
- memset((char *)sop->event_writeset_in + sop->event_fdsz, 0,
- fdsz - sop->event_fdsz);
- memset(sop->event_r_by_fd + n_events_old, 0,
- (n_events-n_events_old) * sizeof(struct event*));
- memset(sop->event_w_by_fd + n_events_old, 0,
- (n_events-n_events_old) * sizeof(struct event*));
-
- sop->event_fdsz = fdsz;
- check_selectop(sop);
-
- return (0);
-
- error:
- event_warn("malloc");
- return (-1);
-}
-
-
-static int
-select_add(void *arg, struct event *ev)
-{
- struct selectop *sop = arg;
-
- if (ev->ev_events & EV_SIGNAL)
- return (evsignal_add(ev));
-
- check_selectop(sop);
- /*
- * Keep track of the highest fd, so that we can calculate the size
- * of the fd_sets for select(2)
- */
- if (sop->event_fds < ev->ev_fd) {
- unsigned int fdsz = sop->event_fdsz;
-
- if (fdsz < sizeof(fd_mask))
- fdsz = sizeof(fd_mask);
-
- while (fdsz <
- (howmany(ev->ev_fd + 1, NFDBITS) * sizeof(fd_mask)))
- fdsz *= 2;
-
- if (fdsz != (unsigned int) sop->event_fdsz) {
- if (select_resize(sop, fdsz)) {
- check_selectop(sop);
- return (-1);
- }
- }
-
- sop->event_fds = ev->ev_fd;
- }
-
- if (ev->ev_events & EV_READ) {
- FD_SET(ev->ev_fd, sop->event_readset_in);
- sop->event_r_by_fd[ev->ev_fd] = ev;
- }
- if (ev->ev_events & EV_WRITE) {
- FD_SET(ev->ev_fd, sop->event_writeset_in);
- sop->event_w_by_fd[ev->ev_fd] = ev;
- }
- check_selectop(sop);
-
- return (0);
-}
-
-/*
- * Nothing to be done here.
- */
-
-static int
-select_del(void *arg, struct event *ev)
-{
- struct selectop *sop = arg;
-
- check_selectop(sop);
- if (ev->ev_events & EV_SIGNAL)
- return (evsignal_del(ev));
-
- if (sop->event_fds < ev->ev_fd) {
- check_selectop(sop);
- return (0);
- }
-
- if (ev->ev_events & EV_READ) {
- FD_CLR(ev->ev_fd, sop->event_readset_in);
- sop->event_r_by_fd[ev->ev_fd] = NULL;
- }
-
- if (ev->ev_events & EV_WRITE) {
- FD_CLR(ev->ev_fd, sop->event_writeset_in);
- sop->event_w_by_fd[ev->ev_fd] = NULL;
- }
-
- check_selectop(sop);
- return (0);
-}
-
-static void
-select_dealloc(struct event_base *base, void *arg)
-{
- struct selectop *sop = arg;
-
- evsignal_dealloc(base);
- if (sop->event_readset_in)
- free(sop->event_readset_in);
- if (sop->event_writeset_in)
- free(sop->event_writeset_in);
- if (sop->event_readset_out)
- free(sop->event_readset_out);
- if (sop->event_writeset_out)
- free(sop->event_writeset_out);
- if (sop->event_r_by_fd)
- free(sop->event_r_by_fd);
- if (sop->event_w_by_fd)
- free(sop->event_w_by_fd);
-
- memset(sop, 0, sizeof(struct selectop));
- free(sop);
-}
-
-#endif /* HAVE_SELECT */
diff --git a/extra/libevent/signal.c b/extra/libevent/signal.c
deleted file mode 100644
index ce164f2f5ea..00000000000
--- a/extra/libevent/signal.c
+++ /dev/null
@@ -1,305 +0,0 @@
-/* $OpenBSD: select.c,v 1.2 2002/06/25 15:50:15 mickey Exp $ */
-
-/*
- * Copyright 2000-2002 Niels Provos <provos@citi.umich.edu>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef WIN32
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <winsock2.h>
-#undef WIN32_LEAN_AND_MEAN
-#endif
-#include <sys/types.h>
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#include <sys/queue.h>
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <errno.h>
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#include <assert.h>
-
-#include "event.h"
-#include "event-internal.h"
-#include "evsignal.h"
-#include "evutil.h"
-#include "log.h"
-
-struct event_base *evsignal_base = NULL;
-
-static void evsignal_handler(int sig);
-
-/* Callback for when the signal handler write a byte to our signaling socket */
-static void
-evsignal_cb(int fd, short what __attribute__((unused)),
- void *arg __attribute__((unused)))
-{
- static char signals[100];
-#ifdef WIN32
- SSIZE_T n;
-#else
- ssize_t n;
-#endif
-
- n = recv(fd, signals, sizeof(signals), 0);
- if (n == -1)
- event_err(1, "%s: read", __func__);
-}
-
-#ifdef HAVE_SETFD
-#define FD_CLOSEONEXEC(x) do { \
- if (fcntl(x, F_SETFD, 1) == -1) \
- event_warn("fcntl(%d, F_SETFD)", x); \
-} while (0)
-#else
-#define FD_CLOSEONEXEC(x)
-#endif
-
-void
-evsignal_init(struct event_base *base)
-{
- /*
- * Our signal handler is going to write to one end of the socket
- * pair to wake up our event loop. The event loop then scans for
- * signals that got delivered.
- */
- if (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, base->sig.ev_signal_pair) == -1)
- event_err(1, "%s: socketpair", __func__);
-
- FD_CLOSEONEXEC(base->sig.ev_signal_pair[0]);
- FD_CLOSEONEXEC(base->sig.ev_signal_pair[1]);
- base->sig.sh_old = NULL;
- base->sig.sh_old_max = 0;
- base->sig.evsignal_caught = 0;
- memset(&base->sig.evsigcaught, 0, sizeof(sig_atomic_t)*NSIG);
-
- evutil_make_socket_nonblocking(base->sig.ev_signal_pair[0]);
-
- event_set(&base->sig.ev_signal, base->sig.ev_signal_pair[1],
- EV_READ | EV_PERSIST, &evsignal_cb, &base->sig.ev_signal);
- base->sig.ev_signal.ev_base = base;
- base->sig.ev_signal.ev_flags |= EVLIST_INTERNAL;
-}
-
-/* Helper: set the signal handler for evsignal to handler in base, so that
- * we can restore the original handler when we clear the current one. */
-int
-_evsignal_set_handler(struct event_base *base,
- int evsignal, void (*handler)(int))
-{
-#ifdef HAVE_SIGACTION
- struct sigaction sa;
-#else
- ev_sighandler_t sh;
-#endif
- struct evsignal_info *sig = &base->sig;
- void *p;
-
- /*
- * resize saved signal handler array up to the highest signal number.
- * a dynamic array is used to keep footprint on the low side.
- */
- if (evsignal >= sig->sh_old_max) {
- event_debug(("%s: evsignal (%d) >= sh_old_max (%d), resizing",
- __func__, evsignal, sig->sh_old_max));
- sig->sh_old_max = evsignal + 1;
- p = realloc(sig->sh_old, sig->sh_old_max * sizeof *sig->sh_old);
- if (p == NULL) {
- event_warn("realloc");
- return (-1);
- }
- sig->sh_old = p;
- }
-
- /* allocate space for previous handler out of dynamic array */
- sig->sh_old[evsignal] = malloc(sizeof *sig->sh_old[evsignal]);
- if (sig->sh_old[evsignal] == NULL) {
- event_warn("malloc");
- return (-1);
- }
-
- /* save previous handler and setup new handler */
-#ifdef HAVE_SIGACTION
- memset(&sa, 0, sizeof(sa));
- sa.sa_handler = handler;
- sa.sa_flags |= SA_RESTART;
- sigfillset(&sa.sa_mask);
-
- if (sigaction(evsignal, &sa, sig->sh_old[evsignal]) == -1) {
- event_warn("sigaction");
- free(sig->sh_old[evsignal]);
- return (-1);
- }
-#else
- if ((sh = signal(evsignal, handler)) == SIG_ERR) {
- event_warn("signal");
- free(sig->sh_old[evsignal]);
- return (-1);
- }
- *sig->sh_old[evsignal] = sh;
-#endif
-
- return (0);
-}
-
-int
-evsignal_add(struct event *ev)
-{
- int evsignal;
- struct event_base *base = ev->ev_base;
- struct evsignal_info *sig = &ev->ev_base->sig;
-
- if (ev->ev_events & (EV_READ|EV_WRITE))
- event_errx(1, "%s: EV_SIGNAL incompatible use", __func__);
- evsignal = EVENT_SIGNAL(ev);
-
- event_debug(("%s: %p: changing signal handler", __func__, ev));
- if (_evsignal_set_handler(base, evsignal, evsignal_handler) == -1)
- return (-1);
-
- /* catch signals if they happen quickly */
- evsignal_base = base;
-
- if (!sig->ev_signal_added) {
- sig->ev_signal_added = 1;
- event_add(&sig->ev_signal, NULL);
- }
-
- return (0);
-}
-
-int
-_evsignal_restore_handler(struct event_base *base, int evsignal)
-{
- int ret = 0;
- struct evsignal_info *sig = &base->sig;
-#ifdef HAVE_SIGACTION
- struct sigaction *sh;
-#else
- ev_sighandler_t *sh;
-#endif
-
- /* restore previous handler */
- sh = sig->sh_old[evsignal];
- sig->sh_old[evsignal] = NULL;
-#ifdef HAVE_SIGACTION
- if (sigaction(evsignal, sh, NULL) == -1) {
- event_warn("sigaction");
- ret = -1;
- }
-#else
- if (signal(evsignal, *sh) == SIG_ERR) {
- event_warn("signal");
- ret = -1;
- }
-#endif
- free(sh);
-
- return ret;
-}
-
-int
-evsignal_del(struct event *ev)
-{
- event_debug(("%s: %p: restoring signal handler", __func__, ev));
- return _evsignal_restore_handler(ev->ev_base, EVENT_SIGNAL(ev));
-}
-
-static void
-evsignal_handler(int sig)
-{
- int save_errno = errno;
-
- if(evsignal_base == NULL) {
- event_warn(
- "%s: received signal %d, but have no base configured",
- __func__, sig);
- return;
- }
-
- evsignal_base->sig.evsigcaught[sig]++;
- evsignal_base->sig.evsignal_caught = 1;
-
-#ifndef HAVE_SIGACTION
- signal(sig, evsignal_handler);
-#endif
-
- /* Wake up our notification mechanism */
- send(evsignal_base->sig.ev_signal_pair[0], "a", 1, 0);
- errno = save_errno;
-}
-
-void
-evsignal_process(struct event_base *base)
-{
- struct event *ev;
- sig_atomic_t ncalls;
-
- base->sig.evsignal_caught = 0;
- TAILQ_FOREACH(ev, &base->sig.signalqueue, ev_signal_next) {
- ncalls = base->sig.evsigcaught[EVENT_SIGNAL(ev)];
- if (ncalls) {
- if (!(ev->ev_events & EV_PERSIST))
- event_del(ev);
- event_active(ev, EV_SIGNAL, ncalls);
- base->sig.evsigcaught[EVENT_SIGNAL(ev)] = 0;
- }
- }
-}
-
-void
-evsignal_dealloc(struct event_base *base)
-{
- if(base->sig.ev_signal_added) {
- event_del(&base->sig.ev_signal);
- base->sig.ev_signal_added = 0;
- }
- assert(TAILQ_EMPTY(&base->sig.signalqueue));
-
- EVUTIL_CLOSESOCKET(base->sig.ev_signal_pair[0]);
- base->sig.ev_signal_pair[0] = -1;
- EVUTIL_CLOSESOCKET(base->sig.ev_signal_pair[1]);
- base->sig.ev_signal_pair[1] = -1;
- base->sig.sh_old_max = 0;
-
- /* per index frees are handled in evsignal_del() */
- free(base->sig.sh_old);
-}
diff --git a/extra/libevent/strlcpy-internal.h b/extra/libevent/strlcpy-internal.h
deleted file mode 100644
index 22b5f61d45e..00000000000
--- a/extra/libevent/strlcpy-internal.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef _STRLCPY_INTERNAL_H_
-#define _STRLCPY_INTERNAL_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif /* HAVE_CONFIG_H */
-
-#ifndef HAVE_STRLCPY
-#include <string.h>
-size_t _event_strlcpy(char *dst, const char *src, size_t siz);
-#define strlcpy _event_strlcpy
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
diff --git a/extra/libevent/strlcpy.c b/extra/libevent/strlcpy.c
deleted file mode 100644
index 5d194527c8c..00000000000
--- a/extra/libevent/strlcpy.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/* $OpenBSD: strlcpy.c,v 1.5 2001/05/13 15:40:16 deraadt Exp $ */
-
-/*
- * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
- * 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.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char *rcsid = "$OpenBSD: strlcpy.c,v 1.5 2001/05/13 15:40:16 deraadt Exp $";
-#endif /* LIBC_SCCS and not lint */
-
-#include <sys/types.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif /* HAVE_CONFIG_H */
-
-#ifndef HAVE_STRLCPY
-#include "strlcpy-internal.h"
-
-/*
- * Copy src to string dst of size siz. At most siz-1 characters
- * will be copied. Always NUL terminates (unless siz == 0).
- * Returns strlen(src); if retval >= siz, truncation occurred.
- */
-size_t
-_event_strlcpy(dst, src, siz)
- char *dst;
- const char *src;
- size_t siz;
-{
- register char *d = dst;
- register const char *s = src;
- register size_t n = siz;
-
- /* Copy as many bytes as will fit */
- if (n != 0 && --n != 0) {
- do {
- if ((*d++ = *s++) == 0)
- break;
- } while (--n != 0);
- }
-
- /* Not enough room in dst, add NUL and traverse rest of src */
- if (n == 0) {
- if (siz != 0)
- *d = '\0'; /* NUL-terminate dst */
- while (*s++)
- ;
- }
-
- return(s - src - 1); /* count does not include NUL */
-}
-#endif