]> git.meshlink.io Git - meshlink/commitdiff
Add "blocking" asynchronous DNS requests.
authorGuus Sliepen <guus@meshlink.io>
Thu, 9 Apr 2020 21:39:19 +0000 (23:39 +0200)
committerGuus Sliepen <guus@meshlink.io>
Thu, 9 Apr 2020 22:06:26 +0000 (00:06 +0200)
These block for a limited amount of time, preventing lookups from taking
too long. Because these requests can be done without the main MeshLink
thread running, we don't use the request queue, but instead spawn a
thread for each blocking request.

src/adns.c
src/adns.h

index 6e988c01f0147a3a0ed270c83fbf2f603534c82a..2776a4c5494bfa562ecb4163812c89740d925957 100644 (file)
@@ -20,6 +20,7 @@
 #include "system.h"
 
 #include <pthread.h>
 #include "system.h"
 
 #include <pthread.h>
+#include <stdatomic.h>
 
 #include "adns.h"
 #include "logger.h"
 
 #include "adns.h"
 #include "logger.h"
@@ -81,13 +82,13 @@ static void adns_cb_handler(event_loop_t *loop, void *data) {
        }
 }
 
        }
 }
 
-extern void init_adns(meshlink_handle_t *mesh) {
+void init_adns(meshlink_handle_t *mesh) {
        signal_add(&mesh->loop, &mesh->adns_signal, adns_cb_handler, mesh, 1);
        meshlink_queue_init(&mesh->adns_queue);
        pthread_create(&mesh->adns_thread, NULL, adns_loop, mesh);
 }
 
        signal_add(&mesh->loop, &mesh->adns_signal, adns_cb_handler, mesh, 1);
        meshlink_queue_init(&mesh->adns_queue);
        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;
        }
        if(!mesh->adns_signal.cb) {
                return;
        }
@@ -111,7 +112,7 @@ extern void exit_adns(meshlink_handle_t *mesh) {
        signal_del(&mesh->loop, &mesh->adns_signal);
 }
 
        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;
        adns_item_t *item = xmalloc(sizeof(*item));
        item->cb = cb;
        item->data = data;
@@ -127,3 +128,88 @@ extern void adns_queue(meshlink_handle_t *mesh, char *host, char *serv, adns_cb_
 
        pthread_cond_signal(&mesh->adns_cond);
 }
 
        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;
+       bool done;
+};
+
+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);
+
+       if(getaddrinfo(info->host, info->serv, NULL, &info->ai)) {
+               info->ai = NULL;
+       }
+
+       pthread_mutex_lock(&info->mutex);
+
+       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 timeout) {
+       struct adns_blocking_info *info = xzalloc(sizeof(*info));
+
+       info->mesh = mesh;
+       info->host = host;
+       info->serv = serv;
+
+       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);
+       }
+
+       pthread_mutex_lock(&info->mutex);
+       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;
+}
index aed15d86ca0742a9a6129085c544f8bd19052a5e..8dc89fe13af185480f8d7f29b04fb3a46432dfe3 100644 (file)
@@ -27,5 +27,6 @@ typedef void (*adns_cb_t)(meshlink_handle_t *mesh, char *host, char *serv, void
 extern void init_adns(meshlink_handle_t *mesh);
 extern void exit_adns(meshlink_handle_t *mesh);
 extern void adns_queue(meshlink_handle_t *mesh, char *host, char *serv, adns_cb_t cb, void *data, int timeout);
 extern void init_adns(meshlink_handle_t *mesh);
 extern void exit_adns(meshlink_handle_t *mesh);
 extern void adns_queue(meshlink_handle_t *mesh, char *host, char *serv, adns_cb_t cb, void *data, int timeout);
+extern struct addrinfo *adns_blocking_request(meshlink_handle_t *mesh, char *host, char *serv, int timeout);
 
 #endif
 
 #endif