|  | /* | 
|  | * 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 "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; | 
|  | #ifndef EVENT_NO_STRUCT | 
|  | 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; | 
|  | }; | 
|  | #else | 
|  | struct event; | 
|  | #endif | 
|  |  | 
|  | #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(const 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 *, const 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 *, | 
|  | const 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 *base, int fd, short events, | 
|  | void (*callback)(int, short, void *), void *arg, | 
|  | const struct timeval *timeout); | 
|  |  | 
|  |  | 
|  | /** | 
|  | 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 *ev, const struct timeval *timeout); | 
|  |  | 
|  |  | 
|  | /** | 
|  | 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 *ev, short event, struct timeval *tv); | 
|  |  | 
|  |  | 
|  | /** | 
|  | 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; | 
|  | }; | 
|  |  | 
|  | #ifndef EVENT_NO_STRUCT | 
|  | struct bufferevent { | 
|  | struct event_base *ev_base; | 
|  |  | 
|  | 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 */ | 
|  | }; | 
|  | #endif | 
|  |  | 
|  | /** | 
|  | 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); | 
|  |  | 
|  |  | 
|  | /** | 
|  | Changes the callbacks for a bufferevent. | 
|  |  | 
|  | @param bufev the bufferevent object for which to change callbacks | 
|  | @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) | 
|  | @see bufferevent_new() | 
|  | */ | 
|  | void bufferevent_setcb(struct bufferevent *bufev, | 
|  | evbuffercb readcb, evbuffercb writecb, everrorcb errorcb, void *cbarg); | 
|  |  | 
|  | /** | 
|  | Changes the file descriptor on which the bufferevent operates. | 
|  |  | 
|  | @param bufev the bufferevent object for which to change the file descriptor | 
|  | @param fd the file descriptor to operate on | 
|  | */ | 
|  | void bufferevent_setfd(struct bufferevent *bufev, int fd); | 
|  |  | 
|  | /** | 
|  | 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); | 
|  |  | 
|  |  | 
|  | /** | 
|  | Sets the watermarks for read and write events. | 
|  |  | 
|  | On input, a bufferevent does not invoke the user read callback unless | 
|  | there is at least low watermark data in the buffer.   If the read buffer | 
|  | is beyond the high watermark, the buffevent stops reading from the network. | 
|  |  | 
|  | On output, the user write callback is invoked whenever the buffered data | 
|  | falls below the low watermark. | 
|  |  | 
|  | @param bufev the bufferevent to be modified | 
|  | @param events EV_READ, EV_WRITE or both | 
|  | @param lowmark the lower watermark to set | 
|  | @param highmark the high watermark to set | 
|  | */ | 
|  |  | 
|  | void bufferevent_setwatermark(struct bufferevent *bufev, short events, | 
|  | size_t lowmark, size_t highmark); | 
|  |  | 
|  | #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 The number of bytes added 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 The number of bytes added 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 | 
|  | */ | 
|  | 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_ */ |