12ee382b6Ssthen /*
22ee382b6Ssthen * util/ub_event_pluggable.c - call registered pluggable event functions
32ee382b6Ssthen *
42ee382b6Ssthen * Copyright (c) 2007, NLnet Labs. All rights reserved.
52ee382b6Ssthen *
62ee382b6Ssthen * This software is open source.
72ee382b6Ssthen *
82ee382b6Ssthen * Redistribution and use in source and binary forms, with or without
92ee382b6Ssthen * modification, are permitted provided that the following conditions
102ee382b6Ssthen * are met:
112ee382b6Ssthen *
122ee382b6Ssthen * Redistributions of source code must retain the above copyright notice,
132ee382b6Ssthen * this list of conditions and the following disclaimer.
142ee382b6Ssthen *
152ee382b6Ssthen * Redistributions in binary form must reproduce the above copyright notice,
162ee382b6Ssthen * this list of conditions and the following disclaimer in the documentation
172ee382b6Ssthen * and/or other materials provided with the distribution.
182ee382b6Ssthen *
192ee382b6Ssthen * Neither the name of the NLNET LABS nor the names of its contributors may
202ee382b6Ssthen * be used to endorse or promote products derived from this software without
212ee382b6Ssthen * specific prior written permission.
222ee382b6Ssthen *
232ee382b6Ssthen * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
242ee382b6Ssthen * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
252ee382b6Ssthen * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
262ee382b6Ssthen * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
272ee382b6Ssthen * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
282ee382b6Ssthen * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
292ee382b6Ssthen * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
302ee382b6Ssthen * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
312ee382b6Ssthen * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
322ee382b6Ssthen * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
332ee382b6Ssthen * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
342ee382b6Ssthen */
352ee382b6Ssthen
362ee382b6Ssthen /**
372ee382b6Ssthen * \file
382ee382b6Ssthen *
392ee382b6Ssthen * This file contains an implementation for the indirection layer for pluggable
402ee382b6Ssthen * events that calls the registered pluggable event loop. It also defines a
412ee382b6Ssthen * default pluggable event loop based on the default libevent (compatibility)
422ee382b6Ssthen * functions.
432ee382b6Ssthen */
442ee382b6Ssthen #include "config.h"
452ee382b6Ssthen #include <sys/time.h>
462ee382b6Ssthen #include "util/ub_event.h"
472ee382b6Ssthen #include "libunbound/unbound-event.h"
482ee382b6Ssthen #include "util/netevent.h"
492ee382b6Ssthen #include "util/log.h"
502ee382b6Ssthen #include "util/fptr_wlist.h"
512ee382b6Ssthen
522ee382b6Ssthen /* We define libevent structures here to hide the libevent stuff. */
532ee382b6Ssthen
542ee382b6Ssthen #ifdef USE_MINI_EVENT
552ee382b6Ssthen # ifdef USE_WINSOCK
562ee382b6Ssthen # include "util/winsock_event.h"
572ee382b6Ssthen # else
582ee382b6Ssthen # include "util/mini_event.h"
592ee382b6Ssthen # endif /* USE_WINSOCK */
602ee382b6Ssthen #else /* USE_MINI_EVENT */
612ee382b6Ssthen /* we use libevent */
622ee382b6Ssthen # ifdef HAVE_EVENT_H
632ee382b6Ssthen # include <event.h>
642ee382b6Ssthen # else
652ee382b6Ssthen # include "event2/event.h"
662ee382b6Ssthen # include "event2/event_struct.h"
672ee382b6Ssthen # include "event2/event_compat.h"
682ee382b6Ssthen # endif
692ee382b6Ssthen #endif /* USE_MINI_EVENT */
702ee382b6Ssthen
712ee382b6Ssthen #if UB_EV_TIMEOUT != EV_TIMEOUT || UB_EV_READ != EV_READ || \
722ee382b6Ssthen UB_EV_WRITE != EV_WRITE || UB_EV_SIGNAL != EV_SIGNAL || \
732ee382b6Ssthen UB_EV_PERSIST != EV_PERSIST
742ee382b6Ssthen /* Only necessary for libev */
752ee382b6Ssthen # define NATIVE_BITS(b) ( \
762ee382b6Ssthen (((b) & UB_EV_TIMEOUT) ? EV_TIMEOUT : 0) \
772ee382b6Ssthen | (((b) & UB_EV_READ ) ? EV_READ : 0) \
782ee382b6Ssthen | (((b) & UB_EV_WRITE ) ? EV_WRITE : 0) \
792ee382b6Ssthen | (((b) & UB_EV_SIGNAL ) ? EV_SIGNAL : 0) \
802ee382b6Ssthen | (((b) & UB_EV_PERSIST) ? EV_PERSIST : 0))
812ee382b6Ssthen
822ee382b6Ssthen # define UB_EV_BITS(b) ( \
832ee382b6Ssthen (((b) & EV_TIMEOUT) ? UB_EV_TIMEOUT : 0) \
842ee382b6Ssthen | (((b) & EV_READ ) ? UB_EV_READ : 0) \
852ee382b6Ssthen | (((b) & EV_WRITE ) ? UB_EV_WRITE : 0) \
862ee382b6Ssthen | (((b) & EV_SIGNAL ) ? UB_EV_SIGNAL : 0) \
872ee382b6Ssthen | (((b) & EV_PERSIST) ? UB_EV_PERSIST : 0))
882ee382b6Ssthen
892ee382b6Ssthen # define UB_EV_BITS_CB(C) void my_ ## C (int fd, short bits, void *arg) \
902ee382b6Ssthen { (C)(fd, UB_EV_BITS(bits), arg); }
912ee382b6Ssthen
922ee382b6Ssthen UB_EV_BITS_CB(comm_point_udp_callback);
932ee382b6Ssthen UB_EV_BITS_CB(comm_point_udp_ancil_callback)
UB_EV_BITS_CB(comm_point_tcp_accept_callback)942ee382b6Ssthen UB_EV_BITS_CB(comm_point_tcp_accept_callback)
952ee382b6Ssthen UB_EV_BITS_CB(comm_point_tcp_handle_callback)
962ee382b6Ssthen UB_EV_BITS_CB(comm_timer_callback)
972ee382b6Ssthen UB_EV_BITS_CB(comm_signal_callback)
982ee382b6Ssthen UB_EV_BITS_CB(comm_point_local_handle_callback)
992ee382b6Ssthen UB_EV_BITS_CB(comm_point_raw_handle_callback)
1002ee382b6Ssthen UB_EV_BITS_CB(tube_handle_signal)
1012ee382b6Ssthen UB_EV_BITS_CB(comm_base_handle_slow_accept)
1022ee382b6Ssthen
1032ee382b6Ssthen static void (*NATIVE_BITS_CB(void (*cb)(int, short, void*)))(int, short, void*)
1042ee382b6Ssthen {
1052ee382b6Ssthen if(cb == comm_point_udp_callback)
1062ee382b6Ssthen return my_comm_point_udp_callback;
1072ee382b6Ssthen else if(cb == comm_point_udp_ancil_callback)
1082ee382b6Ssthen return my_comm_point_udp_ancil_callback;
1092ee382b6Ssthen else if(cb == comm_point_tcp_accept_callback)
1102ee382b6Ssthen return my_comm_point_tcp_accept_callback;
1112ee382b6Ssthen else if(cb == comm_point_tcp_handle_callback)
1122ee382b6Ssthen return my_comm_point_tcp_handle_callback;
1132ee382b6Ssthen else if(cb == comm_timer_callback)
1142ee382b6Ssthen return my_comm_timer_callback;
1152ee382b6Ssthen else if(cb == comm_signal_callback)
1162ee382b6Ssthen return my_comm_signal_callback;
1172ee382b6Ssthen else if(cb == comm_point_local_handle_callback)
1182ee382b6Ssthen return my_comm_point_local_handle_callback;
1192ee382b6Ssthen else if(cb == comm_point_raw_handle_callback)
1202ee382b6Ssthen return my_comm_point_raw_handle_callback;
1212ee382b6Ssthen else if(cb == tube_handle_signal)
1222ee382b6Ssthen return my_tube_handle_signal;
1232ee382b6Ssthen else if(cb == comm_base_handle_slow_accept)
1242ee382b6Ssthen return my_comm_base_handle_slow_accept;
1252ee382b6Ssthen else
1262ee382b6Ssthen return NULL;
1272ee382b6Ssthen }
1282ee382b6Ssthen #else
1292ee382b6Ssthen # define NATIVE_BITS(b) (b)
1302ee382b6Ssthen # define NATIVE_BITS_CB(c) (c)
1312ee382b6Ssthen #endif
1322ee382b6Ssthen
1332ee382b6Ssthen #ifndef EVFLAG_AUTO
1342ee382b6Ssthen #define EVFLAG_AUTO 0
1352ee382b6Ssthen #endif
1362ee382b6Ssthen
1372ee382b6Ssthen struct my_event_base {
1382ee382b6Ssthen struct ub_event_base super;
1392ee382b6Ssthen struct event_base* base;
1402ee382b6Ssthen };
1412ee382b6Ssthen
1422ee382b6Ssthen struct my_event {
1432ee382b6Ssthen struct ub_event super;
1442ee382b6Ssthen struct event ev;
1452ee382b6Ssthen };
1462ee382b6Ssthen
14777079be7Ssthen #define AS_MY_EVENT_BASE(x) ((struct my_event_base*)x)
14877079be7Ssthen #define AS_MY_EVENT(x) ((struct my_event*)x)
1492ee382b6Ssthen
ub_event_get_version(void)15077079be7Ssthen const char* ub_event_get_version(void)
1512ee382b6Ssthen {
1522ee382b6Ssthen return "pluggable-event"PACKAGE_VERSION;
1532ee382b6Ssthen }
1542ee382b6Ssthen
1552ee382b6Ssthen static void
my_event_add_bits(struct ub_event * ev,short bits)1562ee382b6Ssthen my_event_add_bits(struct ub_event* ev, short bits)
1572ee382b6Ssthen {
1582ee382b6Ssthen AS_MY_EVENT(ev)->ev.ev_events |= NATIVE_BITS(bits);
1592ee382b6Ssthen }
1602ee382b6Ssthen
1612ee382b6Ssthen static void
my_event_del_bits(struct ub_event * ev,short bits)1622ee382b6Ssthen my_event_del_bits(struct ub_event* ev, short bits)
1632ee382b6Ssthen {
1642ee382b6Ssthen AS_MY_EVENT(ev)->ev.ev_events &= ~NATIVE_BITS(bits);
1652ee382b6Ssthen }
1662ee382b6Ssthen
1672ee382b6Ssthen static void
my_event_set_fd(struct ub_event * ev,int fd)1682ee382b6Ssthen my_event_set_fd(struct ub_event* ev, int fd)
1692ee382b6Ssthen {
1702ee382b6Ssthen AS_MY_EVENT(ev)->ev.ev_fd = fd;
1712ee382b6Ssthen }
1722ee382b6Ssthen
1732ee382b6Ssthen static void
my_event_free(struct ub_event * ev)1742ee382b6Ssthen my_event_free(struct ub_event* ev)
1752ee382b6Ssthen {
1762ee382b6Ssthen free(AS_MY_EVENT(ev));
1772ee382b6Ssthen }
1782ee382b6Ssthen
1792ee382b6Ssthen static int
my_event_add(struct ub_event * ev,struct timeval * tv)1802ee382b6Ssthen my_event_add(struct ub_event* ev, struct timeval* tv)
1812ee382b6Ssthen {
1822ee382b6Ssthen return event_add(&AS_MY_EVENT(ev)->ev, tv);
1832ee382b6Ssthen }
1842ee382b6Ssthen
1852ee382b6Ssthen static int
my_event_del(struct ub_event * ev)1862ee382b6Ssthen my_event_del(struct ub_event* ev)
1872ee382b6Ssthen {
1882ee382b6Ssthen return event_del(&AS_MY_EVENT(ev)->ev);
1892ee382b6Ssthen }
1902ee382b6Ssthen
1912ee382b6Ssthen static int
my_timer_add(struct ub_event * ev,struct ub_event_base * base,void (* cb)(int,short,void *),void * arg,struct timeval * tv)1922ee382b6Ssthen my_timer_add(struct ub_event* ev, struct ub_event_base* base,
1932ee382b6Ssthen void (*cb)(int, short, void*), void* arg, struct timeval* tv)
1942ee382b6Ssthen {
1952ee382b6Ssthen event_set(&AS_MY_EVENT(ev)->ev, -1, EV_TIMEOUT,NATIVE_BITS_CB(cb),arg);
1962ee382b6Ssthen if (event_base_set(AS_MY_EVENT_BASE(base)->base, &AS_MY_EVENT(ev)->ev)
1972ee382b6Ssthen != 0)
1982ee382b6Ssthen return -1;
1992ee382b6Ssthen return evtimer_add(&AS_MY_EVENT(ev)->ev, tv);
2002ee382b6Ssthen }
2012ee382b6Ssthen
2022ee382b6Ssthen static int
my_timer_del(struct ub_event * ev)2032ee382b6Ssthen my_timer_del(struct ub_event* ev)
2042ee382b6Ssthen {
2052ee382b6Ssthen return evtimer_del(&AS_MY_EVENT(ev)->ev);
2062ee382b6Ssthen }
2072ee382b6Ssthen
2082ee382b6Ssthen static int
my_signal_add(struct ub_event * ev,struct timeval * tv)2092ee382b6Ssthen my_signal_add(struct ub_event* ev, struct timeval* tv)
2102ee382b6Ssthen {
2112ee382b6Ssthen return signal_add(&AS_MY_EVENT(ev)->ev, tv);
2122ee382b6Ssthen }
2132ee382b6Ssthen
2142ee382b6Ssthen static int
my_signal_del(struct ub_event * ev)2152ee382b6Ssthen my_signal_del(struct ub_event* ev)
2162ee382b6Ssthen {
2172ee382b6Ssthen return signal_del(&AS_MY_EVENT(ev)->ev);
2182ee382b6Ssthen }
2192ee382b6Ssthen
2202ee382b6Ssthen static void
my_winsock_unregister_wsaevent(struct ub_event * ev)2212ee382b6Ssthen my_winsock_unregister_wsaevent(struct ub_event* ev)
2222ee382b6Ssthen {
2232ee382b6Ssthen #if defined(USE_MINI_EVENT) && defined(USE_WINSOCK)
2242ee382b6Ssthen winsock_unregister_wsaevent(&AS_MY_EVENT(ev)->ev);
2252ee382b6Ssthen free(AS_MY_EVENT(ev));
2262ee382b6Ssthen #else
2272ee382b6Ssthen (void)ev;
2282ee382b6Ssthen #endif
2292ee382b6Ssthen }
2302ee382b6Ssthen
2312ee382b6Ssthen static void
my_winsock_tcp_wouldblock(struct ub_event * ev,int eventbits)2322ee382b6Ssthen my_winsock_tcp_wouldblock(struct ub_event* ev, int eventbits)
2332ee382b6Ssthen {
2342ee382b6Ssthen #if defined(USE_MINI_EVENT) && defined(USE_WINSOCK)
2352ee382b6Ssthen winsock_tcp_wouldblock(&AS_MY_EVENT(ev)->ev, NATIVE_BITS(eventbits));
2362ee382b6Ssthen #else
2372ee382b6Ssthen (void)ev;
2382ee382b6Ssthen (void)eventbits;
2392ee382b6Ssthen #endif
2402ee382b6Ssthen }
2412ee382b6Ssthen
2422ee382b6Ssthen static struct ub_event_vmt default_event_vmt = {
2432ee382b6Ssthen my_event_add_bits, my_event_del_bits, my_event_set_fd,
2442ee382b6Ssthen my_event_free, my_event_add, my_event_del,
2452ee382b6Ssthen my_timer_add, my_timer_del, my_signal_add, my_signal_del,
2462ee382b6Ssthen my_winsock_unregister_wsaevent, my_winsock_tcp_wouldblock
2472ee382b6Ssthen };
2482ee382b6Ssthen
2492ee382b6Ssthen static void
my_event_base_free(struct ub_event_base * base)2502ee382b6Ssthen my_event_base_free(struct ub_event_base* base)
2512ee382b6Ssthen {
2522ee382b6Ssthen #ifdef USE_MINI_EVENT
2532ee382b6Ssthen event_base_free(AS_MY_EVENT_BASE(base)->base);
2542ee382b6Ssthen #elif defined(HAVE_EVENT_BASE_FREE) && defined(HAVE_EVENT_BASE_ONCE)
2552ee382b6Ssthen /* only libevent 1.2+ has it, but in 1.2 it is broken -
2562ee382b6Ssthen assertion fails on signal handling ev that is not deleted
2572ee382b6Ssthen in libevent 1.3c (event_base_once appears) this is fixed. */
2582ee382b6Ssthen event_base_free(AS_MY_EVENT_BASE(base)->base);
2592ee382b6Ssthen #endif /* HAVE_EVENT_BASE_FREE and HAVE_EVENT_BASE_ONCE */
2602ee382b6Ssthen free(AS_MY_EVENT_BASE(base));
2612ee382b6Ssthen }
2622ee382b6Ssthen
2632ee382b6Ssthen static int
my_event_base_dispatch(struct ub_event_base * base)2642ee382b6Ssthen my_event_base_dispatch(struct ub_event_base* base)
2652ee382b6Ssthen {
2662ee382b6Ssthen return event_base_dispatch(AS_MY_EVENT_BASE(base)->base);
2672ee382b6Ssthen }
2682ee382b6Ssthen
2692ee382b6Ssthen static int
my_event_base_loopexit(struct ub_event_base * base,struct timeval * tv)2702ee382b6Ssthen my_event_base_loopexit(struct ub_event_base* base, struct timeval* tv)
2712ee382b6Ssthen {
2722ee382b6Ssthen return event_base_loopexit(AS_MY_EVENT_BASE(base)->base, tv);
2732ee382b6Ssthen }
2742ee382b6Ssthen
2752ee382b6Ssthen static struct ub_event*
my_event_new(struct ub_event_base * base,int fd,short bits,void (* cb)(int,short,void *),void * arg)2762ee382b6Ssthen my_event_new(struct ub_event_base* base, int fd, short bits,
2772ee382b6Ssthen void (*cb)(int, short, void*), void* arg)
2782ee382b6Ssthen {
2792ee382b6Ssthen struct my_event *my_ev = (struct my_event*)calloc(1,
2802ee382b6Ssthen sizeof(struct my_event));
2812ee382b6Ssthen
2822ee382b6Ssthen if (!my_ev)
2832ee382b6Ssthen return NULL;
2842ee382b6Ssthen
2852ee382b6Ssthen event_set(&my_ev->ev, fd, NATIVE_BITS(bits), NATIVE_BITS_CB(cb), arg);
2862ee382b6Ssthen if (event_base_set(AS_MY_EVENT_BASE(base)->base, &my_ev->ev) != 0) {
2872ee382b6Ssthen free(my_ev);
2882ee382b6Ssthen return NULL;
2892ee382b6Ssthen }
2902ee382b6Ssthen my_ev->super.magic = UB_EVENT_MAGIC;
2912ee382b6Ssthen my_ev->super.vmt = &default_event_vmt;
2922ee382b6Ssthen return &my_ev->super;
2932ee382b6Ssthen }
2942ee382b6Ssthen
2952ee382b6Ssthen static struct ub_event*
my_signal_new(struct ub_event_base * base,int fd,void (* cb)(int,short,void *),void * arg)2962ee382b6Ssthen my_signal_new(struct ub_event_base* base, int fd,
2972ee382b6Ssthen void (*cb)(int, short, void*), void* arg)
2982ee382b6Ssthen {
2992ee382b6Ssthen struct my_event *my_ev = (struct my_event*)calloc(1,
3002ee382b6Ssthen sizeof(struct my_event));
3012ee382b6Ssthen
3022ee382b6Ssthen if (!my_ev)
3032ee382b6Ssthen return NULL;
3042ee382b6Ssthen
3052ee382b6Ssthen signal_set(&my_ev->ev, fd, NATIVE_BITS_CB(cb), arg);
3062ee382b6Ssthen if (event_base_set(AS_MY_EVENT_BASE(base)->base, &my_ev->ev) != 0) {
3072ee382b6Ssthen free(my_ev);
3082ee382b6Ssthen return NULL;
3092ee382b6Ssthen }
3102ee382b6Ssthen my_ev->super.magic = UB_EVENT_MAGIC;
3112ee382b6Ssthen my_ev->super.vmt = &default_event_vmt;
3122ee382b6Ssthen return &my_ev->super;
3132ee382b6Ssthen }
3142ee382b6Ssthen
3152ee382b6Ssthen static struct ub_event*
my_winsock_register_wsaevent(struct ub_event_base * base,void * wsaevent,void (* cb)(int,short,void *),void * arg)3162ee382b6Ssthen my_winsock_register_wsaevent(struct ub_event_base* base, void* wsaevent,
3172ee382b6Ssthen void (*cb)(int, short, void*), void* arg)
3182ee382b6Ssthen {
3192ee382b6Ssthen #if defined(USE_MINI_EVENT) && defined(USE_WINSOCK)
3202ee382b6Ssthen struct my_event *my_ev = (struct my_event*)calloc(1,
3212ee382b6Ssthen sizeof(struct my_event));
3222ee382b6Ssthen
3232ee382b6Ssthen if (!my_ev)
3242ee382b6Ssthen return NULL;
3252ee382b6Ssthen
3262ee382b6Ssthen if (!winsock_register_wsaevent(AS_MY_EVENT_BASE(base)->base,
3272ee382b6Ssthen &my_ev->ev, wsaevent, cb, arg)) {
3282ee382b6Ssthen free(my_ev);
3292ee382b6Ssthen return NULL;
3302ee382b6Ssthen
3312ee382b6Ssthen }
3322ee382b6Ssthen my_ev->super.magic = UB_EVENT_MAGIC;
3332ee382b6Ssthen my_ev->super.vmt = &default_event_vmt;
3342ee382b6Ssthen return &my_ev->super;
3352ee382b6Ssthen #else
3362ee382b6Ssthen (void)base;
3372ee382b6Ssthen (void)wsaevent;
3382ee382b6Ssthen (void)cb;
3392ee382b6Ssthen (void)arg;
3402ee382b6Ssthen return NULL;
3412ee382b6Ssthen #endif
3422ee382b6Ssthen }
3432ee382b6Ssthen
3442ee382b6Ssthen static struct ub_event_base_vmt default_event_base_vmt = {
3452ee382b6Ssthen my_event_base_free, my_event_base_dispatch,
3462ee382b6Ssthen my_event_base_loopexit, my_event_new, my_signal_new,
3472ee382b6Ssthen my_winsock_register_wsaevent
3482ee382b6Ssthen };
3492ee382b6Ssthen
3502ee382b6Ssthen struct ub_event_base*
ub_default_event_base(int sigs,time_t * time_secs,struct timeval * time_tv)3512ee382b6Ssthen ub_default_event_base(int sigs, time_t* time_secs, struct timeval* time_tv)
3522ee382b6Ssthen {
3532ee382b6Ssthen struct my_event_base* my_base = (struct my_event_base*)calloc(1,
3542ee382b6Ssthen sizeof(struct my_event_base));
3552ee382b6Ssthen
3562ee382b6Ssthen if (!my_base)
3572ee382b6Ssthen return NULL;
3582ee382b6Ssthen
3592ee382b6Ssthen #ifdef USE_MINI_EVENT
3602ee382b6Ssthen (void)sigs;
3612ee382b6Ssthen /* use mini event time-sharing feature */
3622ee382b6Ssthen my_base->base = event_init(time_secs, time_tv);
3632ee382b6Ssthen #else
3642ee382b6Ssthen (void)time_secs;
3652ee382b6Ssthen (void)time_tv;
3662ee382b6Ssthen # if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)
3672ee382b6Ssthen /* libev */
3682ee382b6Ssthen if(sigs)
3692ee382b6Ssthen my_base->base = (struct event_base*)ev_default_loop(EVFLAG_AUTO);
3702ee382b6Ssthen else
3712ee382b6Ssthen my_base->base = (struct event_base*)ev_loop_new(EVFLAG_AUTO);
3722ee382b6Ssthen # else
3732ee382b6Ssthen (void)sigs;
3742ee382b6Ssthen # ifdef HAVE_EVENT_BASE_NEW
3752ee382b6Ssthen my_base->base = event_base_new();
3762ee382b6Ssthen # else
3772ee382b6Ssthen my_base->base = event_init();
3782ee382b6Ssthen # endif
3792ee382b6Ssthen # endif
3802ee382b6Ssthen #endif
3812ee382b6Ssthen if (!my_base->base) {
3822ee382b6Ssthen free(my_base);
3832ee382b6Ssthen return NULL;
3842ee382b6Ssthen }
3852ee382b6Ssthen my_base->super.magic = UB_EVENT_MAGIC;
3862ee382b6Ssthen my_base->super.vmt = &default_event_base_vmt;
3872ee382b6Ssthen return &my_base->super;
3882ee382b6Ssthen }
3892ee382b6Ssthen
3902ee382b6Ssthen struct ub_event_base*
ub_libevent_event_base(struct event_base * base)3912ee382b6Ssthen ub_libevent_event_base(struct event_base* base)
3922ee382b6Ssthen {
3932ee382b6Ssthen #ifdef USE_MINI_EVENT
3942ee382b6Ssthen (void)base;
3952ee382b6Ssthen return NULL;
3962ee382b6Ssthen #else
3972ee382b6Ssthen struct my_event_base* my_base = (struct my_event_base*)calloc(1,
3982ee382b6Ssthen sizeof(struct my_event_base));
3992ee382b6Ssthen
4002ee382b6Ssthen if (!my_base)
4012ee382b6Ssthen return NULL;
4022ee382b6Ssthen my_base->super.magic = UB_EVENT_MAGIC;
4032ee382b6Ssthen my_base->super.vmt = &default_event_base_vmt;
4042ee382b6Ssthen my_base->base = base;
4052ee382b6Ssthen return &my_base->super;
4062ee382b6Ssthen #endif
4072ee382b6Ssthen }
4082ee382b6Ssthen
4092ee382b6Ssthen struct event_base*
ub_libevent_get_event_base(struct ub_event_base * base)4102ee382b6Ssthen ub_libevent_get_event_base(struct ub_event_base* base)
4112ee382b6Ssthen {
4122ee382b6Ssthen #ifndef USE_MINI_EVENT
4132ee382b6Ssthen if (base->vmt == &default_event_base_vmt)
4142ee382b6Ssthen return AS_MY_EVENT_BASE(base)->base;
4152ee382b6Ssthen #else
4162ee382b6Ssthen (void)base;
4172ee382b6Ssthen #endif
4182ee382b6Ssthen return NULL;
4192ee382b6Ssthen }
4202ee382b6Ssthen
4212ee382b6Ssthen #if (defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)) && defined(EVBACKEND_SELECT)
ub_ev_backend2str_pluggable(int b)4222ee382b6Ssthen static const char* ub_ev_backend2str_pluggable(int b)
4232ee382b6Ssthen {
4242ee382b6Ssthen switch(b) {
4252ee382b6Ssthen case EVBACKEND_SELECT: return "select";
4262ee382b6Ssthen case EVBACKEND_POLL: return "poll";
4272ee382b6Ssthen case EVBACKEND_EPOLL: return "epoll";
4282ee382b6Ssthen case EVBACKEND_KQUEUE: return "kqueue";
4292ee382b6Ssthen case EVBACKEND_DEVPOLL: return "devpoll";
4302ee382b6Ssthen case EVBACKEND_PORT: return "evport";
4312ee382b6Ssthen }
4322ee382b6Ssthen return "unknown";
4332ee382b6Ssthen }
4342ee382b6Ssthen #endif
4352ee382b6Ssthen
4362ee382b6Ssthen void
ub_get_event_sys(struct ub_event_base * ub_base,const char ** n,const char ** s,const char ** m)4372ee382b6Ssthen ub_get_event_sys(struct ub_event_base* ub_base, const char** n, const char** s,
4382ee382b6Ssthen const char** m)
4392ee382b6Ssthen {
4402ee382b6Ssthen #ifdef USE_WINSOCK
4412ee382b6Ssthen (void)ub_base;
4422ee382b6Ssthen *n = "pluggable-event";
4432ee382b6Ssthen *s = "winsock";
4442ee382b6Ssthen *m = "WSAWaitForMultipleEvents";
4452ee382b6Ssthen #elif defined(USE_MINI_EVENT)
4462ee382b6Ssthen (void)ub_base;
4472ee382b6Ssthen *n = "pluggable-event";
4482ee382b6Ssthen *s = "internal";
4492ee382b6Ssthen *m = "select";
4502ee382b6Ssthen #else
4512ee382b6Ssthen struct event_base* b = ub_libevent_get_event_base(ub_base);
4522ee382b6Ssthen /* This function is only called from comm_base_create, so
4532ee382b6Ssthen * ub_base is guaranteed to exist and to be the default
4542ee382b6Ssthen * event base.
4552ee382b6Ssthen */
456ebf5bb73Ssthen assert(b != NULL);
4572ee382b6Ssthen *n = "pluggable-event";
4582ee382b6Ssthen *s = event_get_version();
4592ee382b6Ssthen # if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)
4602ee382b6Ssthen *n = "pluggable-libev";
4612ee382b6Ssthen # ifdef EVBACKEND_SELECT
4622ee382b6Ssthen *m = ub_ev_backend2str_pluggable(ev_backend((struct ev_loop*)b));
4632ee382b6Ssthen # else
4642ee382b6Ssthen *m = "not obtainable";
4652ee382b6Ssthen # endif
4662ee382b6Ssthen # elif defined(HAVE_EVENT_BASE_GET_METHOD)
4672ee382b6Ssthen *n = "pluggable-libevent";
4682ee382b6Ssthen *m = event_base_get_method(b);
4692ee382b6Ssthen # else
4702ee382b6Ssthen *m = "not obtainable";
4712ee382b6Ssthen # endif
4722ee382b6Ssthen #endif
4732ee382b6Ssthen }
4742ee382b6Ssthen
4752ee382b6Ssthen void
ub_event_base_free(struct ub_event_base * base)4762ee382b6Ssthen ub_event_base_free(struct ub_event_base* base)
4772ee382b6Ssthen {
4782ee382b6Ssthen if (base && base->magic == UB_EVENT_MAGIC) {
4792ee382b6Ssthen fptr_ok(base->vmt != &default_event_base_vmt ||
4802ee382b6Ssthen base->vmt->free == my_event_base_free);
4812ee382b6Ssthen (*base->vmt->free)(base);
4822ee382b6Ssthen }
4832ee382b6Ssthen }
4842ee382b6Ssthen
4852ee382b6Ssthen int
ub_event_base_dispatch(struct ub_event_base * base)4862ee382b6Ssthen ub_event_base_dispatch(struct ub_event_base* base)
4872ee382b6Ssthen {
4882ee382b6Ssthen if (base->magic == UB_EVENT_MAGIC) {
4892ee382b6Ssthen fptr_ok(base->vmt != &default_event_base_vmt ||
4902ee382b6Ssthen base->vmt->dispatch == my_event_base_dispatch);
4912ee382b6Ssthen return (*base->vmt->dispatch)(base);
4922ee382b6Ssthen }
4932ee382b6Ssthen return -1;
4942ee382b6Ssthen }
4952ee382b6Ssthen
4962ee382b6Ssthen int
ub_event_base_loopexit(struct ub_event_base * base)4972ee382b6Ssthen ub_event_base_loopexit(struct ub_event_base* base)
4982ee382b6Ssthen {
4992ee382b6Ssthen if (base->magic == UB_EVENT_MAGIC) {
5002ee382b6Ssthen fptr_ok(base->vmt != &default_event_base_vmt ||
5012ee382b6Ssthen base->vmt->loopexit == my_event_base_loopexit);
5022ee382b6Ssthen return (*base->vmt->loopexit)(base, NULL);
5032ee382b6Ssthen }
5042ee382b6Ssthen return -1;
5052ee382b6Ssthen }
5062ee382b6Ssthen
5072ee382b6Ssthen struct ub_event*
ub_event_new(struct ub_event_base * base,int fd,short bits,void (* cb)(int,short,void *),void * arg)5082ee382b6Ssthen ub_event_new(struct ub_event_base* base, int fd, short bits,
5092ee382b6Ssthen void (*cb)(int, short, void*), void* arg)
5102ee382b6Ssthen {
5112ee382b6Ssthen if (base->magic == UB_EVENT_MAGIC) {
5122ee382b6Ssthen fptr_ok(base->vmt != &default_event_base_vmt ||
5132ee382b6Ssthen base->vmt->new_event == my_event_new);
5142ee382b6Ssthen return (*base->vmt->new_event)(base, fd, bits, cb, arg);
5152ee382b6Ssthen }
5162ee382b6Ssthen return NULL;
5172ee382b6Ssthen }
5182ee382b6Ssthen
5192ee382b6Ssthen struct ub_event*
ub_signal_new(struct ub_event_base * base,int fd,void (* cb)(int,short,void *),void * arg)5202ee382b6Ssthen ub_signal_new(struct ub_event_base* base, int fd,
5212ee382b6Ssthen void (*cb)(int, short, void*), void* arg)
5222ee382b6Ssthen {
5232ee382b6Ssthen if (base->magic == UB_EVENT_MAGIC) {
5242ee382b6Ssthen fptr_ok(base->vmt != &default_event_base_vmt ||
5252ee382b6Ssthen base->vmt->new_signal == my_signal_new);
5262ee382b6Ssthen return (*base->vmt->new_signal)(base, fd, cb, arg);
5272ee382b6Ssthen }
5282ee382b6Ssthen return NULL;
5292ee382b6Ssthen }
5302ee382b6Ssthen
5312ee382b6Ssthen struct ub_event*
ub_winsock_register_wsaevent(struct ub_event_base * base,void * wsaevent,void (* cb)(int,short,void *),void * arg)5322ee382b6Ssthen ub_winsock_register_wsaevent(struct ub_event_base* base, void* wsaevent,
5332ee382b6Ssthen void (*cb)(int, short, void*), void* arg)
5342ee382b6Ssthen {
5352ee382b6Ssthen if (base->magic == UB_EVENT_MAGIC) {
5362ee382b6Ssthen fptr_ok(base->vmt != &default_event_base_vmt ||
5372ee382b6Ssthen base->vmt->winsock_register_wsaevent ==
5382ee382b6Ssthen my_winsock_register_wsaevent);
5392ee382b6Ssthen return (*base->vmt->winsock_register_wsaevent)(base, wsaevent, cb, arg);
5402ee382b6Ssthen }
5412ee382b6Ssthen return NULL;
5422ee382b6Ssthen }
5432ee382b6Ssthen
5442ee382b6Ssthen void
ub_event_add_bits(struct ub_event * ev,short bits)5452ee382b6Ssthen ub_event_add_bits(struct ub_event* ev, short bits)
5462ee382b6Ssthen {
5472ee382b6Ssthen if (ev->magic == UB_EVENT_MAGIC) {
5482ee382b6Ssthen fptr_ok(ev->vmt != &default_event_vmt ||
5492ee382b6Ssthen ev->vmt->add_bits == my_event_add_bits);
5502ee382b6Ssthen (*ev->vmt->add_bits)(ev, bits);
5512ee382b6Ssthen }
5522ee382b6Ssthen }
5532ee382b6Ssthen
5542ee382b6Ssthen void
ub_event_del_bits(struct ub_event * ev,short bits)5552ee382b6Ssthen ub_event_del_bits(struct ub_event* ev, short bits)
5562ee382b6Ssthen {
5572ee382b6Ssthen if (ev->magic == UB_EVENT_MAGIC) {
5582ee382b6Ssthen fptr_ok(ev->vmt != &default_event_vmt ||
5592ee382b6Ssthen ev->vmt->del_bits == my_event_del_bits);
5602ee382b6Ssthen (*ev->vmt->del_bits)(ev, bits);
5612ee382b6Ssthen }
5622ee382b6Ssthen }
5632ee382b6Ssthen
5642ee382b6Ssthen void
ub_event_set_fd(struct ub_event * ev,int fd)5652ee382b6Ssthen ub_event_set_fd(struct ub_event* ev, int fd)
5662ee382b6Ssthen {
5672ee382b6Ssthen if (ev->magic == UB_EVENT_MAGIC) {
5682ee382b6Ssthen fptr_ok(ev->vmt != &default_event_vmt ||
5692ee382b6Ssthen ev->vmt->set_fd == my_event_set_fd);
5702ee382b6Ssthen (*ev->vmt->set_fd)(ev, fd);
5712ee382b6Ssthen }
5722ee382b6Ssthen }
5732ee382b6Ssthen
5742ee382b6Ssthen void
ub_event_free(struct ub_event * ev)5752ee382b6Ssthen ub_event_free(struct ub_event* ev)
5762ee382b6Ssthen {
5772ee382b6Ssthen if (ev && ev->magic == UB_EVENT_MAGIC) {
5782ee382b6Ssthen fptr_ok(ev->vmt != &default_event_vmt ||
5792ee382b6Ssthen ev->vmt->free == my_event_free);
5802ee382b6Ssthen (*ev->vmt->free)(ev);
5812ee382b6Ssthen }
5822ee382b6Ssthen }
5832ee382b6Ssthen
5842ee382b6Ssthen int
ub_event_add(struct ub_event * ev,struct timeval * tv)5852ee382b6Ssthen ub_event_add(struct ub_event* ev, struct timeval* tv)
5862ee382b6Ssthen {
5872ee382b6Ssthen if (ev->magic == UB_EVENT_MAGIC) {
5882ee382b6Ssthen fptr_ok(ev->vmt != &default_event_vmt ||
5892ee382b6Ssthen ev->vmt->add == my_event_add);
5902ee382b6Ssthen return (*ev->vmt->add)(ev, tv);
5912ee382b6Ssthen }
5922ee382b6Ssthen return -1;
5932ee382b6Ssthen }
5942ee382b6Ssthen
5952ee382b6Ssthen int
ub_event_del(struct ub_event * ev)5962ee382b6Ssthen ub_event_del(struct ub_event* ev)
5972ee382b6Ssthen {
59877079be7Ssthen if (ev && ev->magic == UB_EVENT_MAGIC) {
5992ee382b6Ssthen fptr_ok(ev->vmt != &default_event_vmt ||
6002ee382b6Ssthen ev->vmt->del == my_event_del);
6012ee382b6Ssthen return (*ev->vmt->del)(ev);
6022ee382b6Ssthen }
6032ee382b6Ssthen return -1;
6042ee382b6Ssthen }
6052ee382b6Ssthen
6062ee382b6Ssthen int
ub_timer_add(struct ub_event * ev,struct ub_event_base * base,void (* cb)(int,short,void *),void * arg,struct timeval * tv)6072ee382b6Ssthen ub_timer_add(struct ub_event* ev, struct ub_event_base* base,
6082ee382b6Ssthen void (*cb)(int, short, void*), void* arg, struct timeval* tv)
6092ee382b6Ssthen {
6102ee382b6Ssthen if (ev->magic == UB_EVENT_MAGIC) {
6112ee382b6Ssthen fptr_ok(ev->vmt != &default_event_vmt ||
6122ee382b6Ssthen ev->vmt->add_timer == my_timer_add);
6132ee382b6Ssthen return (*ev->vmt->add_timer)(ev, base, cb, arg, tv);
6142ee382b6Ssthen }
6152ee382b6Ssthen return -1;
6162ee382b6Ssthen }
6172ee382b6Ssthen
6182ee382b6Ssthen int
ub_timer_del(struct ub_event * ev)6192ee382b6Ssthen ub_timer_del(struct ub_event* ev)
6202ee382b6Ssthen {
62177079be7Ssthen if (ev && ev->magic == UB_EVENT_MAGIC) {
6222ee382b6Ssthen fptr_ok(ev->vmt != &default_event_vmt ||
6232ee382b6Ssthen ev->vmt->del_timer == my_timer_del);
6242ee382b6Ssthen return (*ev->vmt->del_timer)(ev);
6252ee382b6Ssthen }
6262ee382b6Ssthen return -1;
6272ee382b6Ssthen }
6282ee382b6Ssthen
6292ee382b6Ssthen int
ub_signal_add(struct ub_event * ev,struct timeval * tv)6302ee382b6Ssthen ub_signal_add(struct ub_event* ev, struct timeval* tv)
6312ee382b6Ssthen {
6322ee382b6Ssthen if (ev->magic == UB_EVENT_MAGIC) {
6332ee382b6Ssthen fptr_ok(ev->vmt != &default_event_vmt ||
6342ee382b6Ssthen ev->vmt->add_signal == my_signal_add);
6352ee382b6Ssthen return (*ev->vmt->add_signal)(ev, tv);
6362ee382b6Ssthen }
6372ee382b6Ssthen return -1;
6382ee382b6Ssthen }
6392ee382b6Ssthen
6402ee382b6Ssthen int
ub_signal_del(struct ub_event * ev)6412ee382b6Ssthen ub_signal_del(struct ub_event* ev)
6422ee382b6Ssthen {
64377079be7Ssthen if (ev && ev->magic == UB_EVENT_MAGIC) {
6442ee382b6Ssthen fptr_ok(ev->vmt != &default_event_vmt ||
6452ee382b6Ssthen ev->vmt->del_signal == my_signal_del);
6462ee382b6Ssthen return (*ev->vmt->del_signal)(ev);
6472ee382b6Ssthen }
6482ee382b6Ssthen return -1;
6492ee382b6Ssthen }
6502ee382b6Ssthen
6512ee382b6Ssthen void
ub_winsock_unregister_wsaevent(struct ub_event * ev)6522ee382b6Ssthen ub_winsock_unregister_wsaevent(struct ub_event* ev)
6532ee382b6Ssthen {
65477079be7Ssthen if (ev && ev->magic == UB_EVENT_MAGIC) {
6552ee382b6Ssthen fptr_ok(ev->vmt != &default_event_vmt ||
6562ee382b6Ssthen ev->vmt->winsock_unregister_wsaevent ==
6572ee382b6Ssthen my_winsock_unregister_wsaevent);
6582ee382b6Ssthen (*ev->vmt->winsock_unregister_wsaevent)(ev);
6592ee382b6Ssthen }
6602ee382b6Ssthen }
6612ee382b6Ssthen
6622ee382b6Ssthen void
ub_winsock_tcp_wouldblock(struct ub_event * ev,int eventbits)6632ee382b6Ssthen ub_winsock_tcp_wouldblock(struct ub_event* ev, int eventbits)
6642ee382b6Ssthen {
6652ee382b6Ssthen if (ev->magic == UB_EVENT_MAGIC) {
6662ee382b6Ssthen fptr_ok(ev->vmt != &default_event_vmt ||
6672ee382b6Ssthen ev->vmt->winsock_tcp_wouldblock ==
6682ee382b6Ssthen my_winsock_tcp_wouldblock);
669*191f22c6Ssthen if (ev->vmt->winsock_tcp_wouldblock)
6702ee382b6Ssthen (*ev->vmt->winsock_tcp_wouldblock)(ev, eventbits);
6712ee382b6Ssthen }
6722ee382b6Ssthen }
6732ee382b6Ssthen
ub_comm_base_now(struct comm_base * cb)6742ee382b6Ssthen void ub_comm_base_now(struct comm_base* cb)
6752ee382b6Ssthen {
6762ee382b6Ssthen time_t *tt;
6772ee382b6Ssthen struct timeval *tv;
6782ee382b6Ssthen
6792ee382b6Ssthen #ifdef USE_MINI_EVENT
6802ee382b6Ssthen /** minievent updates the time when it blocks. */
6812ee382b6Ssthen if (comm_base_internal(cb)->magic == UB_EVENT_MAGIC &&
6822ee382b6Ssthen comm_base_internal(cb)->vmt == &default_event_base_vmt)
6832ee382b6Ssthen return; /* Actually using mini event, so do not set time */
6842ee382b6Ssthen #endif /* USE_MINI_EVENT */
6852ee382b6Ssthen
6862ee382b6Ssthen /** fillup the time values in the event base */
6872ee382b6Ssthen comm_base_timept(cb, &tt, &tv);
6882ee382b6Ssthen if(gettimeofday(tv, NULL) < 0) {
6892ee382b6Ssthen log_err("gettimeofday: %s", strerror(errno));
6902ee382b6Ssthen }
691ebf5bb73Ssthen #ifndef S_SPLINT_S
6922ee382b6Ssthen *tt = tv->tv_sec;
693ebf5bb73Ssthen #endif
6942ee382b6Ssthen }
6952ee382b6Ssthen
696