xref: /openbsd-src/sbin/unwind/libunbound/util/ub_event_pluggable.c (revision 411c5950619d1c25dc667db3029d25c33cefb322)
14d1942afSflorian /*
24d1942afSflorian  * util/ub_event_pluggable.c - call registered pluggable event functions
34d1942afSflorian  *
44d1942afSflorian  * Copyright (c) 2007, NLnet Labs. All rights reserved.
54d1942afSflorian  *
64d1942afSflorian  * This software is open source.
74d1942afSflorian  *
84d1942afSflorian  * Redistribution and use in source and binary forms, with or without
94d1942afSflorian  * modification, are permitted provided that the following conditions
104d1942afSflorian  * are met:
114d1942afSflorian  *
124d1942afSflorian  * Redistributions of source code must retain the above copyright notice,
134d1942afSflorian  * this list of conditions and the following disclaimer.
144d1942afSflorian  *
154d1942afSflorian  * Redistributions in binary form must reproduce the above copyright notice,
164d1942afSflorian  * this list of conditions and the following disclaimer in the documentation
174d1942afSflorian  * and/or other materials provided with the distribution.
184d1942afSflorian  *
194d1942afSflorian  * Neither the name of the NLNET LABS nor the names of its contributors may
204d1942afSflorian  * be used to endorse or promote products derived from this software without
214d1942afSflorian  * specific prior written permission.
224d1942afSflorian  *
234d1942afSflorian  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
244d1942afSflorian  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
254d1942afSflorian  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
264d1942afSflorian  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
274d1942afSflorian  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
284d1942afSflorian  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
294d1942afSflorian  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
304d1942afSflorian  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
314d1942afSflorian  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
324d1942afSflorian  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
334d1942afSflorian  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
344d1942afSflorian  */
354d1942afSflorian 
364d1942afSflorian /**
374d1942afSflorian  * \file
384d1942afSflorian  *
394d1942afSflorian  * This file contains an implementation for the indirection layer for pluggable
404d1942afSflorian  * events that calls the registered pluggable event loop.  It also defines a
414d1942afSflorian  * default pluggable event loop based on the default libevent (compatibility)
424d1942afSflorian  * functions.
434d1942afSflorian  */
444d1942afSflorian #include "config.h"
454d1942afSflorian #include <sys/time.h>
464d1942afSflorian #include "util/ub_event.h"
474d1942afSflorian #include "libunbound/unbound-event.h"
484d1942afSflorian #include "util/netevent.h"
494d1942afSflorian #include "util/log.h"
504d1942afSflorian #include "util/fptr_wlist.h"
514d1942afSflorian 
524d1942afSflorian /* We define libevent structures here to hide the libevent stuff. */
534d1942afSflorian 
544d1942afSflorian #ifdef USE_MINI_EVENT
554d1942afSflorian #  ifdef USE_WINSOCK
564d1942afSflorian #    include "util/winsock_event.h"
574d1942afSflorian #  else
584d1942afSflorian #    include "util/mini_event.h"
594d1942afSflorian #  endif /* USE_WINSOCK */
604d1942afSflorian #else /* USE_MINI_EVENT */
614d1942afSflorian    /* we use libevent */
624d1942afSflorian #  ifdef HAVE_EVENT_H
634d1942afSflorian #    include <event.h>
644d1942afSflorian #  else
654d1942afSflorian #    include "event2/event.h"
664d1942afSflorian #    include "event2/event_struct.h"
674d1942afSflorian #    include "event2/event_compat.h"
684d1942afSflorian #  endif
694d1942afSflorian #endif /* USE_MINI_EVENT */
704d1942afSflorian 
714d1942afSflorian #if UB_EV_TIMEOUT != EV_TIMEOUT || UB_EV_READ != EV_READ || \
724d1942afSflorian     UB_EV_WRITE != EV_WRITE || UB_EV_SIGNAL != EV_SIGNAL || \
734d1942afSflorian     UB_EV_PERSIST != EV_PERSIST
744d1942afSflorian /* Only necessary for libev */
754d1942afSflorian #  define NATIVE_BITS(b) ( \
764d1942afSflorian 	  (((b) & UB_EV_TIMEOUT) ? EV_TIMEOUT : 0) \
774d1942afSflorian 	| (((b) & UB_EV_READ   ) ? EV_READ    : 0) \
784d1942afSflorian 	| (((b) & UB_EV_WRITE  ) ? EV_WRITE   : 0) \
794d1942afSflorian 	| (((b) & UB_EV_SIGNAL ) ? EV_SIGNAL  : 0) \
804d1942afSflorian 	| (((b) & UB_EV_PERSIST) ? EV_PERSIST : 0))
814d1942afSflorian 
824d1942afSflorian #  define UB_EV_BITS(b) ( \
834d1942afSflorian 	  (((b) & EV_TIMEOUT) ? UB_EV_TIMEOUT : 0) \
844d1942afSflorian 	| (((b) & EV_READ   ) ? UB_EV_READ    : 0) \
854d1942afSflorian 	| (((b) & EV_WRITE  ) ? UB_EV_WRITE   : 0) \
864d1942afSflorian 	| (((b) & EV_SIGNAL ) ? UB_EV_SIGNAL  : 0) \
874d1942afSflorian 	| (((b) & EV_PERSIST) ? UB_EV_PERSIST : 0))
884d1942afSflorian 
894d1942afSflorian #  define UB_EV_BITS_CB(C) void my_ ## C (int fd, short bits, void *arg) \
904d1942afSflorian 	{ (C)(fd, UB_EV_BITS(bits), arg); }
914d1942afSflorian 
924d1942afSflorian UB_EV_BITS_CB(comm_point_udp_callback);
934d1942afSflorian UB_EV_BITS_CB(comm_point_udp_ancil_callback)
UB_EV_BITS_CB(comm_point_tcp_accept_callback)944d1942afSflorian UB_EV_BITS_CB(comm_point_tcp_accept_callback)
954d1942afSflorian UB_EV_BITS_CB(comm_point_tcp_handle_callback)
964d1942afSflorian UB_EV_BITS_CB(comm_timer_callback)
974d1942afSflorian UB_EV_BITS_CB(comm_signal_callback)
984d1942afSflorian UB_EV_BITS_CB(comm_point_local_handle_callback)
994d1942afSflorian UB_EV_BITS_CB(comm_point_raw_handle_callback)
1004d1942afSflorian UB_EV_BITS_CB(tube_handle_signal)
1014d1942afSflorian UB_EV_BITS_CB(comm_base_handle_slow_accept)
1024d1942afSflorian 
1034d1942afSflorian static void (*NATIVE_BITS_CB(void (*cb)(int, short, void*)))(int, short, void*)
1044d1942afSflorian {
1054d1942afSflorian 	if(cb == comm_point_udp_callback)
1064d1942afSflorian 		return my_comm_point_udp_callback;
1074d1942afSflorian 	else if(cb == comm_point_udp_ancil_callback)
1084d1942afSflorian 		return my_comm_point_udp_ancil_callback;
1094d1942afSflorian 	else if(cb == comm_point_tcp_accept_callback)
1104d1942afSflorian 		return my_comm_point_tcp_accept_callback;
1114d1942afSflorian 	else if(cb == comm_point_tcp_handle_callback)
1124d1942afSflorian 		return my_comm_point_tcp_handle_callback;
1134d1942afSflorian 	else if(cb == comm_timer_callback)
1144d1942afSflorian 		return my_comm_timer_callback;
1154d1942afSflorian 	else if(cb == comm_signal_callback)
1164d1942afSflorian 		return my_comm_signal_callback;
1174d1942afSflorian 	else if(cb == comm_point_local_handle_callback)
1184d1942afSflorian 		return my_comm_point_local_handle_callback;
1194d1942afSflorian 	else if(cb == comm_point_raw_handle_callback)
1204d1942afSflorian 		return my_comm_point_raw_handle_callback;
1214d1942afSflorian 	else if(cb == tube_handle_signal)
1224d1942afSflorian 		return my_tube_handle_signal;
1234d1942afSflorian 	else if(cb == comm_base_handle_slow_accept)
1244d1942afSflorian 		return my_comm_base_handle_slow_accept;
1254d1942afSflorian 	else
1264d1942afSflorian 		return NULL;
1274d1942afSflorian }
1284d1942afSflorian #else
1294d1942afSflorian #  define NATIVE_BITS(b) (b)
1304d1942afSflorian #  define NATIVE_BITS_CB(c) (c)
1314d1942afSflorian #endif
1324d1942afSflorian 
1334d1942afSflorian #ifndef EVFLAG_AUTO
1344d1942afSflorian #define EVFLAG_AUTO 0
1354d1942afSflorian #endif
1364d1942afSflorian 
1374d1942afSflorian struct my_event_base {
1384d1942afSflorian 	struct ub_event_base super;
1394d1942afSflorian 	struct event_base* base;
1404d1942afSflorian };
1414d1942afSflorian 
1424d1942afSflorian struct my_event {
1434d1942afSflorian 	struct ub_event super;
1444d1942afSflorian 	struct event ev;
1454d1942afSflorian };
1464d1942afSflorian 
1474d1942afSflorian #define AS_MY_EVENT_BASE(x) ((struct my_event_base*)x)
1484d1942afSflorian #define AS_MY_EVENT(x) ((struct my_event*)x)
1494d1942afSflorian 
ub_event_get_version(void)1504d1942afSflorian const char* ub_event_get_version(void)
1514d1942afSflorian {
1524d1942afSflorian 	return "pluggable-event"PACKAGE_VERSION;
1534d1942afSflorian }
1544d1942afSflorian 
1554d1942afSflorian static void
my_event_add_bits(struct ub_event * ev,short bits)1564d1942afSflorian my_event_add_bits(struct ub_event* ev, short bits)
1574d1942afSflorian {
1584d1942afSflorian 	AS_MY_EVENT(ev)->ev.ev_events |= NATIVE_BITS(bits);
1594d1942afSflorian }
1604d1942afSflorian 
1614d1942afSflorian static void
my_event_del_bits(struct ub_event * ev,short bits)1624d1942afSflorian my_event_del_bits(struct ub_event* ev, short bits)
1634d1942afSflorian {
1644d1942afSflorian 	AS_MY_EVENT(ev)->ev.ev_events &= ~NATIVE_BITS(bits);
1654d1942afSflorian }
1664d1942afSflorian 
1674d1942afSflorian static void
my_event_set_fd(struct ub_event * ev,int fd)1684d1942afSflorian my_event_set_fd(struct ub_event* ev, int fd)
1694d1942afSflorian {
1704d1942afSflorian 	AS_MY_EVENT(ev)->ev.ev_fd = fd;
1714d1942afSflorian }
1724d1942afSflorian 
1734d1942afSflorian static void
my_event_free(struct ub_event * ev)1744d1942afSflorian my_event_free(struct ub_event* ev)
1754d1942afSflorian {
1764d1942afSflorian 	free(AS_MY_EVENT(ev));
1774d1942afSflorian }
1784d1942afSflorian 
1794d1942afSflorian static int
my_event_add(struct ub_event * ev,struct timeval * tv)1804d1942afSflorian my_event_add(struct ub_event* ev, struct timeval* tv)
1814d1942afSflorian {
1824d1942afSflorian 	return event_add(&AS_MY_EVENT(ev)->ev, tv);
1834d1942afSflorian }
1844d1942afSflorian 
1854d1942afSflorian static int
my_event_del(struct ub_event * ev)1864d1942afSflorian my_event_del(struct ub_event* ev)
1874d1942afSflorian {
1884d1942afSflorian 	return event_del(&AS_MY_EVENT(ev)->ev);
1894d1942afSflorian }
1904d1942afSflorian 
1914d1942afSflorian static int
my_timer_add(struct ub_event * ev,struct ub_event_base * base,void (* cb)(int,short,void *),void * arg,struct timeval * tv)1924d1942afSflorian my_timer_add(struct ub_event* ev, struct ub_event_base* base,
1934d1942afSflorian 	void (*cb)(int, short, void*), void* arg, struct timeval* tv)
1944d1942afSflorian {
1954d1942afSflorian 	event_set(&AS_MY_EVENT(ev)->ev, -1, EV_TIMEOUT,NATIVE_BITS_CB(cb),arg);
1964d1942afSflorian 	if (event_base_set(AS_MY_EVENT_BASE(base)->base, &AS_MY_EVENT(ev)->ev)
1974d1942afSflorian 		!= 0)
1984d1942afSflorian 		return -1;
1994d1942afSflorian 	return evtimer_add(&AS_MY_EVENT(ev)->ev, tv);
2004d1942afSflorian }
2014d1942afSflorian 
2024d1942afSflorian static int
my_timer_del(struct ub_event * ev)2034d1942afSflorian my_timer_del(struct ub_event* ev)
2044d1942afSflorian {
2054d1942afSflorian 	return evtimer_del(&AS_MY_EVENT(ev)->ev);
2064d1942afSflorian }
2074d1942afSflorian 
2084d1942afSflorian static int
my_signal_add(struct ub_event * ev,struct timeval * tv)2094d1942afSflorian my_signal_add(struct ub_event* ev, struct timeval* tv)
2104d1942afSflorian {
2114d1942afSflorian 	return signal_add(&AS_MY_EVENT(ev)->ev, tv);
2124d1942afSflorian }
2134d1942afSflorian 
2144d1942afSflorian static int
my_signal_del(struct ub_event * ev)2154d1942afSflorian my_signal_del(struct ub_event* ev)
2164d1942afSflorian {
2174d1942afSflorian 	return signal_del(&AS_MY_EVENT(ev)->ev);
2184d1942afSflorian }
2194d1942afSflorian 
2204d1942afSflorian static void
my_winsock_unregister_wsaevent(struct ub_event * ev)2214d1942afSflorian my_winsock_unregister_wsaevent(struct ub_event* ev)
2224d1942afSflorian {
2234d1942afSflorian #if defined(USE_MINI_EVENT) && defined(USE_WINSOCK)
2244d1942afSflorian 	winsock_unregister_wsaevent(&AS_MY_EVENT(ev)->ev);
2254d1942afSflorian 	free(AS_MY_EVENT(ev));
2264d1942afSflorian #else
2274d1942afSflorian 	(void)ev;
2284d1942afSflorian #endif
2294d1942afSflorian }
2304d1942afSflorian 
2314d1942afSflorian static void
my_winsock_tcp_wouldblock(struct ub_event * ev,int eventbits)2324d1942afSflorian my_winsock_tcp_wouldblock(struct ub_event* ev, int eventbits)
2334d1942afSflorian {
2344d1942afSflorian #if defined(USE_MINI_EVENT) && defined(USE_WINSOCK)
2354d1942afSflorian 	winsock_tcp_wouldblock(&AS_MY_EVENT(ev)->ev, NATIVE_BITS(eventbits));
2364d1942afSflorian #else
2374d1942afSflorian 	(void)ev;
2384d1942afSflorian 	(void)eventbits;
2394d1942afSflorian #endif
2404d1942afSflorian }
2414d1942afSflorian 
2424d1942afSflorian static struct ub_event_vmt default_event_vmt = {
2434d1942afSflorian 	my_event_add_bits, my_event_del_bits, my_event_set_fd,
2444d1942afSflorian 	my_event_free, my_event_add, my_event_del,
2454d1942afSflorian 	my_timer_add, my_timer_del, my_signal_add, my_signal_del,
2464d1942afSflorian 	my_winsock_unregister_wsaevent, my_winsock_tcp_wouldblock
2474d1942afSflorian };
2484d1942afSflorian 
2494d1942afSflorian static void
my_event_base_free(struct ub_event_base * base)2504d1942afSflorian my_event_base_free(struct ub_event_base* base)
2514d1942afSflorian {
2524d1942afSflorian #ifdef USE_MINI_EVENT
2534d1942afSflorian 	event_base_free(AS_MY_EVENT_BASE(base)->base);
2544d1942afSflorian #elif defined(HAVE_EVENT_BASE_FREE) && defined(HAVE_EVENT_BASE_ONCE)
2554d1942afSflorian 	/* only libevent 1.2+ has it, but in 1.2 it is broken -
2564d1942afSflorian 	   assertion fails on signal handling ev that is not deleted
2574d1942afSflorian  	   in libevent 1.3c (event_base_once appears) this is fixed. */
2584d1942afSflorian 	event_base_free(AS_MY_EVENT_BASE(base)->base);
2594d1942afSflorian #endif /* HAVE_EVENT_BASE_FREE and HAVE_EVENT_BASE_ONCE */
2604d1942afSflorian 	free(AS_MY_EVENT_BASE(base));
2614d1942afSflorian }
2624d1942afSflorian 
2634d1942afSflorian static int
my_event_base_dispatch(struct ub_event_base * base)2644d1942afSflorian my_event_base_dispatch(struct ub_event_base* base)
2654d1942afSflorian {
2664d1942afSflorian 	return event_base_dispatch(AS_MY_EVENT_BASE(base)->base);
2674d1942afSflorian }
2684d1942afSflorian 
2694d1942afSflorian static int
my_event_base_loopexit(struct ub_event_base * base,struct timeval * tv)2704d1942afSflorian my_event_base_loopexit(struct ub_event_base* base, struct timeval* tv)
2714d1942afSflorian {
2724d1942afSflorian 	return event_base_loopexit(AS_MY_EVENT_BASE(base)->base, tv);
2734d1942afSflorian }
2744d1942afSflorian 
2754d1942afSflorian static struct ub_event*
my_event_new(struct ub_event_base * base,int fd,short bits,void (* cb)(int,short,void *),void * arg)2764d1942afSflorian my_event_new(struct ub_event_base* base, int fd, short bits,
2774d1942afSflorian 	void (*cb)(int, short, void*), void* arg)
2784d1942afSflorian {
2794d1942afSflorian 	struct my_event *my_ev = (struct my_event*)calloc(1,
2804d1942afSflorian 		sizeof(struct my_event));
2814d1942afSflorian 
2824d1942afSflorian 	if (!my_ev)
2834d1942afSflorian 		return NULL;
2844d1942afSflorian 
2854d1942afSflorian 	event_set(&my_ev->ev, fd, NATIVE_BITS(bits), NATIVE_BITS_CB(cb), arg);
2864d1942afSflorian 	if (event_base_set(AS_MY_EVENT_BASE(base)->base, &my_ev->ev) != 0) {
2874d1942afSflorian 		free(my_ev);
2884d1942afSflorian 		return NULL;
2894d1942afSflorian 	}
2904d1942afSflorian 	my_ev->super.magic = UB_EVENT_MAGIC;
2914d1942afSflorian 	my_ev->super.vmt = &default_event_vmt;
2924d1942afSflorian 	return &my_ev->super;
2934d1942afSflorian }
2944d1942afSflorian 
2954d1942afSflorian static struct ub_event*
my_signal_new(struct ub_event_base * base,int fd,void (* cb)(int,short,void *),void * arg)2964d1942afSflorian my_signal_new(struct ub_event_base* base, int fd,
2974d1942afSflorian 	void (*cb)(int, short, void*), void* arg)
2984d1942afSflorian {
2994d1942afSflorian 	struct my_event *my_ev = (struct my_event*)calloc(1,
3004d1942afSflorian 		sizeof(struct my_event));
3014d1942afSflorian 
3024d1942afSflorian 	if (!my_ev)
3034d1942afSflorian 		return NULL;
3044d1942afSflorian 
3054d1942afSflorian 	signal_set(&my_ev->ev, fd, NATIVE_BITS_CB(cb), arg);
3064d1942afSflorian 	if (event_base_set(AS_MY_EVENT_BASE(base)->base, &my_ev->ev) != 0) {
3074d1942afSflorian 		free(my_ev);
3084d1942afSflorian 		return NULL;
3094d1942afSflorian 	}
3104d1942afSflorian 	my_ev->super.magic = UB_EVENT_MAGIC;
3114d1942afSflorian 	my_ev->super.vmt = &default_event_vmt;
3124d1942afSflorian 	return &my_ev->super;
3134d1942afSflorian }
3144d1942afSflorian 
3154d1942afSflorian static struct ub_event*
my_winsock_register_wsaevent(struct ub_event_base * base,void * wsaevent,void (* cb)(int,short,void *),void * arg)3164d1942afSflorian my_winsock_register_wsaevent(struct ub_event_base* base, void* wsaevent,
3174d1942afSflorian 	void (*cb)(int, short, void*), void* arg)
3184d1942afSflorian {
3194d1942afSflorian #if defined(USE_MINI_EVENT) && defined(USE_WINSOCK)
3204d1942afSflorian 	struct my_event *my_ev = (struct my_event*)calloc(1,
3214d1942afSflorian 		sizeof(struct my_event));
3224d1942afSflorian 
3234d1942afSflorian 	if (!my_ev)
3244d1942afSflorian 		return NULL;
3254d1942afSflorian 
3264d1942afSflorian 	if (!winsock_register_wsaevent(AS_MY_EVENT_BASE(base)->base,
3274d1942afSflorian 		&my_ev->ev, wsaevent, cb, arg)) {
3284d1942afSflorian 		free(my_ev);
3294d1942afSflorian 		return NULL;
3304d1942afSflorian 
3314d1942afSflorian 	}
3324d1942afSflorian 	my_ev->super.magic = UB_EVENT_MAGIC;
3334d1942afSflorian 	my_ev->super.vmt = &default_event_vmt;
3344d1942afSflorian 	return &my_ev->super;
3354d1942afSflorian #else
3364d1942afSflorian 	(void)base;
3374d1942afSflorian 	(void)wsaevent;
3384d1942afSflorian 	(void)cb;
3394d1942afSflorian 	(void)arg;
3404d1942afSflorian 	return NULL;
3414d1942afSflorian #endif
3424d1942afSflorian }
3434d1942afSflorian 
3444d1942afSflorian static struct ub_event_base_vmt default_event_base_vmt = {
3454d1942afSflorian 	my_event_base_free, my_event_base_dispatch,
3464d1942afSflorian 	my_event_base_loopexit, my_event_new, my_signal_new,
3474d1942afSflorian 	my_winsock_register_wsaevent
3484d1942afSflorian };
3494d1942afSflorian 
3504d1942afSflorian struct ub_event_base*
ub_default_event_base(int sigs,time_t * time_secs,struct timeval * time_tv)3514d1942afSflorian ub_default_event_base(int sigs, time_t* time_secs, struct timeval* time_tv)
3524d1942afSflorian {
3534d1942afSflorian 	struct my_event_base* my_base = (struct my_event_base*)calloc(1,
3544d1942afSflorian 		sizeof(struct my_event_base));
3554d1942afSflorian 
3564d1942afSflorian 	if (!my_base)
3574d1942afSflorian 		return NULL;
3584d1942afSflorian 
3594d1942afSflorian #ifdef USE_MINI_EVENT
3604d1942afSflorian 	(void)sigs;
3614d1942afSflorian 	/* use mini event time-sharing feature */
3624d1942afSflorian 	my_base->base = event_init(time_secs, time_tv);
3634d1942afSflorian #else
3644d1942afSflorian 	(void)time_secs;
3654d1942afSflorian 	(void)time_tv;
3664d1942afSflorian #  if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)
3674d1942afSflorian 	/* libev */
3684d1942afSflorian 	if(sigs)
3694d1942afSflorian 		my_base->base = (struct event_base*)ev_default_loop(EVFLAG_AUTO);
3704d1942afSflorian 	else
3714d1942afSflorian 		my_base->base = (struct event_base*)ev_loop_new(EVFLAG_AUTO);
3724d1942afSflorian #  else
3734d1942afSflorian 	(void)sigs;
3744d1942afSflorian #    ifdef HAVE_EVENT_BASE_NEW
3754d1942afSflorian 	my_base->base = event_base_new();
3764d1942afSflorian #    else
3774d1942afSflorian 	my_base->base = event_init();
3784d1942afSflorian #    endif
3794d1942afSflorian #  endif
3804d1942afSflorian #endif
3814d1942afSflorian 	if (!my_base->base) {
3824d1942afSflorian 		free(my_base);
3834d1942afSflorian 		return NULL;
3844d1942afSflorian 	}
3854d1942afSflorian 	my_base->super.magic = UB_EVENT_MAGIC;
3864d1942afSflorian 	my_base->super.vmt = &default_event_base_vmt;
3874d1942afSflorian 	return &my_base->super;
3884d1942afSflorian }
3894d1942afSflorian 
3904d1942afSflorian struct ub_event_base*
ub_libevent_event_base(struct event_base * base)3914d1942afSflorian ub_libevent_event_base(struct event_base* base)
3924d1942afSflorian {
3934d1942afSflorian #ifdef USE_MINI_EVENT
3944d1942afSflorian 	(void)base;
3954d1942afSflorian 	return NULL;
3964d1942afSflorian #else
3974d1942afSflorian 	struct my_event_base* my_base = (struct my_event_base*)calloc(1,
3984d1942afSflorian 		sizeof(struct my_event_base));
3994d1942afSflorian 
4004d1942afSflorian 	if (!my_base)
4014d1942afSflorian 		return NULL;
4024d1942afSflorian 	my_base->super.magic = UB_EVENT_MAGIC;
4034d1942afSflorian 	my_base->super.vmt = &default_event_base_vmt;
4044d1942afSflorian 	my_base->base = base;
4054d1942afSflorian 	return &my_base->super;
4064d1942afSflorian #endif
4074d1942afSflorian }
4084d1942afSflorian 
4094d1942afSflorian struct event_base*
ub_libevent_get_event_base(struct ub_event_base * base)4104d1942afSflorian ub_libevent_get_event_base(struct ub_event_base* base)
4114d1942afSflorian {
4124d1942afSflorian #ifndef USE_MINI_EVENT
4134d1942afSflorian 	if (base->vmt == &default_event_base_vmt)
4144d1942afSflorian 		return AS_MY_EVENT_BASE(base)->base;
4154d1942afSflorian #else
4164d1942afSflorian 	(void)base;
4174d1942afSflorian #endif
4184d1942afSflorian 	return NULL;
4194d1942afSflorian }
4204d1942afSflorian 
4214d1942afSflorian #if (defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)) && defined(EVBACKEND_SELECT)
ub_ev_backend2str_pluggable(int b)4224d1942afSflorian static const char* ub_ev_backend2str_pluggable(int b)
4234d1942afSflorian {
4244d1942afSflorian 	switch(b) {
4254d1942afSflorian 	case EVBACKEND_SELECT:	return "select";
4264d1942afSflorian 	case EVBACKEND_POLL:	return "poll";
4274d1942afSflorian 	case EVBACKEND_EPOLL:	return "epoll";
4284d1942afSflorian 	case EVBACKEND_KQUEUE:	return "kqueue";
4294d1942afSflorian 	case EVBACKEND_DEVPOLL: return "devpoll";
4304d1942afSflorian 	case EVBACKEND_PORT:	return "evport";
4314d1942afSflorian 	}
4324d1942afSflorian 	return "unknown";
4334d1942afSflorian }
4344d1942afSflorian #endif
4354d1942afSflorian 
4364d1942afSflorian void
ub_get_event_sys(struct ub_event_base * ub_base,const char ** n,const char ** s,const char ** m)4374d1942afSflorian ub_get_event_sys(struct ub_event_base* ub_base, const char** n, const char** s,
4384d1942afSflorian 	const char** m)
4394d1942afSflorian {
4404d1942afSflorian #ifdef USE_WINSOCK
4414d1942afSflorian 	(void)ub_base;
4424d1942afSflorian 	*n = "pluggable-event";
4434d1942afSflorian 	*s = "winsock";
4444d1942afSflorian 	*m = "WSAWaitForMultipleEvents";
4454d1942afSflorian #elif defined(USE_MINI_EVENT)
4464d1942afSflorian 	(void)ub_base;
4474d1942afSflorian 	*n = "pluggable-event";
4484d1942afSflorian 	*s = "internal";
4494d1942afSflorian 	*m = "select";
4504d1942afSflorian #else
4514d1942afSflorian 	struct event_base* b = ub_libevent_get_event_base(ub_base);
4524d1942afSflorian 	/* This function is only called from comm_base_create, so
4534d1942afSflorian 	 * ub_base is guaranteed to exist and to be the default
4544d1942afSflorian 	 * event base.
4554d1942afSflorian 	 */
4564d1942afSflorian 	assert(b != NULL);
4574d1942afSflorian 	*n = "pluggable-event";
4584d1942afSflorian 	*s = event_get_version();
4594d1942afSflorian #  if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)
4604d1942afSflorian 	*n = "pluggable-libev";
4614d1942afSflorian #    ifdef EVBACKEND_SELECT
4624d1942afSflorian 	*m = ub_ev_backend2str_pluggable(ev_backend((struct ev_loop*)b));
4634d1942afSflorian #    else
4644d1942afSflorian 	*m = "not obtainable";
4654d1942afSflorian #    endif
4664d1942afSflorian #  elif defined(HAVE_EVENT_BASE_GET_METHOD)
4674d1942afSflorian 	*n = "pluggable-libevent";
4684d1942afSflorian 	*m = event_base_get_method(b);
4694d1942afSflorian #  else
4704d1942afSflorian 	*m = "not obtainable";
4714d1942afSflorian #  endif
4724d1942afSflorian #endif
4734d1942afSflorian }
4744d1942afSflorian 
4754d1942afSflorian void
ub_event_base_free(struct ub_event_base * base)4764d1942afSflorian ub_event_base_free(struct ub_event_base* base)
4774d1942afSflorian {
4784d1942afSflorian 	if (base && base->magic == UB_EVENT_MAGIC) {
4794d1942afSflorian 		fptr_ok(base->vmt != &default_event_base_vmt ||
4804d1942afSflorian 			base->vmt->free == my_event_base_free);
4814d1942afSflorian 		(*base->vmt->free)(base);
4824d1942afSflorian 	}
4834d1942afSflorian }
4844d1942afSflorian 
4854d1942afSflorian int
ub_event_base_dispatch(struct ub_event_base * base)4864d1942afSflorian ub_event_base_dispatch(struct ub_event_base* base)
4874d1942afSflorian {
4884d1942afSflorian 	if (base->magic == UB_EVENT_MAGIC) {
4894d1942afSflorian 		fptr_ok(base->vmt != &default_event_base_vmt ||
4904d1942afSflorian 			base->vmt->dispatch == my_event_base_dispatch);
4914d1942afSflorian 		return (*base->vmt->dispatch)(base);
4924d1942afSflorian 	}
4934d1942afSflorian 	return -1;
4944d1942afSflorian }
4954d1942afSflorian 
4964d1942afSflorian int
ub_event_base_loopexit(struct ub_event_base * base)4974d1942afSflorian ub_event_base_loopexit(struct ub_event_base* base)
4984d1942afSflorian {
4994d1942afSflorian 	if (base->magic == UB_EVENT_MAGIC) {
5004d1942afSflorian 		fptr_ok(base->vmt != &default_event_base_vmt ||
5014d1942afSflorian 			base->vmt->loopexit == my_event_base_loopexit);
5024d1942afSflorian 		return (*base->vmt->loopexit)(base, NULL);
5034d1942afSflorian 	}
5044d1942afSflorian 	return -1;
5054d1942afSflorian }
5064d1942afSflorian 
5074d1942afSflorian struct ub_event*
ub_event_new(struct ub_event_base * base,int fd,short bits,void (* cb)(int,short,void *),void * arg)5084d1942afSflorian ub_event_new(struct ub_event_base* base, int fd, short bits,
5094d1942afSflorian 	void (*cb)(int, short, void*), void* arg)
5104d1942afSflorian {
5114d1942afSflorian 	if (base->magic == UB_EVENT_MAGIC) {
5124d1942afSflorian 		fptr_ok(base->vmt != &default_event_base_vmt ||
5134d1942afSflorian 			base->vmt->new_event == my_event_new);
5144d1942afSflorian 		return (*base->vmt->new_event)(base, fd, bits, cb, arg);
5154d1942afSflorian 	}
5164d1942afSflorian 	return NULL;
5174d1942afSflorian }
5184d1942afSflorian 
5194d1942afSflorian struct ub_event*
ub_signal_new(struct ub_event_base * base,int fd,void (* cb)(int,short,void *),void * arg)5204d1942afSflorian ub_signal_new(struct ub_event_base* base, int fd,
5214d1942afSflorian 	void (*cb)(int, short, void*), void* arg)
5224d1942afSflorian {
5234d1942afSflorian 	if (base->magic == UB_EVENT_MAGIC) {
5244d1942afSflorian 		fptr_ok(base->vmt != &default_event_base_vmt ||
5254d1942afSflorian 			base->vmt->new_signal == my_signal_new);
5264d1942afSflorian 		return (*base->vmt->new_signal)(base, fd, cb, arg);
5274d1942afSflorian 	}
5284d1942afSflorian 	return NULL;
5294d1942afSflorian }
5304d1942afSflorian 
5314d1942afSflorian struct ub_event*
ub_winsock_register_wsaevent(struct ub_event_base * base,void * wsaevent,void (* cb)(int,short,void *),void * arg)5324d1942afSflorian ub_winsock_register_wsaevent(struct ub_event_base* base, void* wsaevent,
5334d1942afSflorian 	void (*cb)(int, short, void*), void* arg)
5344d1942afSflorian {
5354d1942afSflorian 	if (base->magic == UB_EVENT_MAGIC) {
5364d1942afSflorian 		fptr_ok(base->vmt != &default_event_base_vmt ||
5374d1942afSflorian 			base->vmt->winsock_register_wsaevent ==
5384d1942afSflorian 			my_winsock_register_wsaevent);
5394d1942afSflorian 		return (*base->vmt->winsock_register_wsaevent)(base, wsaevent, cb, arg);
5404d1942afSflorian 	}
5414d1942afSflorian 	return NULL;
5424d1942afSflorian }
5434d1942afSflorian 
5444d1942afSflorian void
ub_event_add_bits(struct ub_event * ev,short bits)5454d1942afSflorian ub_event_add_bits(struct ub_event* ev, short bits)
5464d1942afSflorian {
5474d1942afSflorian 	if (ev->magic == UB_EVENT_MAGIC) {
5484d1942afSflorian 		fptr_ok(ev->vmt != &default_event_vmt ||
5494d1942afSflorian 			ev->vmt->add_bits == my_event_add_bits);
5504d1942afSflorian 		(*ev->vmt->add_bits)(ev, bits);
5514d1942afSflorian 	}
5524d1942afSflorian }
5534d1942afSflorian 
5544d1942afSflorian void
ub_event_del_bits(struct ub_event * ev,short bits)5554d1942afSflorian ub_event_del_bits(struct ub_event* ev, short bits)
5564d1942afSflorian {
5574d1942afSflorian 	if (ev->magic == UB_EVENT_MAGIC) {
5584d1942afSflorian 		fptr_ok(ev->vmt != &default_event_vmt ||
5594d1942afSflorian 			ev->vmt->del_bits == my_event_del_bits);
5604d1942afSflorian 		(*ev->vmt->del_bits)(ev, bits);
5614d1942afSflorian 	}
5624d1942afSflorian }
5634d1942afSflorian 
5644d1942afSflorian void
ub_event_set_fd(struct ub_event * ev,int fd)5654d1942afSflorian ub_event_set_fd(struct ub_event* ev, int fd)
5664d1942afSflorian {
5674d1942afSflorian 	if (ev->magic == UB_EVENT_MAGIC) {
5684d1942afSflorian 		fptr_ok(ev->vmt != &default_event_vmt ||
5694d1942afSflorian 			ev->vmt->set_fd == my_event_set_fd);
5704d1942afSflorian 		(*ev->vmt->set_fd)(ev, fd);
5714d1942afSflorian 	}
5724d1942afSflorian }
5734d1942afSflorian 
5744d1942afSflorian void
ub_event_free(struct ub_event * ev)5754d1942afSflorian ub_event_free(struct ub_event* ev)
5764d1942afSflorian {
5774d1942afSflorian 	if (ev && ev->magic == UB_EVENT_MAGIC) {
5784d1942afSflorian 		fptr_ok(ev->vmt != &default_event_vmt ||
5794d1942afSflorian 			ev->vmt->free == my_event_free);
5804d1942afSflorian 		(*ev->vmt->free)(ev);
5814d1942afSflorian 	}
5824d1942afSflorian }
5834d1942afSflorian 
5844d1942afSflorian int
ub_event_add(struct ub_event * ev,struct timeval * tv)5854d1942afSflorian ub_event_add(struct ub_event* ev, struct timeval* tv)
5864d1942afSflorian {
5874d1942afSflorian 	if (ev->magic == UB_EVENT_MAGIC) {
5884d1942afSflorian 		fptr_ok(ev->vmt != &default_event_vmt ||
5894d1942afSflorian 			ev->vmt->add == my_event_add);
5904d1942afSflorian 		return (*ev->vmt->add)(ev, tv);
5914d1942afSflorian 	}
5924d1942afSflorian        return -1;
5934d1942afSflorian }
5944d1942afSflorian 
5954d1942afSflorian int
ub_event_del(struct ub_event * ev)5964d1942afSflorian ub_event_del(struct ub_event* ev)
5974d1942afSflorian {
5984d1942afSflorian 	if (ev && ev->magic == UB_EVENT_MAGIC) {
5994d1942afSflorian 		fptr_ok(ev->vmt != &default_event_vmt ||
6004d1942afSflorian 			ev->vmt->del == my_event_del);
6014d1942afSflorian 		return (*ev->vmt->del)(ev);
6024d1942afSflorian 	}
6034d1942afSflorian 	return -1;
6044d1942afSflorian }
6054d1942afSflorian 
6064d1942afSflorian int
ub_timer_add(struct ub_event * ev,struct ub_event_base * base,void (* cb)(int,short,void *),void * arg,struct timeval * tv)6074d1942afSflorian ub_timer_add(struct ub_event* ev, struct ub_event_base* base,
6084d1942afSflorian 	void (*cb)(int, short, void*), void* arg, struct timeval* tv)
6094d1942afSflorian {
6104d1942afSflorian 	if (ev->magic == UB_EVENT_MAGIC) {
6114d1942afSflorian 		fptr_ok(ev->vmt != &default_event_vmt ||
6124d1942afSflorian 			ev->vmt->add_timer == my_timer_add);
6134d1942afSflorian 		return (*ev->vmt->add_timer)(ev, base, cb, arg, tv);
6144d1942afSflorian 	}
6154d1942afSflorian 	return -1;
6164d1942afSflorian }
6174d1942afSflorian 
6184d1942afSflorian int
ub_timer_del(struct ub_event * ev)6194d1942afSflorian ub_timer_del(struct ub_event* ev)
6204d1942afSflorian {
6214d1942afSflorian 	if (ev && ev->magic == UB_EVENT_MAGIC) {
6224d1942afSflorian 		fptr_ok(ev->vmt != &default_event_vmt ||
6234d1942afSflorian 			ev->vmt->del_timer == my_timer_del);
6244d1942afSflorian 		return (*ev->vmt->del_timer)(ev);
6254d1942afSflorian 	}
6264d1942afSflorian 	return -1;
6274d1942afSflorian }
6284d1942afSflorian 
6294d1942afSflorian int
ub_signal_add(struct ub_event * ev,struct timeval * tv)6304d1942afSflorian ub_signal_add(struct ub_event* ev, struct timeval* tv)
6314d1942afSflorian {
6324d1942afSflorian 	if (ev->magic == UB_EVENT_MAGIC) {
6334d1942afSflorian 		fptr_ok(ev->vmt != &default_event_vmt ||
6344d1942afSflorian 			ev->vmt->add_signal == my_signal_add);
6354d1942afSflorian 		return (*ev->vmt->add_signal)(ev, tv);
6364d1942afSflorian 	}
6374d1942afSflorian 	return -1;
6384d1942afSflorian }
6394d1942afSflorian 
6404d1942afSflorian int
ub_signal_del(struct ub_event * ev)6414d1942afSflorian ub_signal_del(struct ub_event* ev)
6424d1942afSflorian {
6434d1942afSflorian 	if (ev && ev->magic == UB_EVENT_MAGIC) {
6444d1942afSflorian 		fptr_ok(ev->vmt != &default_event_vmt ||
6454d1942afSflorian 			ev->vmt->del_signal == my_signal_del);
6464d1942afSflorian 		return (*ev->vmt->del_signal)(ev);
6474d1942afSflorian 	}
6484d1942afSflorian 	return -1;
6494d1942afSflorian }
6504d1942afSflorian 
6514d1942afSflorian void
ub_winsock_unregister_wsaevent(struct ub_event * ev)6524d1942afSflorian ub_winsock_unregister_wsaevent(struct ub_event* ev)
6534d1942afSflorian {
6544d1942afSflorian 	if (ev && ev->magic == UB_EVENT_MAGIC) {
6554d1942afSflorian 		fptr_ok(ev->vmt != &default_event_vmt ||
6564d1942afSflorian 			ev->vmt->winsock_unregister_wsaevent ==
6574d1942afSflorian 			my_winsock_unregister_wsaevent);
6584d1942afSflorian 		(*ev->vmt->winsock_unregister_wsaevent)(ev);
6594d1942afSflorian 	}
6604d1942afSflorian }
6614d1942afSflorian 
6624d1942afSflorian void
ub_winsock_tcp_wouldblock(struct ub_event * ev,int eventbits)6634d1942afSflorian ub_winsock_tcp_wouldblock(struct ub_event* ev, int eventbits)
6644d1942afSflorian {
6654d1942afSflorian 	if (ev->magic == UB_EVENT_MAGIC) {
6664d1942afSflorian 		fptr_ok(ev->vmt != &default_event_vmt ||
6674d1942afSflorian 			ev->vmt->winsock_tcp_wouldblock ==
6684d1942afSflorian 			my_winsock_tcp_wouldblock);
669*411c5950Sflorian 		if (ev->vmt->winsock_tcp_wouldblock)
6704d1942afSflorian 			(*ev->vmt->winsock_tcp_wouldblock)(ev, eventbits);
6714d1942afSflorian 	}
6724d1942afSflorian }
6734d1942afSflorian 
ub_comm_base_now(struct comm_base * cb)6744d1942afSflorian void ub_comm_base_now(struct comm_base* cb)
6754d1942afSflorian {
6764d1942afSflorian 	time_t *tt;
6774d1942afSflorian 	struct timeval *tv;
6784d1942afSflorian 
6794d1942afSflorian #ifdef USE_MINI_EVENT
6804d1942afSflorian /** minievent updates the time when it blocks. */
6814d1942afSflorian 	if (comm_base_internal(cb)->magic == UB_EVENT_MAGIC &&
6824d1942afSflorian 	    comm_base_internal(cb)->vmt == &default_event_base_vmt)
6834d1942afSflorian 		return; /* Actually using mini event, so do not set time */
6844d1942afSflorian #endif /* USE_MINI_EVENT */
6854d1942afSflorian 
6864d1942afSflorian /** fillup the time values in the event base */
6874d1942afSflorian 	comm_base_timept(cb, &tt, &tv);
6884d1942afSflorian 	if(gettimeofday(tv, NULL) < 0) {
6894d1942afSflorian 		log_err("gettimeofday: %s", strerror(errno));
6904d1942afSflorian 	}
6914d1942afSflorian #ifndef S_SPLINT_S
6924d1942afSflorian 	*tt = tv->tv_sec;
6934d1942afSflorian #endif
6944d1942afSflorian }
6954d1942afSflorian 
696