|
|
@@ -0,0 +1,97 @@ |
|
|
|
#include "btpd.h" |
|
|
|
|
|
|
|
#include <pthread.h> |
|
|
|
|
|
|
|
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"); |
|
|
|
} |