2014-02-05 23:24:26 -06:00
|
|
|
/**
|
2014-10-10 07:48:52 -05:00
|
|
|
* \file libev.c
|
|
|
|
* \brief Eventloop extension for libev
|
2014-02-05 23:24:26 -06:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2014-02-25 07:12:33 -06:00
|
|
|
* Copyright (c) 2013, NLNet Labs, Verisign, Inc.
|
2014-02-05 23:24:26 -06:00
|
|
|
* 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.
|
2014-02-25 07:23:19 -06:00
|
|
|
* * Neither the names of the copyright holders nor the
|
2014-02-05 23:24:26 -06:00
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2014-05-19 08:50:34 -05:00
|
|
|
#include "getdns/getdns_ext_libev.h"
|
2014-10-08 18:18:53 -05:00
|
|
|
#include "types-internal.h"
|
2014-10-10 07:48:52 -05:00
|
|
|
#include "config.h"
|
2014-05-26 08:56:30 -05:00
|
|
|
|
|
|
|
#ifdef HAVE_LIBEV_EV_H
|
|
|
|
#include <libev/ev.h>
|
|
|
|
#else
|
|
|
|
#include <ev.h>
|
|
|
|
#endif
|
2014-02-05 23:24:26 -06:00
|
|
|
|
2014-10-08 18:18:53 -05:00
|
|
|
typedef struct getdns_libev {
|
|
|
|
getdns_eventloop_vmt *vmt;
|
|
|
|
struct ev_loop *loop;
|
|
|
|
struct mem_funcs mf;
|
|
|
|
} getdns_libev;
|
|
|
|
|
2014-10-10 07:48:52 -05:00
|
|
|
static void
|
|
|
|
getdns_libev_run(getdns_eventloop *loop)
|
2014-10-08 18:18:53 -05:00
|
|
|
{
|
2014-10-10 07:48:52 -05:00
|
|
|
(void) ev_run(((getdns_libev *)loop)->loop, 0);
|
|
|
|
}
|
2014-10-08 18:18:53 -05:00
|
|
|
|
2014-10-10 07:48:52 -05:00
|
|
|
static void
|
|
|
|
getdns_libev_run_once(getdns_eventloop *loop, int blocking)
|
|
|
|
{
|
|
|
|
(void) ev_run(((getdns_libev *)loop)->loop,
|
|
|
|
blocking ? EVRUN_ONCE : EVRUN_NOWAIT);
|
2014-02-21 17:42:04 -06:00
|
|
|
}
|
|
|
|
|
2014-10-10 07:48:52 -05:00
|
|
|
static void
|
2014-10-08 18:18:53 -05:00
|
|
|
getdns_libev_cleanup(getdns_eventloop *loop)
|
|
|
|
{
|
|
|
|
getdns_libev *ext = (getdns_libev *)loop;
|
|
|
|
GETDNS_FREE(ext->mf, ext);
|
2014-02-05 23:24:26 -06:00
|
|
|
}
|
|
|
|
|
2014-10-10 04:14:01 -05:00
|
|
|
typedef struct io_timer {
|
2014-10-10 07:48:52 -05:00
|
|
|
ev_io read;
|
|
|
|
ev_io write;
|
2014-10-10 04:14:01 -05:00
|
|
|
ev_timer timer;
|
|
|
|
} io_timer;
|
|
|
|
|
2014-10-10 07:48:52 -05:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2014-02-05 23:24:26 -06:00
|
|
|
static void
|
2014-10-08 18:18:53 -05:00
|
|
|
getdns_libev_read_cb(struct ev_loop *l, struct ev_io *io, int revents)
|
|
|
|
{
|
|
|
|
getdns_eventloop_event *el_ev = (getdns_eventloop_event *)io->data;
|
|
|
|
assert(el_ev->read_cb);
|
|
|
|
el_ev->read_cb(el_ev->userarg);
|
2014-02-05 23:24:26 -06:00
|
|
|
}
|
|
|
|
|
2014-10-10 07:48:52 -05:00
|
|
|
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);
|
2014-10-14 18:13:39 -05:00
|
|
|
el_ev->write_cb(el_ev->userarg);
|
2014-10-10 07:48:52 -05:00
|
|
|
}
|
|
|
|
|
2014-10-08 18:18:53 -05:00
|
|
|
static void
|
|
|
|
getdns_libev_timeout_cb(struct ev_loop *l, struct ev_timer *timer, int revent)
|
|
|
|
{
|
|
|
|
getdns_eventloop_event *el_ev = (getdns_eventloop_event *)timer->data;
|
|
|
|
assert(el_ev->timeout_cb);
|
|
|
|
el_ev->timeout_cb(el_ev->userarg);
|
2014-02-21 17:42:04 -06:00
|
|
|
}
|
|
|
|
|
2014-02-05 23:24:26 -06:00
|
|
|
static getdns_return_t
|
2014-10-10 07:48:52 -05:00
|
|
|
getdns_libev_schedule(getdns_eventloop *loop,
|
2014-10-08 18:18:53 -05:00
|
|
|
int fd, uint64_t timeout, getdns_eventloop_event *el_ev)
|
|
|
|
{
|
|
|
|
getdns_libev *ext = (getdns_libev *)loop;
|
|
|
|
io_timer *my_ev;
|
|
|
|
ev_io *my_io;
|
|
|
|
ev_timer *my_timer;
|
|
|
|
ev_tstamp to = ((ev_tstamp)timeout) / 1000;
|
|
|
|
|
2014-10-10 07:48:52 -05:00
|
|
|
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);
|
2014-10-08 18:18:53 -05:00
|
|
|
|
|
|
|
if (!(my_ev = GETDNS_MALLOC(ext->mf, io_timer)))
|
|
|
|
return GETDNS_RETURN_MEMORY_ERROR;
|
|
|
|
|
|
|
|
el_ev->ev = my_ev;
|
|
|
|
|
|
|
|
if (el_ev->read_cb) {
|
2014-10-10 07:48:52 -05:00
|
|
|
my_io = &my_ev->read;
|
2014-10-08 18:18:53 -05:00
|
|
|
ev_io_init(my_io, getdns_libev_read_cb, fd, EV_READ);
|
2014-10-10 07:48:52 -05:00
|
|
|
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);
|
2014-10-08 18:18:53 -05:00
|
|
|
}
|
|
|
|
if (el_ev->timeout_cb) {
|
|
|
|
my_timer = &my_ev->timer;
|
|
|
|
ev_timer_init(my_timer, getdns_libev_timeout_cb, to, 0);
|
2014-10-10 07:48:52 -05:00
|
|
|
my_timer->data = el_ev;
|
|
|
|
ev_timer_start(ext->loop, my_timer);
|
2014-10-08 18:18:53 -05:00
|
|
|
}
|
|
|
|
return GETDNS_RETURN_GOOD;
|
2014-02-05 23:24:26 -06:00
|
|
|
}
|
|
|
|
|
2014-10-10 07:48:52 -05:00
|
|
|
getdns_return_t
|
|
|
|
getdns_extension_set_libev_loop(getdns_context *context,
|
|
|
|
struct ev_loop *loop)
|
2014-10-06 13:23:50 -05:00
|
|
|
{
|
2014-10-10 07:48:52 -05:00
|
|
|
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;
|
2014-02-05 23:24:26 -06:00
|
|
|
|
2014-10-10 07:48:52 -05:00
|
|
|
if (!context)
|
|
|
|
return GETDNS_RETURN_BAD_CONTEXT;
|
|
|
|
if (!loop)
|
|
|
|
return GETDNS_RETURN_INVALID_PARAMETER;
|
2014-10-08 18:18:53 -05:00
|
|
|
|
2014-10-10 07:48:52 -05:00
|
|
|
ext = GETDNS_MALLOC(*priv_getdns_context_mf(context), getdns_libev);
|
2014-10-14 18:13:39 -05:00
|
|
|
if (!ext)
|
|
|
|
return GETDNS_RETURN_MEMORY_ERROR;
|
2014-10-10 07:48:52 -05:00
|
|
|
ext->vmt = &getdns_libev_vmt;
|
|
|
|
ext->loop = loop;
|
|
|
|
ext->mf = *priv_getdns_context_mf(context);
|
2014-02-05 23:24:26 -06:00
|
|
|
|
2014-10-14 18:13:39 -05:00
|
|
|
return getdns_context_set_eventloop(context, (getdns_eventloop *)ext);
|
2014-10-10 07:48:52 -05:00
|
|
|
}
|