2016-03-01 09:29:37 -06:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* \file ub_loop.c
|
|
|
|
* @brief Interface to the unbound pluggable event API
|
|
|
|
*
|
|
|
|
* These routines are not intended to be used by applications calling into
|
|
|
|
* the library.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (c) 2013, NLnet Labs, Verisign, Inc.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions are met:
|
|
|
|
* * Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* * 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.
|
|
|
|
* * Neither the names of the copyright holders nor the
|
|
|
|
* names of its contributors may be used to endorse or promote products
|
|
|
|
* derived from this software without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
|
|
* DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
|
|
|
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
|
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
|
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "ub_loop.h"
|
|
|
|
#ifdef HAVE_UNBOUND_EVENT_API
|
|
|
|
|
2016-03-02 05:38:29 -06:00
|
|
|
#define UB_EVENT_API_MAGIC 0x44d74d78
|
|
|
|
|
2016-03-01 09:29:37 -06:00
|
|
|
#ifndef HAVE_UNBOUND_EVENT_H
|
|
|
|
/** event timeout */
|
|
|
|
#define UB_EV_TIMEOUT 0x01
|
|
|
|
/** event fd readable */
|
|
|
|
#define UB_EV_READ 0x02
|
|
|
|
/** event fd writable */
|
|
|
|
#define UB_EV_WRITE 0x04
|
|
|
|
/** event signal */
|
|
|
|
#define UB_EV_SIGNAL 0x08
|
|
|
|
/** event must persist */
|
|
|
|
#define UB_EV_PERSIST 0x10
|
|
|
|
|
|
|
|
struct ub_event_base_vmt {
|
2016-03-02 05:38:29 -06:00
|
|
|
void (*free)(struct ub_event_base*);
|
|
|
|
int (*dispatch)(struct ub_event_base*);
|
|
|
|
int (*loopexit)(struct ub_event_base*, struct timeval*);
|
|
|
|
struct ub_event* (*new_event)(struct ub_event_base*,
|
2016-03-01 09:29:37 -06:00
|
|
|
int fd, short bits, void (*cb)(int, short, void*), void* arg);
|
2016-03-02 05:38:29 -06:00
|
|
|
struct ub_event* (*new_signal)(struct ub_event_base*, int fd,
|
2016-03-01 09:29:37 -06:00
|
|
|
void (*cb)(int, short, void*), void* arg);
|
|
|
|
struct ub_event* (*winsock_register_wsaevent)(struct ub_event_base*,
|
|
|
|
void* wsaevent, void (*cb)(int, short, void*), void* arg);
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ub_event_vmt {
|
2016-03-02 05:38:29 -06:00
|
|
|
void (*add_bits)(struct ub_event*, short);
|
|
|
|
void (*del_bits)(struct ub_event*, short);
|
|
|
|
void (*set_fd)(struct ub_event*, int);
|
|
|
|
void (*free)(struct ub_event*);
|
|
|
|
int (*add)(struct ub_event*, struct timeval*);
|
|
|
|
int (*del)(struct ub_event*);
|
|
|
|
int (*add_timer)(struct ub_event*, struct ub_event_base*,
|
2016-03-01 09:29:37 -06:00
|
|
|
void (*cb)(int, short, void*), void* arg, struct timeval*);
|
2016-03-02 05:38:29 -06:00
|
|
|
int (*del_timer)(struct ub_event*);
|
|
|
|
int (*add_signal)(struct ub_event*, struct timeval*);
|
|
|
|
int (*del_signal)(struct ub_event*);
|
2016-03-01 09:29:37 -06:00
|
|
|
void (*winsock_unregister_wsaevent)(struct ub_event* ev);
|
|
|
|
void (*winsock_tcp_wouldblock)(struct ub_event*, int eventbit);
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ub_event {
|
2016-03-02 05:38:29 -06:00
|
|
|
unsigned long magic;
|
2016-03-01 09:29:37 -06:00
|
|
|
struct ub_event_vmt* vmt;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
2016-03-02 05:38:29 -06:00
|
|
|
|
2016-03-01 09:29:37 -06:00
|
|
|
typedef struct my_event {
|
|
|
|
struct ub_event super;
|
|
|
|
/** event in the getdns event loop */
|
|
|
|
getdns_eventloop_event gev;
|
|
|
|
/** is event already added */
|
|
|
|
int added;
|
|
|
|
|
|
|
|
/** event loop it belongs to */
|
|
|
|
_getdns_ub_loop *loop;
|
|
|
|
/** fd to poll or -1 for timeouts. signal number for sigs. */
|
|
|
|
int fd;
|
|
|
|
/** what events this event is interested in, see EV_.. above. */
|
|
|
|
short bits;
|
|
|
|
/** timeout value */
|
|
|
|
uint64_t timeout;
|
|
|
|
/** callback to call: fd, eventbits, userarg */
|
|
|
|
void (*cb)(int, short, void *arg);
|
|
|
|
/** callback user arg */
|
|
|
|
void *arg;
|
2016-03-09 08:37:47 -06:00
|
|
|
#ifdef USE_WINSOCK
|
|
|
|
int is_tcp;
|
|
|
|
int read_wouldblock;
|
|
|
|
int write_wouldblock;
|
|
|
|
#endif
|
|
|
|
int *active;
|
2016-03-01 09:29:37 -06:00
|
|
|
} my_event;
|
|
|
|
|
|
|
|
#define AS_UB_LOOP(x) \
|
2016-12-08 09:27:43 -06:00
|
|
|
((_getdns_ub_loop *)(x))
|
2016-03-01 09:29:37 -06:00
|
|
|
#define AS_MY_EVENT(x) \
|
2016-12-08 09:27:43 -06:00
|
|
|
((my_event *)(x))
|
2016-03-01 09:29:37 -06:00
|
|
|
|
|
|
|
static void my_event_base_free(struct ub_event_base* base)
|
|
|
|
{
|
2016-03-04 04:52:50 -06:00
|
|
|
/* We don't allocate our event base, so no need to free */
|
2016-03-01 09:29:37 -06:00
|
|
|
(void)base;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int my_event_base_dispatch(struct ub_event_base* base)
|
|
|
|
{
|
|
|
|
(void)base;
|
2016-03-04 04:52:50 -06:00
|
|
|
/* We run the event loop extension for which this ub_event_base is an
|
|
|
|
* interface ourselfs, so no need to let libunbound call dispatch.
|
|
|
|
*/
|
2016-03-17 10:49:05 -05:00
|
|
|
DEBUG_SCHED("UB_LOOP ERROR: my_event_base_dispatch()\n");
|
2016-03-01 09:29:37 -06:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int my_event_base_loopexit(struct ub_event_base* base, struct timeval* tv)
|
|
|
|
{
|
|
|
|
(void)tv;
|
2016-03-04 04:52:50 -06:00
|
|
|
/* Not sure when this will be called. But it is of no influence as we
|
|
|
|
* run the event loop ourself.
|
|
|
|
*/
|
2016-03-01 09:29:37 -06:00
|
|
|
AS_UB_LOOP(base)->running = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-03-17 10:49:05 -05:00
|
|
|
static void clear_my_event(my_event *ev)
|
|
|
|
{
|
|
|
|
DEBUG_SCHED("UB_LOOP: to clear %p(%d, %d, %"PRIu64"), total: %d\n"
|
|
|
|
, ev, ev->fd, ev->bits, ev->timeout, ev->loop->n_events);
|
|
|
|
(ev)->loop->extension->vmt->clear((ev)->loop->extension, &(ev)->gev);
|
|
|
|
(ev)->added = 0;
|
|
|
|
if ((ev)->active) {
|
|
|
|
*(ev)->active = 0;
|
|
|
|
(ev)->active = NULL;
|
|
|
|
}
|
|
|
|
DEBUG_SCHED("UB_LOOP: %p(%d, %d, %"PRIu64") cleared, total: %d\n"
|
|
|
|
, ev, ev->fd, ev->bits, ev->timeout, --ev->loop->n_events);
|
|
|
|
}
|
2016-03-01 09:29:37 -06:00
|
|
|
|
2016-03-09 08:37:47 -06:00
|
|
|
static getdns_return_t schedule_my_event(my_event *ev)
|
2016-03-04 04:52:50 -06:00
|
|
|
{
|
|
|
|
getdns_return_t r;
|
|
|
|
|
2016-03-17 10:49:05 -05:00
|
|
|
DEBUG_SCHED("UB_LOOP: to schedule %p(%d, %d, %"PRIu64"), total: %d\n"
|
|
|
|
, ev, ev->fd, ev->bits, ev->timeout, ev->loop->n_events);
|
|
|
|
if (ev->gev.read_cb || ev->gev.write_cb || ev->gev.timeout_cb) {
|
2016-03-04 04:52:50 -06:00
|
|
|
if ((r = ev->loop->extension->vmt->schedule(
|
2016-03-17 10:49:05 -05:00
|
|
|
ev->loop->extension, ev->fd, ev->timeout, &ev->gev))) {
|
|
|
|
DEBUG_SCHED("UB_LOOP ERROR: scheduling event: %p\n", ev);
|
2016-03-04 04:52:50 -06:00
|
|
|
return r;
|
2016-03-17 10:49:05 -05:00
|
|
|
}
|
2016-03-04 04:52:50 -06:00
|
|
|
ev->added = 1;
|
2016-03-17 10:49:05 -05:00
|
|
|
DEBUG_SCHED("UB_LOOP: event %p(%d, %d, %"PRIu64") scheduled, "
|
|
|
|
"total: %d\n", ev, ev->fd, ev->bits, ev->timeout
|
|
|
|
, ++ev->loop->n_events);
|
2016-03-04 04:52:50 -06:00
|
|
|
}
|
|
|
|
return GETDNS_RETURN_GOOD;
|
|
|
|
}
|
2016-03-01 09:29:37 -06:00
|
|
|
|
|
|
|
static void read_cb(void *userarg)
|
|
|
|
{
|
|
|
|
struct my_event *ev = (struct my_event *)userarg;
|
2016-03-09 08:37:47 -06:00
|
|
|
|
|
|
|
int active = 1;
|
|
|
|
ev->active = &active;
|
|
|
|
|
|
|
|
#ifdef USE_WINSOCK
|
|
|
|
if (ev->is_tcp) {
|
|
|
|
ev->read_wouldblock = 0;
|
|
|
|
do {
|
|
|
|
(*ev->cb)(ev->fd, UB_EV_READ, ev->arg);
|
|
|
|
} while (active && !ev->read_wouldblock && (ev->bits & UB_EV_PERSIST));
|
|
|
|
} else
|
|
|
|
(*ev->cb)(ev->fd, UB_EV_READ, ev->arg);
|
|
|
|
#else
|
|
|
|
(*ev->cb)(ev->fd, UB_EV_READ, ev->arg);
|
|
|
|
#endif
|
|
|
|
if (active) {
|
|
|
|
ev->active = NULL;
|
|
|
|
if ((ev->bits & UB_EV_PERSIST) == 0)
|
2016-03-17 10:49:05 -05:00
|
|
|
clear_my_event(ev);
|
2016-03-09 08:37:47 -06:00
|
|
|
}
|
2016-03-01 09:29:37 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static void write_cb(void *userarg)
|
|
|
|
{
|
|
|
|
struct my_event *ev = (struct my_event *)userarg;
|
2016-03-09 08:37:47 -06:00
|
|
|
|
|
|
|
int active = 1;
|
|
|
|
ev->active = &active;
|
|
|
|
|
|
|
|
#ifdef USE_WINSOCK
|
|
|
|
if (ev->is_tcp) {
|
|
|
|
ev->write_wouldblock = 0;
|
|
|
|
do {
|
|
|
|
(*ev->cb)(ev->fd, UB_EV_WRITE, ev->arg);
|
|
|
|
} while (active && !ev->write_wouldblock && (ev->bits & UB_EV_PERSIST));
|
|
|
|
} else
|
|
|
|
(*ev->cb)(ev->fd, UB_EV_WRITE, ev->arg);
|
|
|
|
#else
|
|
|
|
(*ev->cb)(ev->fd, UB_EV_WRITE, ev->arg);
|
|
|
|
#endif
|
|
|
|
if (active) {
|
|
|
|
ev->active = NULL;
|
|
|
|
if ((ev->bits & UB_EV_PERSIST) == 0)
|
2016-03-17 10:49:05 -05:00
|
|
|
clear_my_event(ev);
|
2016-03-09 08:37:47 -06:00
|
|
|
}
|
2016-03-01 09:29:37 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static void timeout_cb(void *userarg)
|
|
|
|
{
|
|
|
|
struct my_event *ev = (struct my_event *)userarg;
|
2016-03-09 08:37:47 -06:00
|
|
|
|
|
|
|
int active = 1;
|
|
|
|
ev->active = &active;
|
|
|
|
|
2016-03-01 09:29:37 -06:00
|
|
|
(*ev->cb)(ev->fd, UB_EV_TIMEOUT, ev->arg);
|
2016-03-09 08:37:47 -06:00
|
|
|
if (active) {
|
|
|
|
ev->active = NULL;
|
|
|
|
if ((ev->bits & UB_EV_PERSIST) == 0)
|
2016-03-17 10:49:05 -05:00
|
|
|
clear_my_event(ev);
|
2016-03-09 08:37:47 -06:00
|
|
|
}
|
2016-03-01 09:29:37 -06:00
|
|
|
}
|
|
|
|
|
2016-03-04 04:52:50 -06:00
|
|
|
static getdns_return_t set_gev_callbacks(my_event* ev, short bits)
|
2016-03-01 09:29:37 -06:00
|
|
|
{
|
|
|
|
int added = ev->added;
|
|
|
|
|
|
|
|
if (ev->bits != bits) {
|
|
|
|
if (added)
|
2016-03-17 10:49:05 -05:00
|
|
|
clear_my_event(ev);
|
2016-03-01 09:29:37 -06:00
|
|
|
|
|
|
|
ev->gev.read_cb = bits & UB_EV_READ ? read_cb : NULL;
|
|
|
|
ev->gev.write_cb = bits & UB_EV_WRITE ? write_cb : NULL;
|
|
|
|
ev->gev.timeout_cb = bits & UB_EV_TIMEOUT ? timeout_cb : NULL;
|
|
|
|
ev->bits = bits;
|
|
|
|
|
|
|
|
if (added)
|
2016-03-04 04:52:50 -06:00
|
|
|
return schedule_my_event(ev);
|
2016-03-01 09:29:37 -06:00
|
|
|
}
|
2016-03-04 04:52:50 -06:00
|
|
|
return GETDNS_RETURN_GOOD;
|
2016-03-01 09:29:37 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static void my_event_add_bits(struct ub_event* ev, short bits)
|
|
|
|
{
|
2016-03-04 04:52:50 -06:00
|
|
|
(void) set_gev_callbacks(AS_MY_EVENT(ev), AS_MY_EVENT(ev)->bits | bits);
|
2016-03-01 09:29:37 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static void my_event_del_bits(struct ub_event* ev, short bits)
|
|
|
|
{
|
2016-03-04 04:52:50 -06:00
|
|
|
(void) set_gev_callbacks(AS_MY_EVENT(ev), AS_MY_EVENT(ev)->bits & ~bits);
|
2016-03-01 09:29:37 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static void my_event_set_fd(struct ub_event* ub_ev, int fd)
|
|
|
|
{
|
|
|
|
my_event *ev = AS_MY_EVENT(ub_ev);
|
|
|
|
|
|
|
|
if (ev->fd != fd) {
|
|
|
|
if (ev->added) {
|
2016-03-17 10:49:05 -05:00
|
|
|
clear_my_event(ev);
|
2016-03-01 09:29:37 -06:00
|
|
|
ev->fd = fd;
|
2016-03-04 04:52:50 -06:00
|
|
|
(void) schedule_my_event(ev);
|
2016-03-01 09:29:37 -06:00
|
|
|
} else
|
|
|
|
ev->fd = fd;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void my_event_free(struct ub_event* ev)
|
|
|
|
{
|
|
|
|
GETDNS_FREE(AS_MY_EVENT(ev)->loop->mf, ev);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int my_event_del(struct ub_event* ev)
|
|
|
|
{
|
|
|
|
if (AS_MY_EVENT(ev)->added)
|
2016-03-17 10:49:05 -05:00
|
|
|
clear_my_event(AS_MY_EVENT(ev));
|
2016-03-01 09:29:37 -06:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-03-09 08:37:47 -06:00
|
|
|
static int my_event_add(struct ub_event* ub_ev, struct timeval* tv)
|
2016-03-01 09:29:37 -06:00
|
|
|
{
|
2016-03-09 08:37:47 -06:00
|
|
|
my_event *ev = AS_MY_EVENT(ub_ev);
|
|
|
|
#ifdef USE_WINSOCK
|
|
|
|
int t, l = sizeof(t);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (ev->added)
|
|
|
|
my_event_del(&ev->super);
|
|
|
|
if (tv && (ev->bits & UB_EV_TIMEOUT) != 0)
|
|
|
|
ev->timeout = (tv->tv_sec * 1000) + (tv->tv_usec / 1000);
|
|
|
|
#ifdef USE_WINSOCK
|
|
|
|
if ((ev->bits & (UB_EV_READ|UB_EV_WRITE)) && ev->fd != -1 &&
|
|
|
|
getsockopt(ev->fd, SOL_SOCKET, SO_TYPE, (void *)&t, &l) == 0 &&
|
|
|
|
t == SOCK_STREAM) {
|
|
|
|
|
|
|
|
ev->is_tcp = 1;
|
|
|
|
ev->read_wouldblock = 0;
|
|
|
|
ev->write_wouldblock = 0;
|
|
|
|
} else
|
|
|
|
ev->is_tcp = 0;
|
|
|
|
#endif
|
2016-03-04 04:52:50 -06:00
|
|
|
if (schedule_my_event(AS_MY_EVENT(ev)))
|
|
|
|
return -1;
|
2016-03-01 09:29:37 -06:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int my_timer_add(struct ub_event* ub_ev, struct ub_event_base* base,
|
|
|
|
void (*cb)(int, short, void*), void* arg, struct timeval* tv)
|
|
|
|
{
|
|
|
|
my_event *ev = AS_MY_EVENT(ub_ev);
|
|
|
|
|
2016-03-17 10:49:05 -05:00
|
|
|
if (!base || !cb || !tv || AS_UB_LOOP(base) != ev->loop) {
|
|
|
|
DEBUG_SCHED("UB_LOOP ERROR: my_timer_add()\n");
|
2016-03-01 09:29:37 -06:00
|
|
|
return -1;
|
2016-03-17 10:49:05 -05:00
|
|
|
}
|
2016-03-01 09:29:37 -06:00
|
|
|
|
|
|
|
if (ev->added)
|
2016-03-17 10:49:05 -05:00
|
|
|
clear_my_event(ev);
|
2016-03-01 09:29:37 -06:00
|
|
|
|
|
|
|
ev->cb = cb;
|
|
|
|
ev->arg = arg;
|
|
|
|
return my_event_add(ub_ev, tv);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int my_timer_del(struct ub_event* ev)
|
|
|
|
{
|
|
|
|
return my_event_del(ev);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int my_signal_add(struct ub_event* ub_ev, struct timeval* tv)
|
|
|
|
{
|
2016-12-08 07:05:58 -06:00
|
|
|
(void)ub_ev; (void)tv;
|
2016-03-04 04:52:50 -06:00
|
|
|
/* Only unbound daaemon workers use signals */
|
2016-03-17 10:49:05 -05:00
|
|
|
DEBUG_SCHED("UB_LOOP ERROR: signal_add()\n");
|
2016-03-01 09:29:37 -06:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int my_signal_del(struct ub_event* ub_ev)
|
|
|
|
{
|
2016-12-08 07:05:58 -06:00
|
|
|
(void)ub_ev;
|
2016-03-04 04:52:50 -06:00
|
|
|
/* Only unbound daaemon workers use signals */
|
2016-03-17 10:49:05 -05:00
|
|
|
DEBUG_SCHED("UB_LOOP ERROR: signal_del()\n");
|
2016-03-01 09:29:37 -06:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void my_winsock_unregister_wsaevent(struct ub_event* ev)
|
|
|
|
{
|
2016-03-04 04:52:50 -06:00
|
|
|
/* wsa events don't get registered with libunbound */
|
2016-03-01 09:29:37 -06:00
|
|
|
(void)ev;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void my_winsock_tcp_wouldblock(struct ub_event* ev, int bits)
|
|
|
|
{
|
2016-03-09 08:37:47 -06:00
|
|
|
#ifndef USE_WINSOCK
|
2016-03-01 09:29:37 -06:00
|
|
|
(void)ev; (void)bits;
|
2016-03-09 08:37:47 -06:00
|
|
|
#else
|
|
|
|
if (bits & UB_EV_READ)
|
|
|
|
AS_MY_EVENT(ev)->read_wouldblock = 1;
|
|
|
|
if (bits & UB_EV_WRITE)
|
|
|
|
AS_MY_EVENT(ev)->write_wouldblock = 1;
|
|
|
|
#endif
|
2016-03-01 09:29:37 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static struct ub_event* my_event_new(struct ub_event_base* base, int fd,
|
|
|
|
short bits, void (*cb)(int, short, void*), void* arg)
|
|
|
|
{
|
|
|
|
static struct ub_event_vmt vmt = {
|
|
|
|
my_event_add_bits,
|
|
|
|
my_event_del_bits,
|
|
|
|
my_event_set_fd,
|
|
|
|
my_event_free,
|
|
|
|
my_event_add,
|
|
|
|
my_event_del,
|
|
|
|
my_timer_add,
|
|
|
|
my_timer_del,
|
|
|
|
my_signal_add,
|
|
|
|
my_signal_del,
|
|
|
|
my_winsock_unregister_wsaevent,
|
|
|
|
my_winsock_tcp_wouldblock
|
|
|
|
};
|
|
|
|
my_event *ev;
|
|
|
|
|
|
|
|
if (!base || !cb)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
ev = GETDNS_MALLOC(AS_UB_LOOP(base)->mf, my_event);
|
2016-03-02 05:38:29 -06:00
|
|
|
ev->super.magic = UB_EVENT_API_MAGIC;
|
2016-03-01 09:29:37 -06:00
|
|
|
ev->super.vmt = &vmt;
|
|
|
|
ev->loop = AS_UB_LOOP(base);
|
|
|
|
ev->added = 0;
|
|
|
|
ev->fd = fd;
|
|
|
|
ev->bits = bits;
|
2016-12-08 07:44:24 -06:00
|
|
|
ev->timeout = TIMEOUT_FOREVER;
|
2016-03-01 09:29:37 -06:00
|
|
|
ev->cb = cb;
|
|
|
|
ev->arg = arg;
|
2016-03-09 08:37:47 -06:00
|
|
|
#ifdef USE_WINSOCK
|
|
|
|
ev->is_tcp = 0;
|
|
|
|
ev->read_wouldblock = 0;
|
|
|
|
ev->write_wouldblock = 0;
|
|
|
|
#endif
|
|
|
|
ev->active = NULL;
|
2016-03-01 09:29:37 -06:00
|
|
|
ev->gev.userarg = ev;
|
|
|
|
ev->gev.read_cb = bits & UB_EV_READ ? read_cb : NULL;
|
|
|
|
ev->gev.write_cb = bits & UB_EV_WRITE ? write_cb : NULL;
|
|
|
|
ev->gev.timeout_cb = bits & UB_EV_TIMEOUT ? timeout_cb : NULL;
|
|
|
|
return &ev->super;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct ub_event* my_signal_new(struct ub_event_base* base, int fd,
|
|
|
|
void (*cb)(int, short, void*), void* arg)
|
|
|
|
{
|
2016-03-09 08:37:47 -06:00
|
|
|
/* Not applicable, because in unbound used in the daemon only */
|
|
|
|
(void)base; (void)fd; (void)cb; (void)arg;
|
|
|
|
return NULL;
|
2016-03-01 09:29:37 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static struct ub_event* my_winsock_register_wsaevent(struct ub_event_base *b,
|
|
|
|
void* wsaevent, void (*cb)(int, short, void*), void* arg)
|
|
|
|
{
|
|
|
|
/* Not applicable, because in unbound used for tubes only */
|
|
|
|
(void)b; (void)wsaevent; (void)cb; (void)arg;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void _getdns_ub_loop_init(_getdns_ub_loop *loop, struct mem_funcs *mf, getdns_eventloop *extension)
|
|
|
|
{
|
|
|
|
static struct ub_event_base_vmt vmt = {
|
|
|
|
my_event_base_free,
|
|
|
|
my_event_base_dispatch,
|
|
|
|
my_event_base_loopexit,
|
|
|
|
my_event_new,
|
|
|
|
my_signal_new,
|
|
|
|
my_winsock_register_wsaevent
|
|
|
|
};
|
|
|
|
|
2016-03-02 05:38:29 -06:00
|
|
|
loop->super.magic = UB_EVENT_API_MAGIC;
|
2016-03-01 09:29:37 -06:00
|
|
|
loop->super.vmt = &vmt;
|
|
|
|
loop->mf = *mf;
|
|
|
|
loop->extension = extension;
|
|
|
|
loop->running = 1;
|
2016-03-17 10:49:05 -05:00
|
|
|
#if defined(SCHED_DEBUG) && SCHED_DEBUG
|
|
|
|
loop->n_events = 0;
|
|
|
|
#endif
|
2016-03-01 09:29:37 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
/* ub_loop.c */
|