X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=src%2Fadns.c;h=cae8234f499d506d8dedb2ed02a47c9f3ba1cd59;hb=4b6c01b1d5383b1a7417244a31ad4652aab2d5db;hp=6e988c01f0147a3a0ed270c83fbf2f603534c82a;hpb=e25f5166a3edc98f4a333c98881d4899635f1144;p=meshlink diff --git a/src/adns.c b/src/adns.c index 6e988c01..cae8234f 100644 --- a/src/adns.c +++ b/src/adns.c @@ -20,8 +20,10 @@ #include "system.h" #include +#include #include "adns.h" +#include "devtools.h" #include "logger.h" #include "xalloc.h" @@ -47,6 +49,7 @@ static void *adns_loop(void *data) { if(time(NULL) < item->deadline) { logger(mesh, MESHLINK_DEBUG, "Resolving %s port %s", item->host, item->serv); + devtool_adns_resolve_probe(); int result = getaddrinfo(item->host, item->serv, NULL, &item->ai); if(result) { @@ -81,13 +84,14 @@ static void adns_cb_handler(event_loop_t *loop, void *data) { } } -extern void init_adns(meshlink_handle_t *mesh) { - signal_add(&mesh->loop, &mesh->adns_signal, adns_cb_handler, mesh, 1); +void init_adns(meshlink_handle_t *mesh) { meshlink_queue_init(&mesh->adns_queue); + meshlink_queue_init(&mesh->adns_done_queue); + signal_add(&mesh->loop, &mesh->adns_signal, adns_cb_handler, mesh, 1); pthread_create(&mesh->adns_thread, NULL, adns_loop, mesh); } -extern void exit_adns(meshlink_handle_t *mesh) { +void exit_adns(meshlink_handle_t *mesh) { if(!mesh->adns_signal.cb) { return; } @@ -111,7 +115,7 @@ extern void exit_adns(meshlink_handle_t *mesh) { signal_del(&mesh->loop, &mesh->adns_signal); } -extern void adns_queue(meshlink_handle_t *mesh, char *host, char *serv, adns_cb_t cb, void *data, int timeout) { +void adns_queue(meshlink_handle_t *mesh, char *host, char *serv, adns_cb_t cb, void *data, int timeout) { adns_item_t *item = xmalloc(sizeof(*item)); item->cb = cb; item->data = data; @@ -127,3 +131,103 @@ extern void adns_queue(meshlink_handle_t *mesh, char *host, char *serv, adns_cb_ pthread_cond_signal(&mesh->adns_cond); } + +struct adns_blocking_info { + meshlink_handle_t *mesh; + pthread_mutex_t mutex; + pthread_cond_t cond; + char *host; + char *serv; + struct addrinfo *ai; + int socktype; + bool done; +}; + +static void *adns_blocking_handler(void *data) { + struct adns_blocking_info *info = data; + + logger(info->mesh, MESHLINK_DEBUG, "Resolving %s port %s", info->host, info->serv); + devtool_adns_resolve_probe(); + + struct addrinfo hint = { + .ai_family = AF_UNSPEC, + .ai_socktype = info->socktype, + }; + + if(getaddrinfo(info->host, info->serv, &hint, &info->ai)) { + info->ai = NULL; + } + + if(pthread_mutex_lock(&info->mutex) != 0) { + abort(); + } + + bool cleanup = info->done; + + if(!info->done) { + info->done = true; + pthread_cond_signal(&info->cond); + } + + pthread_mutex_unlock(&info->mutex); + + if(cleanup) { + free(info->host); + free(info->serv); + free(info); + } + + return NULL; +} + +struct addrinfo *adns_blocking_request(meshlink_handle_t *mesh, char *host, char *serv, int socktype, int timeout) { + struct adns_blocking_info *info = xzalloc(sizeof(*info)); + + info->mesh = mesh; + info->host = host; + info->serv = serv; + info->socktype = socktype; + pthread_mutex_init(&info->mutex, NULL); + pthread_cond_init(&info->cond, NULL); + + struct timespec deadline; + clock_gettime(CLOCK_REALTIME, &deadline); + deadline.tv_sec += timeout; + + pthread_t thread; + + if(pthread_create(&thread, NULL, adns_blocking_handler, info)) { + free(info->host); + free(info->serv); + free(info); + return NULL; + } else { + pthread_detach(thread); + } + + if(pthread_mutex_lock(&info->mutex) != 0) { + abort(); + } + + pthread_cond_timedwait(&info->cond, &info->mutex, &deadline); + + struct addrinfo *result = NULL; + bool cleanup = info->done; + + if(info->done) { + result = info->ai; + } else { + logger(mesh, MESHLINK_WARNING, "Deadline passed for DNS request %s port %s", host, serv); + info->done = true; + } + + pthread_mutex_unlock(&info->mutex); + + if(cleanup) { + free(info->host); + free(info->serv); + free(info); + } + + return result; +}