From a34d4da7558a61838d031fbaaee9902657c5171e Mon Sep 17 00:00:00 2001 From: Richard Nyberg Date: Tue, 23 Dec 2008 23:35:07 +0100 Subject: [PATCH] Add a thread for performing asynchronous getaddrinfo's. --- btpd/Makefile.am | 2 +- btpd/addrinfo.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++ btpd/btpd.c | 2 + btpd/btpd.h | 6 +++ 4 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 btpd/addrinfo.c diff --git a/btpd/Makefile.am b/btpd/Makefile.am index 2568763..197ee3b 100644 --- a/btpd/Makefile.am +++ b/btpd/Makefile.am @@ -1,6 +1,6 @@ bin_PROGRAMS=btpd btpd_SOURCES=\ - active.c active.h\ + active.c active.h addrinfo.c\ btpd.c btpd.h\ cli_if.c content.c content.h\ download.c download_subr.c download.h\ diff --git a/btpd/addrinfo.c b/btpd/addrinfo.c new file mode 100644 index 0000000..8bff8b2 --- /dev/null +++ b/btpd/addrinfo.c @@ -0,0 +1,97 @@ +#include "btpd.h" + +#include + +struct ai_ctx { + BTPDQ_ENTRY(ai_ctx) entry; + struct addrinfo hints; + struct addrinfo *res; + char node[255], service[6]; + void (*cb)(void *, int, struct addrinfo *); + void *arg; + int cancel; + int error; + short port; +}; + +BTPDQ_HEAD(ai_ctx_tq, ai_ctx); + +static struct ai_ctx_tq m_aiq = BTPDQ_HEAD_INITIALIZER(m_aiq); +static pthread_mutex_t m_aiq_lock; +static pthread_cond_t m_aiq_cond; + +struct ai_ctx * +btpd_addrinfo(const char *node, short port, struct addrinfo *hints, + void (*cb)(void *, int, struct addrinfo *), void *arg) +{ + struct ai_ctx *ctx = btpd_calloc(1, sizeof(*ctx)); + ctx->hints = *hints; + ctx->cb = cb; + ctx->arg = arg; + snprintf(ctx->node, sizeof(ctx->node), "%s", node); + ctx->port = port; + if (port > 0) + snprintf(ctx->service, sizeof(ctx->service), "%hd", port); + + pthread_mutex_lock(&m_aiq_lock); + BTPDQ_INSERT_TAIL(&m_aiq, ctx, entry); + pthread_mutex_unlock(&m_aiq_lock); + pthread_cond_signal(&m_aiq_cond); + + return ctx; +} + +void +btpd_addrinfo_cancel(struct ai_ctx *ctx) +{ + ctx->cancel = 1; +} + +static void +addrinfo_td_cb(void *arg) +{ + struct ai_ctx *ctx = arg; + if (!ctx->cancel) + ctx->cb(ctx->arg, ctx->error, ctx->res); + else if (ctx->error != 0) + freeaddrinfo(ctx->res); + free(ctx); +} + +static void * +addrinfo_td(void *arg) +{ + struct ai_ctx *ctx; + char *service; + while (1) { + pthread_mutex_lock(&m_aiq_lock); + while (BTPDQ_EMPTY(&m_aiq)) + pthread_cond_wait(&m_aiq_cond, &m_aiq_lock); + ctx = BTPDQ_FIRST(&m_aiq); + BTPDQ_REMOVE(&m_aiq, ctx, entry); + pthread_mutex_unlock(&m_aiq_lock); + + service = ctx->port > 0 ? ctx->service : NULL; + ctx->error = getaddrinfo(ctx->node, service, &ctx->hints, &ctx->res); + + td_post_begin(); + td_post(addrinfo_td_cb, ctx); + td_post_end(); + } +} + +static void +errdie(int err, const char *str) +{ + if (err != 0) + btpd_err("addrinfo_init: %s (%s).\n", str, strerror(errno)); +} + +void +addrinfo_init(void) +{ + pthread_t td; + errdie(pthread_mutex_init(&m_aiq_lock, NULL), "pthread_mutex_init"); + errdie(pthread_cond_init(&m_aiq_cond, NULL), "pthread_cond_init"); + errdie(pthread_create(&td, NULL, addrinfo_td, NULL), "pthread_create"); +} diff --git a/btpd/btpd.c b/btpd/btpd.c index c8bd5d2..e6e0f30 100644 --- a/btpd/btpd.c +++ b/btpd/btpd.c @@ -77,6 +77,7 @@ heartbeat_cb(int fd, short type, void *arg) void tr_init(void); void ipc_init(void); void td_init(void); +void addrinfo_init(void); void btpd_init(void) @@ -102,6 +103,7 @@ btpd_init(void) srandom(seed); td_init(); + addrinfo_init(); net_init(); ipc_init(); ul_init(); diff --git a/btpd/btpd.h b/btpd/btpd.h index fe6cabf..f03df65 100644 --- a/btpd/btpd.h +++ b/btpd/btpd.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -84,4 +85,9 @@ void td_post(void (*cb)(void *), void *arg); void td_post_end(); #define td_post_begin td_acquire_lock +typedef struct ai_ctx * aictx_t; +aictx_t btpd_addrinfo(const char *node, short port, struct addrinfo *hints, + void (*cb)(void *, int, struct addrinfo *), void *arg); +void btpd_addrinfo_cancel(aictx_t ctx); + #endif