mirror of https://github.com/getdnsapi/getdns.git
write and run methods for eventloop extension
This commit is contained in:
parent
2172a7280a
commit
f61d2ae262
|
@ -759,11 +759,11 @@ getdns_context_request_count_changed(getdns_context *context, uint32_t prev_rc)
|
|||
return;
|
||||
|
||||
if (context->outbound_requests->count)
|
||||
context->extension->vmt->schedule_read(
|
||||
context->extension->vmt->schedule(
|
||||
context->extension, ub_fd(context->unbound_ctx),
|
||||
TIMEOUT_FOREVER, &context->ub_event);
|
||||
else
|
||||
context->extension->vmt->clear_read(
|
||||
context->extension->vmt->clear(
|
||||
context->extension, &context->ub_event);
|
||||
}
|
||||
|
||||
|
@ -806,6 +806,7 @@ rebuild_ub_ctx(struct getdns_context* context) {
|
|||
|
||||
context->ub_event.userarg = context;
|
||||
context->ub_event.read_cb = getdns_context_ub_read_cb;
|
||||
context->ub_event.write_cb = NULL;
|
||||
context->ub_event.timeout_cb = NULL;
|
||||
|
||||
return GETDNS_RETURN_GOOD;
|
||||
|
@ -1811,17 +1812,15 @@ getdns_context_get_num_pending_requests(struct getdns_context* context,
|
|||
{
|
||||
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
|
||||
|
||||
if (context->outbound_requests->count &&
|
||||
context->extension == &context->mini_event.loop)
|
||||
|
||||
getdns_mini_event_handle_timeouts(
|
||||
&context->mini_event, next_timeout);
|
||||
if (context->outbound_requests->count)
|
||||
context->extension->vmt->run_once(context->extension, 0);
|
||||
|
||||
return context->outbound_requests->count;
|
||||
}
|
||||
|
||||
/* process async reqs */
|
||||
getdns_return_t getdns_context_process_async(struct getdns_context* context)
|
||||
getdns_return_t
|
||||
getdns_context_process_async(struct getdns_context* context)
|
||||
{
|
||||
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
|
||||
|
||||
|
@ -1831,17 +1830,18 @@ getdns_return_t getdns_context_process_async(struct getdns_context* context)
|
|||
context->processing = 0;
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
}
|
||||
if (context->extension == &context->mini_event.loop
|
||||
&& getdns_mini_event_handle_select(&context->mini_event, NULL)) {
|
||||
|
||||
context->processing = 0;
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
}
|
||||
// reset the processing flag
|
||||
context->processing = 0;
|
||||
context->extension->vmt->run_once(context->extension, 0);
|
||||
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
void
|
||||
getdns_context_run(getdns_context *context)
|
||||
{
|
||||
context->extension->vmt->run(context->extension);
|
||||
}
|
||||
|
||||
typedef struct timeout_accumulator {
|
||||
getdns_transaction_t* ids;
|
||||
int idx;
|
||||
|
@ -1872,8 +1872,6 @@ cancel_outstanding_requests(struct getdns_context* context, int fire_callback) {
|
|||
getdns_return_t
|
||||
getdns_context_detach_eventloop(struct getdns_context* context)
|
||||
{
|
||||
getdns_return_t r = GETDNS_RETURN_GOOD;
|
||||
|
||||
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
|
||||
|
||||
/* When called from within a callback, do not execute pending
|
||||
|
@ -1886,13 +1884,10 @@ getdns_context_detach_eventloop(struct getdns_context* context)
|
|||
context->processing = 1;
|
||||
/* cancel all outstanding requests */
|
||||
cancel_outstanding_requests(context, 1);
|
||||
r = context->extension->vmt->cleanup(context->extension);
|
||||
if (r == GETDNS_RETURN_GOOD) {
|
||||
context->extension = &context->mini_event.loop;
|
||||
r = getdns_mini_event_init(context, &context->mini_event);
|
||||
}
|
||||
context->processing = 0;
|
||||
return r;
|
||||
context->extension->vmt->cleanup(context->extension);
|
||||
context->extension = &context->mini_event.loop;
|
||||
return getdns_mini_event_init(context, &context->mini_event);
|
||||
}
|
||||
|
||||
getdns_return_t
|
||||
|
@ -1921,11 +1916,12 @@ getdns_context_schedule_timeout(getdns_context *context, uint64_t timeout,
|
|||
/* Initialize eev_data struct */
|
||||
el_ev->userarg = userarg;
|
||||
el_ev->read_cb = NULL;
|
||||
el_ev->write_cb = NULL;
|
||||
el_ev->timeout_cb = callback;
|
||||
el_ev->ev = NULL;
|
||||
|
||||
return context->extension->vmt->schedule_timeout(
|
||||
context->extension, timeout, el_ev);
|
||||
return context->extension->vmt->schedule(
|
||||
context->extension, -1, timeout, el_ev);
|
||||
}
|
||||
|
||||
getdns_return_t
|
||||
|
@ -1937,8 +1933,7 @@ getdns_context_clear_timeout(getdns_context* context,
|
|||
RETURN_IF_NULL(el_ev->timeout_cb, GETDNS_RETURN_GOOD);
|
||||
|
||||
if (el_ev->timeout_cb) {
|
||||
context->extension->vmt->clear_timeout(
|
||||
context->extension, el_ev);
|
||||
context->extension->vmt->clear(context->extension, el_ev);
|
||||
el_ev->timeout_cb = NULL;
|
||||
}
|
||||
return GETDNS_RETURN_GOOD;
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
/**
|
||||
* \file
|
||||
* \brief Public interfaces to getdns, include in your application to use getdns API.
|
||||
* \file libev.c
|
||||
* \brief Eventloop extension for libev
|
||||
*
|
||||
* This source was taken from the original pseudo-implementation by
|
||||
* Paul Hoffman.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -33,11 +31,9 @@
|
|||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <stdio.h>
|
||||
#include "getdns/getdns_ext_libev.h"
|
||||
#include "config.h"
|
||||
#include "types-internal.h"
|
||||
#include "config.h"
|
||||
|
||||
#ifdef HAVE_LIBEV_EV_H
|
||||
#include <libev/ev.h>
|
||||
|
@ -45,65 +41,58 @@
|
|||
#include <ev.h>
|
||||
#endif
|
||||
|
||||
#define RETURN_IF_NULL(ptr, code) if(ptr == NULL) return code;
|
||||
|
||||
typedef struct getdns_libev {
|
||||
getdns_eventloop_vmt *vmt;
|
||||
struct ev_loop *loop;
|
||||
struct mem_funcs mf;
|
||||
} getdns_libev;
|
||||
|
||||
static getdns_return_t getdns_libev_cleanup(getdns_eventloop *loop);
|
||||
static getdns_return_t getdns_libev_schedule_read(getdns_eventloop *loop,
|
||||
int fd, uint64_t timeout, getdns_eventloop_event *ev);
|
||||
static getdns_return_t getdns_libev_schedule_timeout
|
||||
(getdns_eventloop *loop, uint64_t timeout, getdns_eventloop_event *ev);
|
||||
static getdns_return_t getdns_libev_clear_event
|
||||
(getdns_eventloop *loop, getdns_eventloop_event *ev);
|
||||
|
||||
static getdns_eventloop_vmt getdns_libev_vmt = {
|
||||
getdns_libev_cleanup,
|
||||
getdns_libev_schedule_read,
|
||||
getdns_libev_clear_event,
|
||||
getdns_libev_schedule_timeout,
|
||||
getdns_libev_clear_event,
|
||||
};
|
||||
|
||||
getdns_return_t
|
||||
getdns_extension_set_libev_loop(getdns_context *context,
|
||||
struct ev_loop *loop)
|
||||
static void
|
||||
getdns_libev_run(getdns_eventloop *loop)
|
||||
{
|
||||
getdns_libev *ext;
|
||||
getdns_return_t r;
|
||||
|
||||
RETURN_IF_NULL(context, GETDNS_RETURN_BAD_CONTEXT);
|
||||
RETURN_IF_NULL(loop, GETDNS_RETURN_INVALID_PARAMETER);
|
||||
|
||||
if ((r = getdns_context_detach_eventloop(context)))
|
||||
return r;
|
||||
|
||||
ext = GETDNS_MALLOC(*priv_getdns_context_mf(context), getdns_libev);
|
||||
ext->vmt = &getdns_libev_vmt;
|
||||
ext->loop = loop;
|
||||
ext->mf = *priv_getdns_context_mf(context);
|
||||
|
||||
return getdns_context_set_eventloop(context, (getdns_eventloop *)&ext);
|
||||
(void) ev_run(((getdns_libev *)loop)->loop, 0);
|
||||
}
|
||||
|
||||
static getdns_return_t
|
||||
static void
|
||||
getdns_libev_run_once(getdns_eventloop *loop, int blocking)
|
||||
{
|
||||
(void) ev_run(((getdns_libev *)loop)->loop,
|
||||
blocking ? EVRUN_ONCE : EVRUN_NOWAIT);
|
||||
}
|
||||
|
||||
static void
|
||||
getdns_libev_cleanup(getdns_eventloop *loop)
|
||||
{
|
||||
getdns_libev *ext = (getdns_libev *)loop;
|
||||
|
||||
GETDNS_FREE(ext->mf, ext);
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
typedef struct io_timer {
|
||||
ev_io io;
|
||||
ev_io read;
|
||||
ev_io write;
|
||||
ev_timer timer;
|
||||
} io_timer;
|
||||
|
||||
static getdns_return_t
|
||||
getdns_libev_clear(getdns_eventloop *loop, getdns_eventloop_event *el_ev)
|
||||
{
|
||||
getdns_libev *ext = (getdns_libev *)loop;
|
||||
io_timer *my_ev = (io_timer *)el_ev->ev;
|
||||
|
||||
assert(my_ev);
|
||||
|
||||
if (el_ev->read_cb)
|
||||
ev_io_stop(ext->loop, &my_ev->read);
|
||||
if (el_ev->write_cb)
|
||||
ev_io_stop(ext->loop, &my_ev->write);
|
||||
if (el_ev->timeout_cb)
|
||||
ev_timer_stop(ext->loop, &my_ev->timer);
|
||||
|
||||
GETDNS_FREE(ext->mf, el_ev->ev);
|
||||
el_ev->ev = NULL;
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
static void
|
||||
getdns_libev_read_cb(struct ev_loop *l, struct ev_io *io, int revents)
|
||||
{
|
||||
|
@ -112,6 +101,14 @@ getdns_libev_read_cb(struct ev_loop *l, struct ev_io *io, int revents)
|
|||
el_ev->read_cb(el_ev->userarg);
|
||||
}
|
||||
|
||||
static void
|
||||
getdns_libev_write_cb(struct ev_loop *l, struct ev_io *io, int revents)
|
||||
{
|
||||
getdns_eventloop_event *el_ev = (getdns_eventloop_event *)io->data;
|
||||
assert(el_ev->write_cb);
|
||||
el_ev->read_cb(el_ev->userarg);
|
||||
}
|
||||
|
||||
static void
|
||||
getdns_libev_timeout_cb(struct ev_loop *l, struct ev_timer *timer, int revent)
|
||||
{
|
||||
|
@ -121,7 +118,7 @@ getdns_libev_timeout_cb(struct ev_loop *l, struct ev_timer *timer, int revent)
|
|||
}
|
||||
|
||||
static getdns_return_t
|
||||
getdns_libev_schedule_read(getdns_eventloop *loop,
|
||||
getdns_libev_schedule(getdns_eventloop *loop,
|
||||
int fd, uint64_t timeout, getdns_eventloop_event *el_ev)
|
||||
{
|
||||
getdns_libev *ext = (getdns_libev *)loop;
|
||||
|
@ -130,11 +127,9 @@ getdns_libev_schedule_read(getdns_eventloop *loop,
|
|||
ev_timer *my_timer;
|
||||
ev_tstamp to = ((ev_tstamp)timeout) / 1000;
|
||||
|
||||
if (fd < 0) el_ev->read_cb = NULL;
|
||||
if (timeout == TIMEOUT_FOREVER) el_ev->timeout_cb = NULL;
|
||||
|
||||
if (!el_ev->read_cb && !el_ev->timeout_cb)
|
||||
return GETDNS_RETURN_GOOD; /* Nothing to schedule */
|
||||
assert(el_ev);
|
||||
assert(!(el_ev->read_cb || el_ev->write_cb) || fd >= 0);
|
||||
assert( el_ev->read_cb || el_ev->write_cb || el_ev->timeout_cb);
|
||||
|
||||
if (!(my_ev = GETDNS_MALLOC(ext->mf, io_timer)))
|
||||
return GETDNS_RETURN_MEMORY_ERROR;
|
||||
|
@ -142,43 +137,52 @@ getdns_libev_schedule_read(getdns_eventloop *loop,
|
|||
el_ev->ev = my_ev;
|
||||
|
||||
if (el_ev->read_cb) {
|
||||
my_io = &my_ev->io;
|
||||
my_io->data = el_ev;
|
||||
my_io = &my_ev->read;
|
||||
ev_io_init(my_io, getdns_libev_read_cb, fd, EV_READ);
|
||||
ev_io_start(ext->loop, &my_ev->io);
|
||||
my_io->data = el_ev;
|
||||
ev_io_start(ext->loop, my_io);
|
||||
}
|
||||
if (el_ev->write_cb) {
|
||||
my_io = &my_ev->write;
|
||||
ev_io_init(my_io, getdns_libev_write_cb, fd, EV_WRITE);
|
||||
my_io->data = el_ev;
|
||||
ev_io_start(ext->loop, my_io);
|
||||
}
|
||||
if (el_ev->timeout_cb) {
|
||||
my_timer = &my_ev->timer;
|
||||
my_timer->data = el_ev;
|
||||
ev_timer_init(my_timer, getdns_libev_timeout_cb, to, 0);
|
||||
ev_timer_start(ext->loop, &my_ev->timer);
|
||||
my_timer->data = el_ev;
|
||||
ev_timer_start(ext->loop, my_timer);
|
||||
}
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
static getdns_return_t
|
||||
getdns_libev_schedule_timeout(getdns_eventloop *loop,
|
||||
uint64_t timeout, getdns_eventloop_event *el_ev)
|
||||
getdns_return_t
|
||||
getdns_extension_set_libev_loop(getdns_context *context,
|
||||
struct ev_loop *loop)
|
||||
{
|
||||
return getdns_libev_schedule_read(loop, -1, timeout, el_ev);
|
||||
static getdns_eventloop_vmt getdns_libev_vmt = {
|
||||
getdns_libev_cleanup,
|
||||
getdns_libev_schedule,
|
||||
getdns_libev_clear,
|
||||
getdns_libev_run,
|
||||
getdns_libev_run_once
|
||||
};
|
||||
getdns_libev *ext;
|
||||
getdns_return_t r;
|
||||
|
||||
if (!context)
|
||||
return GETDNS_RETURN_BAD_CONTEXT;
|
||||
if (!loop)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
if ((r = getdns_context_detach_eventloop(context)))
|
||||
return r;
|
||||
|
||||
ext = GETDNS_MALLOC(*priv_getdns_context_mf(context), getdns_libev);
|
||||
ext->vmt = &getdns_libev_vmt;
|
||||
ext->loop = loop;
|
||||
ext->mf = *priv_getdns_context_mf(context);
|
||||
|
||||
return getdns_context_set_eventloop(context, (getdns_eventloop *)&ext);
|
||||
}
|
||||
|
||||
static getdns_return_t
|
||||
getdns_libev_clear_event(getdns_eventloop *loop,
|
||||
getdns_eventloop_event *el_ev)
|
||||
{
|
||||
getdns_libev *ext = (getdns_libev *)loop;
|
||||
io_timer *my_ev = (io_timer *)el_ev->ev;
|
||||
|
||||
assert(my_ev);
|
||||
|
||||
if (el_ev->read_cb)
|
||||
ev_io_stop(ext->loop, &my_ev->io);
|
||||
if (el_ev->timeout_cb)
|
||||
ev_timer_stop(ext->loop, &my_ev->timer);
|
||||
|
||||
GETDNS_FREE(ext->mf, el_ev->ev);
|
||||
el_ev->ev = NULL;
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
/**
|
||||
* \file
|
||||
* \brief Public interfaces to getdns, include in your application to use getdns API.
|
||||
* \file libevent.c
|
||||
* \brief Eventloop extension for libevent
|
||||
*
|
||||
* This source was taken from the original pseudo-implementation by
|
||||
* Paul Hoffman.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -35,8 +33,8 @@
|
|||
|
||||
#include <sys/time.h>
|
||||
#include "getdns/getdns_ext_libevent.h"
|
||||
#include "config.h"
|
||||
#include "types-internal.h"
|
||||
#include "config.h"
|
||||
|
||||
#ifdef HAVE_EVENT2_EVENT_H
|
||||
# include <event2/event.h>
|
||||
|
@ -46,7 +44,6 @@
|
|||
# define event_free free
|
||||
# define evtimer_new(b, cb, arg) event_new((b), -1, 0, (cb), (arg))
|
||||
#endif
|
||||
#define RETURN_IF_NULL(ptr, code) if(ptr == NULL) return code;
|
||||
|
||||
#ifndef HAVE_EVENT_BASE_FREE
|
||||
#define event_base_free(x) /* nop */
|
||||
|
@ -86,49 +83,37 @@ typedef struct getdns_libevent {
|
|||
struct mem_funcs mf;
|
||||
} getdns_libevent;
|
||||
|
||||
static getdns_return_t getdns_libevent_cleanup(getdns_eventloop *loop);
|
||||
static getdns_return_t getdns_libevent_schedule_read(getdns_eventloop *loop,
|
||||
int fd, uint64_t timeout, getdns_eventloop_event *ev);
|
||||
static getdns_return_t getdns_libevent_schedule_timeout
|
||||
(getdns_eventloop *loop, uint64_t timeout, getdns_eventloop_event *ev);
|
||||
static getdns_return_t getdns_libevent_clear_event
|
||||
(getdns_eventloop *loop, getdns_eventloop_event *ev);
|
||||
|
||||
static getdns_eventloop_vmt getdns_libevent_vmt = {
|
||||
getdns_libevent_cleanup,
|
||||
getdns_libevent_schedule_read,
|
||||
getdns_libevent_clear_event,
|
||||
getdns_libevent_schedule_timeout,
|
||||
getdns_libevent_clear_event,
|
||||
};
|
||||
|
||||
getdns_return_t
|
||||
getdns_extension_set_libevent_base(getdns_context *context,
|
||||
struct event_base *base)
|
||||
static void
|
||||
getdns_libevent_run(getdns_eventloop *loop)
|
||||
{
|
||||
getdns_libevent *ext;
|
||||
getdns_return_t r;
|
||||
|
||||
RETURN_IF_NULL(context, GETDNS_RETURN_BAD_CONTEXT);
|
||||
RETURN_IF_NULL(base, GETDNS_RETURN_INVALID_PARAMETER);
|
||||
|
||||
if ((r = getdns_context_detach_eventloop(context)))
|
||||
return r;
|
||||
|
||||
ext = GETDNS_MALLOC(*priv_getdns_context_mf(context), getdns_libevent);
|
||||
ext->vmt = &getdns_libevent_vmt;
|
||||
ext->base = base;
|
||||
ext->mf = *priv_getdns_context_mf(context);
|
||||
|
||||
return getdns_context_set_eventloop(context, (getdns_eventloop *)&ext);
|
||||
(void) event_base_dispatch(((getdns_libevent *)loop)->base);
|
||||
}
|
||||
|
||||
static getdns_return_t
|
||||
static void
|
||||
getdns_libevent_run_once(getdns_eventloop *loop, int blocking)
|
||||
{
|
||||
/* Is this possible with libevent? */
|
||||
}
|
||||
|
||||
static void
|
||||
getdns_libevent_cleanup(getdns_eventloop *loop)
|
||||
{
|
||||
getdns_libevent *ext = (getdns_libevent *)loop;
|
||||
|
||||
GETDNS_FREE(ext->mf, ext);
|
||||
}
|
||||
|
||||
static getdns_return_t
|
||||
getdns_libevent_clear(getdns_eventloop *loop, getdns_eventloop_event *el_ev)
|
||||
{
|
||||
struct event *my_ev = (struct event *)el_ev->ev;
|
||||
|
||||
assert(my_ev);
|
||||
|
||||
if (event_del(my_ev) != 0)
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
|
||||
event_free(my_ev);
|
||||
el_ev->ev = NULL;
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
|
@ -140,6 +125,9 @@ getdns_libevent_callback(evutil_socket_t fd, short bits, void *arg)
|
|||
if (bits & EV_READ) {
|
||||
assert(el_ev->read_cb);
|
||||
el_ev->read_cb(el_ev->userarg);
|
||||
} else if (bits & EV_WRITE) {
|
||||
assert(el_ev->write_cb);
|
||||
el_ev->write_cb(el_ev->userarg);
|
||||
} else if (bits & EV_TIMEOUT) {
|
||||
assert(el_ev->timeout_cb);
|
||||
el_ev->timeout_cb(el_ev->userarg);
|
||||
|
@ -148,51 +136,61 @@ getdns_libevent_callback(evutil_socket_t fd, short bits, void *arg)
|
|||
}
|
||||
|
||||
static getdns_return_t
|
||||
getdns_libevent_schedule_read(getdns_eventloop *loop,
|
||||
getdns_libevent_schedule(getdns_eventloop *loop,
|
||||
int fd, uint64_t timeout, getdns_eventloop_event *el_ev)
|
||||
{
|
||||
getdns_libevent *ext = (getdns_libevent *)loop;
|
||||
struct event *my_ev;
|
||||
struct timeval tv = { timeout / 1000, (timeout % 1000) * 1000 };
|
||||
short bits = ((fd >= 0 && el_ev->read_cb ? EV_READ|EV_PERSIST : 0) |
|
||||
(timeout != TIMEOUT_FOREVER && el_ev->timeout_cb ? EV_TIMEOUT : 0));
|
||||
|
||||
if (!bits)
|
||||
return GETDNS_RETURN_GOOD; /* Nothing to schedule */
|
||||
assert(el_ev);
|
||||
assert(!(el_ev->read_cb || el_ev->write_cb) || fd >= 0);
|
||||
assert( el_ev->read_cb || el_ev->write_cb || el_ev->timeout_cb);
|
||||
|
||||
if (!(my_ev = event_new(
|
||||
ext->base, fd, bits, getdns_libevent_callback, el_ev)))
|
||||
my_ev = event_new(ext->base, fd, (
|
||||
(el_ev->read_cb ? EV_READ|EV_PERSIST : 0) |
|
||||
(el_ev->write_cb ? EV_WRITE|EV_PERSIST : 0) |
|
||||
(el_ev->timeout_cb ? EV_TIMEOUT : 0)),
|
||||
getdns_libevent_callback, el_ev);
|
||||
if (!my_ev)
|
||||
return GETDNS_RETURN_MEMORY_ERROR;
|
||||
|
||||
el_ev->ev = my_ev;
|
||||
if (event_add(my_ev,
|
||||
(timeout != TIMEOUT_FOREVER && el_ev->timeout_cb ? &tv : NULL)))
|
||||
goto error;
|
||||
|
||||
return GETDNS_RETURN_GOOD;
|
||||
error:
|
||||
event_free(my_ev);
|
||||
el_ev->ev = NULL;
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
static getdns_return_t
|
||||
getdns_libevent_schedule_timeout(getdns_eventloop *loop,
|
||||
uint64_t timeout, getdns_eventloop_event *el_ev)
|
||||
{
|
||||
return getdns_libevent_schedule_read(loop, -1, timeout, el_ev);
|
||||
}
|
||||
|
||||
static getdns_return_t
|
||||
getdns_libevent_clear_event(getdns_eventloop *loop,
|
||||
getdns_eventloop_event *el_ev)
|
||||
{
|
||||
assert(el_ev->ev);
|
||||
|
||||
if (event_del(el_ev->ev) != 0)
|
||||
if (event_add(my_ev, el_ev->timeout_cb ? &tv : NULL)) {
|
||||
event_free(my_ev);
|
||||
el_ev->ev = NULL;
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
event_free(el_ev->ev);
|
||||
el_ev->ev = NULL;
|
||||
}
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
getdns_return_t
|
||||
getdns_extension_set_libevent_base(getdns_context *context,
|
||||
struct event_base *base)
|
||||
{
|
||||
static getdns_eventloop_vmt getdns_libevent_vmt = {
|
||||
getdns_libevent_cleanup,
|
||||
getdns_libevent_schedule,
|
||||
getdns_libevent_clear,
|
||||
getdns_libevent_run,
|
||||
getdns_libevent_run_once
|
||||
};
|
||||
getdns_libevent *ext;
|
||||
getdns_return_t r;
|
||||
|
||||
if (!context)
|
||||
return GETDNS_RETURN_BAD_CONTEXT;
|
||||
if (!base)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
if ((r = getdns_context_detach_eventloop(context)))
|
||||
return r;
|
||||
|
||||
ext = GETDNS_MALLOC(*priv_getdns_context_mf(context), getdns_libevent);
|
||||
ext->vmt = &getdns_libevent_vmt;
|
||||
ext->base = base;
|
||||
ext->mf = *priv_getdns_context_mf(context);
|
||||
|
||||
return getdns_context_set_eventloop(context, (getdns_eventloop *)&ext);
|
||||
}
|
||||
|
|
|
@ -32,36 +32,159 @@
|
|||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "extension/libmini_event.h"
|
||||
#include "util/mini_event.h"
|
||||
#include "context.h"
|
||||
|
||||
static void
|
||||
getdns_mini_event_cleanup(getdns_eventloop *loop)
|
||||
{
|
||||
getdns_mini_event *ext = (getdns_mini_event *)loop;
|
||||
getdns_event_base_free(ext->base);
|
||||
}
|
||||
|
||||
void
|
||||
getdns_mini_event_destroy(getdns_mini_event *ext)
|
||||
{
|
||||
assert(ext);
|
||||
ext->loop.vmt->cleanup(&ext->loop);
|
||||
GETDNS_FREE(ext->mf, ext);
|
||||
}
|
||||
|
||||
void getdns_handle_timeouts(struct getdns_event_base* base,
|
||||
struct timeval* now, struct timeval* wait);
|
||||
int getdns_handle_select(struct getdns_event_base* base, struct timeval* wait);
|
||||
|
||||
static getdns_return_t getdns_mini_event_cleanup(getdns_eventloop *loop);
|
||||
static getdns_return_t getdns_mini_event_schedule_read(getdns_eventloop *loop,
|
||||
int fd, uint64_t timeout, getdns_eventloop_event *ev);
|
||||
static getdns_return_t getdns_mini_event_schedule_timeout
|
||||
(getdns_eventloop *loop, uint64_t timeout, getdns_eventloop_event *ev);
|
||||
static getdns_return_t getdns_mini_event_clear_event
|
||||
(getdns_eventloop *loop, getdns_eventloop_event *ev);
|
||||
static int
|
||||
getdns_mini_event_settime(getdns_mini_event *ext)
|
||||
{
|
||||
if (gettimeofday(&ext->time_tv, NULL) < 0)
|
||||
return -1;
|
||||
ext->time_secs = (time_t)ext->time_tv.tv_sec;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static getdns_eventloop_vmt getdns_mini_event_vmt = {
|
||||
getdns_mini_event_cleanup,
|
||||
getdns_mini_event_schedule_read,
|
||||
getdns_mini_event_clear_event,
|
||||
getdns_mini_event_schedule_timeout,
|
||||
getdns_mini_event_clear_event,
|
||||
};
|
||||
static void
|
||||
getdns_mini_event_run(getdns_eventloop *loop)
|
||||
{
|
||||
getdns_mini_event *ext = (getdns_mini_event *)loop;
|
||||
struct timeval wait;
|
||||
|
||||
if (ext->n_events == 0 || getdns_mini_event_settime(ext) < 0)
|
||||
return;
|
||||
|
||||
do (void) getdns_handle_timeouts(ext->base, &ext->time_tv, &wait);
|
||||
while (!getdns_handle_select(ext->base, &wait) && ext->n_events);
|
||||
}
|
||||
|
||||
static void
|
||||
getdns_mini_event_run_once(getdns_eventloop *loop, int blocking)
|
||||
{
|
||||
static struct timeval immediately = { 0, 0 };
|
||||
getdns_mini_event *ext = (getdns_mini_event *)loop;
|
||||
struct timeval wait;
|
||||
|
||||
if (blocking) {
|
||||
if (getdns_mini_event_settime(ext) < 0)
|
||||
return;
|
||||
|
||||
getdns_handle_timeouts(ext->base, &ext->time_tv, &wait);
|
||||
(void) getdns_handle_select(ext->base, &wait);
|
||||
} else {
|
||||
if (getdns_handle_select(ext->base, &immediately) < 0)
|
||||
return;
|
||||
|
||||
getdns_handle_timeouts(ext->base, &ext->time_tv, &wait);
|
||||
}
|
||||
}
|
||||
|
||||
static getdns_return_t
|
||||
getdns_mini_event_clear(getdns_eventloop *loop, getdns_eventloop_event *el_ev)
|
||||
{
|
||||
getdns_mini_event *ext = (getdns_mini_event *)loop;
|
||||
|
||||
assert(el_ev->ev);
|
||||
|
||||
if (getdns_event_del(el_ev->ev) != 0)
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
|
||||
GETDNS_FREE(ext->mf, el_ev->ev);
|
||||
el_ev->ev = NULL;
|
||||
|
||||
ext->n_events--;
|
||||
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
static void
|
||||
getdns_mini_event_callback(int fd, short bits, void *arg)
|
||||
{
|
||||
getdns_eventloop_event *el_ev = (getdns_eventloop_event *)arg;
|
||||
if (bits & EV_READ) {
|
||||
assert(el_ev->read_cb);
|
||||
el_ev->read_cb(el_ev->userarg);
|
||||
} else if (bits & EV_WRITE) {
|
||||
assert(el_ev->write_cb);
|
||||
el_ev->write_cb(el_ev->userarg);
|
||||
} else if (bits & EV_TIMEOUT) {
|
||||
assert(el_ev->timeout_cb);
|
||||
el_ev->timeout_cb(el_ev->userarg);
|
||||
} else
|
||||
assert(ASSERT_UNREACHABLE);
|
||||
}
|
||||
|
||||
static getdns_return_t
|
||||
getdns_mini_event_schedule(getdns_eventloop *loop,
|
||||
int fd, uint64_t timeout, getdns_eventloop_event *el_ev)
|
||||
{
|
||||
getdns_mini_event *ext = (getdns_mini_event *)loop;
|
||||
struct getdns_event *my_ev;
|
||||
struct timeval tv = { timeout / 1000, (timeout % 1000) * 1000 };
|
||||
|
||||
assert(el_ev);
|
||||
assert(!(el_ev->read_cb || el_ev->write_cb) || fd >= 0);
|
||||
assert( el_ev->read_cb || el_ev->write_cb || el_ev->timeout_cb);
|
||||
|
||||
if (!(my_ev = GETDNS_MALLOC(ext->mf, struct getdns_event)))
|
||||
return GETDNS_RETURN_MEMORY_ERROR;
|
||||
|
||||
el_ev->ev = my_ev;
|
||||
getdns_event_set(my_ev, fd, (
|
||||
(el_ev->read_cb ? EV_READ|EV_PERSIST : 0) |
|
||||
(el_ev->write_cb ? EV_WRITE|EV_PERSIST : 0) |
|
||||
(el_ev->timeout_cb ? EV_TIMEOUT : 0)),
|
||||
getdns_mini_event_callback, el_ev);
|
||||
|
||||
if (getdns_mini_event_settime(ext))
|
||||
goto error;
|
||||
|
||||
(void) getdns_event_base_set(ext->base, my_ev);
|
||||
if (getdns_event_add(my_ev, el_ev->timeout_cb ? &tv : NULL))
|
||||
goto error;
|
||||
|
||||
ext->n_events++;
|
||||
|
||||
return GETDNS_RETURN_GOOD;
|
||||
error:
|
||||
GETDNS_FREE(ext->mf, my_ev);
|
||||
el_ev->ev = NULL;
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
getdns_return_t
|
||||
getdns_mini_event_init(getdns_context *context, getdns_mini_event *ext)
|
||||
{
|
||||
if (!context) return GETDNS_RETURN_BAD_CONTEXT;
|
||||
if (!ext) return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
static getdns_eventloop_vmt getdns_mini_event_vmt = {
|
||||
getdns_mini_event_cleanup,
|
||||
getdns_mini_event_schedule,
|
||||
getdns_mini_event_clear,
|
||||
getdns_mini_event_run,
|
||||
getdns_mini_event_run_once
|
||||
};
|
||||
|
||||
if (!context)
|
||||
return GETDNS_RETURN_BAD_CONTEXT;
|
||||
if (!ext)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
ext->loop.vmt = &getdns_mini_event_vmt;
|
||||
ext->base = getdns_event_init(&ext->time_secs, &ext->time_tv);
|
||||
|
@ -81,124 +204,3 @@ getdns_mini_event_create(getdns_context *context, getdns_mini_event **ext)
|
|||
*ext = GETDNS_MALLOC(context->mf, getdns_mini_event);
|
||||
return getdns_mini_event_init(context, *ext);
|
||||
}
|
||||
|
||||
void
|
||||
getdns_mini_event_destroy(getdns_mini_event *ext)
|
||||
{
|
||||
if (ext) {
|
||||
ext->loop.vmt->cleanup(&ext->loop);
|
||||
GETDNS_FREE(ext->mf, ext);
|
||||
}
|
||||
}
|
||||
|
||||
static getdns_return_t
|
||||
getdns_mini_event_cleanup(getdns_eventloop *loop)
|
||||
{
|
||||
getdns_mini_event *ext = (getdns_mini_event *)loop;
|
||||
|
||||
getdns_event_base_free(ext->base);
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
static int
|
||||
getdns_mini_event_settime(getdns_mini_event *ext)
|
||||
{
|
||||
if (gettimeofday(&ext->time_tv, NULL) < 0)
|
||||
return -1;
|
||||
ext->time_secs = (time_t)ext->time_tv.tv_sec;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Call timeouts handlers, and return how long to wait for next one or -1 */
|
||||
void
|
||||
getdns_mini_event_handle_timeouts(getdns_mini_event *ext, struct timeval *wait)
|
||||
{
|
||||
struct timeval dispose = { 0, 0 };
|
||||
|
||||
if (getdns_mini_event_settime(ext) == 0)
|
||||
getdns_handle_timeouts(
|
||||
ext->base, &ext->time_tv, wait ? wait : &dispose);
|
||||
}
|
||||
|
||||
/** Call select and callbacks for that */
|
||||
getdns_return_t
|
||||
getdns_mini_event_handle_select(getdns_mini_event *ext, struct timeval* wait)
|
||||
{
|
||||
static struct timeval immediately = { 0, 0 };
|
||||
|
||||
return getdns_handle_select(ext->base, wait ? wait : &immediately)
|
||||
? GETDNS_RETURN_GENERIC_ERROR : GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
static void
|
||||
getdns_mini_event_callback(int fd, short bits, void *arg)
|
||||
{
|
||||
getdns_eventloop_event *el_ev = (getdns_eventloop_event *)arg;
|
||||
if (bits & EV_READ) {
|
||||
assert(el_ev->read_cb);
|
||||
el_ev->read_cb(el_ev->userarg);
|
||||
} else if (bits & EV_TIMEOUT) {
|
||||
assert(el_ev->timeout_cb);
|
||||
el_ev->timeout_cb(el_ev->userarg);
|
||||
} else
|
||||
assert(ASSERT_UNREACHABLE);
|
||||
}
|
||||
|
||||
static getdns_return_t
|
||||
getdns_mini_event_schedule_read(getdns_eventloop *loop,
|
||||
int fd, uint64_t timeout, getdns_eventloop_event *el_ev)
|
||||
{
|
||||
getdns_mini_event *ext = (getdns_mini_event *)loop;
|
||||
struct getdns_event *my_ev;
|
||||
struct timeval tv = { timeout / 1000, (timeout % 1000) * 1000 };
|
||||
short bits =
|
||||
((fd >= 0 && el_ev->read_cb ? EV_READ : 0) |
|
||||
(timeout!=TIMEOUT_FOREVER && el_ev->timeout_cb ? EV_TIMEOUT : 0));
|
||||
|
||||
if (!bits)
|
||||
return GETDNS_RETURN_GOOD; /* Nothing to schedule */
|
||||
|
||||
if (!(my_ev = GETDNS_MALLOC(ext->mf, struct getdns_event)))
|
||||
return GETDNS_RETURN_MEMORY_ERROR;
|
||||
|
||||
el_ev->ev = my_ev;
|
||||
getdns_event_set(my_ev, fd, bits, getdns_mini_event_callback, el_ev);
|
||||
|
||||
if (getdns_mini_event_settime(ext))
|
||||
goto error;
|
||||
|
||||
(void) getdns_event_base_set(ext->base, my_ev);
|
||||
if (getdns_event_add(my_ev, (
|
||||
timeout != TIMEOUT_FOREVER && el_ev->timeout_cb ? &tv : NULL)))
|
||||
goto error;
|
||||
|
||||
return GETDNS_RETURN_GOOD;
|
||||
error:
|
||||
GETDNS_FREE(ext->mf, my_ev);
|
||||
el_ev->ev = NULL;
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
static getdns_return_t
|
||||
getdns_mini_event_schedule_timeout(getdns_eventloop *loop,
|
||||
uint64_t timeout, getdns_eventloop_event *el_ev)
|
||||
{
|
||||
return getdns_mini_event_schedule_read(loop, -1, timeout, el_ev);
|
||||
}
|
||||
|
||||
static getdns_return_t
|
||||
getdns_mini_event_clear_event(getdns_eventloop *loop,
|
||||
getdns_eventloop_event *el_ev)
|
||||
{
|
||||
getdns_mini_event *ext = (getdns_mini_event *)loop;
|
||||
|
||||
assert(el_ev->ev);
|
||||
|
||||
if (getdns_event_del(el_ev->ev) != 0)
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
GETDNS_FREE(ext->mf, el_ev->ev);
|
||||
el_ev->ev = NULL;
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
/* libmini_event.c */
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#ifndef _GETDNS_LIBMINI_EVENT_H_
|
||||
#define _GETDNS_LIBMINI_EVENT_H_
|
||||
|
||||
#include "config.h"
|
||||
#include "util/mini_event.h"
|
||||
#include "types-internal.h"
|
||||
|
||||
|
@ -42,6 +43,7 @@ typedef struct getdns_mini_event {
|
|||
time_t time_secs;
|
||||
struct timeval time_tv;
|
||||
struct getdns_event_base *base;
|
||||
size_t n_events;
|
||||
struct mem_funcs mf;
|
||||
} getdns_mini_event;
|
||||
|
||||
|
@ -54,12 +56,4 @@ getdns_mini_event_create(getdns_context *ctxt, getdns_mini_event **mini_event);
|
|||
void
|
||||
getdns_mini_event_destroy(getdns_mini_event *mini_event);
|
||||
|
||||
/** Call timeouts handlers, and return how long to wait for next one or -1 */
|
||||
void
|
||||
getdns_mini_event_handle_timeouts(getdns_mini_event *ext, struct timeval *wait);
|
||||
|
||||
/** Call select and callbacks for that */
|
||||
getdns_return_t
|
||||
getdns_mini_event_handle_select(getdns_mini_event *ext, struct timeval* wait);
|
||||
|
||||
#endif /* _GETDNS_LIBMINI_EVENT_H_ */
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
/**
|
||||
* \file
|
||||
* \brief Public interfaces to getdns, include in your application to use getdns API.
|
||||
* \file libuv.c
|
||||
* \brief Eventloop extension for libuv.
|
||||
*
|
||||
* This source was taken from the original pseudo-implementation by
|
||||
* Paul Hoffman.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -33,70 +31,66 @@
|
|||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <stdio.h>
|
||||
#include <uv.h>
|
||||
#include "getdns/getdns_ext_libuv.h"
|
||||
#include "types-internal.h"
|
||||
|
||||
#define RETURN_IF_NULL(ptr, code) if(ptr == NULL) return code;
|
||||
|
||||
typedef struct getdns_libuv {
|
||||
getdns_eventloop_vmt *vmt;
|
||||
uv_loop_t *loop;
|
||||
struct mem_funcs mf;
|
||||
} getdns_libuv;
|
||||
|
||||
static getdns_return_t getdns_libuv_cleanup(getdns_eventloop *loop);
|
||||
static getdns_return_t getdns_libuv_schedule_read(getdns_eventloop *loop,
|
||||
int fd, uint64_t timeout, getdns_eventloop_event *ev);
|
||||
static getdns_return_t getdns_libuv_schedule_timeout
|
||||
(getdns_eventloop *loop, uint64_t timeout, getdns_eventloop_event *ev);
|
||||
static getdns_return_t getdns_libuv_clear_event
|
||||
(getdns_eventloop *loop, getdns_eventloop_event *ev);
|
||||
|
||||
static getdns_eventloop_vmt getdns_libuv_vmt = {
|
||||
getdns_libuv_cleanup,
|
||||
getdns_libuv_schedule_read,
|
||||
getdns_libuv_clear_event,
|
||||
getdns_libuv_schedule_timeout,
|
||||
getdns_libuv_clear_event,
|
||||
};
|
||||
|
||||
getdns_return_t
|
||||
getdns_extension_set_libuv_loop(getdns_context *context, uv_loop_t *loop)
|
||||
static void
|
||||
getdns_libuv_run(getdns_eventloop *loop)
|
||||
{
|
||||
getdns_libuv *ext;
|
||||
getdns_return_t r;
|
||||
|
||||
RETURN_IF_NULL(context, GETDNS_RETURN_BAD_CONTEXT);
|
||||
RETURN_IF_NULL(loop, GETDNS_RETURN_INVALID_PARAMETER);
|
||||
|
||||
if ((r = getdns_context_detach_eventloop(context)))
|
||||
return r;
|
||||
|
||||
ext = GETDNS_MALLOC(*priv_getdns_context_mf(context), getdns_libuv);
|
||||
ext->vmt = &getdns_libuv_vmt;
|
||||
ext->loop = loop;
|
||||
ext->mf = *priv_getdns_context_mf(context);
|
||||
|
||||
return getdns_context_set_eventloop(context, (getdns_eventloop *)&ext);
|
||||
(void) uv_run(((getdns_libuv *)loop)->loop, UV_RUN_DEFAULT);
|
||||
}
|
||||
|
||||
static getdns_return_t
|
||||
static void
|
||||
getdns_libuv_run_once(getdns_eventloop *loop, int blocking)
|
||||
{
|
||||
(void) uv_run(((getdns_libuv *)loop)->loop,
|
||||
blocking ? UV_RUN_ONCE : UV_RUN_NOWAIT);
|
||||
}
|
||||
|
||||
static void
|
||||
getdns_libuv_cleanup(getdns_eventloop *loop)
|
||||
{
|
||||
getdns_libuv *ext = (getdns_libuv *)loop;
|
||||
|
||||
GETDNS_FREE(ext->mf, ext);
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
typedef struct poll_timer {
|
||||
uv_poll_t poll;
|
||||
uv_poll_t read;
|
||||
uv_poll_t write;
|
||||
uv_timer_t timer;
|
||||
} poll_timer;
|
||||
|
||||
static getdns_return_t
|
||||
getdns_libuv_clear(getdns_eventloop *loop, getdns_eventloop_event *el_ev)
|
||||
{
|
||||
getdns_libuv *ext = (getdns_libuv *)loop;
|
||||
poll_timer *my_ev = (poll_timer *)el_ev->ev;
|
||||
|
||||
assert(my_ev);
|
||||
|
||||
if (el_ev->read_cb) {
|
||||
uv_poll_stop(&my_ev->read);
|
||||
uv_close((uv_handle_t *)&my_ev->read, NULL);
|
||||
}
|
||||
if (el_ev->write_cb) {
|
||||
uv_poll_stop(&my_ev->write);
|
||||
uv_close((uv_handle_t *)&my_ev->write, NULL);
|
||||
}
|
||||
if (el_ev->timeout_cb)
|
||||
uv_timer_stop(&my_ev->timer);
|
||||
uv_close((uv_handle_t *)&my_ev->timer, NULL);
|
||||
|
||||
GETDNS_FREE(ext->mf, el_ev->ev);
|
||||
el_ev->ev = NULL;
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
static void
|
||||
getdns_libuv_read_cb(uv_poll_t *poll, int status, int events)
|
||||
|
@ -106,6 +100,14 @@ getdns_libuv_read_cb(uv_poll_t *poll, int status, int events)
|
|||
el_ev->read_cb(el_ev->userarg);
|
||||
}
|
||||
|
||||
static void
|
||||
getdns_libuv_write_cb(uv_poll_t *poll, int status, int events)
|
||||
{
|
||||
getdns_eventloop_event *el_ev = (getdns_eventloop_event *)poll->data;
|
||||
assert(el_ev->write_cb);
|
||||
el_ev->write_cb(el_ev->userarg);
|
||||
}
|
||||
|
||||
static void
|
||||
getdns_libuv_timeout_cb(uv_timer_t *timer, int status)
|
||||
{
|
||||
|
@ -115,7 +117,7 @@ getdns_libuv_timeout_cb(uv_timer_t *timer, int status)
|
|||
}
|
||||
|
||||
static getdns_return_t
|
||||
getdns_libuv_schedule_read(getdns_eventloop *loop,
|
||||
getdns_libuv_schedule(getdns_eventloop *loop,
|
||||
int fd, uint64_t timeout, getdns_eventloop_event *el_ev)
|
||||
{
|
||||
getdns_libuv *ext = (getdns_libuv *)loop;
|
||||
|
@ -123,11 +125,9 @@ getdns_libuv_schedule_read(getdns_eventloop *loop,
|
|||
uv_poll_t *my_poll;
|
||||
uv_timer_t *my_timer;
|
||||
|
||||
if (fd < 0) el_ev->read_cb = NULL;
|
||||
if (timeout == TIMEOUT_FOREVER) el_ev->timeout_cb = NULL;
|
||||
|
||||
if (!el_ev->read_cb && !el_ev->timeout_cb)
|
||||
return GETDNS_RETURN_GOOD; /* Nothing to schedule */
|
||||
assert(el_ev);
|
||||
assert(!(el_ev->read_cb || el_ev->write_cb) || fd >= 0);
|
||||
assert( el_ev->read_cb || el_ev->write_cb || el_ev->timeout_cb);
|
||||
|
||||
if (!(my_ev = GETDNS_MALLOC(ext->mf, poll_timer)))
|
||||
return GETDNS_RETURN_MEMORY_ERROR;
|
||||
|
@ -135,11 +135,17 @@ getdns_libuv_schedule_read(getdns_eventloop *loop,
|
|||
el_ev->ev = my_ev;
|
||||
|
||||
if (el_ev->read_cb) {
|
||||
my_poll = &my_ev->poll;
|
||||
my_poll = &my_ev->read;
|
||||
uv_poll_init(ext->loop, my_poll, fd);
|
||||
my_poll->data = el_ev;
|
||||
uv_poll_start(my_poll, UV_READABLE, getdns_libuv_read_cb);
|
||||
}
|
||||
if (el_ev->write_cb) {
|
||||
my_poll = &my_ev->write;
|
||||
uv_poll_init(ext->loop, my_poll, fd);
|
||||
my_poll->data = el_ev;
|
||||
uv_poll_start(my_poll, UV_WRITABLE, getdns_libuv_write_cb);
|
||||
}
|
||||
if (el_ev->timeout_cb) {
|
||||
my_timer = &my_ev->timer;
|
||||
uv_timer_init(ext->loop, my_timer);
|
||||
|
@ -149,32 +155,31 @@ getdns_libuv_schedule_read(getdns_eventloop *loop,
|
|||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
static getdns_return_t
|
||||
getdns_libuv_schedule_timeout(getdns_eventloop *loop,
|
||||
uint64_t timeout, getdns_eventloop_event *el_ev)
|
||||
getdns_return_t
|
||||
getdns_extension_set_libuv_loop(getdns_context *context, uv_loop_t *loop)
|
||||
{
|
||||
return getdns_libuv_schedule_read(loop, -1, timeout, el_ev);
|
||||
static getdns_eventloop_vmt getdns_libuv_vmt = {
|
||||
getdns_libuv_cleanup,
|
||||
getdns_libuv_schedule,
|
||||
getdns_libuv_clear,
|
||||
getdns_libuv_run,
|
||||
getdns_libuv_run_once
|
||||
};
|
||||
getdns_libuv *ext;
|
||||
getdns_return_t r;
|
||||
|
||||
if (!context)
|
||||
return GETDNS_RETURN_BAD_CONTEXT;
|
||||
if (!loop)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
if ((r = getdns_context_detach_eventloop(context)))
|
||||
return r;
|
||||
|
||||
ext = GETDNS_MALLOC(*priv_getdns_context_mf(context), getdns_libuv);
|
||||
ext->vmt = &getdns_libuv_vmt;
|
||||
ext->loop = loop;
|
||||
ext->mf = *priv_getdns_context_mf(context);
|
||||
|
||||
return getdns_context_set_eventloop(context, (getdns_eventloop *)&ext);
|
||||
}
|
||||
|
||||
static getdns_return_t
|
||||
getdns_libuv_clear_event(getdns_eventloop *loop,
|
||||
getdns_eventloop_event *el_ev)
|
||||
{
|
||||
getdns_libuv *ext = (getdns_libuv *)loop;
|
||||
poll_timer *my_ev = (poll_timer *)el_ev->ev;
|
||||
|
||||
assert(my_ev);
|
||||
|
||||
if (el_ev->read_cb) {
|
||||
uv_poll_stop(&my_ev->poll);
|
||||
uv_close((uv_handle_t *)&my_ev->poll, NULL);
|
||||
}
|
||||
if (el_ev->timeout_cb)
|
||||
uv_timer_stop(&my_ev->timer);
|
||||
uv_close((uv_handle_t *)&my_ev->timer, NULL);
|
||||
|
||||
GETDNS_FREE(ext->mf, el_ev->ev);
|
||||
el_ev->ev = NULL;
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
|
|
|
@ -73,6 +73,7 @@ typedef void (*getdns_eventloop_callback)(void *userarg);
|
|||
typedef struct getdns_eventloop_event {
|
||||
void *userarg;
|
||||
getdns_eventloop_callback read_cb;
|
||||
getdns_eventloop_callback write_cb;
|
||||
getdns_eventloop_callback timeout_cb;
|
||||
|
||||
/* Pointer to the underlying event
|
||||
|
@ -86,45 +87,32 @@ typedef struct getdns_eventloop {
|
|||
getdns_eventloop_vmt *vmt;
|
||||
} getdns_eventloop;
|
||||
|
||||
/* Call the extension to clean up data allocated on initialization. */
|
||||
typedef getdns_return_t (*getdns_eventloop_cleanup)(getdns_eventloop *loop);
|
||||
/* A prototype for a method having no arguments and not return value. */
|
||||
typedef void (*getdns_eventloop_noargs)(getdns_eventloop *loop);
|
||||
|
||||
/* Call the extension to schedule an event that will trigger when
|
||||
* file descriptor fd will become readble.
|
||||
/* Call the extension to schedule an event
|
||||
*
|
||||
* The getdns_eventloop_event must be provided by the caller with the callbacks
|
||||
* and userarg therein already supplied (by the caller). This function must set
|
||||
* and userarg therein already supplied (by the caller). This function will set
|
||||
* the ev pointer (in the getdns_eventloop_event) to refer to the underlying
|
||||
* (extension) event.
|
||||
*/
|
||||
typedef getdns_return_t (*getdns_eventloop_schedule_read)(getdns_eventloop *loop,
|
||||
typedef getdns_return_t (*getdns_eventloop_schedule)(getdns_eventloop *loop,
|
||||
int fd, uint64_t timeout, getdns_eventloop_event *ev);
|
||||
|
||||
/* Call the extension to free a read event. */
|
||||
typedef getdns_return_t (*getdns_eventloop_clear_read)
|
||||
/* Call the extension to clean a scheduled event */
|
||||
typedef getdns_return_t (*getdns_eventloop_clear)
|
||||
(getdns_eventloop *loop, getdns_eventloop_event *ev);
|
||||
|
||||
/* Call the extension to schedule a timer.
|
||||
*
|
||||
* The getdns_eventloop_event must be provided by the caller with the timeout
|
||||
* callback and userarg therein already supplied (by the caller).
|
||||
* This function must set the ev pointer (in the getdns_eventloop_event)
|
||||
* to refer to the underlying (extension) event.
|
||||
*/
|
||||
typedef getdns_return_t (*getdns_eventloop_schedule_timeout)
|
||||
(getdns_eventloop *loop, uint64_t timeout, getdns_eventloop_event *ev);
|
||||
typedef void (*getdns_eventloop_run_once)(getdns_eventloop *loop,int blocking);
|
||||
|
||||
/* Call the extension to free a timer. */
|
||||
typedef getdns_return_t (*getdns_eventloop_clear_timeout)
|
||||
(getdns_eventloop *loop, getdns_eventloop_event *ev);
|
||||
|
||||
/* Virtual Method Table */
|
||||
struct getdns_eventloop_vmt {
|
||||
getdns_eventloop_cleanup cleanup;
|
||||
getdns_eventloop_schedule_read schedule_read;
|
||||
getdns_eventloop_clear_read clear_read;
|
||||
getdns_eventloop_schedule_timeout schedule_timeout;
|
||||
getdns_eventloop_clear_timeout clear_timeout;
|
||||
getdns_eventloop_noargs cleanup;
|
||||
getdns_eventloop_schedule schedule;
|
||||
getdns_eventloop_clear clear;
|
||||
getdns_eventloop_noargs run;
|
||||
getdns_eventloop_run_once run_once;
|
||||
};
|
||||
|
||||
/* set an event loop extension on the context */
|
||||
|
@ -136,6 +124,10 @@ getdns_context_set_eventloop(getdns_context* context,
|
|||
getdns_return_t
|
||||
getdns_context_detach_eventloop(getdns_context *context);
|
||||
|
||||
/* Run the context's event loop until nothing more to do */
|
||||
void
|
||||
getdns_context_run(getdns_context *context);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue