From 8b4c90eaf418a2a206c29ec5587f0f04afd0ec00 Mon Sep 17 00:00:00 2001 From: Neil Cook Date: Thu, 17 Nov 2016 17:21:04 +0000 Subject: [PATCH 01/56] move default eventloop from select to poll, make max fds dependent on value from getrlimit not FD_SETSIZE --- src/extension/default_eventloop.c | 117 +++++++++++++++++++++--------- src/extension/default_eventloop.h | 17 ++--- 2 files changed, 86 insertions(+), 48 deletions(-) diff --git a/src/extension/default_eventloop.c b/src/extension/default_eventloop.c index c27dacde..ec1b1e19 100644 --- a/src/extension/default_eventloop.c +++ b/src/extension/default_eventloop.c @@ -27,10 +27,15 @@ #include "config.h" +#include +#include #include "extension/default_eventloop.h" #include "debug.h" #include "types-internal.h" +static int max_fds = 0; +static int max_timeouts = 0; + static uint64_t get_now_plus(uint64_t amount) { struct timeval tv; @@ -53,15 +58,15 @@ default_eventloop_schedule(getdns_eventloop *loop, _getdns_default_eventloop *default_loop = (_getdns_default_eventloop *)loop; size_t i; - DEBUG_SCHED( "%s(loop: %p, fd: %d, timeout: %"PRIu64", event: %p, FD_SETSIZE: %d)\n" - , __FUNCTION__, loop, fd, timeout, event, FD_SETSIZE); + DEBUG_SCHED( "%s(loop: %p, fd: %d, timeout: %"PRIu64", event: %p, max_fds: %d)\n" + , __FUNCTION__, loop, fd, timeout, event, max_fds); if (!loop || !event) return GETDNS_RETURN_INVALID_PARAMETER; - if (fd >= (int)FD_SETSIZE) { - DEBUG_SCHED( "ERROR: fd %d >= FD_SETSIZE: %d!\n" - , fd, FD_SETSIZE); + if (fd >= (int)max_fds) { + DEBUG_SCHED( "ERROR: fd %d >= max_fds: %d!\n" + , fd, max_fds); return GETDNS_RETURN_GENERIC_ERROR; } if (fd >= 0 && !(event->read_cb || event->write_cb)) { @@ -101,7 +106,7 @@ default_eventloop_schedule(getdns_eventloop *loop, DEBUG_SCHED("ERROR: timeout event with write_cb! Clearing.\n"); event->write_cb = NULL; } - for (i = 0; i < MAX_TIMEOUTS; i++) { + for (i = 0; i < max_timeouts; i++) { if (default_loop->timeout_events[i] == NULL) { default_loop->timeout_events[i] = event; default_loop->timeout_times[i] = get_now_plus(timeout); @@ -126,7 +131,7 @@ default_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) DEBUG_SCHED( "%s(loop: %p, event: %p)\n", __FUNCTION__, loop, event); i = (intptr_t)event->ev - 1; - if (i < 0 || i >= FD_SETSIZE) { + if (i < 0 || i > max_fds) { return GETDNS_RETURN_GENERIC_ERROR; } if (event->timeout_cb && !event->read_cb && !event->write_cb) { @@ -153,7 +158,15 @@ default_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) static void default_eventloop_cleanup(getdns_eventloop *loop) { - (void)loop; + _getdns_default_eventloop *default_loop = (_getdns_default_eventloop *)loop; + if (default_loop->fd_events) + free(default_loop->fd_events); + if (default_loop->fd_timeout_times) + free(default_loop->fd_timeout_times); + if (default_loop->timeout_events) + free(default_loop->timeout_events); + if (default_loop->timeout_times) + free(default_loop->timeout_times); } static void @@ -191,20 +204,19 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) { _getdns_default_eventloop *default_loop = (_getdns_default_eventloop *)loop; - fd_set readfds, writefds; int fd, max_fd = -1; uint64_t now, timeout = TIMEOUT_FOREVER; size_t i; - struct timeval tv; - + int poll_timeout = 0; + struct pollfd* pfds = NULL; + int num_pfds = 0; + if (!loop) return; - - FD_ZERO(&readfds); - FD_ZERO(&writefds); + now = get_now_plus(0); - for (i = 0; i < MAX_TIMEOUTS; i++) { + for (i = 0; i < max_timeouts; i++) { if (!default_loop->timeout_events[i]) continue; if (now > default_loop->timeout_times[i]) @@ -212,50 +224,65 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) else if (default_loop->timeout_times[i] < timeout) timeout = default_loop->timeout_times[i]; } - for (fd = 0; fd < FD_SETSIZE; fd++) { + // first we count the number of fds that will be active + for (fd = 0; fd < max_fds; fd++) { if (!default_loop->fd_events[fd]) continue; - if (default_loop->fd_events[fd]->read_cb) - FD_SET(fd, &readfds); - if (default_loop->fd_events[fd]->write_cb) - FD_SET(fd, &writefds); + if (default_loop->fd_events[fd]->read_cb || + default_loop->fd_events[fd]->write_cb) + num_pfds++; if (fd > max_fd) max_fd = fd; if (default_loop->fd_timeout_times[fd] < timeout) timeout = default_loop->fd_timeout_times[fd]; } - if (max_fd == -1 && timeout == TIMEOUT_FOREVER) + + if ((max_fd == -1 && timeout == (uint64_t)-1) || (num_pfds == 0)) return; - if (! blocking || now > timeout) { - tv.tv_sec = 0; - tv.tv_usec = 0; - } else { - tv.tv_sec = (long)((timeout - now) / 1000000); - tv.tv_usec = (long)((timeout - now) % 1000000); + pfds = calloc(num_pfds, sizeof(struct pollfd)); + for (fd = 0, i=0; fd < max_fds; fd++) { + if (!default_loop->fd_events[fd]) + continue; + if (default_loop->fd_events[fd]->read_cb) { + pfds[i].fd = fd; + pfds[i].events |= POLLIN; + } + if (default_loop->fd_events[fd]->write_cb) { + pfds[i].fd = fd; + pfds[i].events |= POLLOUT; + } } - if (select(max_fd + 1, &readfds, &writefds, NULL, - (timeout == TIMEOUT_FOREVER ? NULL : &tv)) < 0) { - perror("select() failed"); + + if (! blocking || now > timeout) { + poll_timeout = 0; + } else { + poll_timeout = (timeout - now) * 1000; /* turn seconds in millseconds */ + } + if (poll(pfds, num_pfds, poll_timeout) < 0) { + perror("poll() failed"); exit(EXIT_FAILURE); } now = get_now_plus(0); - for (fd = 0; fd < FD_SETSIZE; fd++) { + for (int i = 0; i < num_pfds; i++) { + int fd = pfds[i].fd; if (default_loop->fd_events[fd] && default_loop->fd_events[fd]->read_cb && - FD_ISSET(fd, &readfds)) + (pfds[i].revents & POLLIN)) default_read_cb(fd, default_loop->fd_events[fd]); if (default_loop->fd_events[fd] && default_loop->fd_events[fd]->write_cb && - FD_ISSET(fd, &writefds)) + (pfds[i].revents & POLLOUT)) default_write_cb(fd, default_loop->fd_events[fd]); - + } + if (pfds) + free(pfds); + for (int fd=0; fd < max_fds; fd++) { if (default_loop->fd_events[fd] && default_loop->fd_events[fd]->timeout_cb && now > default_loop->fd_timeout_times[fd]) default_timeout_cb(fd, default_loop->fd_events[fd]); - i = fd; if (default_loop->timeout_events[i] && default_loop->timeout_events[i]->timeout_cb && @@ -274,7 +301,7 @@ default_eventloop_run(getdns_eventloop *loop) return; i = 0; - while (i < MAX_TIMEOUTS) { + while (i < max_timeouts) { if (default_loop->fd_events[i] || default_loop->timeout_events[i]) { default_eventloop_run_once(loop, 1); i = 0; @@ -297,4 +324,22 @@ _getdns_default_eventloop_init(_getdns_default_eventloop *loop) (void) memset(loop, 0, sizeof(_getdns_default_eventloop)); loop->loop.vmt = &default_eventloop_vmt; + + struct rlimit rl; + if (getrlimit(RLIMIT_NOFILE, &rl) == 0) { + max_fds = rl.rlim_cur; + max_timeouts = max_fds; + } else { + DEBUG_SCHED("ERROR: could not obtain RLIMIT_NOFILE from getrlimit()\n"); + max_fds = 0; + max_timeouts = max_fds; + } + if (max_fds) { + loop->fd_events = calloc(max_fds, sizeof(getdns_eventloop_event *)); + loop->fd_timeout_times = calloc(max_fds, sizeof(uint64_t)); + } + if (max_timeouts) { + loop->timeout_events = calloc(max_timeouts, sizeof(getdns_eventloop_event *)); + loop->timeout_times = calloc(max_timeouts, sizeof(uint64_t)); + } } diff --git a/src/extension/default_eventloop.h b/src/extension/default_eventloop.h index 7f6b78f0..67b2eda8 100644 --- a/src/extension/default_eventloop.h +++ b/src/extension/default_eventloop.h @@ -35,20 +35,13 @@ #include "getdns/getdns.h" #include "getdns/getdns_extra.h" -/* No more than select's capability queries can be outstanding, - * The number of outstanding timeouts should be less or equal then - * the number of outstanding queries, so MAX_TIMEOUTS equal to - * FD_SETSIZE should be safe. - */ -#define MAX_TIMEOUTS FD_SETSIZE - -/* Eventloop based on select */ +/* Eventloop based on poll */ typedef struct _getdns_default_eventloop { getdns_eventloop loop; - getdns_eventloop_event *fd_events[FD_SETSIZE]; - uint64_t fd_timeout_times[FD_SETSIZE]; - getdns_eventloop_event *timeout_events[MAX_TIMEOUTS]; - uint64_t timeout_times[MAX_TIMEOUTS]; + getdns_eventloop_event **fd_events; + uint64_t *fd_timeout_times; + getdns_eventloop_event **timeout_events; + uint64_t *timeout_times; } _getdns_default_eventloop; From a9386e621af226a6b2dbc5d1c2b44573ecef2390 Mon Sep 17 00:00:00 2001 From: Neil Cook Date: Thu, 17 Nov 2016 18:26:11 +0000 Subject: [PATCH 02/56] max_fds and max_timeouts part of default eventloop structure --- src/extension/default_eventloop.c | 43 ++++++++++++++----------------- src/extension/default_eventloop.h | 2 ++ 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/src/extension/default_eventloop.c b/src/extension/default_eventloop.c index ec1b1e19..83a1d956 100644 --- a/src/extension/default_eventloop.c +++ b/src/extension/default_eventloop.c @@ -33,9 +33,6 @@ #include "debug.h" #include "types-internal.h" -static int max_fds = 0; -static int max_timeouts = 0; - static uint64_t get_now_plus(uint64_t amount) { struct timeval tv; @@ -59,14 +56,14 @@ default_eventloop_schedule(getdns_eventloop *loop, size_t i; DEBUG_SCHED( "%s(loop: %p, fd: %d, timeout: %"PRIu64", event: %p, max_fds: %d)\n" - , __FUNCTION__, loop, fd, timeout, event, max_fds); + , __FUNCTION__, loop, fd, timeout, event, default_loop->max_fds); if (!loop || !event) return GETDNS_RETURN_INVALID_PARAMETER; - if (fd >= (int)max_fds) { + if (fd >= (int)default_loop->max_fds) { DEBUG_SCHED( "ERROR: fd %d >= max_fds: %d!\n" - , fd, max_fds); + , fd, default_loop->max_fds); return GETDNS_RETURN_GENERIC_ERROR; } if (fd >= 0 && !(event->read_cb || event->write_cb)) { @@ -106,7 +103,7 @@ default_eventloop_schedule(getdns_eventloop *loop, DEBUG_SCHED("ERROR: timeout event with write_cb! Clearing.\n"); event->write_cb = NULL; } - for (i = 0; i < max_timeouts; i++) { + for (i = 0; i < default_loop->max_timeouts; i++) { if (default_loop->timeout_events[i] == NULL) { default_loop->timeout_events[i] = event; default_loop->timeout_times[i] = get_now_plus(timeout); @@ -131,7 +128,7 @@ default_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) DEBUG_SCHED( "%s(loop: %p, event: %p)\n", __FUNCTION__, loop, event); i = (intptr_t)event->ev - 1; - if (i < 0 || i > max_fds) { + if (i < 0 || i > default_loop->max_fds) { return GETDNS_RETURN_GENERIC_ERROR; } if (event->timeout_cb && !event->read_cb && !event->write_cb) { @@ -216,7 +213,7 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) now = get_now_plus(0); - for (i = 0; i < max_timeouts; i++) { + for (i = 0; i < default_loop->max_timeouts; i++) { if (!default_loop->timeout_events[i]) continue; if (now > default_loop->timeout_times[i]) @@ -225,7 +222,7 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) timeout = default_loop->timeout_times[i]; } // first we count the number of fds that will be active - for (fd = 0; fd < max_fds; fd++) { + for (fd = 0; fd < default_loop->max_fds; fd++) { if (!default_loop->fd_events[fd]) continue; if (default_loop->fd_events[fd]->read_cb || @@ -241,7 +238,7 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) return; pfds = calloc(num_pfds, sizeof(struct pollfd)); - for (fd = 0, i=0; fd < max_fds; fd++) { + for (fd = 0, i=0; fd < default_loop->max_fds; fd++) { if (!default_loop->fd_events[fd]) continue; if (default_loop->fd_events[fd]->read_cb) { @@ -278,7 +275,7 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) } if (pfds) free(pfds); - for (int fd=0; fd < max_fds; fd++) { + for (int fd=0; fd < default_loop->max_fds; fd++) { if (default_loop->fd_events[fd] && default_loop->fd_events[fd]->timeout_cb && now > default_loop->fd_timeout_times[fd]) @@ -301,7 +298,7 @@ default_eventloop_run(getdns_eventloop *loop) return; i = 0; - while (i < max_timeouts) { + while (i < default_loop->max_timeouts) { if (default_loop->fd_events[i] || default_loop->timeout_events[i]) { default_eventloop_run_once(loop, 1); i = 0; @@ -327,19 +324,19 @@ _getdns_default_eventloop_init(_getdns_default_eventloop *loop) struct rlimit rl; if (getrlimit(RLIMIT_NOFILE, &rl) == 0) { - max_fds = rl.rlim_cur; - max_timeouts = max_fds; + loop->max_fds = rl.rlim_cur; + loop->max_timeouts = loop->max_fds; } else { DEBUG_SCHED("ERROR: could not obtain RLIMIT_NOFILE from getrlimit()\n"); - max_fds = 0; - max_timeouts = max_fds; + loop->max_fds = 0; + loop->max_timeouts = loop->max_fds; } - if (max_fds) { - loop->fd_events = calloc(max_fds, sizeof(getdns_eventloop_event *)); - loop->fd_timeout_times = calloc(max_fds, sizeof(uint64_t)); + if (loop->max_fds) { + loop->fd_events = calloc(loop->max_fds, sizeof(getdns_eventloop_event *)); + loop->fd_timeout_times = calloc(loop->max_fds, sizeof(uint64_t)); } - if (max_timeouts) { - loop->timeout_events = calloc(max_timeouts, sizeof(getdns_eventloop_event *)); - loop->timeout_times = calloc(max_timeouts, sizeof(uint64_t)); + if (loop->max_timeouts) { + loop->timeout_events = calloc(loop->max_timeouts, sizeof(getdns_eventloop_event *)); + loop->timeout_times = calloc(loop->max_timeouts, sizeof(uint64_t)); } } diff --git a/src/extension/default_eventloop.h b/src/extension/default_eventloop.h index 67b2eda8..285bbc11 100644 --- a/src/extension/default_eventloop.h +++ b/src/extension/default_eventloop.h @@ -38,6 +38,8 @@ /* Eventloop based on poll */ typedef struct _getdns_default_eventloop { getdns_eventloop loop; + int max_fds; + int max_timeouts; getdns_eventloop_event **fd_events; uint64_t *fd_timeout_times; getdns_eventloop_event **timeout_events; From d3b097fffe11a8fc15ce92af63c0dfb227493057 Mon Sep 17 00:00:00 2001 From: Neil Cook Date: Wed, 14 Dec 2016 15:45:39 +0000 Subject: [PATCH 03/56] Rewrite default_eventloop to use hash tables instead of arrays --- src/extension/default_eventloop.c | 216 +++--- src/extension/default_eventloop.h | 16 +- src/util/uthash.h | 1074 +++++++++++++++++++++++++++++ 3 files changed, 1212 insertions(+), 94 deletions(-) create mode 100644 src/util/uthash.h diff --git a/src/extension/default_eventloop.c b/src/extension/default_eventloop.c index 83a1d956..1ae37adc 100644 --- a/src/extension/default_eventloop.c +++ b/src/extension/default_eventloop.c @@ -27,12 +27,41 @@ #include "config.h" +#ifdef USE_WINSOCK + +#else #include +#endif #include #include "extension/default_eventloop.h" #include "debug.h" #include "types-internal.h" +_getdns_eventloop_info *find_event(_getdns_eventloop_info** events, int id) +{ + _getdns_eventloop_info* ev; + + DEBUG_SCHED("finding event in events ptr %p with id %d", *events, id); + + HASH_FIND_INT(*events, &id, ev); + + DEBUG_SCHED("found event in events ptr %p with id %d and ptr %p", *events, id, ev); + + return ev; +} + +void add_event(_getdns_eventloop_info** events, int id, _getdns_eventloop_info* ev) +{ + DEBUG_SCHED("adding event in events ptr %p with id %d and ptr %p", *events, id, ev); + HASH_ADD_INT(*events, id, ev); +} + +void delete_event(_getdns_eventloop_info** events, _getdns_eventloop_info* ev) +{ + DEBUG_SCHED("deleting event in events ptr %p and ptr %p", *events, ev); + HASH_DEL(*events, ev); +} + static uint64_t get_now_plus(uint64_t amount) { struct timeval tv; @@ -72,22 +101,33 @@ default_eventloop_schedule(getdns_eventloop *loop, fd = -1; } if (fd >= 0) { + DEBUG_SCHED("default_eventloop_schedule: find_event(default_loop->fd_events)"); + _getdns_eventloop_info* fd_event = find_event(&default_loop->fd_events, fd); #if defined(SCHED_DEBUG) && SCHED_DEBUG - if (default_loop->fd_events[fd]) { - if (default_loop->fd_events[fd] == event) { + if (fd_event) { + if (fd_event->event == event) { DEBUG_SCHED("WARNING: Event %p not cleared " "before being rescheduled!\n" - , default_loop->fd_events[fd]); + , fd_event->event); } else { DEBUG_SCHED("ERROR: A different event is " "already present at fd slot: %p!\n" - , default_loop->fd_events[fd]); + , fd_event->event); } } #endif - default_loop->fd_events[fd] = event; - default_loop->fd_timeout_times[fd] = get_now_plus(timeout); - event->ev = (void *)(intptr_t)(fd + 1); + /* cleanup the old event if it exists */ + if (fd_event) { + delete_event(&default_loop->fd_events, fd_event); + free(fd_event); + } + fd_event = calloc(1, sizeof(_getdns_eventloop_info)); + fd_event->id = fd; + fd_event->event = event; + fd_event->timeout_time = get_now_plus(timeout); + add_event(&default_loop->fd_events, fd, fd_event); + event->ev = (void *) (intptr_t) fd + 1; + DEBUG_SCHED( "scheduled read/write at %d\n", fd); return GETDNS_RETURN_GOOD; } @@ -104,10 +144,16 @@ default_eventloop_schedule(getdns_eventloop *loop, event->write_cb = NULL; } for (i = 0; i < default_loop->max_timeouts; i++) { - if (default_loop->timeout_events[i] == NULL) { - default_loop->timeout_events[i] = event; - default_loop->timeout_times[i] = get_now_plus(timeout); - event->ev = (void *)(intptr_t)(i + 1); + _getdns_eventloop_info* timeout_event = NULL; + DEBUG_SCHED("default_eventloop_schedule: find_event(default_loop->timeout_events)"); + if ((timeout_event = find_event(&default_loop->timeout_events, i)) == NULL) { + timeout_event = calloc(1, sizeof(_getdns_eventloop_info)); + timeout_event->id = i; + timeout_event->event = event; + timeout_event->timeout_time = get_now_plus(timeout); + add_event(&default_loop->timeout_events, i, timeout_event); + event->ev = (void *) (intptr_t) i + 1; + DEBUG_SCHED( "scheduled timeout at %d\n", (int)i); return GETDNS_RETURN_GOOD; } @@ -132,21 +178,31 @@ default_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) return GETDNS_RETURN_GENERIC_ERROR; } if (event->timeout_cb && !event->read_cb && !event->write_cb) { + DEBUG_SCHED("default_eventloop_clear: find_event(default_loop->timeout_events)"); + _getdns_eventloop_info* timeout_event = find_event(&default_loop->timeout_events, i); #if defined(SCHED_DEBUG) && SCHED_DEBUG - if (default_loop->timeout_events[i] != event) + if (timeout_event && timeout_event->event != event) DEBUG_SCHED( "ERROR: Different/wrong event present at " "timeout slot: %p!\n" - , default_loop->timeout_events[i]); + , timeout_event); #endif - default_loop->timeout_events[i] = NULL; + if (timeout_event) { + delete_event(&default_loop->timeout_events, timeout_event); + free(timeout_event); + } } else { + DEBUG_SCHED("default_eventloop_clear: find_event(default_loop->fd_events)"); + _getdns_eventloop_info* fd_event = find_event(&default_loop->fd_events, i); #if defined(SCHED_DEBUG) && SCHED_DEBUG - if (default_loop->fd_events[i] != event) + if (fd_event && fd_event->event != event) DEBUG_SCHED( "ERROR: Different/wrong event present at " "fd slot: %p!\n" - , default_loop->fd_events[i]); + , fd_event); #endif - default_loop->fd_events[i] = NULL; + if (fd_event) { + delete_event(&default_loop->fd_events, fd_event); + free(fd_event); + } } event->ev = NULL; return GETDNS_RETURN_GOOD; @@ -156,14 +212,8 @@ static void default_eventloop_cleanup(getdns_eventloop *loop) { _getdns_default_eventloop *default_loop = (_getdns_default_eventloop *)loop; - if (default_loop->fd_events) - free(default_loop->fd_events); - if (default_loop->fd_timeout_times) - free(default_loop->fd_timeout_times); - if (default_loop->timeout_events) - free(default_loop->timeout_events); - if (default_loop->timeout_times) - free(default_loop->timeout_times); + HASH_CLEAR(hh, default_loop->fd_events); + HASH_CLEAR(hh, default_loop->timeout_events); } static void @@ -200,91 +250,93 @@ static void default_eventloop_run_once(getdns_eventloop *loop, int blocking) { _getdns_default_eventloop *default_loop = (_getdns_default_eventloop *)loop; - - int fd, max_fd = -1; + _getdns_eventloop_info *s, *tmp; uint64_t now, timeout = TIMEOUT_FOREVER; - size_t i; + size_t i=0; int poll_timeout = 0; struct pollfd* pfds = NULL; int num_pfds = 0; - + if (!loop) return; now = get_now_plus(0); - for (i = 0; i < default_loop->max_timeouts; i++) { - if (!default_loop->timeout_events[i]) - continue; - if (now > default_loop->timeout_times[i]) - default_timeout_cb(-1, default_loop->timeout_events[i]); - else if (default_loop->timeout_times[i] < timeout) - timeout = default_loop->timeout_times[i]; + HASH_ITER(hh, default_loop->timeout_events, s, tmp) { + if (now > s->timeout_time) + default_timeout_cb(-1, s->event); + else if (s->timeout_time < timeout) + timeout = s->timeout_time; } // first we count the number of fds that will be active - for (fd = 0; fd < default_loop->max_fds; fd++) { - if (!default_loop->fd_events[fd]) - continue; - if (default_loop->fd_events[fd]->read_cb || - default_loop->fd_events[fd]->write_cb) + HASH_ITER(hh, default_loop->fd_events, s, tmp) { + if (s->event->read_cb || + s->event->write_cb) num_pfds++; - if (fd > max_fd) - max_fd = fd; - if (default_loop->fd_timeout_times[fd] < timeout) - timeout = default_loop->fd_timeout_times[fd]; + if (s->timeout_time < timeout) + timeout = s->timeout_time; } - if ((max_fd == -1 && timeout == (uint64_t)-1) || (num_pfds == 0)) + if ((timeout == (uint64_t)-1) && (num_pfds == 0)) return; pfds = calloc(num_pfds, sizeof(struct pollfd)); - for (fd = 0, i=0; fd < default_loop->max_fds; fd++) { - if (!default_loop->fd_events[fd]) - continue; - if (default_loop->fd_events[fd]->read_cb) { - pfds[i].fd = fd; + i = 0; + HASH_ITER(hh, default_loop->fd_events, s, tmp) { + if (s->event->read_cb) { + pfds[i].fd = s->id; pfds[i].events |= POLLIN; } - if (default_loop->fd_events[fd]->write_cb) { - pfds[i].fd = fd; + if (s->event->write_cb) { + pfds[i].fd = s->id; pfds[i].events |= POLLOUT; } + i++; } if (! blocking || now > timeout) { poll_timeout = 0; } else { - poll_timeout = (timeout - now) * 1000; /* turn seconds in millseconds */ + poll_timeout = (timeout - now) * 1000; /* turn seconds into millseconds */ } +#ifdef USE_WINSOCK + if (WSAPoll(pfds, num_pfds, poll_timeout) < 0) { +#else if (poll(pfds, num_pfds, poll_timeout) < 0) { +#endif perror("poll() failed"); exit(EXIT_FAILURE); } now = get_now_plus(0); - for (int i = 0; i < num_pfds; i++) { + for (i = 0; i < num_pfds; i++) { int fd = pfds[i].fd; - if (default_loop->fd_events[fd] && - default_loop->fd_events[fd]->read_cb && + DEBUG_SCHED("default_eventloop_runonce: find_event(default_loop->fd_events)"); + _getdns_eventloop_info* fd_event = find_event(&default_loop->fd_events, fd); + if (fd_event && + fd_event->event && + fd_event->event->read_cb && (pfds[i].revents & POLLIN)) - default_read_cb(fd, default_loop->fd_events[fd]); + default_read_cb(fd, fd_event->event); - if (default_loop->fd_events[fd] && - default_loop->fd_events[fd]->write_cb && + if (fd_event && + fd_event->event && + fd_event->event->write_cb && (pfds[i].revents & POLLOUT)) - default_write_cb(fd, default_loop->fd_events[fd]); + default_write_cb(fd, fd_event->event); } if (pfds) free(pfds); - for (int fd=0; fd < default_loop->max_fds; fd++) { - if (default_loop->fd_events[fd] && - default_loop->fd_events[fd]->timeout_cb && - now > default_loop->fd_timeout_times[fd]) - default_timeout_cb(fd, default_loop->fd_events[fd]); - i = fd; - if (default_loop->timeout_events[i] && - default_loop->timeout_events[i]->timeout_cb && - now > default_loop->timeout_times[i]) - default_timeout_cb(-1, default_loop->timeout_events[i]); + HASH_ITER(hh, default_loop->fd_events, s, tmp) { + if (s->event && + s->event->timeout_cb && + now > s->timeout_time) + default_timeout_cb(s->id, s->event); + } + HASH_ITER(hh, default_loop->timeout_events, s, tmp) { + if (s->event && + s->event->timeout_cb && + now > s->timeout_time) + default_timeout_cb(s->id, s->event); } } @@ -292,19 +344,13 @@ static void default_eventloop_run(getdns_eventloop *loop) { _getdns_default_eventloop *default_loop = (_getdns_default_eventloop *)loop; - size_t i; if (!loop) return; - i = 0; - while (i < default_loop->max_timeouts) { - if (default_loop->fd_events[i] || default_loop->timeout_events[i]) { - default_eventloop_run_once(loop, 1); - i = 0; - } else { - i++; - } + /* keep going until all the events are cleared */ + while (default_loop->fd_events && default_loop->timeout_events) { + default_eventloop_run_once(loop, 1); } } @@ -325,18 +371,10 @@ _getdns_default_eventloop_init(_getdns_default_eventloop *loop) struct rlimit rl; if (getrlimit(RLIMIT_NOFILE, &rl) == 0) { loop->max_fds = rl.rlim_cur; - loop->max_timeouts = loop->max_fds; + loop->max_timeouts = loop->max_fds; /* this is somewhat arbitrary */ } else { DEBUG_SCHED("ERROR: could not obtain RLIMIT_NOFILE from getrlimit()\n"); loop->max_fds = 0; loop->max_timeouts = loop->max_fds; } - if (loop->max_fds) { - loop->fd_events = calloc(loop->max_fds, sizeof(getdns_eventloop_event *)); - loop->fd_timeout_times = calloc(loop->max_fds, sizeof(uint64_t)); - } - if (loop->max_timeouts) { - loop->timeout_events = calloc(loop->max_timeouts, sizeof(getdns_eventloop_event *)); - loop->timeout_times = calloc(loop->max_timeouts, sizeof(uint64_t)); - } } diff --git a/src/extension/default_eventloop.h b/src/extension/default_eventloop.h index 285bbc11..bc1d881b 100644 --- a/src/extension/default_eventloop.h +++ b/src/extension/default_eventloop.h @@ -34,19 +34,25 @@ #include "config.h" #include "getdns/getdns.h" #include "getdns/getdns_extra.h" +#include "util/uthash.h" /* Eventloop based on poll */ + +typedef struct _getdns_eventloop_info { + int id; + getdns_eventloop_event *event; + uint64_t timeout_time; + UT_hash_handle hh; +} _getdns_eventloop_info; + typedef struct _getdns_default_eventloop { getdns_eventloop loop; int max_fds; int max_timeouts; - getdns_eventloop_event **fd_events; - uint64_t *fd_timeout_times; - getdns_eventloop_event **timeout_events; - uint64_t *timeout_times; + _getdns_eventloop_info *fd_events; + _getdns_eventloop_info *timeout_events; } _getdns_default_eventloop; - void _getdns_default_eventloop_init(_getdns_default_eventloop *loop); diff --git a/src/util/uthash.h b/src/util/uthash.h new file mode 100644 index 00000000..45d1f9fc --- /dev/null +++ b/src/util/uthash.h @@ -0,0 +1,1074 @@ +/* +Copyright (c) 2003-2016, Troy D. Hanson http://troydhanson.github.com/uthash/ +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. + +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 THE COPYRIGHT OWNER +OR CONTRIBUTORS 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. +*/ + +#ifndef UTHASH_H +#define UTHASH_H + +#define UTHASH_VERSION 2.0.1 + +#include /* memcmp,strlen */ +#include /* ptrdiff_t */ +#include /* exit() */ + +/* These macros use decltype or the earlier __typeof GNU extension. + As decltype is only available in newer compilers (VS2010 or gcc 4.3+ + when compiling c++ source) this code uses whatever method is needed + or, for VS2008 where neither is available, uses casting workarounds. */ +#if defined(_MSC_VER) /* MS compiler */ +#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */ +#define DECLTYPE(x) (decltype(x)) +#else /* VS2008 or older (or VS2010 in C mode) */ +#define NO_DECLTYPE +#define DECLTYPE(x) +#endif +#elif defined(__BORLANDC__) || defined(__LCC__) || defined(__WATCOMC__) +#define NO_DECLTYPE +#define DECLTYPE(x) +#else /* GNU, Sun and other compilers */ +#define DECLTYPE(x) (__typeof(x)) +#endif + +#ifdef NO_DECLTYPE +#define DECLTYPE_ASSIGN(dst,src) \ +do { \ + char **_da_dst = (char**)(&(dst)); \ + *_da_dst = (char*)(src); \ +} while (0) +#else +#define DECLTYPE_ASSIGN(dst,src) \ +do { \ + (dst) = DECLTYPE(dst)(src); \ +} while (0) +#endif + +/* a number of the hash function use uint32_t which isn't defined on Pre VS2010 */ +#if defined(_WIN32) +#if defined(_MSC_VER) && _MSC_VER >= 1600 +#include +#elif defined(__WATCOMC__) || defined(__MINGW32__) || defined(__CYGWIN__) +#include +#else +typedef unsigned int uint32_t; +typedef unsigned char uint8_t; +#endif +#elif defined(__GNUC__) && !defined(__VXWORKS__) +#include +#else +typedef unsigned int uint32_t; +typedef unsigned char uint8_t; +#endif + +#ifndef uthash_fatal +#define uthash_fatal(msg) exit(-1) /* fatal error (out of memory,etc) */ +#endif +#ifndef uthash_malloc +#define uthash_malloc(sz) malloc(sz) /* malloc fcn */ +#endif +#ifndef uthash_free +#define uthash_free(ptr,sz) free(ptr) /* free fcn */ +#endif +#ifndef uthash_strlen +#define uthash_strlen(s) strlen(s) +#endif +#ifndef uthash_memcmp +#define uthash_memcmp(a,b,n) memcmp(a,b,n) +#endif + +#ifndef uthash_noexpand_fyi +#define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */ +#endif +#ifndef uthash_expand_fyi +#define uthash_expand_fyi(tbl) /* can be defined to log expands */ +#endif + +/* initial number of buckets */ +#define HASH_INITIAL_NUM_BUCKETS 32U /* initial number of buckets */ +#define HASH_INITIAL_NUM_BUCKETS_LOG2 5U /* lg2 of initial number of buckets */ +#define HASH_BKT_CAPACITY_THRESH 10U /* expand when bucket count reaches */ + +/* calculate the element whose hash handle address is hhp */ +#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho))) +/* calculate the hash handle from element address elp */ +#define HH_FROM_ELMT(tbl,elp) ((UT_hash_handle *)(((char*)(elp)) + ((tbl)->hho))) + +#define HASH_VALUE(keyptr,keylen,hashv) \ +do { \ + HASH_FCN(keyptr, keylen, hashv); \ +} while (0) + +#define HASH_FIND_BYHASHVALUE(hh,head,keyptr,keylen,hashval,out) \ +do { \ + (out) = NULL; \ + if (head) { \ + unsigned _hf_bkt; \ + HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _hf_bkt); \ + if (HASH_BLOOM_TEST((head)->hh.tbl, hashval) != 0) { \ + HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], keyptr, keylen, hashval, out); \ + } \ + } \ +} while (0) + +#define HASH_FIND(hh,head,keyptr,keylen,out) \ +do { \ + unsigned _hf_hashv; \ + HASH_VALUE(keyptr, keylen, _hf_hashv); \ + HASH_FIND_BYHASHVALUE(hh, head, keyptr, keylen, _hf_hashv, out); \ +} while (0) + +#ifdef HASH_BLOOM +#define HASH_BLOOM_BITLEN (1UL << HASH_BLOOM) +#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8UL) + (((HASH_BLOOM_BITLEN%8UL)!=0UL) ? 1UL : 0UL) +#define HASH_BLOOM_MAKE(tbl) \ +do { \ + (tbl)->bloom_nbits = HASH_BLOOM; \ + (tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \ + if (!((tbl)->bloom_bv)) { uthash_fatal( "out of memory"); } \ + memset((tbl)->bloom_bv, 0, HASH_BLOOM_BYTELEN); \ + (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \ +} while (0) + +#define HASH_BLOOM_FREE(tbl) \ +do { \ + uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \ +} while (0) + +#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8U] |= (1U << ((idx)%8U))) +#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8U] & (1U << ((idx)%8U))) + +#define HASH_BLOOM_ADD(tbl,hashv) \ + HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1U))) + +#define HASH_BLOOM_TEST(tbl,hashv) \ + HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1U))) + +#else +#define HASH_BLOOM_MAKE(tbl) +#define HASH_BLOOM_FREE(tbl) +#define HASH_BLOOM_ADD(tbl,hashv) +#define HASH_BLOOM_TEST(tbl,hashv) (1) +#define HASH_BLOOM_BYTELEN 0U +#endif + +#define HASH_MAKE_TABLE(hh,head) \ +do { \ + (head)->hh.tbl = (UT_hash_table*)uthash_malloc( \ + sizeof(UT_hash_table)); \ + if (!((head)->hh.tbl)) { uthash_fatal( "out of memory"); } \ + memset((head)->hh.tbl, 0, sizeof(UT_hash_table)); \ + (head)->hh.tbl->tail = &((head)->hh); \ + (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \ + (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \ + (head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \ + (head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \ + HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \ + if (! (head)->hh.tbl->buckets) { uthash_fatal( "out of memory"); } \ + memset((head)->hh.tbl->buckets, 0, \ + HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \ + HASH_BLOOM_MAKE((head)->hh.tbl); \ + (head)->hh.tbl->signature = HASH_SIGNATURE; \ +} while (0) + +#define HASH_REPLACE_BYHASHVALUE_INORDER(hh,head,fieldname,keylen_in,hashval,add,replaced,cmpfcn) \ +do { \ + (replaced) = NULL; \ + HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, replaced); \ + if (replaced) { \ + HASH_DELETE(hh, head, replaced); \ + } \ + HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, &((add)->fieldname), keylen_in, hashval, add, cmpfcn); \ +} while (0) + +#define HASH_REPLACE_BYHASHVALUE(hh,head,fieldname,keylen_in,hashval,add,replaced) \ +do { \ + (replaced) = NULL; \ + HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, replaced); \ + if (replaced) { \ + HASH_DELETE(hh, head, replaced); \ + } \ + HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, add); \ +} while (0) + +#define HASH_REPLACE(hh,head,fieldname,keylen_in,add,replaced) \ +do { \ + unsigned _hr_hashv; \ + HASH_VALUE(&((add)->fieldname), keylen_in, _hr_hashv); \ + HASH_REPLACE_BYHASHVALUE(hh, head, fieldname, keylen_in, _hr_hashv, add, replaced); \ +} while (0) + +#define HASH_REPLACE_INORDER(hh,head,fieldname,keylen_in,add,replaced,cmpfcn) \ +do { \ + unsigned _hr_hashv; \ + HASH_VALUE(&((add)->fieldname), keylen_in, _hr_hashv); \ + HASH_REPLACE_BYHASHVALUE_INORDER(hh, head, fieldname, keylen_in, _hr_hashv, add, replaced, cmpfcn); \ +} while (0) + +#define HASH_APPEND_LIST(hh, head, add) \ +do { \ + (add)->hh.next = NULL; \ + (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \ + (head)->hh.tbl->tail->next = (add); \ + (head)->hh.tbl->tail = &((add)->hh); \ +} while (0) + +#define HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh,head,keyptr,keylen_in,hashval,add,cmpfcn) \ +do { \ + unsigned _ha_bkt; \ + (add)->hh.hashv = (hashval); \ + (add)->hh.key = (char*) (keyptr); \ + (add)->hh.keylen = (unsigned) (keylen_in); \ + if (!(head)) { \ + (add)->hh.next = NULL; \ + (add)->hh.prev = NULL; \ + (head) = (add); \ + HASH_MAKE_TABLE(hh, head); \ + } else { \ + struct UT_hash_handle *_hs_iter = &(head)->hh; \ + (add)->hh.tbl = (head)->hh.tbl; \ + do { \ + if (cmpfcn(DECLTYPE(head) ELMT_FROM_HH((head)->hh.tbl, _hs_iter), add) > 0) \ + break; \ + } while ((_hs_iter = _hs_iter->next)); \ + if (_hs_iter) { \ + (add)->hh.next = _hs_iter; \ + if (((add)->hh.prev = _hs_iter->prev)) { \ + HH_FROM_ELMT((head)->hh.tbl, _hs_iter->prev)->next = (add); \ + } else { \ + (head) = (add); \ + } \ + _hs_iter->prev = (add); \ + } else { \ + HASH_APPEND_LIST(hh, head, add); \ + } \ + } \ + (head)->hh.tbl->num_items++; \ + HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt); \ + HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], &(add)->hh); \ + HASH_BLOOM_ADD((head)->hh.tbl, hashval); \ + HASH_EMIT_KEY(hh, head, keyptr, keylen_in); \ + HASH_FSCK(hh, head); \ +} while (0) + +#define HASH_ADD_KEYPTR_INORDER(hh,head,keyptr,keylen_in,add,cmpfcn) \ +do { \ + unsigned _hs_hashv; \ + HASH_VALUE(keyptr, keylen_in, _hs_hashv); \ + HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, keyptr, keylen_in, _hs_hashv, add, cmpfcn); \ +} while (0) + +#define HASH_ADD_BYHASHVALUE_INORDER(hh,head,fieldname,keylen_in,hashval,add,cmpfcn) \ + HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, &((add)->fieldname), keylen_in, hashval, add, cmpfcn) + +#define HASH_ADD_INORDER(hh,head,fieldname,keylen_in,add,cmpfcn) \ + HASH_ADD_KEYPTR_INORDER(hh, head, &((add)->fieldname), keylen_in, add, cmpfcn) + +#define HASH_ADD_KEYPTR_BYHASHVALUE(hh,head,keyptr,keylen_in,hashval,add) \ +do { \ + unsigned _ha_bkt; \ + (add)->hh.hashv = (hashval); \ + (add)->hh.key = (char*) (keyptr); \ + (add)->hh.keylen = (unsigned) (keylen_in); \ + if (!(head)) { \ + (add)->hh.next = NULL; \ + (add)->hh.prev = NULL; \ + (head) = (add); \ + HASH_MAKE_TABLE(hh, head); \ + } else { \ + (add)->hh.tbl = (head)->hh.tbl; \ + HASH_APPEND_LIST(hh, head, add); \ + } \ + (head)->hh.tbl->num_items++; \ + HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt); \ + HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], &(add)->hh); \ + HASH_BLOOM_ADD((head)->hh.tbl, hashval); \ + HASH_EMIT_KEY(hh, head, keyptr, keylen_in); \ + HASH_FSCK(hh, head); \ +} while (0) + +#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \ +do { \ + unsigned _ha_hashv; \ + HASH_VALUE(keyptr, keylen_in, _ha_hashv); \ + HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, keyptr, keylen_in, _ha_hashv, add); \ +} while (0) + +#define HASH_ADD_BYHASHVALUE(hh,head,fieldname,keylen_in,hashval,add) \ + HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, add) + +#define HASH_ADD(hh,head,fieldname,keylen_in,add) \ + HASH_ADD_KEYPTR(hh, head, &((add)->fieldname), keylen_in, add) + +#define HASH_TO_BKT(hashv,num_bkts,bkt) \ +do { \ + bkt = ((hashv) & ((num_bkts) - 1U)); \ +} while (0) + +/* delete "delptr" from the hash table. + * "the usual" patch-up process for the app-order doubly-linked-list. + * The use of _hd_hh_del below deserves special explanation. + * These used to be expressed using (delptr) but that led to a bug + * if someone used the same symbol for the head and deletee, like + * HASH_DELETE(hh,users,users); + * We want that to work, but by changing the head (users) below + * we were forfeiting our ability to further refer to the deletee (users) + * in the patch-up process. Solution: use scratch space to + * copy the deletee pointer, then the latter references are via that + * scratch pointer rather than through the repointed (users) symbol. + */ +#define HASH_DELETE(hh,head,delptr) \ +do { \ + struct UT_hash_handle *_hd_hh_del; \ + if ( ((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL) ) { \ + uthash_free((head)->hh.tbl->buckets, \ + (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \ + HASH_BLOOM_FREE((head)->hh.tbl); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + head = NULL; \ + } else { \ + unsigned _hd_bkt; \ + _hd_hh_del = &((delptr)->hh); \ + if ((delptr) == ELMT_FROM_HH((head)->hh.tbl,(head)->hh.tbl->tail)) { \ + (head)->hh.tbl->tail = \ + (UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) + \ + (head)->hh.tbl->hho); \ + } \ + if ((delptr)->hh.prev != NULL) { \ + ((UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) + \ + (head)->hh.tbl->hho))->next = (delptr)->hh.next; \ + } else { \ + DECLTYPE_ASSIGN(head,(delptr)->hh.next); \ + } \ + if (_hd_hh_del->next != NULL) { \ + ((UT_hash_handle*)((ptrdiff_t)_hd_hh_del->next + \ + (head)->hh.tbl->hho))->prev = \ + _hd_hh_del->prev; \ + } \ + HASH_TO_BKT( _hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \ + HASH_DEL_IN_BKT(hh,(head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \ + (head)->hh.tbl->num_items--; \ + } \ + HASH_FSCK(hh,head); \ +} while (0) + + +/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */ +#define HASH_FIND_STR(head,findstr,out) \ + HASH_FIND(hh,head,findstr,(unsigned)uthash_strlen(findstr),out) +#define HASH_ADD_STR(head,strfield,add) \ + HASH_ADD(hh,head,strfield[0],(unsigned)uthash_strlen(add->strfield),add) +#define HASH_REPLACE_STR(head,strfield,add,replaced) \ + HASH_REPLACE(hh,head,strfield[0],(unsigned)uthash_strlen(add->strfield),add,replaced) +#define HASH_FIND_INT(head,findint,out) \ + HASH_FIND(hh,head,findint,sizeof(int),out) +#define HASH_ADD_INT(head,intfield,add) \ + HASH_ADD(hh,head,intfield,sizeof(int),add) +#define HASH_REPLACE_INT(head,intfield,add,replaced) \ + HASH_REPLACE(hh,head,intfield,sizeof(int),add,replaced) +#define HASH_FIND_PTR(head,findptr,out) \ + HASH_FIND(hh,head,findptr,sizeof(void *),out) +#define HASH_ADD_PTR(head,ptrfield,add) \ + HASH_ADD(hh,head,ptrfield,sizeof(void *),add) +#define HASH_REPLACE_PTR(head,ptrfield,add,replaced) \ + HASH_REPLACE(hh,head,ptrfield,sizeof(void *),add,replaced) +#define HASH_DEL(head,delptr) \ + HASH_DELETE(hh,head,delptr) + +/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined. + * This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined. + */ +#ifdef HASH_DEBUG +#define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0) +#define HASH_FSCK(hh,head) \ +do { \ + struct UT_hash_handle *_thh; \ + if (head) { \ + unsigned _bkt_i; \ + unsigned _count; \ + char *_prev; \ + _count = 0; \ + for( _bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; _bkt_i++) { \ + unsigned _bkt_count = 0; \ + _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \ + _prev = NULL; \ + while (_thh) { \ + if (_prev != (char*)(_thh->hh_prev)) { \ + HASH_OOPS("invalid hh_prev %p, actual %p\n", \ + _thh->hh_prev, _prev ); \ + } \ + _bkt_count++; \ + _prev = (char*)(_thh); \ + _thh = _thh->hh_next; \ + } \ + _count += _bkt_count; \ + if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \ + HASH_OOPS("invalid bucket count %u, actual %u\n", \ + (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \ + } \ + } \ + if (_count != (head)->hh.tbl->num_items) { \ + HASH_OOPS("invalid hh item count %u, actual %u\n", \ + (head)->hh.tbl->num_items, _count ); \ + } \ + /* traverse hh in app order; check next/prev integrity, count */ \ + _count = 0; \ + _prev = NULL; \ + _thh = &(head)->hh; \ + while (_thh) { \ + _count++; \ + if (_prev !=(char*)(_thh->prev)) { \ + HASH_OOPS("invalid prev %p, actual %p\n", \ + _thh->prev, _prev ); \ + } \ + _prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \ + _thh = ( _thh->next ? (UT_hash_handle*)((char*)(_thh->next) + \ + (head)->hh.tbl->hho) : NULL ); \ + } \ + if (_count != (head)->hh.tbl->num_items) { \ + HASH_OOPS("invalid app item count %u, actual %u\n", \ + (head)->hh.tbl->num_items, _count ); \ + } \ + } \ +} while (0) +#else +#define HASH_FSCK(hh,head) +#endif + +/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to + * the descriptor to which this macro is defined for tuning the hash function. + * The app can #include to get the prototype for write(2). */ +#ifdef HASH_EMIT_KEYS +#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \ +do { \ + unsigned _klen = fieldlen; \ + write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \ + write(HASH_EMIT_KEYS, keyptr, (unsigned long)fieldlen); \ +} while (0) +#else +#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) +#endif + +/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */ +#ifdef HASH_FUNCTION +#define HASH_FCN HASH_FUNCTION +#else +#define HASH_FCN HASH_JEN +#endif + +/* The Bernstein hash function, used in Perl prior to v5.6. Note (x<<5+x)=x*33. */ +#define HASH_BER(key,keylen,hashv) \ +do { \ + unsigned _hb_keylen=(unsigned)keylen; \ + const unsigned char *_hb_key=(const unsigned char*)(key); \ + (hashv) = 0; \ + while (_hb_keylen-- != 0U) { \ + (hashv) = (((hashv) << 5) + (hashv)) + *_hb_key++; \ + } \ +} while (0) + + +/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at + * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */ +#define HASH_SAX(key,keylen,hashv) \ +do { \ + unsigned _sx_i; \ + const unsigned char *_hs_key=(const unsigned char*)(key); \ + hashv = 0; \ + for(_sx_i=0; _sx_i < keylen; _sx_i++) { \ + hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \ + } \ +} while (0) +/* FNV-1a variation */ +#define HASH_FNV(key,keylen,hashv) \ +do { \ + unsigned _fn_i; \ + const unsigned char *_hf_key=(const unsigned char*)(key); \ + hashv = 2166136261U; \ + for(_fn_i=0; _fn_i < keylen; _fn_i++) { \ + hashv = hashv ^ _hf_key[_fn_i]; \ + hashv = hashv * 16777619U; \ + } \ +} while (0) + +#define HASH_OAT(key,keylen,hashv) \ +do { \ + unsigned _ho_i; \ + const unsigned char *_ho_key=(const unsigned char*)(key); \ + hashv = 0; \ + for(_ho_i=0; _ho_i < keylen; _ho_i++) { \ + hashv += _ho_key[_ho_i]; \ + hashv += (hashv << 10); \ + hashv ^= (hashv >> 6); \ + } \ + hashv += (hashv << 3); \ + hashv ^= (hashv >> 11); \ + hashv += (hashv << 15); \ +} while (0) + +#define HASH_JEN_MIX(a,b,c) \ +do { \ + a -= b; a -= c; a ^= ( c >> 13 ); \ + b -= c; b -= a; b ^= ( a << 8 ); \ + c -= a; c -= b; c ^= ( b >> 13 ); \ + a -= b; a -= c; a ^= ( c >> 12 ); \ + b -= c; b -= a; b ^= ( a << 16 ); \ + c -= a; c -= b; c ^= ( b >> 5 ); \ + a -= b; a -= c; a ^= ( c >> 3 ); \ + b -= c; b -= a; b ^= ( a << 10 ); \ + c -= a; c -= b; c ^= ( b >> 15 ); \ +} while (0) + +#define HASH_JEN(key,keylen,hashv) \ +do { \ + unsigned _hj_i,_hj_j,_hj_k; \ + unsigned const char *_hj_key=(unsigned const char*)(key); \ + hashv = 0xfeedbeefu; \ + _hj_i = _hj_j = 0x9e3779b9u; \ + _hj_k = (unsigned)(keylen); \ + while (_hj_k >= 12U) { \ + _hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \ + + ( (unsigned)_hj_key[2] << 16 ) \ + + ( (unsigned)_hj_key[3] << 24 ) ); \ + _hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) \ + + ( (unsigned)_hj_key[6] << 16 ) \ + + ( (unsigned)_hj_key[7] << 24 ) ); \ + hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 ) \ + + ( (unsigned)_hj_key[10] << 16 ) \ + + ( (unsigned)_hj_key[11] << 24 ) ); \ + \ + HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ + \ + _hj_key += 12; \ + _hj_k -= 12U; \ + } \ + hashv += (unsigned)(keylen); \ + switch ( _hj_k ) { \ + case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); /* FALLTHROUGH */ \ + case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); /* FALLTHROUGH */ \ + case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); /* FALLTHROUGH */ \ + case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); /* FALLTHROUGH */ \ + case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); /* FALLTHROUGH */ \ + case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); /* FALLTHROUGH */ \ + case 5: _hj_j += _hj_key[4]; /* FALLTHROUGH */ \ + case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); /* FALLTHROUGH */ \ + case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); /* FALLTHROUGH */ \ + case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); /* FALLTHROUGH */ \ + case 1: _hj_i += _hj_key[0]; \ + } \ + HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ +} while (0) + +/* The Paul Hsieh hash function */ +#undef get16bits +#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \ + || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__) +#define get16bits(d) (*((const uint16_t *) (d))) +#endif + +#if !defined (get16bits) +#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \ + +(uint32_t)(((const uint8_t *)(d))[0]) ) +#endif +#define HASH_SFH(key,keylen,hashv) \ +do { \ + unsigned const char *_sfh_key=(unsigned const char*)(key); \ + uint32_t _sfh_tmp, _sfh_len = (uint32_t)keylen; \ + \ + unsigned _sfh_rem = _sfh_len & 3U; \ + _sfh_len >>= 2; \ + hashv = 0xcafebabeu; \ + \ + /* Main loop */ \ + for (;_sfh_len > 0U; _sfh_len--) { \ + hashv += get16bits (_sfh_key); \ + _sfh_tmp = ((uint32_t)(get16bits (_sfh_key+2)) << 11) ^ hashv; \ + hashv = (hashv << 16) ^ _sfh_tmp; \ + _sfh_key += 2U*sizeof (uint16_t); \ + hashv += hashv >> 11; \ + } \ + \ + /* Handle end cases */ \ + switch (_sfh_rem) { \ + case 3: hashv += get16bits (_sfh_key); \ + hashv ^= hashv << 16; \ + hashv ^= (uint32_t)(_sfh_key[sizeof (uint16_t)]) << 18; \ + hashv += hashv >> 11; \ + break; \ + case 2: hashv += get16bits (_sfh_key); \ + hashv ^= hashv << 11; \ + hashv += hashv >> 17; \ + break; \ + case 1: hashv += *_sfh_key; \ + hashv ^= hashv << 10; \ + hashv += hashv >> 1; \ + } \ + \ + /* Force "avalanching" of final 127 bits */ \ + hashv ^= hashv << 3; \ + hashv += hashv >> 5; \ + hashv ^= hashv << 4; \ + hashv += hashv >> 17; \ + hashv ^= hashv << 25; \ + hashv += hashv >> 6; \ +} while (0) + +#ifdef HASH_USING_NO_STRICT_ALIASING +/* The MurmurHash exploits some CPU's (x86,x86_64) tolerance for unaligned reads. + * For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error. + * MurmurHash uses the faster approach only on CPU's where we know it's safe. + * + * Note the preprocessor built-in defines can be emitted using: + * + * gcc -m64 -dM -E - < /dev/null (on gcc) + * cc -## a.c (where a.c is a simple test file) (Sun Studio) + */ +#if (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86)) +#define MUR_GETBLOCK(p,i) p[i] +#else /* non intel */ +#define MUR_PLUS0_ALIGNED(p) (((unsigned long)p & 3UL) == 0UL) +#define MUR_PLUS1_ALIGNED(p) (((unsigned long)p & 3UL) == 1UL) +#define MUR_PLUS2_ALIGNED(p) (((unsigned long)p & 3UL) == 2UL) +#define MUR_PLUS3_ALIGNED(p) (((unsigned long)p & 3UL) == 3UL) +#define WP(p) ((uint32_t*)((unsigned long)(p) & ~3UL)) +#if (defined(__BIG_ENDIAN__) || defined(SPARC) || defined(__ppc__) || defined(__ppc64__)) +#define MUR_THREE_ONE(p) ((((*WP(p))&0x00ffffff) << 8) | (((*(WP(p)+1))&0xff000000) >> 24)) +#define MUR_TWO_TWO(p) ((((*WP(p))&0x0000ffff) <<16) | (((*(WP(p)+1))&0xffff0000) >> 16)) +#define MUR_ONE_THREE(p) ((((*WP(p))&0x000000ff) <<24) | (((*(WP(p)+1))&0xffffff00) >> 8)) +#else /* assume little endian non-intel */ +#define MUR_THREE_ONE(p) ((((*WP(p))&0xffffff00) >> 8) | (((*(WP(p)+1))&0x000000ff) << 24)) +#define MUR_TWO_TWO(p) ((((*WP(p))&0xffff0000) >>16) | (((*(WP(p)+1))&0x0000ffff) << 16)) +#define MUR_ONE_THREE(p) ((((*WP(p))&0xff000000) >>24) | (((*(WP(p)+1))&0x00ffffff) << 8)) +#endif +#define MUR_GETBLOCK(p,i) (MUR_PLUS0_ALIGNED(p) ? ((p)[i]) : \ + (MUR_PLUS1_ALIGNED(p) ? MUR_THREE_ONE(p) : \ + (MUR_PLUS2_ALIGNED(p) ? MUR_TWO_TWO(p) : \ + MUR_ONE_THREE(p)))) +#endif +#define MUR_ROTL32(x,r) (((x) << (r)) | ((x) >> (32 - (r)))) +#define MUR_FMIX(_h) \ +do { \ + _h ^= _h >> 16; \ + _h *= 0x85ebca6bu; \ + _h ^= _h >> 13; \ + _h *= 0xc2b2ae35u; \ + _h ^= _h >> 16; \ +} while (0) + +#define HASH_MUR(key,keylen,hashv) \ +do { \ + const uint8_t *_mur_data = (const uint8_t*)(key); \ + const int _mur_nblocks = (int)(keylen) / 4; \ + uint32_t _mur_h1 = 0xf88D5353u; \ + uint32_t _mur_c1 = 0xcc9e2d51u; \ + uint32_t _mur_c2 = 0x1b873593u; \ + uint32_t _mur_k1 = 0; \ + const uint8_t *_mur_tail; \ + const uint32_t *_mur_blocks = (const uint32_t*)(_mur_data+(_mur_nblocks*4)); \ + int _mur_i; \ + for(_mur_i = -_mur_nblocks; _mur_i!=0; _mur_i++) { \ + _mur_k1 = MUR_GETBLOCK(_mur_blocks,_mur_i); \ + _mur_k1 *= _mur_c1; \ + _mur_k1 = MUR_ROTL32(_mur_k1,15); \ + _mur_k1 *= _mur_c2; \ + \ + _mur_h1 ^= _mur_k1; \ + _mur_h1 = MUR_ROTL32(_mur_h1,13); \ + _mur_h1 = (_mur_h1*5U) + 0xe6546b64u; \ + } \ + _mur_tail = (const uint8_t*)(_mur_data + (_mur_nblocks*4)); \ + _mur_k1=0; \ + switch((keylen) & 3U) { \ + case 3: _mur_k1 ^= (uint32_t)_mur_tail[2] << 16; /* FALLTHROUGH */ \ + case 2: _mur_k1 ^= (uint32_t)_mur_tail[1] << 8; /* FALLTHROUGH */ \ + case 1: _mur_k1 ^= (uint32_t)_mur_tail[0]; \ + _mur_k1 *= _mur_c1; \ + _mur_k1 = MUR_ROTL32(_mur_k1,15); \ + _mur_k1 *= _mur_c2; \ + _mur_h1 ^= _mur_k1; \ + } \ + _mur_h1 ^= (uint32_t)(keylen); \ + MUR_FMIX(_mur_h1); \ + hashv = _mur_h1; \ +} while (0) +#endif /* HASH_USING_NO_STRICT_ALIASING */ + +/* iterate over items in a known bucket to find desired item */ +#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,hashval,out) \ +do { \ + if ((head).hh_head != NULL) { \ + DECLTYPE_ASSIGN(out, ELMT_FROM_HH(tbl, (head).hh_head)); \ + } else { \ + (out) = NULL; \ + } \ + while ((out) != NULL) { \ + if ((out)->hh.hashv == (hashval) && (out)->hh.keylen == (keylen_in)) { \ + if (uthash_memcmp((out)->hh.key, keyptr, keylen_in) == 0) { \ + break; \ + } \ + } \ + if ((out)->hh.hh_next != NULL) { \ + DECLTYPE_ASSIGN(out, ELMT_FROM_HH(tbl, (out)->hh.hh_next)); \ + } else { \ + (out) = NULL; \ + } \ + } \ +} while (0) + +/* add an item to a bucket */ +#define HASH_ADD_TO_BKT(head,addhh) \ +do { \ + head.count++; \ + (addhh)->hh_next = head.hh_head; \ + (addhh)->hh_prev = NULL; \ + if (head.hh_head != NULL) { (head).hh_head->hh_prev = (addhh); } \ + (head).hh_head=addhh; \ + if ((head.count >= ((head.expand_mult+1U) * HASH_BKT_CAPACITY_THRESH)) \ + && ((addhh)->tbl->noexpand != 1U)) { \ + HASH_EXPAND_BUCKETS((addhh)->tbl); \ + } \ +} while (0) + +/* remove an item from a given bucket */ +#define HASH_DEL_IN_BKT(hh,head,hh_del) \ + (head).count--; \ + if ((head).hh_head == hh_del) { \ + (head).hh_head = hh_del->hh_next; \ + } \ + if (hh_del->hh_prev) { \ + hh_del->hh_prev->hh_next = hh_del->hh_next; \ + } \ + if (hh_del->hh_next) { \ + hh_del->hh_next->hh_prev = hh_del->hh_prev; \ + } + +/* Bucket expansion has the effect of doubling the number of buckets + * and redistributing the items into the new buckets. Ideally the + * items will distribute more or less evenly into the new buckets + * (the extent to which this is true is a measure of the quality of + * the hash function as it applies to the key domain). + * + * With the items distributed into more buckets, the chain length + * (item count) in each bucket is reduced. Thus by expanding buckets + * the hash keeps a bound on the chain length. This bounded chain + * length is the essence of how a hash provides constant time lookup. + * + * The calculation of tbl->ideal_chain_maxlen below deserves some + * explanation. First, keep in mind that we're calculating the ideal + * maximum chain length based on the *new* (doubled) bucket count. + * In fractions this is just n/b (n=number of items,b=new num buckets). + * Since the ideal chain length is an integer, we want to calculate + * ceil(n/b). We don't depend on floating point arithmetic in this + * hash, so to calculate ceil(n/b) with integers we could write + * + * ceil(n/b) = (n/b) + ((n%b)?1:0) + * + * and in fact a previous version of this hash did just that. + * But now we have improved things a bit by recognizing that b is + * always a power of two. We keep its base 2 log handy (call it lb), + * so now we can write this with a bit shift and logical AND: + * + * ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0) + * + */ +#define HASH_EXPAND_BUCKETS(tbl) \ +do { \ + unsigned _he_bkt; \ + unsigned _he_bkt_i; \ + struct UT_hash_handle *_he_thh, *_he_hh_nxt; \ + UT_hash_bucket *_he_new_buckets, *_he_newbkt; \ + _he_new_buckets = (UT_hash_bucket*)uthash_malloc( \ + 2UL * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ + if (!_he_new_buckets) { uthash_fatal( "out of memory"); } \ + memset(_he_new_buckets, 0, \ + 2UL * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ + tbl->ideal_chain_maxlen = \ + (tbl->num_items >> (tbl->log2_num_buckets+1U)) + \ + (((tbl->num_items & ((tbl->num_buckets*2U)-1U)) != 0U) ? 1U : 0U); \ + tbl->nonideal_items = 0; \ + for(_he_bkt_i = 0; _he_bkt_i < tbl->num_buckets; _he_bkt_i++) \ + { \ + _he_thh = tbl->buckets[ _he_bkt_i ].hh_head; \ + while (_he_thh != NULL) { \ + _he_hh_nxt = _he_thh->hh_next; \ + HASH_TO_BKT( _he_thh->hashv, tbl->num_buckets*2U, _he_bkt); \ + _he_newbkt = &(_he_new_buckets[ _he_bkt ]); \ + if (++(_he_newbkt->count) > tbl->ideal_chain_maxlen) { \ + tbl->nonideal_items++; \ + _he_newbkt->expand_mult = _he_newbkt->count / \ + tbl->ideal_chain_maxlen; \ + } \ + _he_thh->hh_prev = NULL; \ + _he_thh->hh_next = _he_newbkt->hh_head; \ + if (_he_newbkt->hh_head != NULL) { _he_newbkt->hh_head->hh_prev = \ + _he_thh; } \ + _he_newbkt->hh_head = _he_thh; \ + _he_thh = _he_hh_nxt; \ + } \ + } \ + uthash_free( tbl->buckets, tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \ + tbl->num_buckets *= 2U; \ + tbl->log2_num_buckets++; \ + tbl->buckets = _he_new_buckets; \ + tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) ? \ + (tbl->ineff_expands+1U) : 0U; \ + if (tbl->ineff_expands > 1U) { \ + tbl->noexpand=1; \ + uthash_noexpand_fyi(tbl); \ + } \ + uthash_expand_fyi(tbl); \ +} while (0) + + +/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */ +/* Note that HASH_SORT assumes the hash handle name to be hh. + * HASH_SRT was added to allow the hash handle name to be passed in. */ +#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn) +#define HASH_SRT(hh,head,cmpfcn) \ +do { \ + unsigned _hs_i; \ + unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \ + struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \ + if (head != NULL) { \ + _hs_insize = 1; \ + _hs_looping = 1; \ + _hs_list = &((head)->hh); \ + while (_hs_looping != 0U) { \ + _hs_p = _hs_list; \ + _hs_list = NULL; \ + _hs_tail = NULL; \ + _hs_nmerges = 0; \ + while (_hs_p != NULL) { \ + _hs_nmerges++; \ + _hs_q = _hs_p; \ + _hs_psize = 0; \ + for ( _hs_i = 0; _hs_i < _hs_insize; _hs_i++ ) { \ + _hs_psize++; \ + _hs_q = (UT_hash_handle*)((_hs_q->next != NULL) ? \ + ((void*)((char*)(_hs_q->next) + \ + (head)->hh.tbl->hho)) : NULL); \ + if (! (_hs_q) ) { break; } \ + } \ + _hs_qsize = _hs_insize; \ + while ((_hs_psize > 0U) || ((_hs_qsize > 0U) && (_hs_q != NULL))) {\ + if (_hs_psize == 0U) { \ + _hs_e = _hs_q; \ + _hs_q = (UT_hash_handle*)((_hs_q->next != NULL) ? \ + ((void*)((char*)(_hs_q->next) + \ + (head)->hh.tbl->hho)) : NULL); \ + _hs_qsize--; \ + } else if ( (_hs_qsize == 0U) || (_hs_q == NULL) ) { \ + _hs_e = _hs_p; \ + if (_hs_p != NULL){ \ + _hs_p = (UT_hash_handle*)((_hs_p->next != NULL) ? \ + ((void*)((char*)(_hs_p->next) + \ + (head)->hh.tbl->hho)) : NULL); \ + } \ + _hs_psize--; \ + } else if (( \ + cmpfcn(DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_p)), \ + DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_q))) \ + ) <= 0) { \ + _hs_e = _hs_p; \ + if (_hs_p != NULL){ \ + _hs_p = (UT_hash_handle*)((_hs_p->next != NULL) ? \ + ((void*)((char*)(_hs_p->next) + \ + (head)->hh.tbl->hho)) : NULL); \ + } \ + _hs_psize--; \ + } else { \ + _hs_e = _hs_q; \ + _hs_q = (UT_hash_handle*)((_hs_q->next != NULL) ? \ + ((void*)((char*)(_hs_q->next) + \ + (head)->hh.tbl->hho)) : NULL); \ + _hs_qsize--; \ + } \ + if ( _hs_tail != NULL ) { \ + _hs_tail->next = ((_hs_e != NULL) ? \ + ELMT_FROM_HH((head)->hh.tbl,_hs_e) : NULL); \ + } else { \ + _hs_list = _hs_e; \ + } \ + if (_hs_e != NULL) { \ + _hs_e->prev = ((_hs_tail != NULL) ? \ + ELMT_FROM_HH((head)->hh.tbl,_hs_tail) : NULL); \ + } \ + _hs_tail = _hs_e; \ + } \ + _hs_p = _hs_q; \ + } \ + if (_hs_tail != NULL){ \ + _hs_tail->next = NULL; \ + } \ + if ( _hs_nmerges <= 1U ) { \ + _hs_looping=0; \ + (head)->hh.tbl->tail = _hs_tail; \ + DECLTYPE_ASSIGN(head,ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \ + } \ + _hs_insize *= 2U; \ + } \ + HASH_FSCK(hh,head); \ + } \ +} while (0) + +/* This function selects items from one hash into another hash. + * The end result is that the selected items have dual presence + * in both hashes. There is no copy of the items made; rather + * they are added into the new hash through a secondary hash + * hash handle that must be present in the structure. */ +#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \ +do { \ + unsigned _src_bkt, _dst_bkt; \ + void *_last_elt=NULL, *_elt; \ + UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \ + ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst)); \ + if (src != NULL) { \ + for(_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \ + for(_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \ + _src_hh != NULL; \ + _src_hh = _src_hh->hh_next) { \ + _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \ + if (cond(_elt)) { \ + _dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho); \ + _dst_hh->key = _src_hh->key; \ + _dst_hh->keylen = _src_hh->keylen; \ + _dst_hh->hashv = _src_hh->hashv; \ + _dst_hh->prev = _last_elt; \ + _dst_hh->next = NULL; \ + if (_last_elt_hh != NULL) { _last_elt_hh->next = _elt; } \ + if (dst == NULL) { \ + DECLTYPE_ASSIGN(dst,_elt); \ + HASH_MAKE_TABLE(hh_dst,dst); \ + } else { \ + _dst_hh->tbl = (dst)->hh_dst.tbl; \ + } \ + HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \ + HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt],_dst_hh); \ + (dst)->hh_dst.tbl->num_items++; \ + _last_elt = _elt; \ + _last_elt_hh = _dst_hh; \ + } \ + } \ + } \ + } \ + HASH_FSCK(hh_dst,dst); \ +} while (0) + +#define HASH_CLEAR(hh,head) \ +do { \ + if (head != NULL) { \ + uthash_free((head)->hh.tbl->buckets, \ + (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket)); \ + HASH_BLOOM_FREE((head)->hh.tbl); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + (head)=NULL; \ + } \ +} while (0) + +#define HASH_OVERHEAD(hh,head) \ + ((head != NULL) ? ( \ + (size_t)(((head)->hh.tbl->num_items * sizeof(UT_hash_handle)) + \ + ((head)->hh.tbl->num_buckets * sizeof(UT_hash_bucket)) + \ + sizeof(UT_hash_table) + \ + (HASH_BLOOM_BYTELEN))) : 0U) + +#ifdef NO_DECLTYPE +#define HASH_ITER(hh,head,el,tmp) \ +for(((el)=(head)), ((*(char**)(&(tmp)))=(char*)((head!=NULL)?(head)->hh.next:NULL)); \ + (el) != NULL; ((el)=(tmp)), ((*(char**)(&(tmp)))=(char*)((tmp!=NULL)?(tmp)->hh.next:NULL))) +#else +#define HASH_ITER(hh,head,el,tmp) \ +for(((el)=(head)), ((tmp)=DECLTYPE(el)((head!=NULL)?(head)->hh.next:NULL)); \ + (el) != NULL; ((el)=(tmp)), ((tmp)=DECLTYPE(el)((tmp!=NULL)?(tmp)->hh.next:NULL))) +#endif + +/* obtain a count of items in the hash */ +#define HASH_COUNT(head) HASH_CNT(hh,head) +#define HASH_CNT(hh,head) ((head != NULL)?((head)->hh.tbl->num_items):0U) + +typedef struct UT_hash_bucket { + struct UT_hash_handle *hh_head; + unsigned count; + + /* expand_mult is normally set to 0. In this situation, the max chain length + * threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If + * the bucket's chain exceeds this length, bucket expansion is triggered). + * However, setting expand_mult to a non-zero value delays bucket expansion + * (that would be triggered by additions to this particular bucket) + * until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH. + * (The multiplier is simply expand_mult+1). The whole idea of this + * multiplier is to reduce bucket expansions, since they are expensive, in + * situations where we know that a particular bucket tends to be overused. + * It is better to let its chain length grow to a longer yet-still-bounded + * value, than to do an O(n) bucket expansion too often. + */ + unsigned expand_mult; + +} UT_hash_bucket; + +/* random signature used only to find hash tables in external analysis */ +#define HASH_SIGNATURE 0xa0111fe1u +#define HASH_BLOOM_SIGNATURE 0xb12220f2u + +typedef struct UT_hash_table { + UT_hash_bucket *buckets; + unsigned num_buckets, log2_num_buckets; + unsigned num_items; + struct UT_hash_handle *tail; /* tail hh in app order, for fast append */ + ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */ + + /* in an ideal situation (all buckets used equally), no bucket would have + * more than ceil(#items/#buckets) items. that's the ideal chain length. */ + unsigned ideal_chain_maxlen; + + /* nonideal_items is the number of items in the hash whose chain position + * exceeds the ideal chain maxlen. these items pay the penalty for an uneven + * hash distribution; reaching them in a chain traversal takes >ideal steps */ + unsigned nonideal_items; + + /* ineffective expands occur when a bucket doubling was performed, but + * afterward, more than half the items in the hash had nonideal chain + * positions. If this happens on two consecutive expansions we inhibit any + * further expansion, as it's not helping; this happens when the hash + * function isn't a good fit for the key domain. When expansion is inhibited + * the hash will still work, albeit no longer in constant time. */ + unsigned ineff_expands, noexpand; + + uint32_t signature; /* used only to find hash tables in external analysis */ +#ifdef HASH_BLOOM + uint32_t bloom_sig; /* used only to test bloom exists in external analysis */ + uint8_t *bloom_bv; + uint8_t bloom_nbits; +#endif + +} UT_hash_table; + +typedef struct UT_hash_handle { + struct UT_hash_table *tbl; + void *prev; /* prev element in app order */ + void *next; /* next element in app order */ + struct UT_hash_handle *hh_prev; /* previous hh in bucket order */ + struct UT_hash_handle *hh_next; /* next hh in bucket order */ + void *key; /* ptr to enclosing struct's key */ + unsigned keylen; /* enclosing struct's key len */ + unsigned hashv; /* result of hash-fcn(key) */ +} UT_hash_handle; + +#endif /* UTHASH_H */ From 5cc4028d634b10500fab38a52531c6998b771767 Mon Sep 17 00:00:00 2001 From: Neil Cook Date: Wed, 14 Dec 2016 15:54:10 +0000 Subject: [PATCH 04/56] cleanup poll.h include for non-windows --- src/extension/default_eventloop.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/extension/default_eventloop.c b/src/extension/default_eventloop.c index 1ae37adc..4c6d8349 100644 --- a/src/extension/default_eventloop.c +++ b/src/extension/default_eventloop.c @@ -27,9 +27,7 @@ #include "config.h" -#ifdef USE_WINSOCK - -#else +#ifndef USE_WINSOCK #include #endif #include From 326b6bb410c4ddba46ea07129253da00ba3e43ac Mon Sep 17 00:00:00 2001 From: Neil Cook Date: Wed, 14 Dec 2016 16:10:44 +0000 Subject: [PATCH 05/56] remove redundant debugging --- src/extension/default_eventloop.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/extension/default_eventloop.c b/src/extension/default_eventloop.c index 4c6d8349..6509af7f 100644 --- a/src/extension/default_eventloop.c +++ b/src/extension/default_eventloop.c @@ -39,24 +39,18 @@ _getdns_eventloop_info *find_event(_getdns_eventloop_info** events, int id) { _getdns_eventloop_info* ev; - DEBUG_SCHED("finding event in events ptr %p with id %d", *events, id); - HASH_FIND_INT(*events, &id, ev); - DEBUG_SCHED("found event in events ptr %p with id %d and ptr %p", *events, id, ev); - return ev; } void add_event(_getdns_eventloop_info** events, int id, _getdns_eventloop_info* ev) { - DEBUG_SCHED("adding event in events ptr %p with id %d and ptr %p", *events, id, ev); HASH_ADD_INT(*events, id, ev); } void delete_event(_getdns_eventloop_info** events, _getdns_eventloop_info* ev) { - DEBUG_SCHED("deleting event in events ptr %p and ptr %p", *events, ev); HASH_DEL(*events, ev); } @@ -99,7 +93,6 @@ default_eventloop_schedule(getdns_eventloop *loop, fd = -1; } if (fd >= 0) { - DEBUG_SCHED("default_eventloop_schedule: find_event(default_loop->fd_events)"); _getdns_eventloop_info* fd_event = find_event(&default_loop->fd_events, fd); #if defined(SCHED_DEBUG) && SCHED_DEBUG if (fd_event) { @@ -143,7 +136,6 @@ default_eventloop_schedule(getdns_eventloop *loop, } for (i = 0; i < default_loop->max_timeouts; i++) { _getdns_eventloop_info* timeout_event = NULL; - DEBUG_SCHED("default_eventloop_schedule: find_event(default_loop->timeout_events)"); if ((timeout_event = find_event(&default_loop->timeout_events, i)) == NULL) { timeout_event = calloc(1, sizeof(_getdns_eventloop_info)); timeout_event->id = i; @@ -176,7 +168,6 @@ default_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) return GETDNS_RETURN_GENERIC_ERROR; } if (event->timeout_cb && !event->read_cb && !event->write_cb) { - DEBUG_SCHED("default_eventloop_clear: find_event(default_loop->timeout_events)"); _getdns_eventloop_info* timeout_event = find_event(&default_loop->timeout_events, i); #if defined(SCHED_DEBUG) && SCHED_DEBUG if (timeout_event && timeout_event->event != event) @@ -189,7 +180,6 @@ default_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) free(timeout_event); } } else { - DEBUG_SCHED("default_eventloop_clear: find_event(default_loop->fd_events)"); _getdns_eventloop_info* fd_event = find_event(&default_loop->fd_events, i); #if defined(SCHED_DEBUG) && SCHED_DEBUG if (fd_event && fd_event->event != event) @@ -308,7 +298,6 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) now = get_now_plus(0); for (i = 0; i < num_pfds; i++) { int fd = pfds[i].fd; - DEBUG_SCHED("default_eventloop_runonce: find_event(default_loop->fd_events)"); _getdns_eventloop_info* fd_event = find_event(&default_loop->fd_events, fd); if (fd_event && fd_event->event && From e9e6ff013b60eb5f27460c8b8e2b8bfd4aab25f9 Mon Sep 17 00:00:00 2001 From: Neil Cook Date: Wed, 14 Dec 2016 16:49:24 +0000 Subject: [PATCH 06/56] Fix travis compiler warnings/errors --- src/extension/default_eventloop.c | 4 +++- src/extension/default_eventloop.h | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/extension/default_eventloop.c b/src/extension/default_eventloop.c index 6509af7f..72fd51ec 100644 --- a/src/extension/default_eventloop.c +++ b/src/extension/default_eventloop.c @@ -46,11 +46,13 @@ _getdns_eventloop_info *find_event(_getdns_eventloop_info** events, int id) void add_event(_getdns_eventloop_info** events, int id, _getdns_eventloop_info* ev) { + DEBUG_SCHED("default_eventloop: add_event with id %d", id); HASH_ADD_INT(*events, id, ev); } void delete_event(_getdns_eventloop_info** events, _getdns_eventloop_info* ev) { + DEBUG_SCHED("default_eventloop: delete_event with id %d", ev->id); HASH_DEL(*events, ev); } @@ -243,7 +245,7 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) size_t i=0; int poll_timeout = 0; struct pollfd* pfds = NULL; - int num_pfds = 0; + unsigned int num_pfds = 0; if (!loop) return; diff --git a/src/extension/default_eventloop.h b/src/extension/default_eventloop.h index bc1d881b..f4a7d2b6 100644 --- a/src/extension/default_eventloop.h +++ b/src/extension/default_eventloop.h @@ -47,8 +47,8 @@ typedef struct _getdns_eventloop_info { typedef struct _getdns_default_eventloop { getdns_eventloop loop; - int max_fds; - int max_timeouts; + unsigned int max_fds; + unsigned int max_timeouts; _getdns_eventloop_info *fd_events; _getdns_eventloop_info *timeout_events; } _getdns_default_eventloop; From c1d5ae9a2551a1873289f8b85b61cc78872426cd Mon Sep 17 00:00:00 2001 From: Neil Cook Date: Wed, 14 Dec 2016 17:04:09 +0000 Subject: [PATCH 07/56] set event id in add_event rather than calling function --- src/extension/default_eventloop.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/extension/default_eventloop.c b/src/extension/default_eventloop.c index 72fd51ec..9b81f15d 100644 --- a/src/extension/default_eventloop.c +++ b/src/extension/default_eventloop.c @@ -47,6 +47,7 @@ _getdns_eventloop_info *find_event(_getdns_eventloop_info** events, int id) void add_event(_getdns_eventloop_info** events, int id, _getdns_eventloop_info* ev) { DEBUG_SCHED("default_eventloop: add_event with id %d", id); + ev->id = id; HASH_ADD_INT(*events, id, ev); } @@ -115,7 +116,6 @@ default_eventloop_schedule(getdns_eventloop *loop, free(fd_event); } fd_event = calloc(1, sizeof(_getdns_eventloop_info)); - fd_event->id = fd; fd_event->event = event; fd_event->timeout_time = get_now_plus(timeout); add_event(&default_loop->fd_events, fd, fd_event); @@ -140,7 +140,6 @@ default_eventloop_schedule(getdns_eventloop *loop, _getdns_eventloop_info* timeout_event = NULL; if ((timeout_event = find_event(&default_loop->timeout_events, i)) == NULL) { timeout_event = calloc(1, sizeof(_getdns_eventloop_info)); - timeout_event->id = i; timeout_event->event = event; timeout_event->timeout_time = get_now_plus(timeout); add_event(&default_loop->timeout_events, i, timeout_event); From 0d395639781ff7adbcbc65daeafdc7db23ce1410 Mon Sep 17 00:00:00 2001 From: Neil Cook Date: Wed, 14 Dec 2016 17:50:39 +0000 Subject: [PATCH 08/56] Consisten use of TIMEOUT_FOREVER --- src/extension/default_eventloop.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/extension/default_eventloop.c b/src/extension/default_eventloop.c index 9b81f15d..2e20ca16 100644 --- a/src/extension/default_eventloop.c +++ b/src/extension/default_eventloop.c @@ -266,7 +266,7 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) timeout = s->timeout_time; } - if ((timeout == (uint64_t)-1) && (num_pfds == 0)) + if ((timeout == TIMEOUT_FOREVER) && (num_pfds == 0)) return; pfds = calloc(num_pfds, sizeof(struct pollfd)); @@ -283,7 +283,10 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) i++; } - if (! blocking || now > timeout) { + if (timeout == TIMEOUT_FOREVER) { + poll_timeout = -1; + } + else if (! blocking || now > timeout) { poll_timeout = 0; } else { poll_timeout = (timeout - now) * 1000; /* turn seconds into millseconds */ From 9b715d4743df221768f40632f9e6b4d51760cab2 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Thu, 15 Dec 2016 09:53:49 +0100 Subject: [PATCH 09/56] Suppress compile warnings --- src/extension/default_eventloop.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/extension/default_eventloop.c b/src/extension/default_eventloop.c index 8aeca8a2..342b63f8 100644 --- a/src/extension/default_eventloop.c +++ b/src/extension/default_eventloop.c @@ -102,7 +102,7 @@ default_eventloop_schedule(getdns_eventloop *loop, if (fd_event->event == event) { DEBUG_SCHED("WARNING: Event %p not cleared " "before being rescheduled!\n" - , fd_event->event); + , (void *)fd_event->event); } else { DEBUG_SCHED("ERROR: A different event is " "already present at fd slot: %p!\n" @@ -119,7 +119,7 @@ default_eventloop_schedule(getdns_eventloop *loop, fd_event->event = event; fd_event->timeout_time = get_now_plus(timeout); add_event(&default_loop->fd_events, fd, fd_event); - event->ev = (void *) (intptr_t) fd + 1; + event->ev = (void *) (intptr_t) (fd + 1); DEBUG_SCHED( "scheduled read/write at %d\n", fd); return GETDNS_RETURN_GOOD; @@ -143,7 +143,7 @@ default_eventloop_schedule(getdns_eventloop *loop, timeout_event->event = event; timeout_event->timeout_time = get_now_plus(timeout); add_event(&default_loop->timeout_events, i, timeout_event); - event->ev = (void *) (intptr_t) i + 1; + event->ev = (void *) (intptr_t) (i + 1); DEBUG_SCHED( "scheduled timeout at %d\n", (int)i); return GETDNS_RETURN_GOOD; From 5e26137eda2482acbfee7c6aad49daedfa1162e9 Mon Sep 17 00:00:00 2001 From: Neil Cook Date: Thu, 15 Dec 2016 13:40:40 +0000 Subject: [PATCH 10/56] Fix default_eventloop_run OR instead of AND and hash table iteration safety --- src/extension/default_eventloop.c | 35 ++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/src/extension/default_eventloop.c b/src/extension/default_eventloop.c index 342b63f8..21575e40 100644 --- a/src/extension/default_eventloop.c +++ b/src/extension/default_eventloop.c @@ -46,14 +46,14 @@ _getdns_eventloop_info *find_event(_getdns_eventloop_info** events, int id) void add_event(_getdns_eventloop_info** events, int id, _getdns_eventloop_info* ev) { - DEBUG_SCHED("default_eventloop: add_event with id %d", id); + DEBUG_SCHED("default_eventloop: add_event with id %d\n", id); ev->id = id; HASH_ADD_INT(*events, id, ev); } void delete_event(_getdns_eventloop_info** events, _getdns_eventloop_info* ev) { - DEBUG_SCHED("default_eventloop: delete_event with id %d", ev->id); + DEBUG_SCHED("default_eventloop: delete_event with id %d\n", ev->id); HASH_DEL(*events, ev); } @@ -121,7 +121,7 @@ default_eventloop_schedule(getdns_eventloop *loop, add_event(&default_loop->fd_events, fd, fd_event); event->ev = (void *) (intptr_t) (fd + 1); - DEBUG_SCHED( "scheduled read/write at %d\n", fd); + DEBUG_SCHED( "scheduled read/write at fd %d\n", fd); return GETDNS_RETURN_GOOD; } if (!event->timeout_cb) { @@ -145,7 +145,7 @@ default_eventloop_schedule(getdns_eventloop *loop, add_event(&default_loop->timeout_events, i, timeout_event); event->ev = (void *) (intptr_t) (i + 1); - DEBUG_SCHED( "scheduled timeout at %d\n", (int)i); + DEBUG_SCHED( "scheduled timeout at slot %d\n", (int)i); return GETDNS_RETURN_GOOD; } } @@ -249,7 +249,7 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) if (!loop) return; - + now = get_now_plus(0); HASH_ITER(hh, default_loop->timeout_events, s, tmp) { @@ -318,18 +318,37 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) } if (pfds) free(pfds); + _getdns_eventloop_info* fd_timeout_cbs = NULL; HASH_ITER(hh, default_loop->fd_events, s, tmp) { if (s->event && s->event->timeout_cb && now > s->timeout_time) - default_timeout_cb(s->id, s->event); + add_event(&fd_timeout_cbs, s->id, s); } + /* this is in case the timeout callback deletes the event + and thus messes with the iteration */ + HASH_ITER(hh, fd_timeout_cbs, s, tmp) { + int fd = s->id; + getdns_eventloop_event* event = s->event; + delete_event(&fd_timeout_cbs, s); + default_timeout_cb(fd, event); + } + _getdns_eventloop_info* timeout_timeout_cbs = NULL; HASH_ITER(hh, default_loop->timeout_events, s, tmp) { if (s->event && s->event->timeout_cb && now > s->timeout_time) - default_timeout_cb(s->id, s->event); + add_event(&timeout_timeout_cbs, s->id, s); } + /* this is in case the timeout callback deletes the event + and thus messes with the iteration */ + HASH_ITER(hh, timeout_timeout_cbs, s, tmp) { + int fd = s->id; + getdns_eventloop_event* event = s->event; + delete_event(&timeout_timeout_cbs, s); + default_timeout_cb(fd, event); + } + } static void @@ -341,7 +360,7 @@ default_eventloop_run(getdns_eventloop *loop) return; /* keep going until all the events are cleared */ - while (default_loop->fd_events && default_loop->timeout_events) { + while (default_loop->fd_events || default_loop->timeout_events) { default_eventloop_run_once(loop, 1); } } From 7ebf3924b54b95bc9c3522ec110723e21d4755bf Mon Sep 17 00:00:00 2001 From: Neil Cook Date: Fri, 16 Dec 2016 10:36:21 +0000 Subject: [PATCH 11/56] Copy event pointer out of event hash table before callbacks, because it might be deleted --- src/extension/default_eventloop.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/extension/default_eventloop.c b/src/extension/default_eventloop.c index 21575e40..6262e446 100644 --- a/src/extension/default_eventloop.c +++ b/src/extension/default_eventloop.c @@ -304,17 +304,16 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) for (i = 0; i < num_pfds; i++) { int fd = pfds[i].fd; _getdns_eventloop_info* fd_event = find_event(&default_loop->fd_events, fd); - if (fd_event && - fd_event->event && - fd_event->event->read_cb && - (pfds[i].revents & POLLIN)) - default_read_cb(fd, fd_event->event); + if (fd_event && fd_event->event) { + getdns_eventloop_event* event = fd_event->event; + if (event->read_cb && + (pfds[i].revents & POLLIN)) + default_read_cb(fd, event); - if (fd_event && - fd_event->event && - fd_event->event->write_cb && - (pfds[i].revents & POLLOUT)) - default_write_cb(fd, fd_event->event); + if (event->write_cb && + (pfds[i].revents & POLLOUT)) + default_write_cb(fd, event); + } } if (pfds) free(pfds); From 17da80a8285e17809f886424415073aa19ab1621 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 18 Jan 2017 14:29:32 +0100 Subject: [PATCH 12/56] Feed poll with millisecond timeout --- src/extension/default_eventloop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/extension/default_eventloop.c b/src/extension/default_eventloop.c index 6262e446..17bb2b99 100644 --- a/src/extension/default_eventloop.c +++ b/src/extension/default_eventloop.c @@ -290,7 +290,7 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) else if (! blocking || now > timeout) { poll_timeout = 0; } else { - poll_timeout = (timeout - now) * 1000; /* turn seconds into millseconds */ + poll_timeout = (timeout - now) / 1000; /* turn microseconds into milliseconds */ } #ifdef USE_WINSOCK if (WSAPoll(pfds, num_pfds, poll_timeout) < 0) { From fd3e0c01f7f6a3e1fac3de009b624ec15b4e4d0f Mon Sep 17 00:00:00 2001 From: Neil Cook Date: Wed, 18 Jan 2017 15:12:56 +0000 Subject: [PATCH 13/56] call default_time_cb with -1 instead of index --- src/extension/default_eventloop.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/extension/default_eventloop.c b/src/extension/default_eventloop.c index 17bb2b99..61e04070 100644 --- a/src/extension/default_eventloop.c +++ b/src/extension/default_eventloop.c @@ -246,6 +246,8 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) int poll_timeout = 0; struct pollfd* pfds = NULL; unsigned int num_pfds = 0; + _getdns_eventloop_info* timeout_timeout_cbs = NULL; + _getdns_eventloop_info* fd_timeout_cbs = NULL; if (!loop) return; @@ -254,10 +256,17 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) HASH_ITER(hh, default_loop->timeout_events, s, tmp) { if (now > s->timeout_time) - default_timeout_cb(-1, s->event); + add_event(&timeout_timeout_cbs, s->id, s); else if (s->timeout_time < timeout) timeout = s->timeout_time; } + /* this is in case the timeout callback deletes the event + and thus messes with the iteration */ + HASH_ITER(hh, timeout_timeout_cbs, s, tmp) { + getdns_eventloop_event* event = s->event; + delete_event(&timeout_timeout_cbs, s); + default_timeout_cb(-1, event); + } // first we count the number of fds that will be active HASH_ITER(hh, default_loop->fd_events, s, tmp) { if (s->event->read_cb || @@ -317,7 +326,6 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) } if (pfds) free(pfds); - _getdns_eventloop_info* fd_timeout_cbs = NULL; HASH_ITER(hh, default_loop->fd_events, s, tmp) { if (s->event && s->event->timeout_cb && @@ -332,7 +340,6 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) delete_event(&fd_timeout_cbs, s); default_timeout_cb(fd, event); } - _getdns_eventloop_info* timeout_timeout_cbs = NULL; HASH_ITER(hh, default_loop->timeout_events, s, tmp) { if (s->event && s->event->timeout_cb && @@ -342,10 +349,9 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) /* this is in case the timeout callback deletes the event and thus messes with the iteration */ HASH_ITER(hh, timeout_timeout_cbs, s, tmp) { - int fd = s->id; getdns_eventloop_event* event = s->event; delete_event(&timeout_timeout_cbs, s); - default_timeout_cb(fd, event); + default_timeout_cb(-1, event); } } From dad4aaf6d8ae1784f107a5a883663d823bf9963e Mon Sep 17 00:00:00 2001 From: Neil Cook Date: Wed, 18 Jan 2017 15:31:01 +0000 Subject: [PATCH 14/56] correctly allocate and free memory for eventloop hashes --- src/extension/default_eventloop.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/extension/default_eventloop.c b/src/extension/default_eventloop.c index 61e04070..f9c0e1b2 100644 --- a/src/extension/default_eventloop.c +++ b/src/extension/default_eventloop.c @@ -47,14 +47,18 @@ _getdns_eventloop_info *find_event(_getdns_eventloop_info** events, int id) void add_event(_getdns_eventloop_info** events, int id, _getdns_eventloop_info* ev) { DEBUG_SCHED("default_eventloop: add_event with id %d\n", id); - ev->id = id; - HASH_ADD_INT(*events, id, ev); + _getdns_eventloop_info* myevent = calloc(1, sizeof(_getdns_eventloop_info)); + myevent->event = ev->event; + myevent->id = id; + myevent->timeout_time = ev->timeout_time; + HASH_ADD_INT(*events, id, myevent); } void delete_event(_getdns_eventloop_info** events, _getdns_eventloop_info* ev) { DEBUG_SCHED("default_eventloop: delete_event with id %d\n", ev->id); HASH_DEL(*events, ev); + free(ev); } static uint64_t get_now_plus(uint64_t amount) @@ -113,13 +117,12 @@ default_eventloop_schedule(getdns_eventloop *loop, /* cleanup the old event if it exists */ if (fd_event) { delete_event(&default_loop->fd_events, fd_event); - free(fd_event); } - fd_event = calloc(1, sizeof(_getdns_eventloop_info)); - fd_event->event = event; - fd_event->timeout_time = get_now_plus(timeout); - add_event(&default_loop->fd_events, fd, fd_event); + _getdns_eventloop_info fd_ev; event->ev = (void *) (intptr_t) (fd + 1); + fd_ev.event = event; + fd_ev.timeout_time = get_now_plus(timeout); + add_event(&default_loop->fd_events, fd, &fd_ev); DEBUG_SCHED( "scheduled read/write at fd %d\n", fd); return GETDNS_RETURN_GOOD; @@ -137,12 +140,11 @@ default_eventloop_schedule(getdns_eventloop *loop, event->write_cb = NULL; } for (i = 0; i < default_loop->max_timeouts; i++) { - _getdns_eventloop_info* timeout_event = NULL; - if ((timeout_event = find_event(&default_loop->timeout_events, i)) == NULL) { - timeout_event = calloc(1, sizeof(_getdns_eventloop_info)); - timeout_event->event = event; - timeout_event->timeout_time = get_now_plus(timeout); - add_event(&default_loop->timeout_events, i, timeout_event); + if (find_event(&default_loop->timeout_events, i) == NULL) { + _getdns_eventloop_info timeout_ev; + timeout_ev.event = event; + timeout_ev.timeout_time = get_now_plus(timeout); + add_event(&default_loop->timeout_events, i, &timeout_ev); event->ev = (void *) (intptr_t) (i + 1); DEBUG_SCHED( "scheduled timeout at slot %d\n", (int)i); @@ -179,7 +181,6 @@ default_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) #endif if (timeout_event) { delete_event(&default_loop->timeout_events, timeout_event); - free(timeout_event); } } else { _getdns_eventloop_info* fd_event = find_event(&default_loop->fd_events, i); @@ -191,7 +192,6 @@ default_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) #endif if (fd_event) { delete_event(&default_loop->fd_events, fd_event); - free(fd_event); } } event->ev = NULL; From 2b9987014d60e3e86b15c5321412b90beac13c59 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 1 Feb 2017 21:41:27 +0100 Subject: [PATCH 15/56] Special _vfixed gbuffer property For snprintf style buffers which position can go beyond capacity --- src/context.c | 4 ++-- src/convert.c | 8 ++++---- src/dict.c | 8 ++++---- src/gldns/gbuffer.c | 15 ++++++++++++++- src/gldns/gbuffer.h | 43 ++++++++++++++++++++++++++++++++---------- src/request-internal.c | 2 +- src/util-internal.c | 4 ++-- 7 files changed, 60 insertions(+), 24 deletions(-) diff --git a/src/context.c b/src/context.c index c4f5d0f7..88eb0e4d 100644 --- a/src/context.c +++ b/src/context.c @@ -1354,7 +1354,7 @@ getdns_context_create_with_extended_memory_functions( result->suffixes = no_suffixes; result->suffixes_len = sizeof(no_suffixes); - gldns_buffer_init_frm_data(&gbuf, result->trust_anchors_spc + gldns_buffer_init_frm_data_v(&gbuf, result->trust_anchors_spc , sizeof(result->trust_anchors_spc)); if (!_getdns_parse_ta_file(NULL, &gbuf)) { @@ -2333,7 +2333,7 @@ getdns_context_set_suffix(getdns_context *context, getdns_list *value) context->suffixes_len = sizeof(no_suffixes); return GETDNS_RETURN_GOOD; } - gldns_buffer_init_frm_data(&gbuf, buf_spc, sizeof(buf_spc)); + gldns_buffer_init_frm_data_v(&gbuf, buf_spc, sizeof(buf_spc)); for (;;) { for ( i = 0 ; !(r = getdns_list_get_bindata(value, i, &bindata)) diff --git a/src/convert.c b/src/convert.c index 5e2c2684..df2ff0e5 100644 --- a/src/convert.c +++ b/src/convert.c @@ -297,7 +297,7 @@ getdns_rr_dict2wire_scan( return GETDNS_RETURN_INVALID_PARAMETER; - gldns_buffer_init_frm_data(&gbuf, *wire, *wire_sz); + gldns_buffer_init_frm_data_v(&gbuf, *wire, *wire_sz); if ((r = _getdns_rr_dict2wire(rr_dict, &gbuf))) return r; @@ -447,7 +447,7 @@ getdns_rr_dict2str_scan( if (!rr_dict || !str || !*str || !str_len) return GETDNS_RETURN_INVALID_PARAMETER; - gldns_buffer_init_frm_data(&gbuf, buf, sizeof(buf_spc)); + gldns_buffer_init_frm_data_v(&gbuf, buf, sizeof(buf_spc)); r = _getdns_rr_dict2wire(rr_dict, &gbuf); if (gldns_buffer_position(&gbuf) > sizeof(buf_spc)) { if (!(buf = GETDNS_XMALLOC( @@ -960,7 +960,7 @@ getdns_msg_dict2wire_scan( if (!msg_dict || !wire || !wire_sz || (!*wire && *wire_sz)) return GETDNS_RETURN_INVALID_PARAMETER; - gldns_buffer_init_frm_data(&gbuf, *wire, *wire_sz); + gldns_buffer_init_frm_data_v(&gbuf, *wire, *wire_sz); if ((r = _getdns_msg_dict2wire_buf(msg_dict, &gbuf))) return r; @@ -1036,7 +1036,7 @@ getdns_msg_dict2str_scan( if (!msg_dict || !str || !*str || !str_len) return GETDNS_RETURN_INVALID_PARAMETER; - gldns_buffer_init_frm_data(&gbuf, buf, sizeof(buf_spc)); + gldns_buffer_init_frm_data_v(&gbuf, buf, sizeof(buf_spc)); r = _getdns_msg_dict2wire_buf(msg_dict, &gbuf); if (gldns_buffer_position(&gbuf) > sizeof(buf_spc)) { if (!(buf = GETDNS_XMALLOC( diff --git a/src/dict.c b/src/dict.c index eba1a728..70fa3836 100644 --- a/src/dict.c +++ b/src/dict.c @@ -1186,7 +1186,7 @@ getdns_pretty_snprint_dict(char *str, size_t size, const getdns_dict *dict) if (!dict) return -1; - gldns_buffer_init_frm_data(&buf, str, size); + gldns_buffer_init_frm_data_v(&buf, str, size); return getdns_pp_dict(&buf, 0, dict, 0) < 0 ? -1 : (int)gldns_buffer_position(&buf); } @@ -1220,7 +1220,7 @@ getdns_pretty_snprint_list(char *str, size_t size, const getdns_list *list) if (!list) return -1; - gldns_buffer_init_frm_data(&buf, str, size); + gldns_buffer_init_frm_data_v(&buf, str, size); return getdns_pp_list(&buf, 0, list, 0, 0) < 0 ? -1 : (int)gldns_buffer_position(&buf); } @@ -1255,7 +1255,7 @@ getdns_snprint_json_dict( if (!dict) return -1; - gldns_buffer_init_frm_data(&buf, str, size); + gldns_buffer_init_frm_data_v(&buf, str, size); return getdns_pp_dict(&buf, 0, dict, pretty ? 1 : 2) < 0 ? -1 : (int)gldns_buffer_position(&buf); } @@ -1290,7 +1290,7 @@ getdns_snprint_json_list( if (!list) return -1; - gldns_buffer_init_frm_data(&buf, str, size); + gldns_buffer_init_frm_data_v(&buf, str, size); return getdns_pp_list(&buf, 0, list, 0, pretty ? 1 : 2) < 0 ? -1 : (int)gldns_buffer_position(&buf); } diff --git a/src/gldns/gbuffer.c b/src/gldns/gbuffer.c index ac70415d..cecfe480 100644 --- a/src/gldns/gbuffer.c +++ b/src/gldns/gbuffer.c @@ -33,6 +33,7 @@ gldns_buffer_new(size_t capacity) buffer->_position = 0; buffer->_limit = buffer->_capacity = capacity; buffer->_fixed = 0; + buffer->_vfixed = 0; buffer->_status_err = 0; gldns_buffer_invariant(buffer); @@ -48,6 +49,7 @@ gldns_buffer_new_frm_data(gldns_buffer *buffer, void *data, size_t size) buffer->_position = 0; buffer->_limit = buffer->_capacity = size; buffer->_fixed = 0; + buffer->_vfixed = 0; buffer->_data = malloc(size); if(!buffer->_data) { buffer->_status_err = 1; @@ -66,6 +68,17 @@ gldns_buffer_init_frm_data(gldns_buffer *buffer, void *data, size_t size) buffer->_data = data; buffer->_capacity = buffer->_limit = size; buffer->_fixed = 1; + buffer->_vfixed = 0; +} + +void +gldns_buffer_init_frm_data_v(gldns_buffer *buffer, void *data, size_t size) +{ + memset(buffer, 0, sizeof(*buffer)); + buffer->_data = data; + buffer->_capacity = buffer->_limit = size; + buffer->_fixed = 1; + buffer->_vfixed = 1; } int @@ -126,7 +139,7 @@ gldns_buffer_printf(gldns_buffer *buffer, const char *format, ...) if (written == -1) { buffer->_status_err = 1; return -1; - } else if (!buffer->_fixed && (size_t) written >= remaining) { + } else if (!buffer->_vfixed && (size_t) written >= remaining) { if (!gldns_buffer_reserve(buffer, (size_t) written + 1)) { buffer->_status_err = 1; return -1; diff --git a/src/gldns/gbuffer.h b/src/gldns/gbuffer.h index 2db9e250..67539424 100644 --- a/src/gldns/gbuffer.h +++ b/src/gldns/gbuffer.h @@ -145,6 +145,17 @@ struct gldns_buffer /** If the buffer is fixed it cannot be resized */ unsigned _fixed : 1; + /** If the buffer is vfixed, no more than capacity bytes willl be + * written to _data, however the _position counter will be updated + * with the amount that would have been written in consecutive + * writes. This allows for a modus operandi in which a sequence is + * written on a fixed capacity buffer (perhaps with _data on stack). + * When everything could be written, then the _data is immediately + * usable, if not, then a buffer could be allocated sized precisely + * to fit the data for a second attempt. + */ + unsigned _vfixed : 1; + /** The current state of the buffer. If writing to the buffer fails * for any reason, this value is changed. This way, you can perform * multiple writes in sequence and check for success afterwards. */ @@ -162,9 +173,9 @@ INLINE void gldns_buffer_invariant(gldns_buffer *buffer) { assert(buffer != NULL); - assert(buffer->_position <= buffer->_limit || buffer->_fixed); + assert(buffer->_position <= buffer->_limit || buffer->_vfixed); assert(buffer->_limit <= buffer->_capacity); - assert(buffer->_data != NULL || (buffer->_capacity == 0 && buffer->_fixed)); + assert(buffer->_data != NULL || (buffer->_capacity == 0 && buffer->_vfixed)); } #endif @@ -196,6 +207,17 @@ void gldns_buffer_new_frm_data(gldns_buffer *buffer, void *data, size_t size); */ void gldns_buffer_init_frm_data(gldns_buffer *buffer, void *data, size_t size); +/** + * Setup a buffer with the data pointed to. No data copied, no memory allocs. + * The buffer is fixed. Writes beyond size (the capacity) will update the + * position (and not write data. This allows to determine how big the buffer + * should have been to contain all the written data. + * \param[in] buffer pointer to the buffer to put the data in + * \param[in] data the data to encapsulate in the buffer + * \param[in] size the size of the data + */ +void gldns_buffer_init_frm_data_v(gldns_buffer *buffer, void *data, size_t size); + /** * clears the buffer and make it ready for writing. The buffer's limit * is set to the capacity and the position is set to 0. @@ -259,7 +281,7 @@ gldns_buffer_position(gldns_buffer *buffer) INLINE void gldns_buffer_set_position(gldns_buffer *buffer, size_t mark) { - assert(mark <= buffer->_limit || buffer->_fixed); + assert(mark <= buffer->_limit || buffer->_vfixed); buffer->_position = mark; } @@ -273,7 +295,7 @@ gldns_buffer_set_position(gldns_buffer *buffer, size_t mark) INLINE void gldns_buffer_skip(gldns_buffer *buffer, ssize_t count) { - assert(buffer->_position + count <= buffer->_limit || buffer->_fixed); + assert(buffer->_position + count <= buffer->_limit || buffer->_vfixed); buffer->_position += count; } @@ -345,7 +367,7 @@ int gldns_buffer_reserve(gldns_buffer *buffer, size_t amount); INLINE uint8_t * gldns_buffer_at(const gldns_buffer *buffer, size_t at) { - assert(at <= buffer->_limit || buffer->_fixed); + assert(at <= buffer->_limit || buffer->_vfixed); return buffer->_data + at; } @@ -395,6 +417,7 @@ INLINE size_t gldns_buffer_remaining_at(gldns_buffer *buffer, size_t at) { gldns_buffer_invariant(buffer); + assert(at <= buffer->_limit || buffer->_vfixed); return at < buffer->_limit ? buffer->_limit - at : 0; } @@ -447,7 +470,7 @@ gldns_buffer_available(gldns_buffer *buffer, size_t count) INLINE void gldns_buffer_write_at(gldns_buffer *buffer, size_t at, const void *data, size_t count) { - if (!buffer->_fixed) + if (!buffer->_vfixed) assert(gldns_buffer_available_at(buffer, at, count)); else if (gldns_buffer_remaining_at(buffer, at) == 0) return; @@ -504,7 +527,7 @@ gldns_buffer_write_string(gldns_buffer *buffer, const char *str) INLINE void gldns_buffer_write_u8_at(gldns_buffer *buffer, size_t at, uint8_t data) { - if (buffer->_fixed && at + sizeof(data) > buffer->_limit) return; + if (buffer->_vfixed && at + sizeof(data) > buffer->_limit) return; assert(gldns_buffer_available_at(buffer, at, sizeof(data))); buffer->_data[at] = data; } @@ -530,7 +553,7 @@ gldns_buffer_write_u8(gldns_buffer *buffer, uint8_t data) INLINE void gldns_buffer_write_u16_at(gldns_buffer *buffer, size_t at, uint16_t data) { - if (buffer->_fixed && at + sizeof(data) > buffer->_limit) return; + if (buffer->_vfixed && at + sizeof(data) > buffer->_limit) return; assert(gldns_buffer_available_at(buffer, at, sizeof(data))); gldns_write_uint16(buffer->_data + at, data); } @@ -556,7 +579,7 @@ gldns_buffer_write_u16(gldns_buffer *buffer, uint16_t data) INLINE void gldns_buffer_write_u32_at(gldns_buffer *buffer, size_t at, uint32_t data) { - if (buffer->_fixed && at + sizeof(data) > buffer->_limit) return; + if (buffer->_vfixed && at + sizeof(data) > buffer->_limit) return; assert(gldns_buffer_available_at(buffer, at, sizeof(data))); gldns_write_uint32(buffer->_data + at, data); } @@ -570,7 +593,7 @@ gldns_buffer_write_u32_at(gldns_buffer *buffer, size_t at, uint32_t data) INLINE void gldns_buffer_write_u48_at(gldns_buffer *buffer, size_t at, uint64_t data) { - if (buffer->_fixed && at + 6 > buffer->_limit) return; + if (buffer->_vfixed && at + 6 > buffer->_limit) return; assert(gldns_buffer_available_at(buffer, at, 6)); gldns_write_uint48(buffer->_data + at, data); } diff --git a/src/request-internal.c b/src/request-internal.c index 37ba93b4..7b8af65a 100644 --- a/src/request-internal.c +++ b/src/request-internal.c @@ -383,7 +383,7 @@ _getdns_network_req_add_tsig(getdns_network_req *req) #endif tsig_info = _getdns_get_tsig_info(upstream->tsig_alg); - gldns_buffer_init_frm_data(&gbuf, req->response, MAXIMUM_TSIG_SPACE); + gldns_buffer_init_frm_data_v(&gbuf, req->response, MAXIMUM_TSIG_SPACE); gldns_buffer_write(&gbuf, upstream->tsig_dname, upstream->tsig_dname_len); /* Name */ gldns_buffer_write_u16(&gbuf, GETDNS_RRCLASS_ANY); /* Class */ diff --git a/src/util-internal.c b/src/util-internal.c index c25cf5ce..2bbad80d 100644 --- a/src/util-internal.c +++ b/src/util-internal.c @@ -1510,7 +1510,7 @@ uint8_t *_getdns_list2wire( gldns_buffer gbuf; size_t sz; - gldns_buffer_init_frm_data(&gbuf, buf, *buf_len); + gldns_buffer_init_frm_data_v(&gbuf, buf, *buf_len); _getdns_list2wire_buf(&gbuf, l); if ((sz = gldns_buffer_position(&gbuf)) <= *buf_len) { @@ -1531,7 +1531,7 @@ uint8_t *_getdns_reply2wire( gldns_buffer gbuf; size_t sz; - gldns_buffer_init_frm_data(&gbuf, buf, *buf_len); + gldns_buffer_init_frm_data_v(&gbuf, buf, *buf_len); _getdns_reply2wire_buf(&gbuf, r); if ((sz = gldns_buffer_position(&gbuf)) <= *buf_len) { From 60443fb7fd482c696d624dbde6477b25987af444 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Mon, 13 Feb 2017 11:56:25 +0100 Subject: [PATCH 16/56] Choice of poll or select based default event loop --- configure.ac | 27 +- src/Makefile.in | 8 +- src/extension/default_eventloop.h | 36 +-- .../{default_eventloop.c => poll_eventloop.c} | 141 ++++---- src/extension/poll_eventloop.h | 60 ++++ src/extension/select_eventloop.c | 300 ++++++++++++++++++ src/extension/select_eventloop.h | 58 ++++ 7 files changed, 538 insertions(+), 92 deletions(-) rename src/extension/{default_eventloop.c => poll_eventloop.c} (72%) create mode 100644 src/extension/poll_eventloop.h create mode 100644 src/extension/select_eventloop.c create mode 100644 src/extension/select_eventloop.h diff --git a/configure.ac b/configure.ac index f3b35c98..74709630 100644 --- a/configure.ac +++ b/configure.ac @@ -214,6 +214,31 @@ case "$enable_debug_keep_connections_open" in ;; esac + +DEFAULT_EVENTLOOP=select_eventloop +AC_CHECK_HEADERS([sys/poll.h poll.h sys/resource.h],,, [AC_INCLUDES_DEFAULT]) +AC_CHECK_FUNCS([getrlimit]) +AC_ARG_ENABLE(poll-eventloop, AC_HELP_STRING([--disable-poll-eventloop], [Disable default eventloop based on poll (default=enabled if available)])) +case "$enable_poll_eventloop" in + no) + ;; + yes|*) +AC_MSG_CHECKING(for poll) +AC_LINK_IFELSE([AC_LANG_PROGRAM([ +#ifdef HAVE_SYS_POLL_H +#include +#else +#include +#endif +], [int rc; rc = poll((struct pollfd *)(0), 0, 0);])], [ +AC_MSG_RESULT(yes) +AC_DEFINE_UNQUOTED([USE_POLL_DEFAULT_EVENTLOOP], [1], [Define this to enable a default eventloop based on poll().]) +DEFAULT_EVENTLOOP=poll_eventloop +],[AC_MSG_RESULT(no)]) + ;; +esac +AC_SUBST(DEFAULT_EVENTLOOP) + AC_ARG_ENABLE(tcp-fastopen, AC_HELP_STRING([--disable-tcp-fastopen], Disable TCP Fast Open (default=enabled if available)), enable_tcp_fastopen="$enableval", enable_tcp_fastopen=yes) if test "x$enable_tcp_fastopen" = xno; then @@ -1076,8 +1101,6 @@ if test "$ac_cv_func_arc4random" = "no"; then ]) fi -AC_DEFINE(USE_MINI_EVENT, 1, [Needed for sync stub resolver functions]) - AC_TYPE_SIGNAL case `uname` in diff --git a/src/Makefile.in b/src/Makefile.in index bcd858e2..94f1500b 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -65,6 +65,8 @@ EXTENSION_LIBUV_LDFLAGS=@EXTENSION_LIBUV_LDFLAGS@ C99COMPATFLAGS=@C99COMPATFLAGS@ +DEFAULT_EVENTLOOP_OBJ=@DEFAULT_EVENTLOOP@.lo + GETDNS_OBJ=const-info.lo convert.lo dict.lo dnssec.lo general.lo \ list.lo request-internal.lo pubkey-pinning.lo rr-dict.lo \ rr-iter.lo server.lo stub.lo sync.lo ub_loop.lo util-internal.lo \ @@ -81,7 +83,7 @@ UTIL_OBJ=rbtree.lo val_secalgo.lo JSMN_OBJ=jsmn.lo -EXTENSION_OBJ=default_eventloop.lo libevent.lo libev.lo +EXTENSION_OBJ=$(DEFAULT_EVENTLOOP_OBJ) libevent.lo libev.lo NON_C99_OBJS=context.lo libuv.lo @@ -152,8 +154,8 @@ libgetdns_ext_ev.la: libgetdns.la libev.lo $(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ libev.lo libgetdns.la $(LDFLAGS) $(EXTENSION_LIBEV_LDFLAGS) $(EXTENSION_LIBEV_EXT_LIBS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/extension/libev.symbols -libgetdns.la: $(GETDNS_OBJ) version.lo context.lo default_eventloop.lo $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(JSMN_OBJ) - $(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ $(GETDNS_OBJ) version.lo context.lo default_eventloop.lo $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(JSMN_OBJ) $(LDFLAGS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/libgetdns.symbols +libgetdns.la: $(GETDNS_OBJ) version.lo context.lo $(DEFAULT_EVENTLOOP_OBJ) $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(JSMN_OBJ) + $(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ $(GETDNS_OBJ) version.lo context.lo $(DEFAULT_EVENTLOOP_OBJ) $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(JSMN_OBJ) $(LDFLAGS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/libgetdns.symbols test: all cd test && $(MAKE) $@ diff --git a/src/extension/default_eventloop.h b/src/extension/default_eventloop.h index f4a7d2b6..7b611349 100644 --- a/src/extension/default_eventloop.h +++ b/src/extension/default_eventloop.h @@ -1,6 +1,6 @@ /* * \file default_eventloop.h - * @brief Build in default eventloop extension that uses select. + * @brief Build in default eventloop extension that uses either poll or select. * */ /* @@ -32,29 +32,13 @@ #ifndef DEFAULT_EVENTLOOP_H_ #define DEFAULT_EVENTLOOP_H_ #include "config.h" -#include "getdns/getdns.h" -#include "getdns/getdns_extra.h" -#include "util/uthash.h" - -/* Eventloop based on poll */ - -typedef struct _getdns_eventloop_info { - int id; - getdns_eventloop_event *event; - uint64_t timeout_time; - UT_hash_handle hh; -} _getdns_eventloop_info; - -typedef struct _getdns_default_eventloop { - getdns_eventloop loop; - unsigned int max_fds; - unsigned int max_timeouts; - _getdns_eventloop_info *fd_events; - _getdns_eventloop_info *timeout_events; -} _getdns_default_eventloop; - -void -_getdns_default_eventloop_init(_getdns_default_eventloop *loop); - +#ifdef USE_POLL_DEFAULT_EVENTLOOP +#include "extension/poll_eventloop.h" +#define _getdns_default_eventloop _getdns_poll_eventloop +#define _getdns_default_eventloop_init _getdns_poll_eventloop_init +#else +#include "extension/select_eventloop.h" +#define _getdns_default_eventloop _getdns_select_eventloop +#define _getdns_default_eventloop_init _getdns_select_eventloop_init +#endif #endif - diff --git a/src/extension/default_eventloop.c b/src/extension/poll_eventloop.c similarity index 72% rename from src/extension/default_eventloop.c rename to src/extension/poll_eventloop.c index f9c0e1b2..ede0f20a 100644 --- a/src/extension/default_eventloop.c +++ b/src/extension/poll_eventloop.c @@ -27,15 +27,20 @@ #include "config.h" -#ifndef USE_WINSOCK +#ifdef HAVE_SYS_POLL_H +#include +#else #include #endif +#ifdef HAVE_SYS_RESOURCE_H #include -#include "extension/default_eventloop.h" +#endif +#include "extension/poll_eventloop.h" #include "debug.h" #include "types-internal.h" -_getdns_eventloop_info *find_event(_getdns_eventloop_info** events, int id) +static _getdns_eventloop_info * +find_event(_getdns_eventloop_info** events, int id) { _getdns_eventloop_info* ev; @@ -44,9 +49,10 @@ _getdns_eventloop_info *find_event(_getdns_eventloop_info** events, int id) return ev; } -void add_event(_getdns_eventloop_info** events, int id, _getdns_eventloop_info* ev) +static void +add_event(_getdns_eventloop_info** events, int id, _getdns_eventloop_info* ev) { - DEBUG_SCHED("default_eventloop: add_event with id %d\n", id); + DEBUG_SCHED("poll_eventloop: add_event with id %d\n", id); _getdns_eventloop_info* myevent = calloc(1, sizeof(_getdns_eventloop_info)); myevent->event = ev->event; myevent->id = id; @@ -54,9 +60,10 @@ void add_event(_getdns_eventloop_info** events, int id, _getdns_eventloop_info* HASH_ADD_INT(*events, id, myevent); } -void delete_event(_getdns_eventloop_info** events, _getdns_eventloop_info* ev) +static void +delete_event(_getdns_eventloop_info** events, _getdns_eventloop_info* ev) { - DEBUG_SCHED("default_eventloop: delete_event with id %d\n", ev->id); + DEBUG_SCHED("poll_eventloop: delete_event with id %d\n", ev->id); HASH_DEL(*events, ev); free(ev); } @@ -77,30 +84,33 @@ static uint64_t get_now_plus(uint64_t amount) } static getdns_return_t -default_eventloop_schedule(getdns_eventloop *loop, +poll_eventloop_schedule(getdns_eventloop *loop, int fd, uint64_t timeout, getdns_eventloop_event *event) { - _getdns_default_eventloop *default_loop = (_getdns_default_eventloop *)loop; + _getdns_poll_eventloop *poll_loop = (_getdns_poll_eventloop *)loop; size_t i; DEBUG_SCHED( "%s(loop: %p, fd: %d, timeout: %"PRIu64", event: %p, max_fds: %d)\n" - , __FUNC__, (void *)loop, fd, timeout, (void *)event, default_loop->max_fds); + , __FUNC__, (void *)loop, fd, timeout, (void *)event, poll_loop->max_fds); if (!loop || !event) return GETDNS_RETURN_INVALID_PARAMETER; - if (fd >= (int)default_loop->max_fds) { + +#ifdef HAVE_GETRLIMIT + if (fd >= (int)poll_loop->max_fds) { DEBUG_SCHED( "ERROR: fd %d >= max_fds: %d!\n" - , fd, default_loop->max_fds); + , fd, poll_loop->max_fds); return GETDNS_RETURN_GENERIC_ERROR; } +#endif if (fd >= 0 && !(event->read_cb || event->write_cb)) { DEBUG_SCHED("WARNING: fd event without " "read or write cb!\n"); fd = -1; } if (fd >= 0) { - _getdns_eventloop_info* fd_event = find_event(&default_loop->fd_events, fd); + _getdns_eventloop_info* fd_event = find_event(&poll_loop->fd_events, fd); #if defined(SCHED_DEBUG) && SCHED_DEBUG if (fd_event) { if (fd_event->event == event) { @@ -116,13 +126,13 @@ default_eventloop_schedule(getdns_eventloop *loop, #endif /* cleanup the old event if it exists */ if (fd_event) { - delete_event(&default_loop->fd_events, fd_event); + delete_event(&poll_loop->fd_events, fd_event); } _getdns_eventloop_info fd_ev; event->ev = (void *) (intptr_t) (fd + 1); fd_ev.event = event; fd_ev.timeout_time = get_now_plus(timeout); - add_event(&default_loop->fd_events, fd, &fd_ev); + add_event(&poll_loop->fd_events, fd, &fd_ev); DEBUG_SCHED( "scheduled read/write at fd %d\n", fd); return GETDNS_RETURN_GOOD; @@ -139,12 +149,12 @@ default_eventloop_schedule(getdns_eventloop *loop, DEBUG_SCHED("ERROR: timeout event with write_cb! Clearing.\n"); event->write_cb = NULL; } - for (i = 0; i < default_loop->max_timeouts; i++) { - if (find_event(&default_loop->timeout_events, i) == NULL) { + for (i = poll_loop->timeout_id + 1; i != poll_loop->timeout_id; i++) { + if (find_event(&poll_loop->timeout_events, i) == NULL) { _getdns_eventloop_info timeout_ev; timeout_ev.event = event; timeout_ev.timeout_time = get_now_plus(timeout); - add_event(&default_loop->timeout_events, i, &timeout_ev); + add_event(&poll_loop->timeout_events, i, &timeout_ev); event->ev = (void *) (intptr_t) (i + 1); DEBUG_SCHED( "scheduled timeout at slot %d\n", (int)i); @@ -156,9 +166,9 @@ default_eventloop_schedule(getdns_eventloop *loop, } static getdns_return_t -default_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) +poll_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) { - _getdns_default_eventloop *default_loop = (_getdns_default_eventloop *)loop; + _getdns_poll_eventloop *poll_loop = (_getdns_poll_eventloop *)loop; ssize_t i; if (!loop || !event) @@ -167,11 +177,15 @@ default_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) DEBUG_SCHED( "%s(loop: %p, event: %p)\n", __FUNC__, (void *)loop, (void *)event); i = (intptr_t)event->ev - 1; - if (i < 0 || i > default_loop->max_fds) { + if (i < 0 +#ifdef HAVE_GETRLIMIT + || i > poll_loop->max_fds +#endif + ) { return GETDNS_RETURN_GENERIC_ERROR; } if (event->timeout_cb && !event->read_cb && !event->write_cb) { - _getdns_eventloop_info* timeout_event = find_event(&default_loop->timeout_events, i); + _getdns_eventloop_info* timeout_event = find_event(&poll_loop->timeout_events, i); #if defined(SCHED_DEBUG) && SCHED_DEBUG if (timeout_event && timeout_event->event != event) DEBUG_SCHED( "ERROR: Different/wrong event present at " @@ -180,10 +194,10 @@ default_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) #endif if (timeout_event) { - delete_event(&default_loop->timeout_events, timeout_event); + delete_event(&poll_loop->timeout_events, timeout_event); } } else { - _getdns_eventloop_info* fd_event = find_event(&default_loop->fd_events, i); + _getdns_eventloop_info* fd_event = find_event(&poll_loop->fd_events, i); #if defined(SCHED_DEBUG) && SCHED_DEBUG if (fd_event && fd_event->event != event) DEBUG_SCHED( "ERROR: Different/wrong event present at " @@ -191,7 +205,7 @@ default_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) , (void *)fd_event); #endif if (fd_event) { - delete_event(&default_loop->fd_events, fd_event); + delete_event(&poll_loop->fd_events, fd_event); } } event->ev = NULL; @@ -199,15 +213,15 @@ default_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) } static void -default_eventloop_cleanup(getdns_eventloop *loop) +poll_eventloop_cleanup(getdns_eventloop *loop) { - _getdns_default_eventloop *default_loop = (_getdns_default_eventloop *)loop; - HASH_CLEAR(hh, default_loop->fd_events); - HASH_CLEAR(hh, default_loop->timeout_events); + _getdns_poll_eventloop *poll_loop = (_getdns_poll_eventloop *)loop; + HASH_CLEAR(hh, poll_loop->fd_events); + HASH_CLEAR(hh, poll_loop->timeout_events); } static void -default_read_cb(int fd, getdns_eventloop_event *event) +poll_read_cb(int fd, getdns_eventloop_event *event) { #if !defined(SCHED_DEBUG) || !SCHED_DEBUG (void)fd; @@ -217,7 +231,7 @@ default_read_cb(int fd, getdns_eventloop_event *event) } static void -default_write_cb(int fd, getdns_eventloop_event *event) +poll_write_cb(int fd, getdns_eventloop_event *event) { #if !defined(SCHED_DEBUG) || !SCHED_DEBUG (void)fd; @@ -227,7 +241,7 @@ default_write_cb(int fd, getdns_eventloop_event *event) } static void -default_timeout_cb(int fd, getdns_eventloop_event *event) +poll_timeout_cb(int fd, getdns_eventloop_event *event) { #if !defined(SCHED_DEBUG) || !SCHED_DEBUG (void)fd; @@ -237,9 +251,9 @@ default_timeout_cb(int fd, getdns_eventloop_event *event) } static void -default_eventloop_run_once(getdns_eventloop *loop, int blocking) +poll_eventloop_run_once(getdns_eventloop *loop, int blocking) { - _getdns_default_eventloop *default_loop = (_getdns_default_eventloop *)loop; + _getdns_poll_eventloop *poll_loop = (_getdns_poll_eventloop *)loop; _getdns_eventloop_info *s, *tmp; uint64_t now, timeout = TIMEOUT_FOREVER; size_t i=0; @@ -254,7 +268,7 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) now = get_now_plus(0); - HASH_ITER(hh, default_loop->timeout_events, s, tmp) { + HASH_ITER(hh, poll_loop->timeout_events, s, tmp) { if (now > s->timeout_time) add_event(&timeout_timeout_cbs, s->id, s); else if (s->timeout_time < timeout) @@ -265,10 +279,10 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) HASH_ITER(hh, timeout_timeout_cbs, s, tmp) { getdns_eventloop_event* event = s->event; delete_event(&timeout_timeout_cbs, s); - default_timeout_cb(-1, event); + poll_timeout_cb(-1, event); } // first we count the number of fds that will be active - HASH_ITER(hh, default_loop->fd_events, s, tmp) { + HASH_ITER(hh, poll_loop->fd_events, s, tmp) { if (s->event->read_cb || s->event->write_cb) num_pfds++; @@ -281,7 +295,7 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) pfds = calloc(num_pfds, sizeof(struct pollfd)); i = 0; - HASH_ITER(hh, default_loop->fd_events, s, tmp) { + HASH_ITER(hh, poll_loop->fd_events, s, tmp) { if (s->event->read_cb) { pfds[i].fd = s->id; pfds[i].events |= POLLIN; @@ -312,21 +326,21 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) now = get_now_plus(0); for (i = 0; i < num_pfds; i++) { int fd = pfds[i].fd; - _getdns_eventloop_info* fd_event = find_event(&default_loop->fd_events, fd); + _getdns_eventloop_info* fd_event = find_event(&poll_loop->fd_events, fd); if (fd_event && fd_event->event) { getdns_eventloop_event* event = fd_event->event; if (event->read_cb && (pfds[i].revents & POLLIN)) - default_read_cb(fd, event); + poll_read_cb(fd, event); if (event->write_cb && (pfds[i].revents & POLLOUT)) - default_write_cb(fd, event); + poll_write_cb(fd, event); } } if (pfds) free(pfds); - HASH_ITER(hh, default_loop->fd_events, s, tmp) { + HASH_ITER(hh, poll_loop->fd_events, s, tmp) { if (s->event && s->event->timeout_cb && now > s->timeout_time) @@ -338,9 +352,9 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) int fd = s->id; getdns_eventloop_event* event = s->event; delete_event(&fd_timeout_cbs, s); - default_timeout_cb(fd, event); + poll_timeout_cb(fd, event); } - HASH_ITER(hh, default_loop->timeout_events, s, tmp) { + HASH_ITER(hh, poll_loop->timeout_events, s, tmp) { if (s->event && s->event->timeout_cb && now > s->timeout_time) @@ -351,46 +365,51 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) HASH_ITER(hh, timeout_timeout_cbs, s, tmp) { getdns_eventloop_event* event = s->event; delete_event(&timeout_timeout_cbs, s); - default_timeout_cb(-1, event); + poll_timeout_cb(-1, event); } } static void -default_eventloop_run(getdns_eventloop *loop) +poll_eventloop_run(getdns_eventloop *loop) { - _getdns_default_eventloop *default_loop = (_getdns_default_eventloop *)loop; + _getdns_poll_eventloop *poll_loop = (_getdns_poll_eventloop *)loop; if (!loop) return; /* keep going until all the events are cleared */ - while (default_loop->fd_events || default_loop->timeout_events) { - default_eventloop_run_once(loop, 1); + while (poll_loop->fd_events || poll_loop->timeout_events) { + poll_eventloop_run_once(loop, 1); } } void -_getdns_default_eventloop_init(_getdns_default_eventloop *loop) +_getdns_poll_eventloop_init(_getdns_poll_eventloop *loop) { - static getdns_eventloop_vmt default_eventloop_vmt = { - default_eventloop_cleanup, - default_eventloop_schedule, - default_eventloop_clear, - default_eventloop_run, - default_eventloop_run_once +#ifdef HAVE_GETRLIMIT + struct rlimit rl; +#endif + static getdns_eventloop_vmt poll_eventloop_vmt = { + poll_eventloop_cleanup, + poll_eventloop_schedule, + poll_eventloop_clear, + poll_eventloop_run, + poll_eventloop_run_once }; - (void) memset(loop, 0, sizeof(_getdns_default_eventloop)); - loop->loop.vmt = &default_eventloop_vmt; + (void) memset(loop, 0, sizeof(_getdns_poll_eventloop)); + loop->loop.vmt = &poll_eventloop_vmt; - struct rlimit rl; +#ifdef HAVE_GETRLIMIT if (getrlimit(RLIMIT_NOFILE, &rl) == 0) { loop->max_fds = rl.rlim_cur; - loop->max_timeouts = loop->max_fds; /* this is somewhat arbitrary */ } else { DEBUG_SCHED("ERROR: could not obtain RLIMIT_NOFILE from getrlimit()\n"); +#endif loop->max_fds = 0; - loop->max_timeouts = loop->max_fds; +#if HAVE_GETRLIMIT } +#endif + loop->timeout_id = 0; } diff --git a/src/extension/poll_eventloop.h b/src/extension/poll_eventloop.h new file mode 100644 index 00000000..0c06aa4c --- /dev/null +++ b/src/extension/poll_eventloop.h @@ -0,0 +1,60 @@ +/* + * \file poll_eventloop.h + * @brief Build in default eventloop extension that uses select. + * + */ +/* + * Copyright (c) 2013, NLNet Labs, Verisign, Inc. + * 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. + * * Neither the names of the copyright holders nor the + * 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. + */ +#ifndef POLL_EVENTLOOP_H_ +#define POLL_EVENTLOOP_H_ +#include "config.h" +#include "getdns/getdns.h" +#include "getdns/getdns_extra.h" +#include "util/uthash.h" + +/* Eventloop based on poll */ + +typedef struct _getdns_eventloop_info { + int id; + getdns_eventloop_event *event; + uint64_t timeout_time; + UT_hash_handle hh; +} _getdns_eventloop_info; + +typedef struct _getdns_poll_eventloop { + getdns_eventloop loop; + unsigned int max_fds; + unsigned int timeout_id; + _getdns_eventloop_info *fd_events; + _getdns_eventloop_info *timeout_events; +} _getdns_poll_eventloop; + +void +_getdns_poll_eventloop_init(_getdns_poll_eventloop *loop); + +#endif + diff --git a/src/extension/select_eventloop.c b/src/extension/select_eventloop.c new file mode 100644 index 00000000..35aa64b7 --- /dev/null +++ b/src/extension/select_eventloop.c @@ -0,0 +1,300 @@ +/* + * Copyright (c) 2013, NLNet Labs, Verisign, Inc. + * 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. + * * Neither the names of the copyright holders nor the + * 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. + */ + +#include "config.h" + +#include "extension/select_eventloop.h" +#include "debug.h" +#include "types-internal.h" + +static uint64_t get_now_plus(uint64_t amount) +{ + struct timeval tv; + uint64_t now; + + if (gettimeofday(&tv, NULL)) { + perror("gettimeofday() failed"); + exit(EXIT_FAILURE); + } + now = tv.tv_sec * 1000000 + tv.tv_usec; + + return (now + amount * 1000) >= now + ? now + amount * 1000 : TIMEOUT_FOREVER; +} + +static getdns_return_t +select_eventloop_schedule(getdns_eventloop *loop, + int fd, uint64_t timeout, getdns_eventloop_event *event) +{ + _getdns_select_eventloop *select_loop = (_getdns_select_eventloop *)loop; + size_t i; + + DEBUG_SCHED( "%s(loop: %p, fd: %d, timeout: %"PRIu64", event: %p, FD_SETSIZE: %d)\n" + , __FUNC__, (void *)loop, fd, timeout, (void *)event, FD_SETSIZE); + + if (!loop || !event) + return GETDNS_RETURN_INVALID_PARAMETER; + + if (fd >= (int)FD_SETSIZE) { + DEBUG_SCHED( "ERROR: fd %d >= FD_SETSIZE: %d!\n" + , fd, FD_SETSIZE); + return GETDNS_RETURN_GENERIC_ERROR; + } + if (fd >= 0 && !(event->read_cb || event->write_cb)) { + DEBUG_SCHED("WARNING: fd event without " + "read or write cb!\n"); + fd = -1; + } + if (fd >= 0) { +#if defined(SCHED_DEBUG) && SCHED_DEBUG + if (select_loop->fd_events[fd]) { + if (select_loop->fd_events[fd] == event) { + DEBUG_SCHED("WARNING: Event %p not cleared " + "before being rescheduled!\n" + , (void *)select_loop->fd_events[fd]); + } else { + DEBUG_SCHED("ERROR: A different event is " + "already present at fd slot: %p!\n" + , (void *)select_loop->fd_events[fd]); + } + } +#endif + select_loop->fd_events[fd] = event; + select_loop->fd_timeout_times[fd] = get_now_plus(timeout); + event->ev = (void *)(intptr_t)(fd + 1); + DEBUG_SCHED( "scheduled read/write at %d\n", fd); + return GETDNS_RETURN_GOOD; + } + if (!event->timeout_cb) { + DEBUG_SCHED("ERROR: fd < 0 without timeout_cb!\n"); + return GETDNS_RETURN_GENERIC_ERROR; + } + if (event->read_cb) { + DEBUG_SCHED("ERROR: timeout event with read_cb! Clearing.\n"); + event->read_cb = NULL; + } + if (event->write_cb) { + DEBUG_SCHED("ERROR: timeout event with write_cb! Clearing.\n"); + event->write_cb = NULL; + } + for (i = 0; i < MAX_TIMEOUTS; i++) { + if (select_loop->timeout_events[i] == NULL) { + select_loop->timeout_events[i] = event; + select_loop->timeout_times[i] = get_now_plus(timeout); + event->ev = (void *)(intptr_t)(i + 1); + DEBUG_SCHED( "scheduled timeout at %d\n", (int)i); + return GETDNS_RETURN_GOOD; + } + } + DEBUG_SCHED("ERROR: Out of timeout slots!\n"); + return GETDNS_RETURN_GENERIC_ERROR; +} + +static getdns_return_t +select_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) +{ + _getdns_select_eventloop *select_loop = (_getdns_select_eventloop *)loop; + ssize_t i; + + if (!loop || !event) + return GETDNS_RETURN_INVALID_PARAMETER; + + DEBUG_SCHED( "%s(loop: %p, event: %p)\n", __FUNC__, (void *)loop, (void *)event); + + i = (intptr_t)event->ev - 1; + if (i < 0 || i >= FD_SETSIZE) { + return GETDNS_RETURN_GENERIC_ERROR; + } + if (event->timeout_cb && !event->read_cb && !event->write_cb) { +#if defined(SCHED_DEBUG) && SCHED_DEBUG + if (select_loop->timeout_events[i] != event) + DEBUG_SCHED( "ERROR: Different/wrong event present at " + "timeout slot: %p!\n" + , (void *)select_loop->timeout_events[i]); +#endif + select_loop->timeout_events[i] = NULL; + } else { +#if defined(SCHED_DEBUG) && SCHED_DEBUG + if (select_loop->fd_events[i] != event) + DEBUG_SCHED( "ERROR: Different/wrong event present at " + "fd slot: %p!\n" + , (void *)select_loop->fd_events[i]); +#endif + select_loop->fd_events[i] = NULL; + } + event->ev = NULL; + return GETDNS_RETURN_GOOD; +} + +static void +select_eventloop_cleanup(getdns_eventloop *loop) +{ + (void)loop; +} + +static void +select_read_cb(int fd, getdns_eventloop_event *event) +{ +#if !defined(SCHED_DEBUG) || !SCHED_DEBUG + (void)fd; +#endif + DEBUG_SCHED( "%s(fd: %d, event: %p)\n", __FUNC__, fd, (void *)event); + event->read_cb(event->userarg); +} + +static void +select_write_cb(int fd, getdns_eventloop_event *event) +{ +#if !defined(SCHED_DEBUG) || !SCHED_DEBUG + (void)fd; +#endif + DEBUG_SCHED( "%s(fd: %d, event: %p)\n", __FUNC__, fd, (void *)event); + event->write_cb(event->userarg); +} + +static void +select_timeout_cb(int fd, getdns_eventloop_event *event) +{ +#if !defined(SCHED_DEBUG) || !SCHED_DEBUG + (void)fd; +#endif + DEBUG_SCHED( "%s(fd: %d, event: %p)\n", __FUNC__, fd, (void *)event); + event->timeout_cb(event->userarg); +} + +static void +select_eventloop_run_once(getdns_eventloop *loop, int blocking) +{ + _getdns_select_eventloop *select_loop = (_getdns_select_eventloop *)loop; + + fd_set readfds, writefds; + int fd, max_fd = -1; + uint64_t now, timeout = TIMEOUT_FOREVER; + size_t i; + struct timeval tv; + + if (!loop) + return; + + FD_ZERO(&readfds); + FD_ZERO(&writefds); + now = get_now_plus(0); + + for (i = 0; i < MAX_TIMEOUTS; i++) { + if (!select_loop->timeout_events[i]) + continue; + if (now > select_loop->timeout_times[i]) + select_timeout_cb(-1, select_loop->timeout_events[i]); + else if (select_loop->timeout_times[i] < timeout) + timeout = select_loop->timeout_times[i]; + } + for (fd = 0; fd < (int)FD_SETSIZE; fd++) { + if (!select_loop->fd_events[fd]) + continue; + if (select_loop->fd_events[fd]->read_cb) + FD_SET(fd, &readfds); + if (select_loop->fd_events[fd]->write_cb) + FD_SET(fd, &writefds); + if (fd > max_fd) + max_fd = fd; + if (select_loop->fd_timeout_times[fd] < timeout) + timeout = select_loop->fd_timeout_times[fd]; + } + if (max_fd == -1 && timeout == TIMEOUT_FOREVER) + return; + + if (! blocking || now > timeout) { + tv.tv_sec = 0; + tv.tv_usec = 0; + } else { + tv.tv_sec = (long)((timeout - now) / 1000000); + tv.tv_usec = (long)((timeout - now) % 1000000); + } + if (select(max_fd + 1, &readfds, &writefds, NULL, + (timeout == TIMEOUT_FOREVER ? NULL : &tv)) < 0) { + perror("select() failed"); + exit(EXIT_FAILURE); + } + now = get_now_plus(0); + for (fd = 0; fd < (int)FD_SETSIZE; fd++) { + if (select_loop->fd_events[fd] && + select_loop->fd_events[fd]->read_cb && + FD_ISSET(fd, &readfds)) + select_read_cb(fd, select_loop->fd_events[fd]); + + if (select_loop->fd_events[fd] && + select_loop->fd_events[fd]->write_cb && + FD_ISSET(fd, &writefds)) + select_write_cb(fd, select_loop->fd_events[fd]); + + if (select_loop->fd_events[fd] && + select_loop->fd_events[fd]->timeout_cb && + now > select_loop->fd_timeout_times[fd]) + select_timeout_cb(fd, select_loop->fd_events[fd]); + + i = fd; + if (select_loop->timeout_events[i] && + select_loop->timeout_events[i]->timeout_cb && + now > select_loop->timeout_times[i]) + select_timeout_cb(-1, select_loop->timeout_events[i]); + } +} + +static void +select_eventloop_run(getdns_eventloop *loop) +{ + _getdns_select_eventloop *select_loop = (_getdns_select_eventloop *)loop; + size_t i; + + if (!loop) + return; + + i = 0; + while (i < MAX_TIMEOUTS) { + if (select_loop->fd_events[i] || select_loop->timeout_events[i]) { + select_eventloop_run_once(loop, 1); + i = 0; + } else { + i++; + } + } +} + +void +_getdns_select_eventloop_init(_getdns_select_eventloop *loop) +{ + static getdns_eventloop_vmt select_eventloop_vmt = { + select_eventloop_cleanup, + select_eventloop_schedule, + select_eventloop_clear, + select_eventloop_run, + select_eventloop_run_once + }; + + (void) memset(loop, 0, sizeof(_getdns_select_eventloop)); + loop->loop.vmt = &select_eventloop_vmt; +} diff --git a/src/extension/select_eventloop.h b/src/extension/select_eventloop.h new file mode 100644 index 00000000..40dfb549 --- /dev/null +++ b/src/extension/select_eventloop.h @@ -0,0 +1,58 @@ +/* + * \file select_eventloop.h + * @brief Build in default eventloop extension that uses select. + * + */ +/* + * Copyright (c) 2013, NLNet Labs, Verisign, Inc. + * 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. + * * Neither the names of the copyright holders nor the + * 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. + */ +#ifndef SELECT_EVENTLOOP_H_ +#define SELECT_EVENTLOOP_H_ +#include "config.h" +#include "getdns/getdns.h" +#include "getdns/getdns_extra.h" + +/* No more than select's capability queries can be outstanding, + * The number of outstanding timeouts should be less or equal then + * the number of outstanding queries, so MAX_TIMEOUTS equal to + * FD_SETSIZE should be safe. + */ +#define MAX_TIMEOUTS FD_SETSIZE + +/* Eventloop based on select */ +typedef struct _getdns_select_eventloop { + getdns_eventloop loop; + getdns_eventloop_event *fd_events[FD_SETSIZE]; + uint64_t fd_timeout_times[FD_SETSIZE]; + getdns_eventloop_event *timeout_events[MAX_TIMEOUTS]; + uint64_t timeout_times[MAX_TIMEOUTS]; +} _getdns_select_eventloop; + + +void +_getdns_select_eventloop_init(_getdns_select_eventloop *loop); + +#endif From 30e1683d2fa9128655b861a8da293ddfaca018c9 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Mon, 13 Feb 2017 12:32:10 +0100 Subject: [PATCH 17/56] Deal with windows vsnprintf in config.h --- configure.ac | 27 +++++++++++++++------------ src/gldns/gbuffer.c | 7 +++---- src/gldns/gbuffer.h | 19 ++----------------- src/gldns/wire2str.c | 2 +- 4 files changed, 21 insertions(+), 34 deletions(-) diff --git a/configure.ac b/configure.ac index f3b35c98..8ae4d4db 100644 --- a/configure.ac +++ b/configure.ac @@ -1101,17 +1101,16 @@ AH_BOTTOM([ #endif #ifdef GETDNS_ON_WINDOWS -/* On windows it is allowed to increase the FD_SETSIZE - * (and nescessary to make our custom eventloop work) - * See: https://support.microsoft.com/en-us/kb/111855 - */ -#ifndef FD_SETSIZE -#define FD_SETSIZE 1024 -#endif - -#define PRIsz "%Iu" + /* On windows it is allowed to increase the FD_SETSIZE + * (and nescessary to make our custom eventloop work) + * See: https://support.microsoft.com/en-us/kb/111855 + */ +# ifndef FD_SETSIZE +# define FD_SETSIZE 1024 +# endif +# define PRIsz "%Iu" #else -#define PRIsz "%zu" +# define PRIsz "%zu" #endif #include @@ -1148,8 +1147,6 @@ AH_BOTTOM([ #define FD_SET_T #endif - - #ifdef __cplusplus extern "C" { #endif @@ -1204,6 +1201,12 @@ int inet_pton(int af, const char* src, void* dst); const char *inet_ntop(int af, const void *src, char *dst, size_t size); #endif +#ifdef USE_WINSOCK +static inline int _gldns_custom_vsnprintf(char *str, size_t size, const char *format, va_list ap) +{ int r = vsnprintf(str, size, format, ap); return r == -1 ? _vscprintf(format, ap) : r; } +# define vsnprintf _gldns_custom_vsnprintf +#endif + #ifdef __cplusplus } #endif diff --git a/src/gldns/gbuffer.c b/src/gldns/gbuffer.c index cecfe480..77398905 100644 --- a/src/gldns/gbuffer.c +++ b/src/gldns/gbuffer.c @@ -133,8 +133,8 @@ gldns_buffer_printf(gldns_buffer *buffer, const char *format, ...) remaining = gldns_buffer_remaining(buffer); va_start(args, format); - written = _gldns_vsnprintf((char*)gldns_buffer_current(buffer), - remaining, format, args); + written = vsnprintf((char *) gldns_buffer_current(buffer), remaining, + format, args); va_end(args); if (written == -1) { buffer->_status_err = 1; @@ -145,8 +145,7 @@ gldns_buffer_printf(gldns_buffer *buffer, const char *format, ...) return -1; } va_start(args, format); - written = _gldns_vsnprintf( - (char *) gldns_buffer_current(buffer), + written = vsnprintf((char *) gldns_buffer_current(buffer), gldns_buffer_remaining(buffer), format, args); va_end(args); if (written == -1) { diff --git a/src/gldns/gbuffer.h b/src/gldns/gbuffer.h index 67539424..15dca675 100644 --- a/src/gldns/gbuffer.h +++ b/src/gldns/gbuffer.h @@ -27,21 +27,6 @@ extern "C" { # endif #endif -#ifndef USE_WINSOCK -#define _gldns_vsnprintf vsnprintf -#else -/* Unlike Linux and BSD, vsnprintf on Windows returns -1 on overflow. - * Here it is redefined to always return the amount printed - * if enough space had been available. - */ -INLINE int -_gldns_vsnprintf(char *str, size_t size, const char *format, va_list ap) -{ - int r = vsnprintf(str, size, format, ap); - return r == -1 ? _vscprintf(format, ap) : r; -} -#endif - /* * Copy data allowing for unaligned accesses in network byte order * (big endian). @@ -175,7 +160,7 @@ gldns_buffer_invariant(gldns_buffer *buffer) assert(buffer != NULL); assert(buffer->_position <= buffer->_limit || buffer->_vfixed); assert(buffer->_limit <= buffer->_capacity); - assert(buffer->_data != NULL || (buffer->_capacity == 0 && buffer->_vfixed)); + assert(buffer->_data != NULL || (buffer->_vfixed && buffer->_capacity == 0)); } #endif @@ -210,7 +195,7 @@ void gldns_buffer_init_frm_data(gldns_buffer *buffer, void *data, size_t size); /** * Setup a buffer with the data pointed to. No data copied, no memory allocs. * The buffer is fixed. Writes beyond size (the capacity) will update the - * position (and not write data. This allows to determine how big the buffer + * position (and not write data). This allows to determine how big the buffer * should have been to contain all the written data. * \param[in] buffer pointer to the buffer to put the data in * \param[in] data the data to encapsulate in the buffer diff --git a/src/gldns/wire2str.c b/src/gldns/wire2str.c index 50d00967..2d427d86 100644 --- a/src/gldns/wire2str.c +++ b/src/gldns/wire2str.c @@ -279,7 +279,7 @@ int gldns_wire2str_dname_buf(uint8_t* d, size_t dlen, char* s, size_t slen) int gldns_str_vprint(char** str, size_t* slen, const char* format, va_list args) { - int w = _gldns_vsnprintf(*str, *slen, format, args); + int w = vsnprintf(*str, *slen, format, args); if(w < 0) { /* error in printout */ return 0; From 549de0de60549053c0109be0ed6653a3f9a49780 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Tue, 14 Feb 2017 13:41:58 +0100 Subject: [PATCH 18/56] Use of custom mem funcs by uthash --- src/extension/poll_eventloop.c | 34 ++++++++++++++++++++-------------- src/extension/poll_eventloop.h | 5 +++++ 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/extension/poll_eventloop.c b/src/extension/poll_eventloop.c index ede0f20a..17e51552 100644 --- a/src/extension/poll_eventloop.c +++ b/src/extension/poll_eventloop.c @@ -37,7 +37,6 @@ #endif #include "extension/poll_eventloop.h" #include "debug.h" -#include "types-internal.h" static _getdns_eventloop_info * find_event(_getdns_eventloop_info** events, int id) @@ -50,7 +49,8 @@ find_event(_getdns_eventloop_info** events, int id) } static void -add_event(_getdns_eventloop_info** events, int id, _getdns_eventloop_info* ev) +add_event(struct mem_funcs *mf, + _getdns_eventloop_info** events, int id, _getdns_eventloop_info* ev) { DEBUG_SCHED("poll_eventloop: add_event with id %d\n", id); _getdns_eventloop_info* myevent = calloc(1, sizeof(_getdns_eventloop_info)); @@ -61,7 +61,8 @@ add_event(_getdns_eventloop_info** events, int id, _getdns_eventloop_info* ev) } static void -delete_event(_getdns_eventloop_info** events, _getdns_eventloop_info* ev) +delete_event(struct mem_funcs *mf, + _getdns_eventloop_info** events,_getdns_eventloop_info* ev) { DEBUG_SCHED("poll_eventloop: delete_event with id %d\n", ev->id); HASH_DEL(*events, ev); @@ -88,6 +89,7 @@ poll_eventloop_schedule(getdns_eventloop *loop, int fd, uint64_t timeout, getdns_eventloop_event *event) { _getdns_poll_eventloop *poll_loop = (_getdns_poll_eventloop *)loop; + struct mem_funcs *mf = &poll_loop->mf; size_t i; DEBUG_SCHED( "%s(loop: %p, fd: %d, timeout: %"PRIu64", event: %p, max_fds: %d)\n" @@ -126,13 +128,13 @@ poll_eventloop_schedule(getdns_eventloop *loop, #endif /* cleanup the old event if it exists */ if (fd_event) { - delete_event(&poll_loop->fd_events, fd_event); + delete_event(mf, &poll_loop->fd_events, fd_event); } _getdns_eventloop_info fd_ev; event->ev = (void *) (intptr_t) (fd + 1); fd_ev.event = event; fd_ev.timeout_time = get_now_plus(timeout); - add_event(&poll_loop->fd_events, fd, &fd_ev); + add_event(mf, &poll_loop->fd_events, fd, &fd_ev); DEBUG_SCHED( "scheduled read/write at fd %d\n", fd); return GETDNS_RETURN_GOOD; @@ -154,7 +156,7 @@ poll_eventloop_schedule(getdns_eventloop *loop, _getdns_eventloop_info timeout_ev; timeout_ev.event = event; timeout_ev.timeout_time = get_now_plus(timeout); - add_event(&poll_loop->timeout_events, i, &timeout_ev); + add_event(mf, &poll_loop->timeout_events, i, &timeout_ev); event->ev = (void *) (intptr_t) (i + 1); DEBUG_SCHED( "scheduled timeout at slot %d\n", (int)i); @@ -169,6 +171,7 @@ static getdns_return_t poll_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) { _getdns_poll_eventloop *poll_loop = (_getdns_poll_eventloop *)loop; + struct mem_funcs *mf = &poll_loop->mf; ssize_t i; if (!loop || !event) @@ -194,7 +197,7 @@ poll_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) #endif if (timeout_event) { - delete_event(&poll_loop->timeout_events, timeout_event); + delete_event(mf, &poll_loop->timeout_events, timeout_event); } } else { _getdns_eventloop_info* fd_event = find_event(&poll_loop->fd_events, i); @@ -205,7 +208,7 @@ poll_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) , (void *)fd_event); #endif if (fd_event) { - delete_event(&poll_loop->fd_events, fd_event); + delete_event(mf, &poll_loop->fd_events, fd_event); } } event->ev = NULL; @@ -216,6 +219,8 @@ static void poll_eventloop_cleanup(getdns_eventloop *loop) { _getdns_poll_eventloop *poll_loop = (_getdns_poll_eventloop *)loop; + struct mem_funcs *mf = &poll_loop->mf; + HASH_CLEAR(hh, poll_loop->fd_events); HASH_CLEAR(hh, poll_loop->timeout_events); } @@ -254,6 +259,7 @@ static void poll_eventloop_run_once(getdns_eventloop *loop, int blocking) { _getdns_poll_eventloop *poll_loop = (_getdns_poll_eventloop *)loop; + struct mem_funcs *mf = &poll_loop->mf; _getdns_eventloop_info *s, *tmp; uint64_t now, timeout = TIMEOUT_FOREVER; size_t i=0; @@ -270,7 +276,7 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) HASH_ITER(hh, poll_loop->timeout_events, s, tmp) { if (now > s->timeout_time) - add_event(&timeout_timeout_cbs, s->id, s); + add_event(mf, &timeout_timeout_cbs, s->id, s); else if (s->timeout_time < timeout) timeout = s->timeout_time; } @@ -278,7 +284,7 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) and thus messes with the iteration */ HASH_ITER(hh, timeout_timeout_cbs, s, tmp) { getdns_eventloop_event* event = s->event; - delete_event(&timeout_timeout_cbs, s); + delete_event(mf, &timeout_timeout_cbs, s); poll_timeout_cb(-1, event); } // first we count the number of fds that will be active @@ -344,27 +350,27 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) if (s->event && s->event->timeout_cb && now > s->timeout_time) - add_event(&fd_timeout_cbs, s->id, s); + add_event(mf, &fd_timeout_cbs, s->id, s); } /* this is in case the timeout callback deletes the event and thus messes with the iteration */ HASH_ITER(hh, fd_timeout_cbs, s, tmp) { int fd = s->id; getdns_eventloop_event* event = s->event; - delete_event(&fd_timeout_cbs, s); + delete_event(mf, &fd_timeout_cbs, s); poll_timeout_cb(fd, event); } HASH_ITER(hh, poll_loop->timeout_events, s, tmp) { if (s->event && s->event->timeout_cb && now > s->timeout_time) - add_event(&timeout_timeout_cbs, s->id, s); + add_event(mf, &timeout_timeout_cbs, s->id, s); } /* this is in case the timeout callback deletes the event and thus messes with the iteration */ HASH_ITER(hh, timeout_timeout_cbs, s, tmp) { getdns_eventloop_event* event = s->event; - delete_event(&timeout_timeout_cbs, s); + delete_event(mf, &timeout_timeout_cbs, s); poll_timeout_cb(-1, event); } diff --git a/src/extension/poll_eventloop.h b/src/extension/poll_eventloop.h index 0c06aa4c..aef3a57d 100644 --- a/src/extension/poll_eventloop.h +++ b/src/extension/poll_eventloop.h @@ -34,6 +34,10 @@ #include "config.h" #include "getdns/getdns.h" #include "getdns/getdns_extra.h" +#include "types-internal.h" + +#define uthash_malloc(sz) ((void *)GETDNS_XMALLOC(*mf, unsigned char, sz)) +#define uthash_free(ptr,sz) GETDNS_FREE(*mf, ptr) #include "util/uthash.h" /* Eventloop based on poll */ @@ -47,6 +51,7 @@ typedef struct _getdns_eventloop_info { typedef struct _getdns_poll_eventloop { getdns_eventloop loop; + struct mem_funcs mf; unsigned int max_fds; unsigned int timeout_id; _getdns_eventloop_info *fd_events; From 7484b8c37b0ca4cb14efc04b5025172abf601f65 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 15 Feb 2017 10:22:41 +0100 Subject: [PATCH 19/56] Initialize default eventloop with custom mem funcs --- src/Makefile.in | 92 +++++++++++++++++++------------- src/context.c | 6 +-- src/extension/poll_eventloop.c | 3 +- src/extension/poll_eventloop.h | 2 +- src/extension/select_eventloop.c | 4 +- src/extension/select_eventloop.h | 2 +- 6 files changed, 63 insertions(+), 46 deletions(-) diff --git a/src/Makefile.in b/src/Makefile.in index 94f1500b..77297c42 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -220,85 +220,97 @@ const-info.lo const-info.o: $(srcdir)/const-info.c getdns/getdns.h getdns/getdns context.lo context.o: $(srcdir)/context.c config.h $(srcdir)/debug.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \ $(srcdir)/gldns/wire2str.h $(srcdir)/context.h getdns/getdns.h getdns/getdns_extra.h \ getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ - $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \ - $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ - $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/list.h $(srcdir)/dict.h \ - $(srcdir)/pubkey-pinning.h + $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ + getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/server.h \ + $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ + $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/list.h $(srcdir)/dict.h $(srcdir)/pubkey-pinning.h convert.lo convert.o: $(srcdir)/convert.c config.h getdns/getdns.h getdns/getdns_extra.h \ getdns/getdns.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ - $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \ - $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ + $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ + getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/debug.h \ + $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/parseutil.h \ $(srcdir)/const-info.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/jsmn/jsmn.h $(srcdir)/convert.h dict.lo dict.o: $(srcdir)/dict.c config.h $(srcdir)/types-internal.h getdns/getdns.h \ getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h \ - $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h \ - $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ - $(srcdir)/gldns/pkthdr.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/const-info.h $(srcdir)/gldns/wire2str.h + $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \ + $(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ + $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ + $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/const-info.h \ + $(srcdir)/gldns/wire2str.h dnssec.lo dnssec.o: $(srcdir)/dnssec.c config.h $(srcdir)/debug.h getdns/getdns.h $(srcdir)/context.h \ getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ - $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \ - $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ - $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \ - $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/parseutil.h $(srcdir)/general.h $(srcdir)/dict.h \ - $(srcdir)/list.h $(srcdir)/util/val_secalgo.h + $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ + getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/server.h \ + $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ + $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h \ + $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/parseutil.h $(srcdir)/general.h $(srcdir)/dict.h $(srcdir)/list.h \ + $(srcdir)/util/val_secalgo.h general.lo general.o: $(srcdir)/general.c config.h $(srcdir)/general.h getdns/getdns.h $(srcdir)/types-internal.h \ getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/ub_loop.h $(srcdir)/debug.h \ $(srcdir)/gldns/wire2str.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \ - getdns/getdns_extra.h $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ + $(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ + $(srcdir)/util/uthash.h $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/dict.h \ $(srcdir)/mdns.h list.lo list.o: $(srcdir)/list.c $(srcdir)/types-internal.h getdns/getdns.h getdns/getdns_extra.h \ getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h config.h $(srcdir)/context.h \ - $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \ - $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ - $(srcdir)/list.h $(srcdir)/dict.h + $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ + getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/debug.h \ + $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/list.h \ + $(srcdir)/dict.h mdns.lo mdns.o: $(srcdir)/mdns.c config.h $(srcdir)/debug.h $(srcdir)/context.h getdns/getdns.h \ getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ - $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \ - $(srcdir)/server.h $(srcdir)/general.h $(srcdir)/gldns/pkthdr.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ + $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ + getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/server.h \ + $(srcdir)/general.h $(srcdir)/gldns/pkthdr.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ $(srcdir)/gldns/gbuffer.h $(srcdir)/mdns.h pubkey-pinning.lo pubkey-pinning.o: $(srcdir)/pubkey-pinning.c config.h $(srcdir)/debug.h getdns/getdns.h \ $(srcdir)/context.h getdns/getdns.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h config.h \ - getdns/getdns_extra.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h \ - $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h + $(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ + $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ + $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h request-internal.lo request-internal.o: $(srcdir)/request-internal.c config.h $(srcdir)/types-internal.h \ getdns/getdns.h getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \ $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \ - getdns/getdns_extra.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ + $(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ + $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h \ $(srcdir)/gldns/rrdef.h $(srcdir)/dict.h $(srcdir)/convert.h rr-dict.lo rr-dict.o: $(srcdir)/rr-dict.c $(srcdir)/rr-dict.h config.h getdns/getdns.h $(srcdir)/gldns/gbuffer.h \ $(srcdir)/util-internal.h $(srcdir)/context.h getdns/getdns_extra.h getdns/getdns.h \ $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h config.h \ - getdns/getdns_extra.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h \ - $(srcdir)/gldns/pkthdr.h $(srcdir)/dict.h + $(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ + $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dict.h rr-iter.lo rr-iter.o: $(srcdir)/rr-iter.c $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h config.h getdns/getdns.h \ $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h server.lo server.o: $(srcdir)/server.c config.h getdns/getdns_extra.h getdns/getdns.h \ $(srcdir)/context.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ - $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \ - $(srcdir)/debug.h $(srcdir)/server.h + $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ + getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/debug.h \ + $(srcdir)/server.h stub.lo stub.o: $(srcdir)/stub.c config.h $(srcdir)/debug.h $(srcdir)/stub.h getdns/getdns.h $(srcdir)/types-internal.h \ getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/gldns/gbuffer.h \ $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \ $(srcdir)/gldns/wire2str.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/context.h \ - $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \ - $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/general.h $(srcdir)/pubkey-pinning.h + $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ + getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/server.h \ + $(srcdir)/util-internal.h $(srcdir)/general.h $(srcdir)/pubkey-pinning.h sync.lo sync.o: $(srcdir)/sync.c getdns/getdns.h config.h $(srcdir)/context.h getdns/getdns_extra.h \ getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ - $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \ - $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/general.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ - $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h \ - $(srcdir)/gldns/wire2str.h + $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ + getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/debug.h \ + $(srcdir)/server.h $(srcdir)/general.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ + $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/gldns/wire2str.h ub_loop.lo ub_loop.o: $(srcdir)/ub_loop.c $(srcdir)/ub_loop.h config.h getdns/getdns.h \ getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ $(srcdir)/debug.h util-internal.lo util-internal.o: $(srcdir)/util-internal.c config.h getdns/getdns.h $(srcdir)/dict.h \ $(srcdir)/util/rbtree.h $(srcdir)/types-internal.h getdns/getdns_extra.h getdns/getdns.h \ $(srcdir)/list.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \ - getdns/getdns_extra.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ + $(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ + $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/dnssec.h \ $(srcdir)/gldns/rrdef.h version.lo version.o: version.c @@ -331,10 +343,6 @@ rbtree.lo rbtree.o: $(srcdir)/util/rbtree.c config.h $(srcdir)/util/log.h $(srcd val_secalgo.lo val_secalgo.o: $(srcdir)/util/val_secalgo.c config.h $(srcdir)/util/val_secalgo.h $(srcdir)/util/log.h \ $(srcdir)/debug.h config.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/gbuffer.h jsmn.lo jsmn.o: $(srcdir)/jsmn/jsmn.c $(srcdir)/jsmn/jsmn.h -default_eventloop.lo default_eventloop.o: $(srcdir)/extension/default_eventloop.c config.h \ - $(srcdir)/extension/default_eventloop.h getdns/getdns.h getdns/getdns_extra.h \ - $(srcdir)/debug.h config.h $(srcdir)/types-internal.h getdns/getdns.h getdns/getdns_extra.h \ - $(srcdir)/util/rbtree.h libev.lo libev.o: $(srcdir)/extension/libev.c config.h $(srcdir)/types-internal.h getdns/getdns.h \ getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \ $(srcdir)/getdns/getdns_ext_libev.h getdns/getdns_extra.h @@ -344,3 +352,11 @@ libevent.lo libevent.o: $(srcdir)/extension/libevent.c config.h $(srcdir)/types- libuv.lo libuv.o: $(srcdir)/extension/libuv.c config.h $(srcdir)/debug.h config.h $(srcdir)/types-internal.h \ getdns/getdns.h getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \ $(srcdir)/getdns/getdns_ext_libuv.h getdns/getdns_extra.h +poll_eventloop.lo poll_eventloop.o: $(srcdir)/extension/poll_eventloop.c config.h \ + $(srcdir)/extension/poll_eventloop.h getdns/getdns.h getdns/getdns_extra.h \ + $(srcdir)/types-internal.h getdns/getdns.h getdns/getdns_extra.h $(srcdir)/util/rbtree.h \ + $(srcdir)/util/uthash.h $(srcdir)/debug.h config.h +select_eventloop.lo select_eventloop.o: $(srcdir)/extension/select_eventloop.c config.h \ + $(srcdir)/extension/select_eventloop.h getdns/getdns.h getdns/getdns_extra.h \ + $(srcdir)/debug.h config.h $(srcdir)/types-internal.h getdns/getdns.h getdns/getdns_extra.h \ + $(srcdir)/util/rbtree.h diff --git a/src/context.c b/src/context.c index c4f5d0f7..7dab4ecf 100644 --- a/src/context.c +++ b/src/context.c @@ -1388,8 +1388,8 @@ getdns_context_create_with_extended_memory_functions( result->tls_ctx = NULL; result->extension = &result->default_eventloop.loop; - _getdns_default_eventloop_init(&result->default_eventloop); - _getdns_default_eventloop_init(&result->sync_eventloop); + _getdns_default_eventloop_init(&result->mf, &result->default_eventloop); + _getdns_default_eventloop_init(&result->mf, &result->sync_eventloop); /* request extension defaults */ @@ -3403,7 +3403,7 @@ getdns_context_detach_eventloop(struct getdns_context* context) cancel_outstanding_requests(context, 1); context->extension->vmt->cleanup(context->extension); context->extension = &context->default_eventloop.loop; - _getdns_default_eventloop_init(&context->default_eventloop); + _getdns_default_eventloop_init(&context->mf, &context->default_eventloop); #ifdef HAVE_UNBOUND_EVENT_API if (_getdns_ub_loop_enabled(&context->ub_loop)) context->ub_loop.extension = context->extension; diff --git a/src/extension/poll_eventloop.c b/src/extension/poll_eventloop.c index 17e51552..b5c95c85 100644 --- a/src/extension/poll_eventloop.c +++ b/src/extension/poll_eventloop.c @@ -391,7 +391,7 @@ poll_eventloop_run(getdns_eventloop *loop) } void -_getdns_poll_eventloop_init(_getdns_poll_eventloop *loop) +_getdns_poll_eventloop_init(struct mem_funcs *mf, _getdns_poll_eventloop *loop) { #ifdef HAVE_GETRLIMIT struct rlimit rl; @@ -406,6 +406,7 @@ _getdns_poll_eventloop_init(_getdns_poll_eventloop *loop) (void) memset(loop, 0, sizeof(_getdns_poll_eventloop)); loop->loop.vmt = &poll_eventloop_vmt; + loop->mf = *mf; #ifdef HAVE_GETRLIMIT if (getrlimit(RLIMIT_NOFILE, &rl) == 0) { diff --git a/src/extension/poll_eventloop.h b/src/extension/poll_eventloop.h index aef3a57d..9c58b042 100644 --- a/src/extension/poll_eventloop.h +++ b/src/extension/poll_eventloop.h @@ -59,7 +59,7 @@ typedef struct _getdns_poll_eventloop { } _getdns_poll_eventloop; void -_getdns_poll_eventloop_init(_getdns_poll_eventloop *loop); +_getdns_poll_eventloop_init(struct mem_funcs *mf, _getdns_poll_eventloop *loop); #endif diff --git a/src/extension/select_eventloop.c b/src/extension/select_eventloop.c index 35aa64b7..1b889fc1 100644 --- a/src/extension/select_eventloop.c +++ b/src/extension/select_eventloop.c @@ -285,7 +285,7 @@ select_eventloop_run(getdns_eventloop *loop) } void -_getdns_select_eventloop_init(_getdns_select_eventloop *loop) +_getdns_select_eventloop_init(struct mem_funcs *mf, _getdns_select_eventloop *loop) { static getdns_eventloop_vmt select_eventloop_vmt = { select_eventloop_cleanup, @@ -294,7 +294,7 @@ _getdns_select_eventloop_init(_getdns_select_eventloop *loop) select_eventloop_run, select_eventloop_run_once }; - + (void) mf; (void) memset(loop, 0, sizeof(_getdns_select_eventloop)); loop->loop.vmt = &select_eventloop_vmt; } diff --git a/src/extension/select_eventloop.h b/src/extension/select_eventloop.h index 40dfb549..e830a2ac 100644 --- a/src/extension/select_eventloop.h +++ b/src/extension/select_eventloop.h @@ -53,6 +53,6 @@ typedef struct _getdns_select_eventloop { void -_getdns_select_eventloop_init(_getdns_select_eventloop *loop); +_getdns_select_eventloop_init(struct mem_funcs *mf, _getdns_select_eventloop *loop); #endif From c936f0c51d38d540583822aee6e918c54d27a623 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 15 Feb 2017 10:56:19 +0100 Subject: [PATCH 20/56] Other allocs and frees with custom mem funcs too --- src/extension/poll_eventloop.c | 59 +++++++++++++++++++++++----------- src/extension/poll_eventloop.h | 6 ++-- 2 files changed, 45 insertions(+), 20 deletions(-) diff --git a/src/extension/poll_eventloop.c b/src/extension/poll_eventloop.c index b5c95c85..d85e254f 100644 --- a/src/extension/poll_eventloop.c +++ b/src/extension/poll_eventloop.c @@ -53,7 +53,8 @@ add_event(struct mem_funcs *mf, _getdns_eventloop_info** events, int id, _getdns_eventloop_info* ev) { DEBUG_SCHED("poll_eventloop: add_event with id %d\n", id); - _getdns_eventloop_info* myevent = calloc(1, sizeof(_getdns_eventloop_info)); + _getdns_eventloop_info* myevent = GETDNS_MALLOC(*mf, _getdns_eventloop_info); + /* not necessary -- (void) memset(myevent, 0, sizeof(_getdns_eventloop_info)); */ myevent->event = ev->event; myevent->id = id; myevent->timeout_time = ev->timeout_time; @@ -62,11 +63,11 @@ add_event(struct mem_funcs *mf, static void delete_event(struct mem_funcs *mf, - _getdns_eventloop_info** events,_getdns_eventloop_info* ev) + _getdns_eventloop_info** events, _getdns_eventloop_info* ev) { DEBUG_SCHED("poll_eventloop: delete_event with id %d\n", ev->id); HASH_DEL(*events, ev); - free(ev); + GETDNS_FREE(*mf, ev); } static uint64_t get_now_plus(uint64_t amount) @@ -221,6 +222,11 @@ poll_eventloop_cleanup(getdns_eventloop *loop) _getdns_poll_eventloop *poll_loop = (_getdns_poll_eventloop *)loop; struct mem_funcs *mf = &poll_loop->mf; + if (poll_loop->pfds) { + GETDNS_FREE(*mf, poll_loop->pfds); + poll_loop->pfds = NULL; + poll_loop->pfds_capacity = 0; + } HASH_CLEAR(hh, poll_loop->fd_events); HASH_CLEAR(hh, poll_loop->timeout_events); } @@ -255,6 +261,17 @@ poll_timeout_cb(int fd, getdns_eventloop_event *event) event->timeout_cb(event->userarg); } +static unsigned long up_pow2(unsigned long v) +{ + v--; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + return v + 1; +} + static void poll_eventloop_run_once(getdns_eventloop *loop, int blocking) { @@ -264,7 +281,6 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) uint64_t now, timeout = TIMEOUT_FOREVER; size_t i=0; int poll_timeout = 0; - struct pollfd* pfds = NULL; unsigned int num_pfds = 0; _getdns_eventloop_info* timeout_timeout_cbs = NULL; _getdns_eventloop_info* fd_timeout_cbs = NULL; @@ -287,7 +303,7 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) delete_event(mf, &timeout_timeout_cbs, s); poll_timeout_cb(-1, event); } - // first we count the number of fds that will be active + /* first we count the number of fds that will be active */ HASH_ITER(hh, poll_loop->fd_events, s, tmp) { if (s->event->read_cb || s->event->write_cb) @@ -299,16 +315,22 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) if ((timeout == TIMEOUT_FOREVER) && (num_pfds == 0)) return; - pfds = calloc(num_pfds, sizeof(struct pollfd)); + if (num_pfds > poll_loop->pfds_capacity) { + poll_loop->pfds_capacity = up_pow2(num_pfds); + if (poll_loop->pfds) { + poll_loop->pfds = GETDNS_XMALLOC(poll_loop->mf, struct pollfd, poll_loop->pfds_capacity); + } else + poll_loop->pfds = GETDNS_XREALLOC(poll_loop->mf, poll_loop->pfds, struct pollfd, poll_loop->pfds_capacity); + } i = 0; HASH_ITER(hh, poll_loop->fd_events, s, tmp) { if (s->event->read_cb) { - pfds[i].fd = s->id; - pfds[i].events |= POLLIN; + poll_loop->pfds[i].fd = s->id; + poll_loop->pfds[i].events |= POLLIN; } if (s->event->write_cb) { - pfds[i].fd = s->id; - pfds[i].events |= POLLOUT; + poll_loop->pfds[i].fd = s->id; + poll_loop->pfds[i].events |= POLLOUT; } i++; } @@ -322,30 +344,28 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) poll_timeout = (timeout - now) / 1000; /* turn microseconds into milliseconds */ } #ifdef USE_WINSOCK - if (WSAPoll(pfds, num_pfds, poll_timeout) < 0) { + if (WSAPoll(poll_loop->pfds, num_pfds, poll_timeout) < 0) { #else - if (poll(pfds, num_pfds, poll_timeout) < 0) { + if (poll(poll_loop->pfds, num_pfds, poll_timeout) < 0) { #endif perror("poll() failed"); exit(EXIT_FAILURE); } now = get_now_plus(0); for (i = 0; i < num_pfds; i++) { - int fd = pfds[i].fd; + int fd = poll_loop->pfds[i].fd; _getdns_eventloop_info* fd_event = find_event(&poll_loop->fd_events, fd); if (fd_event && fd_event->event) { getdns_eventloop_event* event = fd_event->event; if (event->read_cb && - (pfds[i].revents & POLLIN)) + (poll_loop->pfds[i].revents & POLLIN)) poll_read_cb(fd, event); if (event->write_cb && - (pfds[i].revents & POLLOUT)) + (poll_loop->pfds[i].revents & POLLOUT)) poll_write_cb(fd, event); } } - if (pfds) - free(pfds); HASH_ITER(hh, poll_loop->fd_events, s, tmp) { if (s->event && s->event->timeout_cb && @@ -404,7 +424,6 @@ _getdns_poll_eventloop_init(struct mem_funcs *mf, _getdns_poll_eventloop *loop) poll_eventloop_run_once }; - (void) memset(loop, 0, sizeof(_getdns_poll_eventloop)); loop->loop.vmt = &poll_eventloop_vmt; loop->mf = *mf; @@ -419,4 +438,8 @@ _getdns_poll_eventloop_init(struct mem_funcs *mf, _getdns_poll_eventloop *loop) } #endif loop->timeout_id = 0; + loop->pfds = NULL; + loop->pfds_capacity = 0; + loop->fd_events = NULL; + loop->timeout_events = NULL; } diff --git a/src/extension/poll_eventloop.h b/src/extension/poll_eventloop.h index 9c58b042..8c742e20 100644 --- a/src/extension/poll_eventloop.h +++ b/src/extension/poll_eventloop.h @@ -54,8 +54,10 @@ typedef struct _getdns_poll_eventloop { struct mem_funcs mf; unsigned int max_fds; unsigned int timeout_id; - _getdns_eventloop_info *fd_events; - _getdns_eventloop_info *timeout_events; + struct pollfd *pfds; + unsigned long pfds_capacity; + _getdns_eventloop_info *fd_events; + _getdns_eventloop_info *timeout_events; } _getdns_poll_eventloop; void From 3e8822e0e23f81dc9a65d3fe675f5a460a48cc42 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 15 Feb 2017 11:43:07 +0100 Subject: [PATCH 21/56] Fix uninitialized data error in valgrind check --- src/extension/poll_eventloop.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/extension/poll_eventloop.c b/src/extension/poll_eventloop.c index d85e254f..1eba706a 100644 --- a/src/extension/poll_eventloop.c +++ b/src/extension/poll_eventloop.c @@ -324,16 +324,18 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) } i = 0; HASH_ITER(hh, poll_loop->fd_events, s, tmp) { - if (s->event->read_cb) { - poll_loop->pfds[i].fd = s->id; + if (!s->event->read_cb && !s->event->write_cb) + continue; + poll_loop->pfds[i].fd = s->id; + poll_loop->pfds[i].events = 0; + poll_loop->pfds[i].revents = 0; /* <-- probably not needed */ + if (s->event->read_cb) poll_loop->pfds[i].events |= POLLIN; - } - if (s->event->write_cb) { - poll_loop->pfds[i].fd = s->id; + if (s->event->write_cb) poll_loop->pfds[i].events |= POLLOUT; - } i++; } + assert(i == num_pfds); if (timeout == TIMEOUT_FOREVER) { poll_timeout = -1; From b7c2e53a82f9f49202854fb9fbc75132a7139b5c Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 15 Feb 2017 12:21:29 +0100 Subject: [PATCH 22/56] Off by one problem? --- src/extension/poll_eventloop.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/extension/poll_eventloop.c b/src/extension/poll_eventloop.c index 1eba706a..331e5d4b 100644 --- a/src/extension/poll_eventloop.c +++ b/src/extension/poll_eventloop.c @@ -315,12 +315,16 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) if ((timeout == TIMEOUT_FOREVER) && (num_pfds == 0)) return; - if (num_pfds > poll_loop->pfds_capacity) { - poll_loop->pfds_capacity = up_pow2(num_pfds); + if (num_pfds >= poll_loop->pfds_capacity) { + poll_loop->pfds_capacity = up_pow2(num_pfds + 1); if (poll_loop->pfds) { poll_loop->pfds = GETDNS_XMALLOC(poll_loop->mf, struct pollfd, poll_loop->pfds_capacity); } else poll_loop->pfds = GETDNS_XREALLOC(poll_loop->mf, poll_loop->pfds, struct pollfd, poll_loop->pfds_capacity); + if (poll_loop->pfds == 0) { + poll_loop->pfds_capacity = 0; + return; + } } i = 0; HASH_ITER(hh, poll_loop->fd_events, s, tmp) { From 840ba8c85d29d52b51cf17e83dadf969f559a8ee Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 15 Feb 2017 12:46:48 +0100 Subject: [PATCH 23/56] Reference fixes jsmn --- src/jsmn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jsmn b/src/jsmn index 49024a6e..868c22e3 160000 --- a/src/jsmn +++ b/src/jsmn @@ -1 +1 @@ -Subproject commit 49024a6e11739c866bce0e9f3617278b98906ad0 +Subproject commit 868c22e35ec223fc26ddefdb9ca83901dc6e2534 From 04f6a2b13b6382575e8351ab7859d611e6946afb Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 15 Feb 2017 12:47:55 +0100 Subject: [PATCH 24/56] Fixed dependencies --- spec/example/Makefile.in | 24 ++- src/Makefile.in | 368 ++++++++++++++++++++++++--------------- src/test/Makefile.in | 71 +++++--- src/tools/Makefile.in | 7 +- 4 files changed, 298 insertions(+), 172 deletions(-) diff --git a/spec/example/Makefile.in b/spec/example/Makefile.in index 7bf5e016..8ff7f2d1 100644 --- a/spec/example/Makefile.in +++ b/spec/example/Makefile.in @@ -149,16 +149,24 @@ depend: # Dependencies for the examples example-all-functions.lo example-all-functions.o: $(srcdir)/example-all-functions.c $(srcdir)/getdns_libevent.h \ - ../../src/config.h ../../src/getdns/getdns.h \ - $(srcdir)/../../src/getdns/getdns_ext_libevent.h ../../src/getdns/getdns_extra.h -example-reverse.lo example-reverse.o: $(srcdir)/example-reverse.c $(srcdir)/getdns_libevent.h ../../src/config.h \ - ../../src/getdns/getdns.h $(srcdir)/../../src/getdns/getdns_ext_libevent.h \ + ../../src/config.h \ + ../../src/getdns/getdns.h \ + $(srcdir)/../../src/getdns/getdns_ext_libevent.h \ + ../../src/getdns/getdns_extra.h +example-reverse.lo example-reverse.o: $(srcdir)/example-reverse.c $(srcdir)/getdns_libevent.h \ + ../../src/config.h \ + ../../src/getdns/getdns.h \ + $(srcdir)/../../src/getdns/getdns_ext_libevent.h \ ../../src/getdns/getdns_extra.h example-simple-answers.lo example-simple-answers.o: $(srcdir)/example-simple-answers.c $(srcdir)/getdns_libevent.h \ - ../../src/config.h ../../src/getdns/getdns.h \ - $(srcdir)/../../src/getdns/getdns_ext_libevent.h ../../src/getdns/getdns_extra.h + ../../src/config.h \ + ../../src/getdns/getdns.h \ + $(srcdir)/../../src/getdns/getdns_ext_libevent.h \ + ../../src/getdns/getdns_extra.h example-synchronous.lo example-synchronous.o: $(srcdir)/example-synchronous.c $(srcdir)/getdns_core_only.h \ ../../src/getdns/getdns.h -example-tree.lo example-tree.o: $(srcdir)/example-tree.c $(srcdir)/getdns_libevent.h ../../src/config.h \ - ../../src/getdns/getdns.h $(srcdir)/../../src/getdns/getdns_ext_libevent.h \ +example-tree.lo example-tree.o: $(srcdir)/example-tree.c $(srcdir)/getdns_libevent.h \ + ../../src/config.h \ + ../../src/getdns/getdns.h \ + $(srcdir)/../../src/getdns/getdns_ext_libevent.h \ ../../src/getdns/getdns_extra.h diff --git a/src/Makefile.in b/src/Makefile.in index 77297c42..33a6c946 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -215,148 +215,236 @@ depend: FORCE: # Dependencies for gldns, utils, the extensions and compat functions -const-info.lo const-info.o: $(srcdir)/const-info.c getdns/getdns.h getdns/getdns_extra.h \ - getdns/getdns.h $(srcdir)/const-info.h -context.lo context.o: $(srcdir)/context.c config.h $(srcdir)/debug.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \ - $(srcdir)/gldns/wire2str.h $(srcdir)/context.h getdns/getdns.h getdns/getdns_extra.h \ - getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ - $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ - getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/server.h \ - $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ - $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/list.h $(srcdir)/dict.h $(srcdir)/pubkey-pinning.h -convert.lo convert.o: $(srcdir)/convert.c config.h getdns/getdns.h getdns/getdns_extra.h \ - getdns/getdns.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ - $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ - getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/debug.h \ - $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ - $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/parseutil.h \ - $(srcdir)/const-info.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/jsmn/jsmn.h $(srcdir)/convert.h -dict.lo dict.o: $(srcdir)/dict.c config.h $(srcdir)/types-internal.h getdns/getdns.h \ - getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h \ - $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \ - $(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ - $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ - $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/const-info.h \ - $(srcdir)/gldns/wire2str.h -dnssec.lo dnssec.o: $(srcdir)/dnssec.c config.h $(srcdir)/debug.h getdns/getdns.h $(srcdir)/context.h \ - getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ - $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ - getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/server.h \ - $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ - $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h \ - $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/parseutil.h $(srcdir)/general.h $(srcdir)/dict.h $(srcdir)/list.h \ - $(srcdir)/util/val_secalgo.h -general.lo general.o: $(srcdir)/general.c config.h $(srcdir)/general.h getdns/getdns.h $(srcdir)/types-internal.h \ - getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/ub_loop.h $(srcdir)/debug.h \ - $(srcdir)/gldns/wire2str.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \ - $(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ - $(srcdir)/util/uthash.h $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ - $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/dict.h \ - $(srcdir)/mdns.h -list.lo list.o: $(srcdir)/list.c $(srcdir)/types-internal.h getdns/getdns.h getdns/getdns_extra.h \ - getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h config.h $(srcdir)/context.h \ - $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ - getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/debug.h \ - $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/list.h \ - $(srcdir)/dict.h -mdns.lo mdns.o: $(srcdir)/mdns.c config.h $(srcdir)/debug.h $(srcdir)/context.h getdns/getdns.h \ - getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ - $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ - getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/server.h \ - $(srcdir)/general.h $(srcdir)/gldns/pkthdr.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ +const-info.lo const-info.o: $(srcdir)/const-info.c \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/const-info.h +context.lo context.o: $(srcdir)/context.c \ + config.h \ + $(srcdir)/debug.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/context.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h \ + $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h \ + $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ + $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/list.h $(srcdir)/dict.h \ + $(srcdir)/pubkey-pinning.h +convert.lo convert.o: $(srcdir)/convert.c \ + config.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ + $(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \ + $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h \ + $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/wire2str.h \ + $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/parseutil.h $(srcdir)/const-info.h $(srcdir)/dict.h \ + $(srcdir)/list.h $(srcdir)/jsmn/jsmn.h $(srcdir)/convert.h +dict.lo dict.o: $(srcdir)/dict.c \ + config.h \ + $(srcdir)/types-internal.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h \ + $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h \ + $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ + $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/const-info.h $(srcdir)/gldns/wire2str.h +dnssec.lo dnssec.o: $(srcdir)/dnssec.c \ + config.h \ + $(srcdir)/debug.h \ + getdns/getdns.h \ + $(srcdir)/context.h \ + getdns/getdns_extra.h \ + $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h \ + $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h \ + $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ + $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \ + $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/parseutil.h $(srcdir)/general.h $(srcdir)/dict.h \ + $(srcdir)/list.h $(srcdir)/util/val_secalgo.h +general.lo general.o: $(srcdir)/general.c \ + config.h \ + $(srcdir)/general.h \ + getdns/getdns.h \ + $(srcdir)/types-internal.h \ + getdns/getdns_extra.h \ + $(srcdir)/util/rbtree.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/gldns/wire2str.h $(srcdir)/context.h \ + $(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \ + $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h \ + $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h \ + $(srcdir)/dict.h $(srcdir)/mdns.h +list.lo list.o: $(srcdir)/list.c $(srcdir)/types-internal.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h \ + config.h \ + $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \ + $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h \ + $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/list.h $(srcdir)/dict.h +mdns.lo mdns.o: $(srcdir)/mdns.c \ + config.h \ + $(srcdir)/debug.h $(srcdir)/context.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h \ + $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h \ + $(srcdir)/server.h $(srcdir)/general.h $(srcdir)/gldns/pkthdr.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ $(srcdir)/gldns/gbuffer.h $(srcdir)/mdns.h -pubkey-pinning.lo pubkey-pinning.o: $(srcdir)/pubkey-pinning.c config.h $(srcdir)/debug.h getdns/getdns.h \ - $(srcdir)/context.h getdns/getdns.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ - $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h config.h \ - $(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ - $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ - $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h -request-internal.lo request-internal.o: $(srcdir)/request-internal.c config.h $(srcdir)/types-internal.h \ - getdns/getdns.h getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \ - $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \ - $(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ - $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ - $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h \ - $(srcdir)/gldns/rrdef.h $(srcdir)/dict.h $(srcdir)/convert.h -rr-dict.lo rr-dict.o: $(srcdir)/rr-dict.c $(srcdir)/rr-dict.h config.h getdns/getdns.h $(srcdir)/gldns/gbuffer.h \ - $(srcdir)/util-internal.h $(srcdir)/context.h getdns/getdns_extra.h getdns/getdns.h \ - $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h config.h \ - $(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ - $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dict.h -rr-iter.lo rr-iter.o: $(srcdir)/rr-iter.c $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h config.h getdns/getdns.h \ +pubkey-pinning.lo pubkey-pinning.o: $(srcdir)/pubkey-pinning.c \ + config.h \ + $(srcdir)/debug.h \ + getdns/getdns.h \ + $(srcdir)/context.h \ + getdns/getdns_extra.h \ + $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h \ + $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h \ + $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ + $(srcdir)/gldns/pkthdr.h +request-internal.lo request-internal.o: $(srcdir)/request-internal.c \ + config.h \ + $(srcdir)/types-internal.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h \ + $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h \ + $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ + $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/dict.h $(srcdir)/convert.h +rr-dict.lo rr-dict.o: $(srcdir)/rr-dict.c $(srcdir)/rr-dict.h \ + config.h \ + getdns/getdns.h \ + $(srcdir)/gldns/gbuffer.h $(srcdir)/util-internal.h $(srcdir)/context.h \ + getdns/getdns_extra.h \ + $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h \ + $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h \ + $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dict.h +rr-iter.lo rr-iter.o: $(srcdir)/rr-iter.c $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ + config.h \ + getdns/getdns.h \ $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h -server.lo server.o: $(srcdir)/server.c config.h getdns/getdns_extra.h getdns/getdns.h \ - $(srcdir)/context.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ - $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ - getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/debug.h \ - $(srcdir)/server.h -stub.lo stub.o: $(srcdir)/stub.c config.h $(srcdir)/debug.h $(srcdir)/stub.h getdns/getdns.h $(srcdir)/types-internal.h \ - getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/gldns/gbuffer.h \ - $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \ - $(srcdir)/gldns/wire2str.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/context.h \ - $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ - getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/server.h \ - $(srcdir)/util-internal.h $(srcdir)/general.h $(srcdir)/pubkey-pinning.h -sync.lo sync.o: $(srcdir)/sync.c getdns/getdns.h config.h $(srcdir)/context.h getdns/getdns_extra.h \ - getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ - $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ - getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/debug.h \ - $(srcdir)/server.h $(srcdir)/general.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ - $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/gldns/wire2str.h -ub_loop.lo ub_loop.o: $(srcdir)/ub_loop.c $(srcdir)/ub_loop.h config.h getdns/getdns.h \ - getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ - $(srcdir)/debug.h -util-internal.lo util-internal.o: $(srcdir)/util-internal.c config.h getdns/getdns.h $(srcdir)/dict.h \ - $(srcdir)/util/rbtree.h $(srcdir)/types-internal.h getdns/getdns_extra.h getdns/getdns.h \ - $(srcdir)/list.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \ - $(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ - $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ - $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/dnssec.h \ - $(srcdir)/gldns/rrdef.h -version.lo version.o: version.c -gbuffer.lo gbuffer.o: $(srcdir)/gldns/gbuffer.c config.h $(srcdir)/gldns/gbuffer.h -keyraw.lo keyraw.o: $(srcdir)/gldns/keyraw.c config.h $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/rrdef.h -parse.lo parse.o: $(srcdir)/gldns/parse.c config.h $(srcdir)/gldns/parse.h $(srcdir)/gldns/parseutil.h \ +server.lo server.o: $(srcdir)/server.c \ + config.h \ + getdns/getdns_extra.h \ + getdns/getdns.h \ + $(srcdir)/context.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h \ + $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h \ + $(srcdir)/debug.h $(srcdir)/server.h +stub.lo stub.o: $(srcdir)/stub.c \ + config.h \ + $(srcdir)/debug.h $(srcdir)/stub.h \ + getdns/getdns.h \ + $(srcdir)/types-internal.h \ + getdns/getdns_extra.h \ + $(srcdir)/util/rbtree.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h \ + $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ + $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \ + $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util-internal.h \ + $(srcdir)/general.h $(srcdir)/pubkey-pinning.h +sync.lo sync.o: $(srcdir)/sync.c \ + getdns/getdns.h \ + config.h \ + $(srcdir)/context.h \ + getdns/getdns_extra.h \ + $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h \ + $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h \ + $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/general.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ + $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h \ + $(srcdir)/gldns/wire2str.h +ub_loop.lo ub_loop.o: $(srcdir)/ub_loop.c $(srcdir)/ub_loop.h \ + config.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/debug.h +util-internal.lo util-internal.o: $(srcdir)/util-internal.c \ + config.h \ + getdns/getdns.h \ + $(srcdir)/dict.h $(srcdir)/util/rbtree.h $(srcdir)/types-internal.h \ + getdns/getdns_extra.h \ + $(srcdir)/list.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h \ + $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h \ + $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ + $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h +gbuffer.lo gbuffer.o: $(srcdir)/gldns/gbuffer.c \ + config.h \ $(srcdir)/gldns/gbuffer.h -parseutil.lo parseutil.o: $(srcdir)/gldns/parseutil.c config.h $(srcdir)/gldns/parseutil.h -rrdef.lo rrdef.o: $(srcdir)/gldns/rrdef.c config.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/parseutil.h -str2wire.lo str2wire.o: $(srcdir)/gldns/str2wire.c config.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \ - $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/parse.h $(srcdir)/gldns/parseutil.h -wire2str.lo wire2str.o: $(srcdir)/gldns/wire2str.c config.h $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/str2wire.h \ - $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/parseutil.h $(srcdir)/gldns/gbuffer.h \ - $(srcdir)/gldns/keyraw.h -arc4_lock.lo arc4_lock.o: $(srcdir)/compat/arc4_lock.c config.h -arc4random.lo arc4random.o: $(srcdir)/compat/arc4random.c config.h $(srcdir)/compat/chacha_private.h -arc4random_uniform.lo arc4random_uniform.o: $(srcdir)/compat/arc4random_uniform.c config.h -explicit_bzero.lo explicit_bzero.o: $(srcdir)/compat/explicit_bzero.c config.h -getentropy_linux.lo getentropy_linux.o: $(srcdir)/compat/getentropy_linux.c config.h -getentropy_osx.lo getentropy_osx.o: $(srcdir)/compat/getentropy_osx.c config.h -getentropy_solaris.lo getentropy_solaris.o: $(srcdir)/compat/getentropy_solaris.c config.h +keyraw.lo keyraw.o: $(srcdir)/gldns/keyraw.c \ + config.h \ + $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/rrdef.h +parse.lo parse.o: $(srcdir)/gldns/parse.c \ + config.h \ + $(srcdir)/gldns/parse.h $(srcdir)/gldns/parseutil.h $(srcdir)/gldns/gbuffer.h +parseutil.lo parseutil.o: $(srcdir)/gldns/parseutil.c \ + config.h \ + $(srcdir)/gldns/parseutil.h +rrdef.lo rrdef.o: $(srcdir)/gldns/rrdef.c \ + config.h \ + $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/parseutil.h +str2wire.lo str2wire.o: $(srcdir)/gldns/str2wire.c \ + config.h \ + $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/gbuffer.h \ + $(srcdir)/gldns/parse.h $(srcdir)/gldns/parseutil.h +wire2str.lo wire2str.o: $(srcdir)/gldns/wire2str.c \ + config.h \ + $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/pkthdr.h \ + $(srcdir)/gldns/parseutil.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/keyraw.h +arc4_lock.lo arc4_lock.o: $(srcdir)/compat/arc4_lock.c \ + config.h +arc4random.lo arc4random.o: $(srcdir)/compat/arc4random.c \ + config.h \ + $(srcdir)/compat/chacha_private.h +arc4random_uniform.lo arc4random_uniform.o: $(srcdir)/compat/arc4random_uniform.c \ + config.h +explicit_bzero.lo explicit_bzero.o: $(srcdir)/compat/explicit_bzero.c \ + config.h +getentropy_linux.lo getentropy_linux.o: $(srcdir)/compat/getentropy_linux.c \ + config.h +getentropy_osx.lo getentropy_osx.o: $(srcdir)/compat/getentropy_osx.c \ + config.h +getentropy_solaris.lo getentropy_solaris.o: $(srcdir)/compat/getentropy_solaris.c \ + config.h getentropy_win.lo getentropy_win.o: $(srcdir)/compat/getentropy_win.c -gettimeofday.lo gettimeofday.o: $(srcdir)/compat/gettimeofday.c config.h -inet_ntop.lo inet_ntop.o: $(srcdir)/compat/inet_ntop.c config.h -inet_pton.lo inet_pton.o: $(srcdir)/compat/inet_pton.c config.h -sha512.lo sha512.o: $(srcdir)/compat/sha512.c config.h -strlcpy.lo strlcpy.o: $(srcdir)/compat/strlcpy.c config.h -rbtree.lo rbtree.o: $(srcdir)/util/rbtree.c config.h $(srcdir)/util/log.h $(srcdir)/debug.h config.h \ - $(srcdir)/util/fptr_wlist.h $(srcdir)/util/rbtree.h -val_secalgo.lo val_secalgo.o: $(srcdir)/util/val_secalgo.c config.h $(srcdir)/util/val_secalgo.h $(srcdir)/util/log.h \ - $(srcdir)/debug.h config.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/gbuffer.h +gettimeofday.lo gettimeofday.o: $(srcdir)/compat/gettimeofday.c \ + config.h +inet_ntop.lo inet_ntop.o: $(srcdir)/compat/inet_ntop.c \ + config.h +inet_pton.lo inet_pton.o: $(srcdir)/compat/inet_pton.c \ + config.h +sha512.lo sha512.o: $(srcdir)/compat/sha512.c \ + config.h +strlcpy.lo strlcpy.o: $(srcdir)/compat/strlcpy.c \ + config.h +rbtree.lo rbtree.o: $(srcdir)/util/rbtree.c \ + config.h \ + $(srcdir)/util/log.h $(srcdir)/debug.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/rbtree.h +val_secalgo.lo val_secalgo.o: $(srcdir)/util/val_secalgo.c \ + config.h \ + $(srcdir)/util/val_secalgo.h $(srcdir)/util/log.h $(srcdir)/debug.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/keyraw.h \ + $(srcdir)/gldns/gbuffer.h jsmn.lo jsmn.o: $(srcdir)/jsmn/jsmn.c $(srcdir)/jsmn/jsmn.h -libev.lo libev.o: $(srcdir)/extension/libev.c config.h $(srcdir)/types-internal.h getdns/getdns.h \ - getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \ - $(srcdir)/getdns/getdns_ext_libev.h getdns/getdns_extra.h -libevent.lo libevent.o: $(srcdir)/extension/libevent.c config.h $(srcdir)/types-internal.h \ - getdns/getdns.h getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \ - $(srcdir)/getdns/getdns_ext_libevent.h getdns/getdns_extra.h -libuv.lo libuv.o: $(srcdir)/extension/libuv.c config.h $(srcdir)/debug.h config.h $(srcdir)/types-internal.h \ - getdns/getdns.h getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \ - $(srcdir)/getdns/getdns_ext_libuv.h getdns/getdns_extra.h -poll_eventloop.lo poll_eventloop.o: $(srcdir)/extension/poll_eventloop.c config.h \ - $(srcdir)/extension/poll_eventloop.h getdns/getdns.h getdns/getdns_extra.h \ - $(srcdir)/types-internal.h getdns/getdns.h getdns/getdns_extra.h $(srcdir)/util/rbtree.h \ - $(srcdir)/util/uthash.h $(srcdir)/debug.h config.h -select_eventloop.lo select_eventloop.o: $(srcdir)/extension/select_eventloop.c config.h \ - $(srcdir)/extension/select_eventloop.h getdns/getdns.h getdns/getdns_extra.h \ - $(srcdir)/debug.h config.h $(srcdir)/types-internal.h getdns/getdns.h getdns/getdns_extra.h \ - $(srcdir)/util/rbtree.h +libev.lo libev.o: $(srcdir)/extension/libev.c \ + config.h \ + $(srcdir)/types-internal.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/util/rbtree.h $(srcdir)/getdns/getdns_ext_libev.h +libevent.lo libevent.o: $(srcdir)/extension/libevent.c \ + config.h \ + $(srcdir)/types-internal.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/util/rbtree.h $(srcdir)/getdns/getdns_ext_libevent.h +libuv.lo libuv.o: $(srcdir)/extension/libuv.c \ + config.h \ + $(srcdir)/debug.h $(srcdir)/types-internal.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/util/rbtree.h $(srcdir)/getdns/getdns_ext_libuv.h +poll_eventloop.lo poll_eventloop.o: $(srcdir)/extension/poll_eventloop.c \ + config.h \ + $(srcdir)/extension/poll_eventloop.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/uthash.h $(srcdir)/debug.h +select_eventloop.lo select_eventloop.o: $(srcdir)/extension/select_eventloop.c \ + config.h \ + $(srcdir)/extension/select_eventloop.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/debug.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h diff --git a/src/test/Makefile.in b/src/test/Makefile.in index c481fdab..758435c1 100644 --- a/src/test/Makefile.in +++ b/src/test/Makefile.in @@ -216,10 +216,13 @@ depend: .PHONY: clean test # Dependencies for the unit tests -check_getdns.lo check_getdns.o: $(srcdir)/check_getdns.c ../getdns/getdns.h $(srcdir)/check_getdns_common.h \ - ../getdns/getdns_extra.h $(srcdir)/check_getdns_address.h \ - $(srcdir)/check_getdns_address_sync.h $(srcdir)/check_getdns_cancel_callback.h \ - $(srcdir)/check_getdns_context_create.h $(srcdir)/check_getdns_context_destroy.h \ +check_getdns.lo check_getdns.o: $(srcdir)/check_getdns.c \ + ../getdns/getdns.h \ + $(srcdir)/check_getdns_common.h \ + ../getdns/getdns_extra.h \ + $(srcdir)/check_getdns_address.h $(srcdir)/check_getdns_address_sync.h \ + $(srcdir)/check_getdns_cancel_callback.h $(srcdir)/check_getdns_context_create.h \ + $(srcdir)/check_getdns_context_destroy.h \ $(srcdir)/check_getdns_context_set_context_update_callback.h \ $(srcdir)/check_getdns_context_set_dns_transport.h \ $(srcdir)/check_getdns_context_set_timeout.h \ @@ -239,34 +242,58 @@ check_getdns.lo check_getdns.o: $(srcdir)/check_getdns.c ../getdns/getdns.h $(sr $(srcdir)/check_getdns_list_get_list.h $(srcdir)/check_getdns_pretty_print_dict.h \ $(srcdir)/check_getdns_service.h $(srcdir)/check_getdns_service_sync.h \ $(srcdir)/check_getdns_transport.h -check_getdns_common.lo check_getdns_common.o: $(srcdir)/check_getdns_common.c ../getdns/getdns.h \ - ../config.h $(srcdir)/check_getdns_common.h ../getdns/getdns_extra.h \ +check_getdns_common.lo check_getdns_common.o: $(srcdir)/check_getdns_common.c \ + ../getdns/getdns.h \ + ../config.h \ + $(srcdir)/check_getdns_common.h \ + ../getdns/getdns_extra.h \ $(srcdir)/check_getdns_eventloop.h check_getdns_context_set_timeout.lo check_getdns_context_set_timeout.o: $(srcdir)/check_getdns_context_set_timeout.c \ $(srcdir)/check_getdns_context_set_timeout.h $(srcdir)/check_getdns_common.h \ - ../getdns/getdns.h ../getdns/getdns_extra.h + ../getdns/getdns.h \ + ../getdns/getdns_extra.h check_getdns_libev.lo check_getdns_libev.o: $(srcdir)/check_getdns_libev.c $(srcdir)/check_getdns_eventloop.h \ - ../config.h ../getdns/getdns.h $(srcdir)/../getdns/getdns_ext_libev.h \ - ../getdns/getdns_extra.h $(srcdir)/check_getdns_common.h + ../config.h \ + ../getdns/getdns.h \ + $(srcdir)/../getdns/getdns_ext_libev.h \ + ../getdns/getdns_extra.h \ + $(srcdir)/check_getdns_common.h check_getdns_libevent.lo check_getdns_libevent.o: $(srcdir)/check_getdns_libevent.c $(srcdir)/check_getdns_eventloop.h \ - ../config.h ../getdns/getdns.h $(srcdir)/../getdns/getdns_ext_libevent.h \ - ../getdns/getdns_extra.h $(srcdir)/check_getdns_libevent.h $(srcdir)/check_getdns_common.h + ../config.h \ + ../getdns/getdns.h \ + $(srcdir)/../getdns/getdns_ext_libevent.h \ + ../getdns/getdns_extra.h \ + $(srcdir)/check_getdns_libevent.h $(srcdir)/check_getdns_common.h check_getdns_libuv.lo check_getdns_libuv.o: $(srcdir)/check_getdns_libuv.c $(srcdir)/check_getdns_eventloop.h \ - ../config.h ../getdns/getdns.h $(srcdir)/../getdns/getdns_ext_libuv.h \ - ../getdns/getdns_extra.h $(srcdir)/check_getdns_common.h + ../config.h \ + ../getdns/getdns.h \ + $(srcdir)/../getdns/getdns_ext_libuv.h \ + ../getdns/getdns_extra.h \ + $(srcdir)/check_getdns_common.h check_getdns_selectloop.lo check_getdns_selectloop.o: $(srcdir)/check_getdns_selectloop.c \ - $(srcdir)/check_getdns_eventloop.h ../config.h ../getdns/getdns.h \ + $(srcdir)/check_getdns_eventloop.h \ + ../config.h \ + ../getdns/getdns.h \ ../getdns/getdns_extra.h check_getdns_transport.lo check_getdns_transport.o: $(srcdir)/check_getdns_transport.c \ - $(srcdir)/check_getdns_transport.h $(srcdir)/check_getdns_common.h ../getdns/getdns.h \ + $(srcdir)/check_getdns_transport.h $(srcdir)/check_getdns_common.h \ + ../getdns/getdns.h \ ../getdns/getdns_extra.h -scratchpad.template.lo scratchpad.template.o: scratchpad.template.c ../getdns/getdns.h \ +scratchpad.template.lo scratchpad.template.o: scratchpad.template.c \ + ../getdns/getdns.h \ ../getdns/getdns_extra.h testmessages.lo testmessages.o: $(srcdir)/testmessages.c $(srcdir)/testmessages.h -tests_dict.lo tests_dict.o: $(srcdir)/tests_dict.c $(srcdir)/testmessages.h ../getdns/getdns.h -tests_list.lo tests_list.o: $(srcdir)/tests_list.c $(srcdir)/testmessages.h ../getdns/getdns.h -tests_namespaces.lo tests_namespaces.o: $(srcdir)/tests_namespaces.c $(srcdir)/testmessages.h ../getdns/getdns.h -tests_stub_async.lo tests_stub_async.o: $(srcdir)/tests_stub_async.c ../config.h $(srcdir)/testmessages.h \ - ../getdns/getdns.h ../getdns/getdns_extra.h -tests_stub_sync.lo tests_stub_sync.o: $(srcdir)/tests_stub_sync.c $(srcdir)/testmessages.h ../getdns/getdns.h \ +tests_dict.lo tests_dict.o: $(srcdir)/tests_dict.c $(srcdir)/testmessages.h \ + ../getdns/getdns.h +tests_list.lo tests_list.o: $(srcdir)/tests_list.c $(srcdir)/testmessages.h \ + ../getdns/getdns.h +tests_namespaces.lo tests_namespaces.o: $(srcdir)/tests_namespaces.c $(srcdir)/testmessages.h \ + ../getdns/getdns.h +tests_stub_async.lo tests_stub_async.o: $(srcdir)/tests_stub_async.c \ + ../config.h \ + $(srcdir)/testmessages.h \ + ../getdns/getdns.h \ + ../getdns/getdns_extra.h +tests_stub_sync.lo tests_stub_sync.o: $(srcdir)/tests_stub_sync.c $(srcdir)/testmessages.h \ + ../getdns/getdns.h \ ../getdns/getdns_extra.h diff --git a/src/tools/Makefile.in b/src/tools/Makefile.in index d98cf437..d066e824 100644 --- a/src/tools/Makefile.in +++ b/src/tools/Makefile.in @@ -113,5 +113,8 @@ depend: .PHONY: clean test # Dependencies for getdns_query -getdns_query.lo getdns_query.o: $(srcdir)/getdns_query.c ../config.h $(srcdir)/../debug.h ../config.h \ - ../getdns/getdns.h ../getdns/getdns_extra.h +getdns_query.lo getdns_query.o: $(srcdir)/getdns_query.c \ + ../config.h \ + $(srcdir)/../debug.h \ + ../getdns/getdns.h \ + ../getdns/getdns_extra.h From b2fe9673de39bf638f6b8ec64e99ce58952fb07d Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 15 Feb 2017 13:08:47 +0100 Subject: [PATCH 25/56] Fix realloc pfds set error + callback order error --- src/extension/poll_eventloop.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/extension/poll_eventloop.c b/src/extension/poll_eventloop.c index 331e5d4b..f5e609ab 100644 --- a/src/extension/poll_eventloop.c +++ b/src/extension/poll_eventloop.c @@ -317,7 +317,7 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) if (num_pfds >= poll_loop->pfds_capacity) { poll_loop->pfds_capacity = up_pow2(num_pfds + 1); - if (poll_loop->pfds) { + if (!poll_loop->pfds) { poll_loop->pfds = GETDNS_XMALLOC(poll_loop->mf, struct pollfd, poll_loop->pfds_capacity); } else poll_loop->pfds = GETDNS_XREALLOC(poll_loop->mf, poll_loop->pfds, struct pollfd, poll_loop->pfds_capacity); @@ -363,13 +363,13 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) _getdns_eventloop_info* fd_event = find_event(&poll_loop->fd_events, fd); if (fd_event && fd_event->event) { getdns_eventloop_event* event = fd_event->event; - if (event->read_cb && - (poll_loop->pfds[i].revents & POLLIN)) - poll_read_cb(fd, event); - if (event->write_cb && (poll_loop->pfds[i].revents & POLLOUT)) poll_write_cb(fd, event); + + else if (event->read_cb && + (poll_loop->pfds[i].revents & POLLIN)) + poll_read_cb(fd, event); } } HASH_ITER(hh, poll_loop->fd_events, s, tmp) { From c805d40585b977fb4f20d9ae1a3462e6362540a9 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 15 Feb 2017 14:04:34 +0100 Subject: [PATCH 26/56] Clean in place executed unit tests --- src/test/tpkg/clean.sh | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100755 src/test/tpkg/clean.sh diff --git a/src/test/tpkg/clean.sh b/src/test/tpkg/clean.sh new file mode 100755 index 00000000..b3ebef5e --- /dev/null +++ b/src/test/tpkg/clean.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +export SRCDIR=`dirname $0` +( cd $SRCDIR + ./tpkg clean + rm -fr build build-stub-only build-event-loops install scan-build-reports .tpkg.var.master +) From 7b6b0ff642fdb0c2a735818e2759fac2b77eeca6 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 15 Feb 2017 14:57:30 +0100 Subject: [PATCH 27/56] No helper copy variables --- src/extension/poll_eventloop.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/src/extension/poll_eventloop.c b/src/extension/poll_eventloop.c index f5e609ab..65fd17c9 100644 --- a/src/extension/poll_eventloop.c +++ b/src/extension/poll_eventloop.c @@ -49,15 +49,16 @@ find_event(_getdns_eventloop_info** events, int id) } static void -add_event(struct mem_funcs *mf, - _getdns_eventloop_info** events, int id, _getdns_eventloop_info* ev) +add_event(struct mem_funcs *mf, _getdns_eventloop_info** events, + int id, getdns_eventloop_event *event, uint64_t timeout_time) { DEBUG_SCHED("poll_eventloop: add_event with id %d\n", id); _getdns_eventloop_info* myevent = GETDNS_MALLOC(*mf, _getdns_eventloop_info); /* not necessary -- (void) memset(myevent, 0, sizeof(_getdns_eventloop_info)); */ - myevent->event = ev->event; + myevent->id = id; - myevent->timeout_time = ev->timeout_time; + myevent->event = event; + myevent->timeout_time = timeout_time; HASH_ADD_INT(*events, id, myevent); } @@ -131,11 +132,8 @@ poll_eventloop_schedule(getdns_eventloop *loop, if (fd_event) { delete_event(mf, &poll_loop->fd_events, fd_event); } - _getdns_eventloop_info fd_ev; event->ev = (void *) (intptr_t) (fd + 1); - fd_ev.event = event; - fd_ev.timeout_time = get_now_plus(timeout); - add_event(mf, &poll_loop->fd_events, fd, &fd_ev); + add_event(mf, &poll_loop->fd_events, fd, event, get_now_plus(timeout)); DEBUG_SCHED( "scheduled read/write at fd %d\n", fd); return GETDNS_RETURN_GOOD; @@ -154,11 +152,8 @@ poll_eventloop_schedule(getdns_eventloop *loop, } for (i = poll_loop->timeout_id + 1; i != poll_loop->timeout_id; i++) { if (find_event(&poll_loop->timeout_events, i) == NULL) { - _getdns_eventloop_info timeout_ev; - timeout_ev.event = event; - timeout_ev.timeout_time = get_now_plus(timeout); - add_event(mf, &poll_loop->timeout_events, i, &timeout_ev); event->ev = (void *) (intptr_t) (i + 1); + add_event(mf, &poll_loop->timeout_events, i, event, get_now_plus(timeout)); DEBUG_SCHED( "scheduled timeout at slot %d\n", (int)i); return GETDNS_RETURN_GOOD; @@ -292,7 +287,7 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) HASH_ITER(hh, poll_loop->timeout_events, s, tmp) { if (now > s->timeout_time) - add_event(mf, &timeout_timeout_cbs, s->id, s); + add_event(mf, &timeout_timeout_cbs, s->id, s->event, s->timeout_time); else if (s->timeout_time < timeout) timeout = s->timeout_time; } @@ -376,7 +371,7 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) if (s->event && s->event->timeout_cb && now > s->timeout_time) - add_event(mf, &fd_timeout_cbs, s->id, s); + add_event(mf, &fd_timeout_cbs, s->id, s->event, s->timeout_time); } /* this is in case the timeout callback deletes the event and thus messes with the iteration */ @@ -390,7 +385,7 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) if (s->event && s->event->timeout_cb && now > s->timeout_time) - add_event(mf, &timeout_timeout_cbs, s->id, s); + add_event(mf, &timeout_timeout_cbs, s->id, s->event, s->timeout_time); } /* this is in case the timeout callback deletes the event and thus messes with the iteration */ From e4eddca2592c638b42d9457237236c83953a8af1 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 15 Feb 2017 15:10:11 +0100 Subject: [PATCH 28/56] Reference event_info directly --- src/extension/poll_eventloop.c | 53 +++++++++------------------------- 1 file changed, 13 insertions(+), 40 deletions(-) diff --git a/src/extension/poll_eventloop.c b/src/extension/poll_eventloop.c index 65fd17c9..2f40c30a 100644 --- a/src/extension/poll_eventloop.c +++ b/src/extension/poll_eventloop.c @@ -48,7 +48,7 @@ find_event(_getdns_eventloop_info** events, int id) return ev; } -static void +static _getdns_eventloop_info * add_event(struct mem_funcs *mf, _getdns_eventloop_info** events, int id, getdns_eventloop_event *event, uint64_t timeout_time) { @@ -60,6 +60,7 @@ add_event(struct mem_funcs *mf, _getdns_eventloop_info** events, myevent->event = event; myevent->timeout_time = timeout_time; HASH_ADD_INT(*events, id, myevent); + return myevent; } static void @@ -132,8 +133,7 @@ poll_eventloop_schedule(getdns_eventloop *loop, if (fd_event) { delete_event(mf, &poll_loop->fd_events, fd_event); } - event->ev = (void *) (intptr_t) (fd + 1); - add_event(mf, &poll_loop->fd_events, fd, event, get_now_plus(timeout)); + event->ev = add_event(mf, &poll_loop->fd_events, fd, event, get_now_plus(timeout)); DEBUG_SCHED( "scheduled read/write at fd %d\n", fd); return GETDNS_RETURN_GOOD; @@ -152,8 +152,7 @@ poll_eventloop_schedule(getdns_eventloop *loop, } for (i = poll_loop->timeout_id + 1; i != poll_loop->timeout_id; i++) { if (find_event(&poll_loop->timeout_events, i) == NULL) { - event->ev = (void *) (intptr_t) (i + 1); - add_event(mf, &poll_loop->timeout_events, i, event, get_now_plus(timeout)); + event->ev = add_event(mf, &poll_loop->timeout_events, i, event, get_now_plus(timeout)); DEBUG_SCHED( "scheduled timeout at slot %d\n", (int)i); return GETDNS_RETURN_GOOD; @@ -168,46 +167,20 @@ poll_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) { _getdns_poll_eventloop *poll_loop = (_getdns_poll_eventloop *)loop; struct mem_funcs *mf = &poll_loop->mf; - ssize_t i; if (!loop || !event) return GETDNS_RETURN_INVALID_PARAMETER; DEBUG_SCHED( "%s(loop: %p, event: %p)\n", __FUNC__, (void *)loop, (void *)event); - i = (intptr_t)event->ev - 1; - if (i < 0 -#ifdef HAVE_GETRLIMIT - || i > poll_loop->max_fds -#endif - ) { - return GETDNS_RETURN_GENERIC_ERROR; - } - if (event->timeout_cb && !event->read_cb && !event->write_cb) { - _getdns_eventloop_info* timeout_event = find_event(&poll_loop->timeout_events, i); -#if defined(SCHED_DEBUG) && SCHED_DEBUG - if (timeout_event && timeout_event->event != event) - DEBUG_SCHED( "ERROR: Different/wrong event present at " - "timeout slot: %p!\n" - , (void *)timeout_event); + assert(event->ev); -#endif - if (timeout_event) { - delete_event(mf, &poll_loop->timeout_events, timeout_event); - } - } else { - _getdns_eventloop_info* fd_event = find_event(&poll_loop->fd_events, i); -#if defined(SCHED_DEBUG) && SCHED_DEBUG - if (fd_event && fd_event->event != event) - DEBUG_SCHED( "ERROR: Different/wrong event present at " - "fd slot: %p!\n" - , (void *)fd_event); -#endif - if (fd_event) { - delete_event(mf, &poll_loop->fd_events, fd_event); - } - } + delete_event(mf, + ( event->timeout_cb && !event->read_cb && !event->write_cb + ? &poll_loop->timeout_events : &poll_loop->fd_events + ), event->ev); event->ev = NULL; + return GETDNS_RETURN_GOOD; } @@ -287,7 +260,7 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) HASH_ITER(hh, poll_loop->timeout_events, s, tmp) { if (now > s->timeout_time) - add_event(mf, &timeout_timeout_cbs, s->id, s->event, s->timeout_time); + (void) add_event(mf, &timeout_timeout_cbs, s->id, s->event, s->timeout_time); else if (s->timeout_time < timeout) timeout = s->timeout_time; } @@ -371,7 +344,7 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) if (s->event && s->event->timeout_cb && now > s->timeout_time) - add_event(mf, &fd_timeout_cbs, s->id, s->event, s->timeout_time); + (void) add_event(mf, &fd_timeout_cbs, s->id, s->event, s->timeout_time); } /* this is in case the timeout callback deletes the event and thus messes with the iteration */ @@ -385,7 +358,7 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) if (s->event && s->event->timeout_cb && now > s->timeout_time) - add_event(mf, &timeout_timeout_cbs, s->id, s->event, s->timeout_time); + (void) add_event(mf, &timeout_timeout_cbs, s->id, s->event, s->timeout_time); } /* this is in case the timeout callback deletes the event and thus messes with the iteration */ From 445470d831c125a9fb8af52eeffd9d760fc0862c Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Thu, 16 Feb 2017 10:32:17 +0100 Subject: [PATCH 29/56] Rename a gldns function --- src/context.c | 4 ++-- src/convert.c | 8 ++++---- src/dict.c | 8 ++++---- src/gldns/gbuffer.c | 2 +- src/gldns/gbuffer.h | 10 ++++++---- src/request-internal.c | 2 +- src/util-internal.c | 4 ++-- 7 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/context.c b/src/context.c index 88eb0e4d..14c78a09 100644 --- a/src/context.c +++ b/src/context.c @@ -1354,7 +1354,7 @@ getdns_context_create_with_extended_memory_functions( result->suffixes = no_suffixes; result->suffixes_len = sizeof(no_suffixes); - gldns_buffer_init_frm_data_v(&gbuf, result->trust_anchors_spc + gldns_buffer_init_vfixed_frm_data(&gbuf, result->trust_anchors_spc , sizeof(result->trust_anchors_spc)); if (!_getdns_parse_ta_file(NULL, &gbuf)) { @@ -2333,7 +2333,7 @@ getdns_context_set_suffix(getdns_context *context, getdns_list *value) context->suffixes_len = sizeof(no_suffixes); return GETDNS_RETURN_GOOD; } - gldns_buffer_init_frm_data_v(&gbuf, buf_spc, sizeof(buf_spc)); + gldns_buffer_init_vfixed_frm_data(&gbuf, buf_spc, sizeof(buf_spc)); for (;;) { for ( i = 0 ; !(r = getdns_list_get_bindata(value, i, &bindata)) diff --git a/src/convert.c b/src/convert.c index df2ff0e5..11919107 100644 --- a/src/convert.c +++ b/src/convert.c @@ -297,7 +297,7 @@ getdns_rr_dict2wire_scan( return GETDNS_RETURN_INVALID_PARAMETER; - gldns_buffer_init_frm_data_v(&gbuf, *wire, *wire_sz); + gldns_buffer_init_vfixed_frm_data(&gbuf, *wire, *wire_sz); if ((r = _getdns_rr_dict2wire(rr_dict, &gbuf))) return r; @@ -447,7 +447,7 @@ getdns_rr_dict2str_scan( if (!rr_dict || !str || !*str || !str_len) return GETDNS_RETURN_INVALID_PARAMETER; - gldns_buffer_init_frm_data_v(&gbuf, buf, sizeof(buf_spc)); + gldns_buffer_init_vfixed_frm_data(&gbuf, buf, sizeof(buf_spc)); r = _getdns_rr_dict2wire(rr_dict, &gbuf); if (gldns_buffer_position(&gbuf) > sizeof(buf_spc)) { if (!(buf = GETDNS_XMALLOC( @@ -960,7 +960,7 @@ getdns_msg_dict2wire_scan( if (!msg_dict || !wire || !wire_sz || (!*wire && *wire_sz)) return GETDNS_RETURN_INVALID_PARAMETER; - gldns_buffer_init_frm_data_v(&gbuf, *wire, *wire_sz); + gldns_buffer_init_vfixed_frm_data(&gbuf, *wire, *wire_sz); if ((r = _getdns_msg_dict2wire_buf(msg_dict, &gbuf))) return r; @@ -1036,7 +1036,7 @@ getdns_msg_dict2str_scan( if (!msg_dict || !str || !*str || !str_len) return GETDNS_RETURN_INVALID_PARAMETER; - gldns_buffer_init_frm_data_v(&gbuf, buf, sizeof(buf_spc)); + gldns_buffer_init_vfixed_frm_data(&gbuf, buf, sizeof(buf_spc)); r = _getdns_msg_dict2wire_buf(msg_dict, &gbuf); if (gldns_buffer_position(&gbuf) > sizeof(buf_spc)) { if (!(buf = GETDNS_XMALLOC( diff --git a/src/dict.c b/src/dict.c index 70fa3836..23b42531 100644 --- a/src/dict.c +++ b/src/dict.c @@ -1186,7 +1186,7 @@ getdns_pretty_snprint_dict(char *str, size_t size, const getdns_dict *dict) if (!dict) return -1; - gldns_buffer_init_frm_data_v(&buf, str, size); + gldns_buffer_init_vfixed_frm_data(&buf, str, size); return getdns_pp_dict(&buf, 0, dict, 0) < 0 ? -1 : (int)gldns_buffer_position(&buf); } @@ -1220,7 +1220,7 @@ getdns_pretty_snprint_list(char *str, size_t size, const getdns_list *list) if (!list) return -1; - gldns_buffer_init_frm_data_v(&buf, str, size); + gldns_buffer_init_vfixed_frm_data(&buf, str, size); return getdns_pp_list(&buf, 0, list, 0, 0) < 0 ? -1 : (int)gldns_buffer_position(&buf); } @@ -1255,7 +1255,7 @@ getdns_snprint_json_dict( if (!dict) return -1; - gldns_buffer_init_frm_data_v(&buf, str, size); + gldns_buffer_init_vfixed_frm_data(&buf, str, size); return getdns_pp_dict(&buf, 0, dict, pretty ? 1 : 2) < 0 ? -1 : (int)gldns_buffer_position(&buf); } @@ -1290,7 +1290,7 @@ getdns_snprint_json_list( if (!list) return -1; - gldns_buffer_init_frm_data_v(&buf, str, size); + gldns_buffer_init_vfixed_frm_data(&buf, str, size); return getdns_pp_list(&buf, 0, list, 0, pretty ? 1 : 2) < 0 ? -1 : (int)gldns_buffer_position(&buf); } diff --git a/src/gldns/gbuffer.c b/src/gldns/gbuffer.c index 77398905..04c257fb 100644 --- a/src/gldns/gbuffer.c +++ b/src/gldns/gbuffer.c @@ -72,7 +72,7 @@ gldns_buffer_init_frm_data(gldns_buffer *buffer, void *data, size_t size) } void -gldns_buffer_init_frm_data_v(gldns_buffer *buffer, void *data, size_t size) +gldns_buffer_init_vfixed_frm_data(gldns_buffer *buffer, void *data, size_t size) { memset(buffer, 0, sizeof(*buffer)); buffer->_data = data; diff --git a/src/gldns/gbuffer.h b/src/gldns/gbuffer.h index 15dca675..1b1eb498 100644 --- a/src/gldns/gbuffer.h +++ b/src/gldns/gbuffer.h @@ -194,14 +194,16 @@ void gldns_buffer_init_frm_data(gldns_buffer *buffer, void *data, size_t size); /** * Setup a buffer with the data pointed to. No data copied, no memory allocs. - * The buffer is fixed. Writes beyond size (the capacity) will update the - * position (and not write data). This allows to determine how big the buffer - * should have been to contain all the written data. + * The buffer is "virtually" fixed. Writes beyond size (the capacity) will + * only update position, but no data will be written beyond capacity. This + * allows to determine how big the buffer should have been to contain all the + * written data, by looking at the position with gldns_buffer_position(), + * similarly to the return value of POSIX's snprintf. * \param[in] buffer pointer to the buffer to put the data in * \param[in] data the data to encapsulate in the buffer * \param[in] size the size of the data */ -void gldns_buffer_init_frm_data_v(gldns_buffer *buffer, void *data, size_t size); +void gldns_buffer_init_vfixed_frm_data(gldns_buffer *buffer, void *data, size_t size); /** * clears the buffer and make it ready for writing. The buffer's limit diff --git a/src/request-internal.c b/src/request-internal.c index 7b8af65a..8193acb7 100644 --- a/src/request-internal.c +++ b/src/request-internal.c @@ -383,7 +383,7 @@ _getdns_network_req_add_tsig(getdns_network_req *req) #endif tsig_info = _getdns_get_tsig_info(upstream->tsig_alg); - gldns_buffer_init_frm_data_v(&gbuf, req->response, MAXIMUM_TSIG_SPACE); + gldns_buffer_init_vfixed_frm_data(&gbuf, req->response, MAXIMUM_TSIG_SPACE); gldns_buffer_write(&gbuf, upstream->tsig_dname, upstream->tsig_dname_len); /* Name */ gldns_buffer_write_u16(&gbuf, GETDNS_RRCLASS_ANY); /* Class */ diff --git a/src/util-internal.c b/src/util-internal.c index 2bbad80d..fe05cd83 100644 --- a/src/util-internal.c +++ b/src/util-internal.c @@ -1510,7 +1510,7 @@ uint8_t *_getdns_list2wire( gldns_buffer gbuf; size_t sz; - gldns_buffer_init_frm_data_v(&gbuf, buf, *buf_len); + gldns_buffer_init_vfixed_frm_data(&gbuf, buf, *buf_len); _getdns_list2wire_buf(&gbuf, l); if ((sz = gldns_buffer_position(&gbuf)) <= *buf_len) { @@ -1531,7 +1531,7 @@ uint8_t *_getdns_reply2wire( gldns_buffer gbuf; size_t sz; - gldns_buffer_init_frm_data_v(&gbuf, buf, *buf_len); + gldns_buffer_init_vfixed_frm_data(&gbuf, buf, *buf_len); _getdns_reply2wire_buf(&gbuf, r); if ((sz = gldns_buffer_position(&gbuf)) <= *buf_len) { From e87e907128c480196c89a4aa3317360b9e1e0e6e Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Thu, 16 Feb 2017 11:01:48 +0100 Subject: [PATCH 30/56] Constants for Edward Curves --- src/gldns/rrdef.h | 2 ++ src/gldns/wire2str.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/gldns/rrdef.h b/src/gldns/rrdef.h index f00fa33c..58132c23 100644 --- a/src/gldns/rrdef.h +++ b/src/gldns/rrdef.h @@ -372,6 +372,8 @@ enum gldns_enum_algorithm GLDNS_ECC_GOST = 12, /* RFC 5933 */ GLDNS_ECDSAP256SHA256 = 13, /* RFC 6605 */ GLDNS_ECDSAP384SHA384 = 14, /* RFC 6605 */ + GLDNS_ED25519 = 15, /* RFC 8080 */ + GLDNS_ED448 = 16, /* RFC 8080 */ GLDNS_INDIRECT = 252, GLDNS_PRIVATEDNS = 253, GLDNS_PRIVATEOID = 254 diff --git a/src/gldns/wire2str.c b/src/gldns/wire2str.c index 2d427d86..35a6df9d 100644 --- a/src/gldns/wire2str.c +++ b/src/gldns/wire2str.c @@ -47,6 +47,8 @@ static gldns_lookup_table gldns_algorithms_data[] = { { GLDNS_ECC_GOST, "ECC-GOST"}, { GLDNS_ECDSAP256SHA256, "ECDSAP256SHA256"}, { GLDNS_ECDSAP384SHA384, "ECDSAP384SHA384"}, + { GLDNS_ED25519, "ED25519"}, + { GLDNS_ED448, "ED448"}, { GLDNS_INDIRECT, "INDIRECT" }, { GLDNS_PRIVATEDNS, "PRIVATEDNS" }, { GLDNS_PRIVATEOID, "PRIVATEOID" }, From 2d35993c836fc776845d48343f6af86e634eaa95 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Thu, 16 Feb 2017 15:22:57 +0100 Subject: [PATCH 31/56] Timeout events in array --- src/extension/poll_eventloop.c | 150 +++++++++++++++++++++++---------- src/extension/poll_eventloop.h | 11 ++- 2 files changed, 114 insertions(+), 47 deletions(-) diff --git a/src/extension/poll_eventloop.c b/src/extension/poll_eventloop.c index 2f40c30a..a88fb231 100644 --- a/src/extension/poll_eventloop.c +++ b/src/extension/poll_eventloop.c @@ -38,6 +38,44 @@ #include "extension/poll_eventloop.h" #include "debug.h" +enum { init_pfds_capacity = 64 + , init_to_events_capacity = 64 }; + +static void *get_to_event(_getdns_poll_eventloop *loop, + getdns_eventloop_event *event, uint64_t timeout_time) +{ + unsigned long i = 0; + + while (i < loop->to_events_capacity && loop->to_events[i].event) i++; + + if (i == loop->to_events_capacity) { + if (i) { + _getdns_poll_to_event *to_events = GETDNS_XREALLOC( + loop->mf, loop->to_events, _getdns_poll_to_event, i * 2); + if (!to_events) + return NULL; + (void) memset(&loop->to_events[i], 0, + sizeof(_getdns_poll_to_event) * i); + + loop->to_events_capacity = i * 2; + loop->to_events = to_events; + } else { + if (!(loop->to_events = GETDNS_XMALLOC(loop->mf, + _getdns_poll_to_event, init_to_events_capacity))) + return NULL; + + (void) memset(loop->to_events, 0, + sizeof(_getdns_poll_to_event) + * init_to_events_capacity); + + loop->to_events_capacity = init_to_events_capacity; + } + } + loop->to_events[i].event = event; + loop->to_events[i].timeout_time = timeout_time; + return (void *) (intptr_t) (i + 1); +} + static _getdns_eventloop_info * find_event(_getdns_eventloop_info** events, int id) { @@ -93,7 +131,6 @@ poll_eventloop_schedule(getdns_eventloop *loop, { _getdns_poll_eventloop *poll_loop = (_getdns_poll_eventloop *)loop; struct mem_funcs *mf = &poll_loop->mf; - size_t i; DEBUG_SCHED( "%s(loop: %p, fd: %d, timeout: %"PRIu64", event: %p, max_fds: %d)\n" , __FUNC__, (void *)loop, fd, timeout, (void *)event, poll_loop->max_fds); @@ -150,13 +187,9 @@ poll_eventloop_schedule(getdns_eventloop *loop, DEBUG_SCHED("ERROR: timeout event with write_cb! Clearing.\n"); event->write_cb = NULL; } - for (i = poll_loop->timeout_id + 1; i != poll_loop->timeout_id; i++) { - if (find_event(&poll_loop->timeout_events, i) == NULL) { - event->ev = add_event(mf, &poll_loop->timeout_events, i, event, get_now_plus(timeout)); - - DEBUG_SCHED( "scheduled timeout at slot %d\n", (int)i); - return GETDNS_RETURN_GOOD; - } + if ((event->ev = get_to_event(poll_loop, event, get_now_plus(timeout)))) { + DEBUG_SCHED("scheduled timeout at slot %p\n", event->ev); + return GETDNS_RETURN_GOOD; } DEBUG_SCHED("ERROR: Out of timeout slots!\n"); return GETDNS_RETURN_GENERIC_ERROR; @@ -175,12 +208,29 @@ poll_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) assert(event->ev); - delete_event(mf, - ( event->timeout_cb && !event->read_cb && !event->write_cb - ? &poll_loop->timeout_events : &poll_loop->fd_events - ), event->ev); - event->ev = NULL; + if (event->timeout_cb && !event->read_cb && !event->write_cb) { + unsigned long i = ((unsigned long) (intptr_t) event->ev) - 1; + /* This may happen with full recursive synchronous requests + * with the unbound pluggable event API, because the default + * poll_eventloop is temporarily replaced by a poll_eventloop + * used only in synchronous calls. When the synchronous request + * had an answer, the poll_eventloop for the synchronous is + * cleaned, however it could still have outstanding events. + */ + if (i >= poll_loop->to_events_capacity || + poll_loop->to_events[i].event != event) { + event->ev = NULL; + DEBUG_SCHED( "ERROR: Event mismatch %p\n", (void *)event->ev); + return GETDNS_RETURN_GENERIC_ERROR; + } + + poll_loop->to_events[i].event = NULL; + DEBUG_SCHED( "cleared timeout at slot %p\n", event->ev); + } else + delete_event(mf, &poll_loop->fd_events, event->ev); + + event->ev = NULL; return GETDNS_RETURN_GOOD; } @@ -195,8 +245,12 @@ poll_eventloop_cleanup(getdns_eventloop *loop) poll_loop->pfds = NULL; poll_loop->pfds_capacity = 0; } + if (poll_loop->to_events) { + GETDNS_FREE(*mf, poll_loop->to_events); + poll_loop->to_events = NULL; + poll_loop->to_events_capacity = 0; + } HASH_CLEAR(hh, poll_loop->fd_events); - HASH_CLEAR(hh, poll_loop->timeout_events); } static void @@ -247,10 +301,9 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) struct mem_funcs *mf = &poll_loop->mf; _getdns_eventloop_info *s, *tmp; uint64_t now, timeout = TIMEOUT_FOREVER; - size_t i=0; + size_t i = 0; int poll_timeout = 0; unsigned int num_pfds = 0; - _getdns_eventloop_info* timeout_timeout_cbs = NULL; _getdns_eventloop_info* fd_timeout_cbs = NULL; if (!loop) @@ -258,18 +311,15 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) now = get_now_plus(0); - HASH_ITER(hh, poll_loop->timeout_events, s, tmp) { - if (now > s->timeout_time) - (void) add_event(mf, &timeout_timeout_cbs, s->id, s->event, s->timeout_time); - else if (s->timeout_time < timeout) - timeout = s->timeout_time; + for (i = 0; i < poll_loop->to_events_capacity; i++) { + if (poll_loop->to_events[i].event && + poll_loop->to_events[i].timeout_time < now) + poll_timeout_cb(-1, poll_loop->to_events[i].event); } - /* this is in case the timeout callback deletes the event - and thus messes with the iteration */ - HASH_ITER(hh, timeout_timeout_cbs, s, tmp) { - getdns_eventloop_event* event = s->event; - delete_event(mf, &timeout_timeout_cbs, s); - poll_timeout_cb(-1, event); + for (i = 0; i < poll_loop->to_events_capacity; i++) { + if (poll_loop->to_events[i].event && + poll_loop->to_events[i].timeout_time < timeout) + timeout = poll_loop->to_events[i].timeout_time; } /* first we count the number of fds that will be active */ HASH_ITER(hh, poll_loop->fd_events, s, tmp) { @@ -354,20 +404,22 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) delete_event(mf, &fd_timeout_cbs, s); poll_timeout_cb(fd, event); } - HASH_ITER(hh, poll_loop->timeout_events, s, tmp) { - if (s->event && - s->event->timeout_cb && - now > s->timeout_time) - (void) add_event(mf, &timeout_timeout_cbs, s->id, s->event, s->timeout_time); - } - /* this is in case the timeout callback deletes the event - and thus messes with the iteration */ - HASH_ITER(hh, timeout_timeout_cbs, s, tmp) { - getdns_eventloop_event* event = s->event; - delete_event(mf, &timeout_timeout_cbs, s); - poll_timeout_cb(-1, event); + for (i = 0; i < poll_loop->to_events_capacity; i++) { + if (poll_loop->to_events[i].event && + poll_loop->to_events[i].timeout_time < now) + poll_timeout_cb(-1, poll_loop->to_events[i].event); } +} +static unsigned long to_events_used(_getdns_poll_eventloop *loop) +{ + unsigned int i, count = 0; + + for (i = 0; i < loop->to_events_capacity; i++) { + if (loop->to_events[i].event) + count++; + } + return count; } static void @@ -379,7 +431,7 @@ poll_eventloop_run(getdns_eventloop *loop) return; /* keep going until all the events are cleared */ - while (poll_loop->fd_events || poll_loop->timeout_events) { + while (poll_loop->fd_events || to_events_used(poll_loop)) { poll_eventloop_run_once(loop, 1); } } @@ -411,9 +463,19 @@ _getdns_poll_eventloop_init(struct mem_funcs *mf, _getdns_poll_eventloop *loop) #if HAVE_GETRLIMIT } #endif - loop->timeout_id = 0; - loop->pfds = NULL; - loop->pfds_capacity = 0; + loop->pfds_capacity = init_pfds_capacity; + if (!(loop->pfds = GETDNS_XMALLOC( + *mf, struct pollfd, init_pfds_capacity))) + loop->pfds_capacity = 0; + loop->fd_events = NULL; - loop->timeout_events = NULL; + loop->to_events_capacity = init_to_events_capacity; + if ((loop->to_events = GETDNS_XMALLOC( + *mf, _getdns_poll_to_event, init_to_events_capacity))) + (void) memset(loop->to_events, 0, + sizeof(_getdns_poll_to_event) * init_to_events_capacity); + else + loop->to_events_capacity = 0; + } + diff --git a/src/extension/poll_eventloop.h b/src/extension/poll_eventloop.h index 8c742e20..8481b743 100644 --- a/src/extension/poll_eventloop.h +++ b/src/extension/poll_eventloop.h @@ -49,15 +49,20 @@ typedef struct _getdns_eventloop_info { UT_hash_handle hh; } _getdns_eventloop_info; +typedef struct _getdns_poll_to_event { + getdns_eventloop_event *event; + uint64_t timeout_time; +} _getdns_poll_to_event; + typedef struct _getdns_poll_eventloop { getdns_eventloop loop; struct mem_funcs mf; unsigned int max_fds; - unsigned int timeout_id; - struct pollfd *pfds; unsigned long pfds_capacity; + struct pollfd *pfds; _getdns_eventloop_info *fd_events; - _getdns_eventloop_info *timeout_events; + unsigned long to_events_capacity; + _getdns_poll_to_event *to_events; } _getdns_poll_eventloop; void From f6d46689b653be0da02b1da5defcb76f9f8d3cc2 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Thu, 16 Feb 2017 16:26:41 +0100 Subject: [PATCH 32/56] Fixed time allocation and free for to_events --- src/extension/poll_eventloop.c | 115 +++++++++++++++++++++------------ src/extension/poll_eventloop.h | 5 +- 2 files changed, 78 insertions(+), 42 deletions(-) diff --git a/src/extension/poll_eventloop.c b/src/extension/poll_eventloop.c index a88fb231..12319849 100644 --- a/src/extension/poll_eventloop.c +++ b/src/extension/poll_eventloop.c @@ -44,20 +44,18 @@ enum { init_pfds_capacity = 64 static void *get_to_event(_getdns_poll_eventloop *loop, getdns_eventloop_event *event, uint64_t timeout_time) { - unsigned long i = 0; - - while (i < loop->to_events_capacity && loop->to_events[i].event) i++; - - if (i == loop->to_events_capacity) { - if (i) { + if (loop->to_events_free == loop->to_events_capacity) { + if (loop->to_events_free) { _getdns_poll_to_event *to_events = GETDNS_XREALLOC( - loop->mf, loop->to_events, _getdns_poll_to_event, i * 2); + loop->mf, loop->to_events, _getdns_poll_to_event, + loop->to_events_free * 2); if (!to_events) return NULL; - (void) memset(&loop->to_events[i], 0, - sizeof(_getdns_poll_to_event) * i); + (void) memset(&loop->to_events[loop->to_events_free], + 0, sizeof(_getdns_poll_to_event) + * loop->to_events_free); - loop->to_events_capacity = i * 2; + loop->to_events_capacity = loop->to_events_free * 2; loop->to_events = to_events; } else { if (!(loop->to_events = GETDNS_XMALLOC(loop->mf, @@ -71,9 +69,10 @@ static void *get_to_event(_getdns_poll_eventloop *loop, loop->to_events_capacity = init_to_events_capacity; } } - loop->to_events[i].event = event; - loop->to_events[i].timeout_time = timeout_time; - return (void *) (intptr_t) (i + 1); + loop->to_events[loop->to_events_free].event = event; + loop->to_events[loop->to_events_free].timeout_time = timeout_time; + loop->to_events_n_used++; + return (void *) (intptr_t) (++loop->to_events_free); } static _getdns_eventloop_info * @@ -209,7 +208,7 @@ poll_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) assert(event->ev); if (event->timeout_cb && !event->read_cb && !event->write_cb) { - unsigned long i = ((unsigned long) (intptr_t) event->ev) - 1; + size_t i = ((size_t) (intptr_t) event->ev) - 1; /* This may happen with full recursive synchronous requests * with the unbound pluggable event API, because the default @@ -224,8 +223,10 @@ poll_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) DEBUG_SCHED( "ERROR: Event mismatch %p\n", (void *)event->ev); return GETDNS_RETURN_GENERIC_ERROR; } - poll_loop->to_events[i].event = NULL; + if (--poll_loop->to_events_n_used == 0) { + poll_loop->to_events_free = 0; + } DEBUG_SCHED( "cleared timeout at slot %p\n", event->ev); } else delete_event(mf, &poll_loop->fd_events, event->ev); @@ -249,6 +250,8 @@ poll_eventloop_cleanup(getdns_eventloop *loop) GETDNS_FREE(*mf, poll_loop->to_events); poll_loop->to_events = NULL; poll_loop->to_events_capacity = 0; + poll_loop->to_events_free = 0; + poll_loop->to_events_n_used = 0; } HASH_CLEAR(hh, poll_loop->fd_events); } @@ -301,7 +304,7 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) struct mem_funcs *mf = &poll_loop->mf; _getdns_eventloop_info *s, *tmp; uint64_t now, timeout = TIMEOUT_FOREVER; - size_t i = 0; + size_t i = 0, j; int poll_timeout = 0; unsigned int num_pfds = 0; _getdns_eventloop_info* fd_timeout_cbs = NULL; @@ -311,15 +314,41 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) now = get_now_plus(0); - for (i = 0; i < poll_loop->to_events_capacity; i++) { - if (poll_loop->to_events[i].event && - poll_loop->to_events[i].timeout_time < now) - poll_timeout_cb(-1, poll_loop->to_events[i].event); + for (i = 0, j = 0; i < poll_loop->to_events_free; i++, j++) { + while (poll_loop->to_events[i].event == NULL) { + if (++i == poll_loop->to_events_free) { + poll_loop->to_events_free = j; + break; + } + } + if (j < i) { + if (j >= poll_loop->to_events_free) + break; + poll_loop->to_events[j] = poll_loop->to_events[i]; + poll_loop->to_events[i].event = NULL; + poll_loop->to_events[j].event->ev = + (void *) (intptr_t) (j + 1); + } + if (poll_loop->to_events[j].timeout_time < now) + poll_timeout_cb(-1, poll_loop->to_events[j].event); } - for (i = 0; i < poll_loop->to_events_capacity; i++) { - if (poll_loop->to_events[i].event && - poll_loop->to_events[i].timeout_time < timeout) - timeout = poll_loop->to_events[i].timeout_time; + for (i = 0, j = 0; i < poll_loop->to_events_free; i++, j++) { + while (poll_loop->to_events[i].event == NULL) { + if (++i == poll_loop->to_events_free) { + poll_loop->to_events_free = j; + break; + } + } + if (j < i) { + if (j >= poll_loop->to_events_free) + break; + poll_loop->to_events[j] = poll_loop->to_events[i]; + poll_loop->to_events[i].event = NULL; + poll_loop->to_events[j].event->ev = + (void *) (intptr_t) (j + 1); + } + if (poll_loop->to_events[j].timeout_time < timeout) + timeout = poll_loop->to_events[j].timeout_time; } /* first we count the number of fds that will be active */ HASH_ITER(hh, poll_loop->fd_events, s, tmp) { @@ -404,24 +433,26 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) delete_event(mf, &fd_timeout_cbs, s); poll_timeout_cb(fd, event); } - for (i = 0; i < poll_loop->to_events_capacity; i++) { - if (poll_loop->to_events[i].event && - poll_loop->to_events[i].timeout_time < now) - poll_timeout_cb(-1, poll_loop->to_events[i].event); + for (i = 0, j = 0; i < poll_loop->to_events_free; i++, j++) { + while (poll_loop->to_events[i].event == NULL) { + if (++i == poll_loop->to_events_free) { + poll_loop->to_events_free = j; + break; + } + } + if (j < i) { + if (j >= poll_loop->to_events_free) + break; + poll_loop->to_events[j] = poll_loop->to_events[i]; + poll_loop->to_events[i].event = NULL; + poll_loop->to_events[j].event->ev = + (void *) (intptr_t) (j + 1); + } + if (poll_loop->to_events[j].timeout_time < now) + poll_timeout_cb(-1, poll_loop->to_events[j].event); } } -static unsigned long to_events_used(_getdns_poll_eventloop *loop) -{ - unsigned int i, count = 0; - - for (i = 0; i < loop->to_events_capacity; i++) { - if (loop->to_events[i].event) - count++; - } - return count; -} - static void poll_eventloop_run(getdns_eventloop *loop) { @@ -431,7 +462,7 @@ poll_eventloop_run(getdns_eventloop *loop) return; /* keep going until all the events are cleared */ - while (poll_loop->fd_events || to_events_used(poll_loop)) { + while (poll_loop->fd_events || poll_loop->to_events_n_used) { poll_eventloop_run_once(loop, 1); } } @@ -469,6 +500,7 @@ _getdns_poll_eventloop_init(struct mem_funcs *mf, _getdns_poll_eventloop *loop) loop->pfds_capacity = 0; loop->fd_events = NULL; + loop->to_events_capacity = init_to_events_capacity; if ((loop->to_events = GETDNS_XMALLOC( *mf, _getdns_poll_to_event, init_to_events_capacity))) @@ -476,6 +508,7 @@ _getdns_poll_eventloop_init(struct mem_funcs *mf, _getdns_poll_eventloop *loop) sizeof(_getdns_poll_to_event) * init_to_events_capacity); else loop->to_events_capacity = 0; - + loop->to_events_free = 0; + loop->to_events_n_used = 0; } diff --git a/src/extension/poll_eventloop.h b/src/extension/poll_eventloop.h index 8481b743..51118b24 100644 --- a/src/extension/poll_eventloop.h +++ b/src/extension/poll_eventloop.h @@ -61,8 +61,11 @@ typedef struct _getdns_poll_eventloop { unsigned long pfds_capacity; struct pollfd *pfds; _getdns_eventloop_info *fd_events; - unsigned long to_events_capacity; + + size_t to_events_capacity; _getdns_poll_to_event *to_events; + size_t to_events_free; + size_t to_events_n_used; } _getdns_poll_eventloop; void From d20bbde25eb2b3e08145eef2ebf1864e704de8e7 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Thu, 16 Feb 2017 22:41:37 +0100 Subject: [PATCH 33/56] Fixed time allocation and free for fd_events --- src/extension/poll_eventloop.c | 364 ++++++----- src/extension/poll_eventloop.h | 38 +- src/util/uthash.h | 1074 -------------------------------- 3 files changed, 214 insertions(+), 1262 deletions(-) delete mode 100644 src/util/uthash.h diff --git a/src/extension/poll_eventloop.c b/src/extension/poll_eventloop.c index 12319849..c55c8ec9 100644 --- a/src/extension/poll_eventloop.c +++ b/src/extension/poll_eventloop.c @@ -38,7 +38,7 @@ #include "extension/poll_eventloop.h" #include "debug.h" -enum { init_pfds_capacity = 64 +enum { init_fd_events_capacity = 64 , init_to_events_capacity = 64 }; static void *get_to_event(_getdns_poll_eventloop *loop, @@ -46,24 +46,24 @@ static void *get_to_event(_getdns_poll_eventloop *loop, { if (loop->to_events_free == loop->to_events_capacity) { if (loop->to_events_free) { - _getdns_poll_to_event *to_events = GETDNS_XREALLOC( - loop->mf, loop->to_events, _getdns_poll_to_event, + _getdns_poll_event *to_events = GETDNS_XREALLOC( + loop->mf, loop->to_events, _getdns_poll_event, loop->to_events_free * 2); if (!to_events) return NULL; (void) memset(&loop->to_events[loop->to_events_free], - 0, sizeof(_getdns_poll_to_event) + 0, sizeof(_getdns_poll_event) * loop->to_events_free); loop->to_events_capacity = loop->to_events_free * 2; loop->to_events = to_events; } else { if (!(loop->to_events = GETDNS_XMALLOC(loop->mf, - _getdns_poll_to_event, init_to_events_capacity))) + _getdns_poll_event, init_to_events_capacity))) return NULL; (void) memset(loop->to_events, 0, - sizeof(_getdns_poll_to_event) + sizeof(_getdns_poll_event) * init_to_events_capacity); loop->to_events_capacity = init_to_events_capacity; @@ -75,38 +75,61 @@ static void *get_to_event(_getdns_poll_eventloop *loop, return (void *) (intptr_t) (++loop->to_events_free); } -static _getdns_eventloop_info * -find_event(_getdns_eventloop_info** events, int id) +static void *get_fd_event(_getdns_poll_eventloop *loop, int fd, + getdns_eventloop_event *event, uint64_t timeout_time) { - _getdns_eventloop_info* ev; + if (loop->fd_events_free == loop->fd_events_capacity) { + if (loop->fd_events_free) { + _getdns_poll_event *fd_events = GETDNS_XREALLOC( + loop->mf, loop->fd_events, _getdns_poll_event, + loop->fd_events_free * 2); + struct pollfd *pfds = GETDNS_XREALLOC( + loop->mf, loop->pfds, struct pollfd, + loop->fd_events_free * 2); - HASH_FIND_INT(*events, &id, ev); + if (!fd_events || !pfds) { + if (fd_events) + GETDNS_FREE(loop->mf, fd_events); + if (pfds) + GETDNS_FREE(loop->mf, pfds); + return NULL; + } + (void) memset(&loop->fd_events[loop->fd_events_free], + 0, sizeof(_getdns_poll_event) + * loop->fd_events_free); + (void) memset(&loop->pfds[loop->fd_events_free], + 0, sizeof(struct pollfd) * loop->fd_events_free); - return ev; -} + loop->fd_events_capacity = loop->fd_events_free * 2; + loop->fd_events = fd_events; + loop->pfds = pfds; + } else { + if (!(loop->fd_events = GETDNS_XMALLOC(loop->mf, + _getdns_poll_event, init_fd_events_capacity)) || + !(loop->pfds = GETDNS_XMALLOC(loop->mf, + struct pollfd, init_fd_events_capacity))) { + GETDNS_NULL_FREE(loop->mf, loop->fd_events); + return NULL; + } + (void) memset(loop->fd_events, 0, + sizeof(_getdns_poll_event) + * init_fd_events_capacity); + (void) memset(loop->pfds, 0, + sizeof(struct pollfd) * init_fd_events_capacity); -static _getdns_eventloop_info * -add_event(struct mem_funcs *mf, _getdns_eventloop_info** events, - int id, getdns_eventloop_event *event, uint64_t timeout_time) -{ - DEBUG_SCHED("poll_eventloop: add_event with id %d\n", id); - _getdns_eventloop_info* myevent = GETDNS_MALLOC(*mf, _getdns_eventloop_info); - /* not necessary -- (void) memset(myevent, 0, sizeof(_getdns_eventloop_info)); */ - - myevent->id = id; - myevent->event = event; - myevent->timeout_time = timeout_time; - HASH_ADD_INT(*events, id, myevent); - return myevent; -} - -static void -delete_event(struct mem_funcs *mf, - _getdns_eventloop_info** events, _getdns_eventloop_info* ev) -{ - DEBUG_SCHED("poll_eventloop: delete_event with id %d\n", ev->id); - HASH_DEL(*events, ev); - GETDNS_FREE(*mf, ev); + loop->fd_events_capacity = init_fd_events_capacity; + } + } + loop->pfds[loop->fd_events_free].fd = fd; + loop->pfds[loop->fd_events_free].events = 0; + if (event->read_cb) + loop->pfds[loop->fd_events_free].events |= POLLIN; + if (event->write_cb) + loop->pfds[loop->fd_events_free].events |= POLLOUT; + loop->fd_events[loop->fd_events_free].event = event; + loop->fd_events[loop->fd_events_free].timeout_time = timeout_time; + loop->fd_events_n_used++; + return (void *) (intptr_t) (++loop->fd_events_free); } static uint64_t get_now_plus(uint64_t amount) @@ -129,7 +152,6 @@ poll_eventloop_schedule(getdns_eventloop *loop, int fd, uint64_t timeout, getdns_eventloop_event *event) { _getdns_poll_eventloop *poll_loop = (_getdns_poll_eventloop *)loop; - struct mem_funcs *mf = &poll_loop->mf; DEBUG_SCHED( "%s(loop: %p, fd: %d, timeout: %"PRIu64", event: %p, max_fds: %d)\n" , __FUNC__, (void *)loop, fd, timeout, (void *)event, poll_loop->max_fds); @@ -151,27 +173,13 @@ poll_eventloop_schedule(getdns_eventloop *loop, fd = -1; } if (fd >= 0) { - _getdns_eventloop_info* fd_event = find_event(&poll_loop->fd_events, fd); -#if defined(SCHED_DEBUG) && SCHED_DEBUG - if (fd_event) { - if (fd_event->event == event) { - DEBUG_SCHED("WARNING: Event %p not cleared " - "before being rescheduled!\n" - , (void *)fd_event->event); - } else { - DEBUG_SCHED("ERROR: A different event is " - "already present at fd slot: %p!\n" - , (void *)fd_event->event); - } + if (!(event->ev = get_fd_event( + poll_loop, fd, event, get_now_plus(timeout)))) { + DEBUG_SCHED("ERROR: scheduled read/write slots!\n"); + return GETDNS_RETURN_GENERIC_ERROR; } -#endif - /* cleanup the old event if it exists */ - if (fd_event) { - delete_event(mf, &poll_loop->fd_events, fd_event); - } - event->ev = add_event(mf, &poll_loop->fd_events, fd, event, get_now_plus(timeout)); - - DEBUG_SCHED( "scheduled read/write at fd %d\n", fd); + DEBUG_SCHED( "scheduled read/write at for %d at %p\n" + , fd, (void *)event->ev); return GETDNS_RETURN_GOOD; } if (!event->timeout_cb) { @@ -186,28 +194,28 @@ poll_eventloop_schedule(getdns_eventloop *loop, DEBUG_SCHED("ERROR: timeout event with write_cb! Clearing.\n"); event->write_cb = NULL; } - if ((event->ev = get_to_event(poll_loop, event, get_now_plus(timeout)))) { - DEBUG_SCHED("scheduled timeout at slot %p\n", event->ev); - return GETDNS_RETURN_GOOD; + if (!(event->ev = get_to_event(poll_loop, event, get_now_plus(timeout)))) { + DEBUG_SCHED("ERROR: Out of timeout slots!\n"); + return GETDNS_RETURN_GENERIC_ERROR; } - DEBUG_SCHED("ERROR: Out of timeout slots!\n"); - return GETDNS_RETURN_GENERIC_ERROR; + DEBUG_SCHED("scheduled timeout at slot %p\n", (void *)event->ev); + return GETDNS_RETURN_GOOD; } static getdns_return_t poll_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) { _getdns_poll_eventloop *poll_loop = (_getdns_poll_eventloop *)loop; - struct mem_funcs *mf = &poll_loop->mf; if (!loop || !event) return GETDNS_RETURN_INVALID_PARAMETER; DEBUG_SCHED( "%s(loop: %p, event: %p)\n", __FUNC__, (void *)loop, (void *)event); - assert(event->ev); + if (!event->ev) + return GETDNS_RETURN_GOOD; - if (event->timeout_cb && !event->read_cb && !event->write_cb) { + else if (event->timeout_cb && !event->read_cb && !event->write_cb) { size_t i = ((size_t) (intptr_t) event->ev) - 1; /* This may happen with full recursive synchronous requests @@ -227,10 +235,31 @@ poll_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) if (--poll_loop->to_events_n_used == 0) { poll_loop->to_events_free = 0; } - DEBUG_SCHED( "cleared timeout at slot %p\n", event->ev); - } else - delete_event(mf, &poll_loop->fd_events, event->ev); + DEBUG_SCHED( "cleared timeout at slot %p\n", (void *)event->ev); + } else { + size_t i = ((size_t) (intptr_t) event->ev) - 1; + /* This may happen with full recursive synchronous requests + * with the unbound pluggable event API, because the default + * poll_eventloop is temporarily replaced by a poll_eventloop + * used only in synchronous calls. When the synchronous request + * had an answer, the poll_eventloop for the synchronous is + * cleaned, however it could still have outstanding events. + */ + if (i >= poll_loop->fd_events_capacity || + poll_loop->fd_events[i].event != event) { + event->ev = NULL; + DEBUG_SCHED( "ERROR: Event mismatch %p\n", (void *)event->ev); + return GETDNS_RETURN_GENERIC_ERROR; + } + poll_loop->fd_events[i].event = NULL; + if (--poll_loop->fd_events_n_used == 0) { + poll_loop->fd_events_free = 0; + } + DEBUG_SCHED( "cleared read/write for %d at slot %p\n" + , poll_loop->pfds[i].fd, (void *)event->ev); + poll_loop->pfds[i].fd = -1; /* Not necessary, but to be sure */ + } event->ev = NULL; return GETDNS_RETURN_GOOD; } @@ -241,10 +270,13 @@ poll_eventloop_cleanup(getdns_eventloop *loop) _getdns_poll_eventloop *poll_loop = (_getdns_poll_eventloop *)loop; struct mem_funcs *mf = &poll_loop->mf; - if (poll_loop->pfds) { - GETDNS_FREE(*mf, poll_loop->pfds); - poll_loop->pfds = NULL; - poll_loop->pfds_capacity = 0; + GETDNS_NULL_FREE(*mf, poll_loop->pfds); + if (poll_loop->fd_events) { + GETDNS_FREE(*mf, poll_loop->fd_events); + poll_loop->fd_events = NULL; + poll_loop->fd_events_capacity = 0; + poll_loop->fd_events_free = 0; + poll_loop->fd_events_n_used = 0; } if (poll_loop->to_events) { GETDNS_FREE(*mf, poll_loop->to_events); @@ -253,7 +285,6 @@ poll_eventloop_cleanup(getdns_eventloop *loop) poll_loop->to_events_free = 0; poll_loop->to_events_n_used = 0; } - HASH_CLEAR(hh, poll_loop->fd_events); } static void @@ -277,37 +308,19 @@ poll_write_cb(int fd, getdns_eventloop_event *event) } static void -poll_timeout_cb(int fd, getdns_eventloop_event *event) +poll_timeout_cb(getdns_eventloop_event *event) { -#if !defined(SCHED_DEBUG) || !SCHED_DEBUG - (void)fd; -#endif - DEBUG_SCHED( "%s(fd: %d, event: %p)\n", __FUNC__, fd, (void *)event); + DEBUG_SCHED( "%s(event: %p)\n", __FUNC__, (void *)event); event->timeout_cb(event->userarg); } -static unsigned long up_pow2(unsigned long v) -{ - v--; - v |= v >> 1; - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - return v + 1; -} - static void poll_eventloop_run_once(getdns_eventloop *loop, int blocking) { _getdns_poll_eventloop *poll_loop = (_getdns_poll_eventloop *)loop; - struct mem_funcs *mf = &poll_loop->mf; - _getdns_eventloop_info *s, *tmp; uint64_t now, timeout = TIMEOUT_FOREVER; size_t i = 0, j; int poll_timeout = 0; - unsigned int num_pfds = 0; - _getdns_eventloop_info* fd_timeout_cbs = NULL; if (!loop) return; @@ -330,7 +343,7 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) (void *) (intptr_t) (j + 1); } if (poll_loop->to_events[j].timeout_time < now) - poll_timeout_cb(-1, poll_loop->to_events[j].event); + poll_timeout_cb(poll_loop->to_events[j].event); } for (i = 0, j = 0; i < poll_loop->to_events_free; i++, j++) { while (poll_loop->to_events[i].event == NULL) { @@ -350,89 +363,98 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) if (poll_loop->to_events[j].timeout_time < timeout) timeout = poll_loop->to_events[j].timeout_time; } - /* first we count the number of fds that will be active */ - HASH_ITER(hh, poll_loop->fd_events, s, tmp) { - if (s->event->read_cb || - s->event->write_cb) - num_pfds++; - if (s->timeout_time < timeout) - timeout = s->timeout_time; - } - - if ((timeout == TIMEOUT_FOREVER) && (num_pfds == 0)) + if ((timeout == TIMEOUT_FOREVER) && (poll_loop->fd_events_free == 0)) return; - if (num_pfds >= poll_loop->pfds_capacity) { - poll_loop->pfds_capacity = up_pow2(num_pfds + 1); - if (!poll_loop->pfds) { - poll_loop->pfds = GETDNS_XMALLOC(poll_loop->mf, struct pollfd, poll_loop->pfds_capacity); - } else - poll_loop->pfds = GETDNS_XREALLOC(poll_loop->mf, poll_loop->pfds, struct pollfd, poll_loop->pfds_capacity); - if (poll_loop->pfds == 0) { - poll_loop->pfds_capacity = 0; - return; + for (i = 0, j = 0; i < poll_loop->fd_events_free; i++, j++) { + while (poll_loop->fd_events[i].event == NULL) { + if (++i == poll_loop->fd_events_free) { + poll_loop->fd_events_free = j; + break; + } } + if (j < i) { + if (j >= poll_loop->fd_events_free) + break; + poll_loop->fd_events[j] = poll_loop->fd_events[i]; + poll_loop->fd_events[i].event = NULL; + poll_loop->fd_events[j].event->ev = + (void *) (intptr_t) (j + 1); + poll_loop->pfds[j] = poll_loop->pfds[i]; + poll_loop->pfds[i].fd = -1; + } + if (poll_loop->fd_events[j].timeout_time < timeout) + timeout = poll_loop->fd_events[j].timeout_time; } - i = 0; - HASH_ITER(hh, poll_loop->fd_events, s, tmp) { - if (!s->event->read_cb && !s->event->write_cb) - continue; - poll_loop->pfds[i].fd = s->id; - poll_loop->pfds[i].events = 0; - poll_loop->pfds[i].revents = 0; /* <-- probably not needed */ - if (s->event->read_cb) - poll_loop->pfds[i].events |= POLLIN; - if (s->event->write_cb) - poll_loop->pfds[i].events |= POLLOUT; - i++; - } - assert(i == num_pfds); if (timeout == TIMEOUT_FOREVER) { poll_timeout = -1; - } - else if (! blocking || now > timeout) { + + } else if (! blocking || now > timeout) { poll_timeout = 0; } else { - poll_timeout = (timeout - now) / 1000; /* turn microseconds into milliseconds */ + /* turn microseconds into milliseconds */ + poll_timeout = (timeout - now) / 1000; } #ifdef USE_WINSOCK - if (WSAPoll(poll_loop->pfds, num_pfds, poll_timeout) < 0) { + if (WSAPoll(poll_loop->pfds, poll_loop->fd_events_free, poll_timeout) < 0) { #else - if (poll(poll_loop->pfds, num_pfds, poll_timeout) < 0) { + if (poll(poll_loop->pfds, poll_loop->fd_events_free, poll_timeout) < 0) { #endif perror("poll() failed"); exit(EXIT_FAILURE); } now = get_now_plus(0); - for (i = 0; i < num_pfds; i++) { - int fd = poll_loop->pfds[i].fd; - _getdns_eventloop_info* fd_event = find_event(&poll_loop->fd_events, fd); - if (fd_event && fd_event->event) { - getdns_eventloop_event* event = fd_event->event; - if (event->write_cb && - (poll_loop->pfds[i].revents & POLLOUT)) - poll_write_cb(fd, event); - else if (event->read_cb && - (poll_loop->pfds[i].revents & POLLIN)) - poll_read_cb(fd, event); + for (i = 0, j = 0; i < poll_loop->fd_events_free; i++, j++) { + while (poll_loop->fd_events[i].event == NULL) { + if (++i == poll_loop->fd_events_free) { + poll_loop->fd_events_free = j; + break; + } } + if (j < i) { + if (j >= poll_loop->fd_events_free) + break; + poll_loop->fd_events[j] = poll_loop->fd_events[i]; + poll_loop->fd_events[i].event = NULL; + poll_loop->fd_events[j].event->ev = + (void *) (intptr_t) (j + 1); + poll_loop->pfds[j] = poll_loop->pfds[i]; + poll_loop->pfds[i].fd = -1; + } + if (poll_loop->fd_events[j].event->write_cb && + poll_loop->pfds[j].revents & POLLOUT) + poll_write_cb( poll_loop->pfds[j].fd + , poll_loop->fd_events[j].event); + + if (poll_loop->fd_events[j].event && + poll_loop->fd_events[j].event->read_cb && + poll_loop->pfds[j].revents & POLLIN) + poll_read_cb( poll_loop->pfds[j].fd + , poll_loop->fd_events[j].event); } - HASH_ITER(hh, poll_loop->fd_events, s, tmp) { - if (s->event && - s->event->timeout_cb && - now > s->timeout_time) - (void) add_event(mf, &fd_timeout_cbs, s->id, s->event, s->timeout_time); - } - /* this is in case the timeout callback deletes the event - and thus messes with the iteration */ - HASH_ITER(hh, fd_timeout_cbs, s, tmp) { - int fd = s->id; - getdns_eventloop_event* event = s->event; - delete_event(mf, &fd_timeout_cbs, s); - poll_timeout_cb(fd, event); + for (i = 0, j = 0; i < poll_loop->fd_events_free; i++, j++) { + while (poll_loop->fd_events[i].event == NULL) { + if (++i == poll_loop->fd_events_free) { + poll_loop->fd_events_free = j; + break; + } + } + if (j < i) { + if (j >= poll_loop->fd_events_free) + break; + poll_loop->fd_events[j] = poll_loop->fd_events[i]; + poll_loop->fd_events[i].event = NULL; + poll_loop->fd_events[j].event->ev = + (void *) (intptr_t) (j + 1); + poll_loop->pfds[j] = poll_loop->pfds[i]; + poll_loop->pfds[i].fd = -1; + } + if (poll_loop->fd_events[j].timeout_time < now) + poll_timeout_cb(poll_loop->fd_events[j].event); } + for (i = 0, j = 0; i < poll_loop->to_events_free; i++, j++) { while (poll_loop->to_events[i].event == NULL) { if (++i == poll_loop->to_events_free) { @@ -449,7 +471,7 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) (void *) (intptr_t) (j + 1); } if (poll_loop->to_events[j].timeout_time < now) - poll_timeout_cb(-1, poll_loop->to_events[j].event); + poll_timeout_cb(poll_loop->to_events[j].event); } } @@ -462,7 +484,7 @@ poll_eventloop_run(getdns_eventloop *loop) return; /* keep going until all the events are cleared */ - while (poll_loop->fd_events || poll_loop->to_events_n_used) { + while (poll_loop->fd_events_n_used || poll_loop->to_events_n_used) { poll_eventloop_run_once(loop, 1); } } @@ -494,21 +516,33 @@ _getdns_poll_eventloop_init(struct mem_funcs *mf, _getdns_poll_eventloop *loop) #if HAVE_GETRLIMIT } #endif - loop->pfds_capacity = init_pfds_capacity; - if (!(loop->pfds = GETDNS_XMALLOC( - *mf, struct pollfd, init_pfds_capacity))) - loop->pfds_capacity = 0; - - loop->fd_events = NULL; - loop->to_events_capacity = init_to_events_capacity; if ((loop->to_events = GETDNS_XMALLOC( - *mf, _getdns_poll_to_event, init_to_events_capacity))) + *mf, _getdns_poll_event, init_to_events_capacity))) (void) memset(loop->to_events, 0, - sizeof(_getdns_poll_to_event) * init_to_events_capacity); + sizeof(_getdns_poll_event) * init_to_events_capacity); else loop->to_events_capacity = 0; loop->to_events_free = 0; loop->to_events_n_used = 0; + + loop->fd_events_capacity = init_fd_events_capacity; + if ((loop->fd_events = GETDNS_XMALLOC( + *mf, _getdns_poll_event, init_fd_events_capacity)) && + (loop->pfds = GETDNS_XMALLOC( + *mf, struct pollfd, init_fd_events_capacity))) { + (void) memset(loop->fd_events, 0, + sizeof(_getdns_poll_event) * init_fd_events_capacity); + (void) memset(loop->pfds, 0, + sizeof(struct pollfd) * init_fd_events_capacity); + } else { + loop->fd_events_capacity = 0; + if (loop->fd_events) { + GETDNS_FREE(*mf, loop->fd_events); + loop->fd_events = NULL; + } + } + loop->fd_events_free = 0; + loop->fd_events_n_used = 0; } diff --git a/src/extension/poll_eventloop.h b/src/extension/poll_eventloop.h index 51118b24..2643c30e 100644 --- a/src/extension/poll_eventloop.h +++ b/src/extension/poll_eventloop.h @@ -36,36 +36,28 @@ #include "getdns/getdns_extra.h" #include "types-internal.h" -#define uthash_malloc(sz) ((void *)GETDNS_XMALLOC(*mf, unsigned char, sz)) -#define uthash_free(ptr,sz) GETDNS_FREE(*mf, ptr) -#include "util/uthash.h" - /* Eventloop based on poll */ -typedef struct _getdns_eventloop_info { - int id; +typedef struct _getdns_poll_event { getdns_eventloop_event *event; uint64_t timeout_time; - UT_hash_handle hh; -} _getdns_eventloop_info; - -typedef struct _getdns_poll_to_event { - getdns_eventloop_event *event; - uint64_t timeout_time; -} _getdns_poll_to_event; +} _getdns_poll_event; typedef struct _getdns_poll_eventloop { - getdns_eventloop loop; - struct mem_funcs mf; - unsigned int max_fds; - unsigned long pfds_capacity; - struct pollfd *pfds; - _getdns_eventloop_info *fd_events; + getdns_eventloop loop; + struct mem_funcs mf; + unsigned int max_fds; - size_t to_events_capacity; - _getdns_poll_to_event *to_events; - size_t to_events_free; - size_t to_events_n_used; + struct pollfd *pfds; + size_t fd_events_capacity; + _getdns_poll_event *fd_events; + size_t fd_events_free; + size_t fd_events_n_used; + + size_t to_events_capacity; + _getdns_poll_event *to_events; + size_t to_events_free; + size_t to_events_n_used; } _getdns_poll_eventloop; void diff --git a/src/util/uthash.h b/src/util/uthash.h deleted file mode 100644 index 45d1f9fc..00000000 --- a/src/util/uthash.h +++ /dev/null @@ -1,1074 +0,0 @@ -/* -Copyright (c) 2003-2016, Troy D. Hanson http://troydhanson.github.com/uthash/ -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. - -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 THE COPYRIGHT OWNER -OR CONTRIBUTORS 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. -*/ - -#ifndef UTHASH_H -#define UTHASH_H - -#define UTHASH_VERSION 2.0.1 - -#include /* memcmp,strlen */ -#include /* ptrdiff_t */ -#include /* exit() */ - -/* These macros use decltype or the earlier __typeof GNU extension. - As decltype is only available in newer compilers (VS2010 or gcc 4.3+ - when compiling c++ source) this code uses whatever method is needed - or, for VS2008 where neither is available, uses casting workarounds. */ -#if defined(_MSC_VER) /* MS compiler */ -#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */ -#define DECLTYPE(x) (decltype(x)) -#else /* VS2008 or older (or VS2010 in C mode) */ -#define NO_DECLTYPE -#define DECLTYPE(x) -#endif -#elif defined(__BORLANDC__) || defined(__LCC__) || defined(__WATCOMC__) -#define NO_DECLTYPE -#define DECLTYPE(x) -#else /* GNU, Sun and other compilers */ -#define DECLTYPE(x) (__typeof(x)) -#endif - -#ifdef NO_DECLTYPE -#define DECLTYPE_ASSIGN(dst,src) \ -do { \ - char **_da_dst = (char**)(&(dst)); \ - *_da_dst = (char*)(src); \ -} while (0) -#else -#define DECLTYPE_ASSIGN(dst,src) \ -do { \ - (dst) = DECLTYPE(dst)(src); \ -} while (0) -#endif - -/* a number of the hash function use uint32_t which isn't defined on Pre VS2010 */ -#if defined(_WIN32) -#if defined(_MSC_VER) && _MSC_VER >= 1600 -#include -#elif defined(__WATCOMC__) || defined(__MINGW32__) || defined(__CYGWIN__) -#include -#else -typedef unsigned int uint32_t; -typedef unsigned char uint8_t; -#endif -#elif defined(__GNUC__) && !defined(__VXWORKS__) -#include -#else -typedef unsigned int uint32_t; -typedef unsigned char uint8_t; -#endif - -#ifndef uthash_fatal -#define uthash_fatal(msg) exit(-1) /* fatal error (out of memory,etc) */ -#endif -#ifndef uthash_malloc -#define uthash_malloc(sz) malloc(sz) /* malloc fcn */ -#endif -#ifndef uthash_free -#define uthash_free(ptr,sz) free(ptr) /* free fcn */ -#endif -#ifndef uthash_strlen -#define uthash_strlen(s) strlen(s) -#endif -#ifndef uthash_memcmp -#define uthash_memcmp(a,b,n) memcmp(a,b,n) -#endif - -#ifndef uthash_noexpand_fyi -#define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */ -#endif -#ifndef uthash_expand_fyi -#define uthash_expand_fyi(tbl) /* can be defined to log expands */ -#endif - -/* initial number of buckets */ -#define HASH_INITIAL_NUM_BUCKETS 32U /* initial number of buckets */ -#define HASH_INITIAL_NUM_BUCKETS_LOG2 5U /* lg2 of initial number of buckets */ -#define HASH_BKT_CAPACITY_THRESH 10U /* expand when bucket count reaches */ - -/* calculate the element whose hash handle address is hhp */ -#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho))) -/* calculate the hash handle from element address elp */ -#define HH_FROM_ELMT(tbl,elp) ((UT_hash_handle *)(((char*)(elp)) + ((tbl)->hho))) - -#define HASH_VALUE(keyptr,keylen,hashv) \ -do { \ - HASH_FCN(keyptr, keylen, hashv); \ -} while (0) - -#define HASH_FIND_BYHASHVALUE(hh,head,keyptr,keylen,hashval,out) \ -do { \ - (out) = NULL; \ - if (head) { \ - unsigned _hf_bkt; \ - HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _hf_bkt); \ - if (HASH_BLOOM_TEST((head)->hh.tbl, hashval) != 0) { \ - HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], keyptr, keylen, hashval, out); \ - } \ - } \ -} while (0) - -#define HASH_FIND(hh,head,keyptr,keylen,out) \ -do { \ - unsigned _hf_hashv; \ - HASH_VALUE(keyptr, keylen, _hf_hashv); \ - HASH_FIND_BYHASHVALUE(hh, head, keyptr, keylen, _hf_hashv, out); \ -} while (0) - -#ifdef HASH_BLOOM -#define HASH_BLOOM_BITLEN (1UL << HASH_BLOOM) -#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8UL) + (((HASH_BLOOM_BITLEN%8UL)!=0UL) ? 1UL : 0UL) -#define HASH_BLOOM_MAKE(tbl) \ -do { \ - (tbl)->bloom_nbits = HASH_BLOOM; \ - (tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \ - if (!((tbl)->bloom_bv)) { uthash_fatal( "out of memory"); } \ - memset((tbl)->bloom_bv, 0, HASH_BLOOM_BYTELEN); \ - (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \ -} while (0) - -#define HASH_BLOOM_FREE(tbl) \ -do { \ - uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \ -} while (0) - -#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8U] |= (1U << ((idx)%8U))) -#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8U] & (1U << ((idx)%8U))) - -#define HASH_BLOOM_ADD(tbl,hashv) \ - HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1U))) - -#define HASH_BLOOM_TEST(tbl,hashv) \ - HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1U))) - -#else -#define HASH_BLOOM_MAKE(tbl) -#define HASH_BLOOM_FREE(tbl) -#define HASH_BLOOM_ADD(tbl,hashv) -#define HASH_BLOOM_TEST(tbl,hashv) (1) -#define HASH_BLOOM_BYTELEN 0U -#endif - -#define HASH_MAKE_TABLE(hh,head) \ -do { \ - (head)->hh.tbl = (UT_hash_table*)uthash_malloc( \ - sizeof(UT_hash_table)); \ - if (!((head)->hh.tbl)) { uthash_fatal( "out of memory"); } \ - memset((head)->hh.tbl, 0, sizeof(UT_hash_table)); \ - (head)->hh.tbl->tail = &((head)->hh); \ - (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \ - (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \ - (head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \ - (head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \ - HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \ - if (! (head)->hh.tbl->buckets) { uthash_fatal( "out of memory"); } \ - memset((head)->hh.tbl->buckets, 0, \ - HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \ - HASH_BLOOM_MAKE((head)->hh.tbl); \ - (head)->hh.tbl->signature = HASH_SIGNATURE; \ -} while (0) - -#define HASH_REPLACE_BYHASHVALUE_INORDER(hh,head,fieldname,keylen_in,hashval,add,replaced,cmpfcn) \ -do { \ - (replaced) = NULL; \ - HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, replaced); \ - if (replaced) { \ - HASH_DELETE(hh, head, replaced); \ - } \ - HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, &((add)->fieldname), keylen_in, hashval, add, cmpfcn); \ -} while (0) - -#define HASH_REPLACE_BYHASHVALUE(hh,head,fieldname,keylen_in,hashval,add,replaced) \ -do { \ - (replaced) = NULL; \ - HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, replaced); \ - if (replaced) { \ - HASH_DELETE(hh, head, replaced); \ - } \ - HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, add); \ -} while (0) - -#define HASH_REPLACE(hh,head,fieldname,keylen_in,add,replaced) \ -do { \ - unsigned _hr_hashv; \ - HASH_VALUE(&((add)->fieldname), keylen_in, _hr_hashv); \ - HASH_REPLACE_BYHASHVALUE(hh, head, fieldname, keylen_in, _hr_hashv, add, replaced); \ -} while (0) - -#define HASH_REPLACE_INORDER(hh,head,fieldname,keylen_in,add,replaced,cmpfcn) \ -do { \ - unsigned _hr_hashv; \ - HASH_VALUE(&((add)->fieldname), keylen_in, _hr_hashv); \ - HASH_REPLACE_BYHASHVALUE_INORDER(hh, head, fieldname, keylen_in, _hr_hashv, add, replaced, cmpfcn); \ -} while (0) - -#define HASH_APPEND_LIST(hh, head, add) \ -do { \ - (add)->hh.next = NULL; \ - (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \ - (head)->hh.tbl->tail->next = (add); \ - (head)->hh.tbl->tail = &((add)->hh); \ -} while (0) - -#define HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh,head,keyptr,keylen_in,hashval,add,cmpfcn) \ -do { \ - unsigned _ha_bkt; \ - (add)->hh.hashv = (hashval); \ - (add)->hh.key = (char*) (keyptr); \ - (add)->hh.keylen = (unsigned) (keylen_in); \ - if (!(head)) { \ - (add)->hh.next = NULL; \ - (add)->hh.prev = NULL; \ - (head) = (add); \ - HASH_MAKE_TABLE(hh, head); \ - } else { \ - struct UT_hash_handle *_hs_iter = &(head)->hh; \ - (add)->hh.tbl = (head)->hh.tbl; \ - do { \ - if (cmpfcn(DECLTYPE(head) ELMT_FROM_HH((head)->hh.tbl, _hs_iter), add) > 0) \ - break; \ - } while ((_hs_iter = _hs_iter->next)); \ - if (_hs_iter) { \ - (add)->hh.next = _hs_iter; \ - if (((add)->hh.prev = _hs_iter->prev)) { \ - HH_FROM_ELMT((head)->hh.tbl, _hs_iter->prev)->next = (add); \ - } else { \ - (head) = (add); \ - } \ - _hs_iter->prev = (add); \ - } else { \ - HASH_APPEND_LIST(hh, head, add); \ - } \ - } \ - (head)->hh.tbl->num_items++; \ - HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt); \ - HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], &(add)->hh); \ - HASH_BLOOM_ADD((head)->hh.tbl, hashval); \ - HASH_EMIT_KEY(hh, head, keyptr, keylen_in); \ - HASH_FSCK(hh, head); \ -} while (0) - -#define HASH_ADD_KEYPTR_INORDER(hh,head,keyptr,keylen_in,add,cmpfcn) \ -do { \ - unsigned _hs_hashv; \ - HASH_VALUE(keyptr, keylen_in, _hs_hashv); \ - HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, keyptr, keylen_in, _hs_hashv, add, cmpfcn); \ -} while (0) - -#define HASH_ADD_BYHASHVALUE_INORDER(hh,head,fieldname,keylen_in,hashval,add,cmpfcn) \ - HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, &((add)->fieldname), keylen_in, hashval, add, cmpfcn) - -#define HASH_ADD_INORDER(hh,head,fieldname,keylen_in,add,cmpfcn) \ - HASH_ADD_KEYPTR_INORDER(hh, head, &((add)->fieldname), keylen_in, add, cmpfcn) - -#define HASH_ADD_KEYPTR_BYHASHVALUE(hh,head,keyptr,keylen_in,hashval,add) \ -do { \ - unsigned _ha_bkt; \ - (add)->hh.hashv = (hashval); \ - (add)->hh.key = (char*) (keyptr); \ - (add)->hh.keylen = (unsigned) (keylen_in); \ - if (!(head)) { \ - (add)->hh.next = NULL; \ - (add)->hh.prev = NULL; \ - (head) = (add); \ - HASH_MAKE_TABLE(hh, head); \ - } else { \ - (add)->hh.tbl = (head)->hh.tbl; \ - HASH_APPEND_LIST(hh, head, add); \ - } \ - (head)->hh.tbl->num_items++; \ - HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt); \ - HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], &(add)->hh); \ - HASH_BLOOM_ADD((head)->hh.tbl, hashval); \ - HASH_EMIT_KEY(hh, head, keyptr, keylen_in); \ - HASH_FSCK(hh, head); \ -} while (0) - -#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \ -do { \ - unsigned _ha_hashv; \ - HASH_VALUE(keyptr, keylen_in, _ha_hashv); \ - HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, keyptr, keylen_in, _ha_hashv, add); \ -} while (0) - -#define HASH_ADD_BYHASHVALUE(hh,head,fieldname,keylen_in,hashval,add) \ - HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, add) - -#define HASH_ADD(hh,head,fieldname,keylen_in,add) \ - HASH_ADD_KEYPTR(hh, head, &((add)->fieldname), keylen_in, add) - -#define HASH_TO_BKT(hashv,num_bkts,bkt) \ -do { \ - bkt = ((hashv) & ((num_bkts) - 1U)); \ -} while (0) - -/* delete "delptr" from the hash table. - * "the usual" patch-up process for the app-order doubly-linked-list. - * The use of _hd_hh_del below deserves special explanation. - * These used to be expressed using (delptr) but that led to a bug - * if someone used the same symbol for the head and deletee, like - * HASH_DELETE(hh,users,users); - * We want that to work, but by changing the head (users) below - * we were forfeiting our ability to further refer to the deletee (users) - * in the patch-up process. Solution: use scratch space to - * copy the deletee pointer, then the latter references are via that - * scratch pointer rather than through the repointed (users) symbol. - */ -#define HASH_DELETE(hh,head,delptr) \ -do { \ - struct UT_hash_handle *_hd_hh_del; \ - if ( ((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL) ) { \ - uthash_free((head)->hh.tbl->buckets, \ - (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \ - HASH_BLOOM_FREE((head)->hh.tbl); \ - uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ - head = NULL; \ - } else { \ - unsigned _hd_bkt; \ - _hd_hh_del = &((delptr)->hh); \ - if ((delptr) == ELMT_FROM_HH((head)->hh.tbl,(head)->hh.tbl->tail)) { \ - (head)->hh.tbl->tail = \ - (UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) + \ - (head)->hh.tbl->hho); \ - } \ - if ((delptr)->hh.prev != NULL) { \ - ((UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) + \ - (head)->hh.tbl->hho))->next = (delptr)->hh.next; \ - } else { \ - DECLTYPE_ASSIGN(head,(delptr)->hh.next); \ - } \ - if (_hd_hh_del->next != NULL) { \ - ((UT_hash_handle*)((ptrdiff_t)_hd_hh_del->next + \ - (head)->hh.tbl->hho))->prev = \ - _hd_hh_del->prev; \ - } \ - HASH_TO_BKT( _hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \ - HASH_DEL_IN_BKT(hh,(head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \ - (head)->hh.tbl->num_items--; \ - } \ - HASH_FSCK(hh,head); \ -} while (0) - - -/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */ -#define HASH_FIND_STR(head,findstr,out) \ - HASH_FIND(hh,head,findstr,(unsigned)uthash_strlen(findstr),out) -#define HASH_ADD_STR(head,strfield,add) \ - HASH_ADD(hh,head,strfield[0],(unsigned)uthash_strlen(add->strfield),add) -#define HASH_REPLACE_STR(head,strfield,add,replaced) \ - HASH_REPLACE(hh,head,strfield[0],(unsigned)uthash_strlen(add->strfield),add,replaced) -#define HASH_FIND_INT(head,findint,out) \ - HASH_FIND(hh,head,findint,sizeof(int),out) -#define HASH_ADD_INT(head,intfield,add) \ - HASH_ADD(hh,head,intfield,sizeof(int),add) -#define HASH_REPLACE_INT(head,intfield,add,replaced) \ - HASH_REPLACE(hh,head,intfield,sizeof(int),add,replaced) -#define HASH_FIND_PTR(head,findptr,out) \ - HASH_FIND(hh,head,findptr,sizeof(void *),out) -#define HASH_ADD_PTR(head,ptrfield,add) \ - HASH_ADD(hh,head,ptrfield,sizeof(void *),add) -#define HASH_REPLACE_PTR(head,ptrfield,add,replaced) \ - HASH_REPLACE(hh,head,ptrfield,sizeof(void *),add,replaced) -#define HASH_DEL(head,delptr) \ - HASH_DELETE(hh,head,delptr) - -/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined. - * This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined. - */ -#ifdef HASH_DEBUG -#define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0) -#define HASH_FSCK(hh,head) \ -do { \ - struct UT_hash_handle *_thh; \ - if (head) { \ - unsigned _bkt_i; \ - unsigned _count; \ - char *_prev; \ - _count = 0; \ - for( _bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; _bkt_i++) { \ - unsigned _bkt_count = 0; \ - _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \ - _prev = NULL; \ - while (_thh) { \ - if (_prev != (char*)(_thh->hh_prev)) { \ - HASH_OOPS("invalid hh_prev %p, actual %p\n", \ - _thh->hh_prev, _prev ); \ - } \ - _bkt_count++; \ - _prev = (char*)(_thh); \ - _thh = _thh->hh_next; \ - } \ - _count += _bkt_count; \ - if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \ - HASH_OOPS("invalid bucket count %u, actual %u\n", \ - (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \ - } \ - } \ - if (_count != (head)->hh.tbl->num_items) { \ - HASH_OOPS("invalid hh item count %u, actual %u\n", \ - (head)->hh.tbl->num_items, _count ); \ - } \ - /* traverse hh in app order; check next/prev integrity, count */ \ - _count = 0; \ - _prev = NULL; \ - _thh = &(head)->hh; \ - while (_thh) { \ - _count++; \ - if (_prev !=(char*)(_thh->prev)) { \ - HASH_OOPS("invalid prev %p, actual %p\n", \ - _thh->prev, _prev ); \ - } \ - _prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \ - _thh = ( _thh->next ? (UT_hash_handle*)((char*)(_thh->next) + \ - (head)->hh.tbl->hho) : NULL ); \ - } \ - if (_count != (head)->hh.tbl->num_items) { \ - HASH_OOPS("invalid app item count %u, actual %u\n", \ - (head)->hh.tbl->num_items, _count ); \ - } \ - } \ -} while (0) -#else -#define HASH_FSCK(hh,head) -#endif - -/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to - * the descriptor to which this macro is defined for tuning the hash function. - * The app can #include to get the prototype for write(2). */ -#ifdef HASH_EMIT_KEYS -#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \ -do { \ - unsigned _klen = fieldlen; \ - write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \ - write(HASH_EMIT_KEYS, keyptr, (unsigned long)fieldlen); \ -} while (0) -#else -#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) -#endif - -/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */ -#ifdef HASH_FUNCTION -#define HASH_FCN HASH_FUNCTION -#else -#define HASH_FCN HASH_JEN -#endif - -/* The Bernstein hash function, used in Perl prior to v5.6. Note (x<<5+x)=x*33. */ -#define HASH_BER(key,keylen,hashv) \ -do { \ - unsigned _hb_keylen=(unsigned)keylen; \ - const unsigned char *_hb_key=(const unsigned char*)(key); \ - (hashv) = 0; \ - while (_hb_keylen-- != 0U) { \ - (hashv) = (((hashv) << 5) + (hashv)) + *_hb_key++; \ - } \ -} while (0) - - -/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at - * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */ -#define HASH_SAX(key,keylen,hashv) \ -do { \ - unsigned _sx_i; \ - const unsigned char *_hs_key=(const unsigned char*)(key); \ - hashv = 0; \ - for(_sx_i=0; _sx_i < keylen; _sx_i++) { \ - hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \ - } \ -} while (0) -/* FNV-1a variation */ -#define HASH_FNV(key,keylen,hashv) \ -do { \ - unsigned _fn_i; \ - const unsigned char *_hf_key=(const unsigned char*)(key); \ - hashv = 2166136261U; \ - for(_fn_i=0; _fn_i < keylen; _fn_i++) { \ - hashv = hashv ^ _hf_key[_fn_i]; \ - hashv = hashv * 16777619U; \ - } \ -} while (0) - -#define HASH_OAT(key,keylen,hashv) \ -do { \ - unsigned _ho_i; \ - const unsigned char *_ho_key=(const unsigned char*)(key); \ - hashv = 0; \ - for(_ho_i=0; _ho_i < keylen; _ho_i++) { \ - hashv += _ho_key[_ho_i]; \ - hashv += (hashv << 10); \ - hashv ^= (hashv >> 6); \ - } \ - hashv += (hashv << 3); \ - hashv ^= (hashv >> 11); \ - hashv += (hashv << 15); \ -} while (0) - -#define HASH_JEN_MIX(a,b,c) \ -do { \ - a -= b; a -= c; a ^= ( c >> 13 ); \ - b -= c; b -= a; b ^= ( a << 8 ); \ - c -= a; c -= b; c ^= ( b >> 13 ); \ - a -= b; a -= c; a ^= ( c >> 12 ); \ - b -= c; b -= a; b ^= ( a << 16 ); \ - c -= a; c -= b; c ^= ( b >> 5 ); \ - a -= b; a -= c; a ^= ( c >> 3 ); \ - b -= c; b -= a; b ^= ( a << 10 ); \ - c -= a; c -= b; c ^= ( b >> 15 ); \ -} while (0) - -#define HASH_JEN(key,keylen,hashv) \ -do { \ - unsigned _hj_i,_hj_j,_hj_k; \ - unsigned const char *_hj_key=(unsigned const char*)(key); \ - hashv = 0xfeedbeefu; \ - _hj_i = _hj_j = 0x9e3779b9u; \ - _hj_k = (unsigned)(keylen); \ - while (_hj_k >= 12U) { \ - _hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \ - + ( (unsigned)_hj_key[2] << 16 ) \ - + ( (unsigned)_hj_key[3] << 24 ) ); \ - _hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) \ - + ( (unsigned)_hj_key[6] << 16 ) \ - + ( (unsigned)_hj_key[7] << 24 ) ); \ - hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 ) \ - + ( (unsigned)_hj_key[10] << 16 ) \ - + ( (unsigned)_hj_key[11] << 24 ) ); \ - \ - HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ - \ - _hj_key += 12; \ - _hj_k -= 12U; \ - } \ - hashv += (unsigned)(keylen); \ - switch ( _hj_k ) { \ - case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); /* FALLTHROUGH */ \ - case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); /* FALLTHROUGH */ \ - case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); /* FALLTHROUGH */ \ - case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); /* FALLTHROUGH */ \ - case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); /* FALLTHROUGH */ \ - case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); /* FALLTHROUGH */ \ - case 5: _hj_j += _hj_key[4]; /* FALLTHROUGH */ \ - case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); /* FALLTHROUGH */ \ - case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); /* FALLTHROUGH */ \ - case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); /* FALLTHROUGH */ \ - case 1: _hj_i += _hj_key[0]; \ - } \ - HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ -} while (0) - -/* The Paul Hsieh hash function */ -#undef get16bits -#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \ - || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__) -#define get16bits(d) (*((const uint16_t *) (d))) -#endif - -#if !defined (get16bits) -#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \ - +(uint32_t)(((const uint8_t *)(d))[0]) ) -#endif -#define HASH_SFH(key,keylen,hashv) \ -do { \ - unsigned const char *_sfh_key=(unsigned const char*)(key); \ - uint32_t _sfh_tmp, _sfh_len = (uint32_t)keylen; \ - \ - unsigned _sfh_rem = _sfh_len & 3U; \ - _sfh_len >>= 2; \ - hashv = 0xcafebabeu; \ - \ - /* Main loop */ \ - for (;_sfh_len > 0U; _sfh_len--) { \ - hashv += get16bits (_sfh_key); \ - _sfh_tmp = ((uint32_t)(get16bits (_sfh_key+2)) << 11) ^ hashv; \ - hashv = (hashv << 16) ^ _sfh_tmp; \ - _sfh_key += 2U*sizeof (uint16_t); \ - hashv += hashv >> 11; \ - } \ - \ - /* Handle end cases */ \ - switch (_sfh_rem) { \ - case 3: hashv += get16bits (_sfh_key); \ - hashv ^= hashv << 16; \ - hashv ^= (uint32_t)(_sfh_key[sizeof (uint16_t)]) << 18; \ - hashv += hashv >> 11; \ - break; \ - case 2: hashv += get16bits (_sfh_key); \ - hashv ^= hashv << 11; \ - hashv += hashv >> 17; \ - break; \ - case 1: hashv += *_sfh_key; \ - hashv ^= hashv << 10; \ - hashv += hashv >> 1; \ - } \ - \ - /* Force "avalanching" of final 127 bits */ \ - hashv ^= hashv << 3; \ - hashv += hashv >> 5; \ - hashv ^= hashv << 4; \ - hashv += hashv >> 17; \ - hashv ^= hashv << 25; \ - hashv += hashv >> 6; \ -} while (0) - -#ifdef HASH_USING_NO_STRICT_ALIASING -/* The MurmurHash exploits some CPU's (x86,x86_64) tolerance for unaligned reads. - * For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error. - * MurmurHash uses the faster approach only on CPU's where we know it's safe. - * - * Note the preprocessor built-in defines can be emitted using: - * - * gcc -m64 -dM -E - < /dev/null (on gcc) - * cc -## a.c (where a.c is a simple test file) (Sun Studio) - */ -#if (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86)) -#define MUR_GETBLOCK(p,i) p[i] -#else /* non intel */ -#define MUR_PLUS0_ALIGNED(p) (((unsigned long)p & 3UL) == 0UL) -#define MUR_PLUS1_ALIGNED(p) (((unsigned long)p & 3UL) == 1UL) -#define MUR_PLUS2_ALIGNED(p) (((unsigned long)p & 3UL) == 2UL) -#define MUR_PLUS3_ALIGNED(p) (((unsigned long)p & 3UL) == 3UL) -#define WP(p) ((uint32_t*)((unsigned long)(p) & ~3UL)) -#if (defined(__BIG_ENDIAN__) || defined(SPARC) || defined(__ppc__) || defined(__ppc64__)) -#define MUR_THREE_ONE(p) ((((*WP(p))&0x00ffffff) << 8) | (((*(WP(p)+1))&0xff000000) >> 24)) -#define MUR_TWO_TWO(p) ((((*WP(p))&0x0000ffff) <<16) | (((*(WP(p)+1))&0xffff0000) >> 16)) -#define MUR_ONE_THREE(p) ((((*WP(p))&0x000000ff) <<24) | (((*(WP(p)+1))&0xffffff00) >> 8)) -#else /* assume little endian non-intel */ -#define MUR_THREE_ONE(p) ((((*WP(p))&0xffffff00) >> 8) | (((*(WP(p)+1))&0x000000ff) << 24)) -#define MUR_TWO_TWO(p) ((((*WP(p))&0xffff0000) >>16) | (((*(WP(p)+1))&0x0000ffff) << 16)) -#define MUR_ONE_THREE(p) ((((*WP(p))&0xff000000) >>24) | (((*(WP(p)+1))&0x00ffffff) << 8)) -#endif -#define MUR_GETBLOCK(p,i) (MUR_PLUS0_ALIGNED(p) ? ((p)[i]) : \ - (MUR_PLUS1_ALIGNED(p) ? MUR_THREE_ONE(p) : \ - (MUR_PLUS2_ALIGNED(p) ? MUR_TWO_TWO(p) : \ - MUR_ONE_THREE(p)))) -#endif -#define MUR_ROTL32(x,r) (((x) << (r)) | ((x) >> (32 - (r)))) -#define MUR_FMIX(_h) \ -do { \ - _h ^= _h >> 16; \ - _h *= 0x85ebca6bu; \ - _h ^= _h >> 13; \ - _h *= 0xc2b2ae35u; \ - _h ^= _h >> 16; \ -} while (0) - -#define HASH_MUR(key,keylen,hashv) \ -do { \ - const uint8_t *_mur_data = (const uint8_t*)(key); \ - const int _mur_nblocks = (int)(keylen) / 4; \ - uint32_t _mur_h1 = 0xf88D5353u; \ - uint32_t _mur_c1 = 0xcc9e2d51u; \ - uint32_t _mur_c2 = 0x1b873593u; \ - uint32_t _mur_k1 = 0; \ - const uint8_t *_mur_tail; \ - const uint32_t *_mur_blocks = (const uint32_t*)(_mur_data+(_mur_nblocks*4)); \ - int _mur_i; \ - for(_mur_i = -_mur_nblocks; _mur_i!=0; _mur_i++) { \ - _mur_k1 = MUR_GETBLOCK(_mur_blocks,_mur_i); \ - _mur_k1 *= _mur_c1; \ - _mur_k1 = MUR_ROTL32(_mur_k1,15); \ - _mur_k1 *= _mur_c2; \ - \ - _mur_h1 ^= _mur_k1; \ - _mur_h1 = MUR_ROTL32(_mur_h1,13); \ - _mur_h1 = (_mur_h1*5U) + 0xe6546b64u; \ - } \ - _mur_tail = (const uint8_t*)(_mur_data + (_mur_nblocks*4)); \ - _mur_k1=0; \ - switch((keylen) & 3U) { \ - case 3: _mur_k1 ^= (uint32_t)_mur_tail[2] << 16; /* FALLTHROUGH */ \ - case 2: _mur_k1 ^= (uint32_t)_mur_tail[1] << 8; /* FALLTHROUGH */ \ - case 1: _mur_k1 ^= (uint32_t)_mur_tail[0]; \ - _mur_k1 *= _mur_c1; \ - _mur_k1 = MUR_ROTL32(_mur_k1,15); \ - _mur_k1 *= _mur_c2; \ - _mur_h1 ^= _mur_k1; \ - } \ - _mur_h1 ^= (uint32_t)(keylen); \ - MUR_FMIX(_mur_h1); \ - hashv = _mur_h1; \ -} while (0) -#endif /* HASH_USING_NO_STRICT_ALIASING */ - -/* iterate over items in a known bucket to find desired item */ -#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,hashval,out) \ -do { \ - if ((head).hh_head != NULL) { \ - DECLTYPE_ASSIGN(out, ELMT_FROM_HH(tbl, (head).hh_head)); \ - } else { \ - (out) = NULL; \ - } \ - while ((out) != NULL) { \ - if ((out)->hh.hashv == (hashval) && (out)->hh.keylen == (keylen_in)) { \ - if (uthash_memcmp((out)->hh.key, keyptr, keylen_in) == 0) { \ - break; \ - } \ - } \ - if ((out)->hh.hh_next != NULL) { \ - DECLTYPE_ASSIGN(out, ELMT_FROM_HH(tbl, (out)->hh.hh_next)); \ - } else { \ - (out) = NULL; \ - } \ - } \ -} while (0) - -/* add an item to a bucket */ -#define HASH_ADD_TO_BKT(head,addhh) \ -do { \ - head.count++; \ - (addhh)->hh_next = head.hh_head; \ - (addhh)->hh_prev = NULL; \ - if (head.hh_head != NULL) { (head).hh_head->hh_prev = (addhh); } \ - (head).hh_head=addhh; \ - if ((head.count >= ((head.expand_mult+1U) * HASH_BKT_CAPACITY_THRESH)) \ - && ((addhh)->tbl->noexpand != 1U)) { \ - HASH_EXPAND_BUCKETS((addhh)->tbl); \ - } \ -} while (0) - -/* remove an item from a given bucket */ -#define HASH_DEL_IN_BKT(hh,head,hh_del) \ - (head).count--; \ - if ((head).hh_head == hh_del) { \ - (head).hh_head = hh_del->hh_next; \ - } \ - if (hh_del->hh_prev) { \ - hh_del->hh_prev->hh_next = hh_del->hh_next; \ - } \ - if (hh_del->hh_next) { \ - hh_del->hh_next->hh_prev = hh_del->hh_prev; \ - } - -/* Bucket expansion has the effect of doubling the number of buckets - * and redistributing the items into the new buckets. Ideally the - * items will distribute more or less evenly into the new buckets - * (the extent to which this is true is a measure of the quality of - * the hash function as it applies to the key domain). - * - * With the items distributed into more buckets, the chain length - * (item count) in each bucket is reduced. Thus by expanding buckets - * the hash keeps a bound on the chain length. This bounded chain - * length is the essence of how a hash provides constant time lookup. - * - * The calculation of tbl->ideal_chain_maxlen below deserves some - * explanation. First, keep in mind that we're calculating the ideal - * maximum chain length based on the *new* (doubled) bucket count. - * In fractions this is just n/b (n=number of items,b=new num buckets). - * Since the ideal chain length is an integer, we want to calculate - * ceil(n/b). We don't depend on floating point arithmetic in this - * hash, so to calculate ceil(n/b) with integers we could write - * - * ceil(n/b) = (n/b) + ((n%b)?1:0) - * - * and in fact a previous version of this hash did just that. - * But now we have improved things a bit by recognizing that b is - * always a power of two. We keep its base 2 log handy (call it lb), - * so now we can write this with a bit shift and logical AND: - * - * ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0) - * - */ -#define HASH_EXPAND_BUCKETS(tbl) \ -do { \ - unsigned _he_bkt; \ - unsigned _he_bkt_i; \ - struct UT_hash_handle *_he_thh, *_he_hh_nxt; \ - UT_hash_bucket *_he_new_buckets, *_he_newbkt; \ - _he_new_buckets = (UT_hash_bucket*)uthash_malloc( \ - 2UL * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ - if (!_he_new_buckets) { uthash_fatal( "out of memory"); } \ - memset(_he_new_buckets, 0, \ - 2UL * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ - tbl->ideal_chain_maxlen = \ - (tbl->num_items >> (tbl->log2_num_buckets+1U)) + \ - (((tbl->num_items & ((tbl->num_buckets*2U)-1U)) != 0U) ? 1U : 0U); \ - tbl->nonideal_items = 0; \ - for(_he_bkt_i = 0; _he_bkt_i < tbl->num_buckets; _he_bkt_i++) \ - { \ - _he_thh = tbl->buckets[ _he_bkt_i ].hh_head; \ - while (_he_thh != NULL) { \ - _he_hh_nxt = _he_thh->hh_next; \ - HASH_TO_BKT( _he_thh->hashv, tbl->num_buckets*2U, _he_bkt); \ - _he_newbkt = &(_he_new_buckets[ _he_bkt ]); \ - if (++(_he_newbkt->count) > tbl->ideal_chain_maxlen) { \ - tbl->nonideal_items++; \ - _he_newbkt->expand_mult = _he_newbkt->count / \ - tbl->ideal_chain_maxlen; \ - } \ - _he_thh->hh_prev = NULL; \ - _he_thh->hh_next = _he_newbkt->hh_head; \ - if (_he_newbkt->hh_head != NULL) { _he_newbkt->hh_head->hh_prev = \ - _he_thh; } \ - _he_newbkt->hh_head = _he_thh; \ - _he_thh = _he_hh_nxt; \ - } \ - } \ - uthash_free( tbl->buckets, tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \ - tbl->num_buckets *= 2U; \ - tbl->log2_num_buckets++; \ - tbl->buckets = _he_new_buckets; \ - tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) ? \ - (tbl->ineff_expands+1U) : 0U; \ - if (tbl->ineff_expands > 1U) { \ - tbl->noexpand=1; \ - uthash_noexpand_fyi(tbl); \ - } \ - uthash_expand_fyi(tbl); \ -} while (0) - - -/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */ -/* Note that HASH_SORT assumes the hash handle name to be hh. - * HASH_SRT was added to allow the hash handle name to be passed in. */ -#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn) -#define HASH_SRT(hh,head,cmpfcn) \ -do { \ - unsigned _hs_i; \ - unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \ - struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \ - if (head != NULL) { \ - _hs_insize = 1; \ - _hs_looping = 1; \ - _hs_list = &((head)->hh); \ - while (_hs_looping != 0U) { \ - _hs_p = _hs_list; \ - _hs_list = NULL; \ - _hs_tail = NULL; \ - _hs_nmerges = 0; \ - while (_hs_p != NULL) { \ - _hs_nmerges++; \ - _hs_q = _hs_p; \ - _hs_psize = 0; \ - for ( _hs_i = 0; _hs_i < _hs_insize; _hs_i++ ) { \ - _hs_psize++; \ - _hs_q = (UT_hash_handle*)((_hs_q->next != NULL) ? \ - ((void*)((char*)(_hs_q->next) + \ - (head)->hh.tbl->hho)) : NULL); \ - if (! (_hs_q) ) { break; } \ - } \ - _hs_qsize = _hs_insize; \ - while ((_hs_psize > 0U) || ((_hs_qsize > 0U) && (_hs_q != NULL))) {\ - if (_hs_psize == 0U) { \ - _hs_e = _hs_q; \ - _hs_q = (UT_hash_handle*)((_hs_q->next != NULL) ? \ - ((void*)((char*)(_hs_q->next) + \ - (head)->hh.tbl->hho)) : NULL); \ - _hs_qsize--; \ - } else if ( (_hs_qsize == 0U) || (_hs_q == NULL) ) { \ - _hs_e = _hs_p; \ - if (_hs_p != NULL){ \ - _hs_p = (UT_hash_handle*)((_hs_p->next != NULL) ? \ - ((void*)((char*)(_hs_p->next) + \ - (head)->hh.tbl->hho)) : NULL); \ - } \ - _hs_psize--; \ - } else if (( \ - cmpfcn(DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_p)), \ - DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_q))) \ - ) <= 0) { \ - _hs_e = _hs_p; \ - if (_hs_p != NULL){ \ - _hs_p = (UT_hash_handle*)((_hs_p->next != NULL) ? \ - ((void*)((char*)(_hs_p->next) + \ - (head)->hh.tbl->hho)) : NULL); \ - } \ - _hs_psize--; \ - } else { \ - _hs_e = _hs_q; \ - _hs_q = (UT_hash_handle*)((_hs_q->next != NULL) ? \ - ((void*)((char*)(_hs_q->next) + \ - (head)->hh.tbl->hho)) : NULL); \ - _hs_qsize--; \ - } \ - if ( _hs_tail != NULL ) { \ - _hs_tail->next = ((_hs_e != NULL) ? \ - ELMT_FROM_HH((head)->hh.tbl,_hs_e) : NULL); \ - } else { \ - _hs_list = _hs_e; \ - } \ - if (_hs_e != NULL) { \ - _hs_e->prev = ((_hs_tail != NULL) ? \ - ELMT_FROM_HH((head)->hh.tbl,_hs_tail) : NULL); \ - } \ - _hs_tail = _hs_e; \ - } \ - _hs_p = _hs_q; \ - } \ - if (_hs_tail != NULL){ \ - _hs_tail->next = NULL; \ - } \ - if ( _hs_nmerges <= 1U ) { \ - _hs_looping=0; \ - (head)->hh.tbl->tail = _hs_tail; \ - DECLTYPE_ASSIGN(head,ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \ - } \ - _hs_insize *= 2U; \ - } \ - HASH_FSCK(hh,head); \ - } \ -} while (0) - -/* This function selects items from one hash into another hash. - * The end result is that the selected items have dual presence - * in both hashes. There is no copy of the items made; rather - * they are added into the new hash through a secondary hash - * hash handle that must be present in the structure. */ -#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \ -do { \ - unsigned _src_bkt, _dst_bkt; \ - void *_last_elt=NULL, *_elt; \ - UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \ - ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst)); \ - if (src != NULL) { \ - for(_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \ - for(_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \ - _src_hh != NULL; \ - _src_hh = _src_hh->hh_next) { \ - _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \ - if (cond(_elt)) { \ - _dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho); \ - _dst_hh->key = _src_hh->key; \ - _dst_hh->keylen = _src_hh->keylen; \ - _dst_hh->hashv = _src_hh->hashv; \ - _dst_hh->prev = _last_elt; \ - _dst_hh->next = NULL; \ - if (_last_elt_hh != NULL) { _last_elt_hh->next = _elt; } \ - if (dst == NULL) { \ - DECLTYPE_ASSIGN(dst,_elt); \ - HASH_MAKE_TABLE(hh_dst,dst); \ - } else { \ - _dst_hh->tbl = (dst)->hh_dst.tbl; \ - } \ - HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \ - HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt],_dst_hh); \ - (dst)->hh_dst.tbl->num_items++; \ - _last_elt = _elt; \ - _last_elt_hh = _dst_hh; \ - } \ - } \ - } \ - } \ - HASH_FSCK(hh_dst,dst); \ -} while (0) - -#define HASH_CLEAR(hh,head) \ -do { \ - if (head != NULL) { \ - uthash_free((head)->hh.tbl->buckets, \ - (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket)); \ - HASH_BLOOM_FREE((head)->hh.tbl); \ - uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ - (head)=NULL; \ - } \ -} while (0) - -#define HASH_OVERHEAD(hh,head) \ - ((head != NULL) ? ( \ - (size_t)(((head)->hh.tbl->num_items * sizeof(UT_hash_handle)) + \ - ((head)->hh.tbl->num_buckets * sizeof(UT_hash_bucket)) + \ - sizeof(UT_hash_table) + \ - (HASH_BLOOM_BYTELEN))) : 0U) - -#ifdef NO_DECLTYPE -#define HASH_ITER(hh,head,el,tmp) \ -for(((el)=(head)), ((*(char**)(&(tmp)))=(char*)((head!=NULL)?(head)->hh.next:NULL)); \ - (el) != NULL; ((el)=(tmp)), ((*(char**)(&(tmp)))=(char*)((tmp!=NULL)?(tmp)->hh.next:NULL))) -#else -#define HASH_ITER(hh,head,el,tmp) \ -for(((el)=(head)), ((tmp)=DECLTYPE(el)((head!=NULL)?(head)->hh.next:NULL)); \ - (el) != NULL; ((el)=(tmp)), ((tmp)=DECLTYPE(el)((tmp!=NULL)?(tmp)->hh.next:NULL))) -#endif - -/* obtain a count of items in the hash */ -#define HASH_COUNT(head) HASH_CNT(hh,head) -#define HASH_CNT(hh,head) ((head != NULL)?((head)->hh.tbl->num_items):0U) - -typedef struct UT_hash_bucket { - struct UT_hash_handle *hh_head; - unsigned count; - - /* expand_mult is normally set to 0. In this situation, the max chain length - * threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If - * the bucket's chain exceeds this length, bucket expansion is triggered). - * However, setting expand_mult to a non-zero value delays bucket expansion - * (that would be triggered by additions to this particular bucket) - * until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH. - * (The multiplier is simply expand_mult+1). The whole idea of this - * multiplier is to reduce bucket expansions, since they are expensive, in - * situations where we know that a particular bucket tends to be overused. - * It is better to let its chain length grow to a longer yet-still-bounded - * value, than to do an O(n) bucket expansion too often. - */ - unsigned expand_mult; - -} UT_hash_bucket; - -/* random signature used only to find hash tables in external analysis */ -#define HASH_SIGNATURE 0xa0111fe1u -#define HASH_BLOOM_SIGNATURE 0xb12220f2u - -typedef struct UT_hash_table { - UT_hash_bucket *buckets; - unsigned num_buckets, log2_num_buckets; - unsigned num_items; - struct UT_hash_handle *tail; /* tail hh in app order, for fast append */ - ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */ - - /* in an ideal situation (all buckets used equally), no bucket would have - * more than ceil(#items/#buckets) items. that's the ideal chain length. */ - unsigned ideal_chain_maxlen; - - /* nonideal_items is the number of items in the hash whose chain position - * exceeds the ideal chain maxlen. these items pay the penalty for an uneven - * hash distribution; reaching them in a chain traversal takes >ideal steps */ - unsigned nonideal_items; - - /* ineffective expands occur when a bucket doubling was performed, but - * afterward, more than half the items in the hash had nonideal chain - * positions. If this happens on two consecutive expansions we inhibit any - * further expansion, as it's not helping; this happens when the hash - * function isn't a good fit for the key domain. When expansion is inhibited - * the hash will still work, albeit no longer in constant time. */ - unsigned ineff_expands, noexpand; - - uint32_t signature; /* used only to find hash tables in external analysis */ -#ifdef HASH_BLOOM - uint32_t bloom_sig; /* used only to test bloom exists in external analysis */ - uint8_t *bloom_bv; - uint8_t bloom_nbits; -#endif - -} UT_hash_table; - -typedef struct UT_hash_handle { - struct UT_hash_table *tbl; - void *prev; /* prev element in app order */ - void *next; /* next element in app order */ - struct UT_hash_handle *hh_prev; /* previous hh in bucket order */ - struct UT_hash_handle *hh_next; /* next hh in bucket order */ - void *key; /* ptr to enclosing struct's key */ - unsigned keylen; /* enclosing struct's key len */ - unsigned hashv; /* result of hash-fcn(key) */ -} UT_hash_handle; - -#endif /* UTHASH_H */ From a6859a08d3fdfd9d653333107e381bdcaab6e8a3 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Thu, 16 Feb 2017 22:48:16 +0100 Subject: [PATCH 34/56] Remove getrlimit from poll_eventloop No use to check for this limit, because the filedescriptor is already open. --- configure.ac | 1 - spec/example/Makefile.in | 24 +-- src/Makefile.in | 357 ++++++++++++--------------------- src/extension/poll_eventloop.c | 25 +-- src/extension/poll_eventloop.h | 1 - src/test/Makefile.in | 71 ++----- src/tools/Makefile.in | 7 +- 7 files changed, 166 insertions(+), 320 deletions(-) diff --git a/configure.ac b/configure.ac index 4b50c13c..555b7792 100644 --- a/configure.ac +++ b/configure.ac @@ -217,7 +217,6 @@ esac DEFAULT_EVENTLOOP=select_eventloop AC_CHECK_HEADERS([sys/poll.h poll.h sys/resource.h],,, [AC_INCLUDES_DEFAULT]) -AC_CHECK_FUNCS([getrlimit]) AC_ARG_ENABLE(poll-eventloop, AC_HELP_STRING([--disable-poll-eventloop], [Disable default eventloop based on poll (default=enabled if available)])) case "$enable_poll_eventloop" in no) diff --git a/spec/example/Makefile.in b/spec/example/Makefile.in index 8ff7f2d1..7bf5e016 100644 --- a/spec/example/Makefile.in +++ b/spec/example/Makefile.in @@ -149,24 +149,16 @@ depend: # Dependencies for the examples example-all-functions.lo example-all-functions.o: $(srcdir)/example-all-functions.c $(srcdir)/getdns_libevent.h \ - ../../src/config.h \ - ../../src/getdns/getdns.h \ - $(srcdir)/../../src/getdns/getdns_ext_libevent.h \ - ../../src/getdns/getdns_extra.h -example-reverse.lo example-reverse.o: $(srcdir)/example-reverse.c $(srcdir)/getdns_libevent.h \ - ../../src/config.h \ - ../../src/getdns/getdns.h \ - $(srcdir)/../../src/getdns/getdns_ext_libevent.h \ + ../../src/config.h ../../src/getdns/getdns.h \ + $(srcdir)/../../src/getdns/getdns_ext_libevent.h ../../src/getdns/getdns_extra.h +example-reverse.lo example-reverse.o: $(srcdir)/example-reverse.c $(srcdir)/getdns_libevent.h ../../src/config.h \ + ../../src/getdns/getdns.h $(srcdir)/../../src/getdns/getdns_ext_libevent.h \ ../../src/getdns/getdns_extra.h example-simple-answers.lo example-simple-answers.o: $(srcdir)/example-simple-answers.c $(srcdir)/getdns_libevent.h \ - ../../src/config.h \ - ../../src/getdns/getdns.h \ - $(srcdir)/../../src/getdns/getdns_ext_libevent.h \ - ../../src/getdns/getdns_extra.h + ../../src/config.h ../../src/getdns/getdns.h \ + $(srcdir)/../../src/getdns/getdns_ext_libevent.h ../../src/getdns/getdns_extra.h example-synchronous.lo example-synchronous.o: $(srcdir)/example-synchronous.c $(srcdir)/getdns_core_only.h \ ../../src/getdns/getdns.h -example-tree.lo example-tree.o: $(srcdir)/example-tree.c $(srcdir)/getdns_libevent.h \ - ../../src/config.h \ - ../../src/getdns/getdns.h \ - $(srcdir)/../../src/getdns/getdns_ext_libevent.h \ +example-tree.lo example-tree.o: $(srcdir)/example-tree.c $(srcdir)/getdns_libevent.h ../../src/config.h \ + ../../src/getdns/getdns.h $(srcdir)/../../src/getdns/getdns_ext_libevent.h \ ../../src/getdns/getdns_extra.h diff --git a/src/Makefile.in b/src/Makefile.in index 33a6c946..6c5375e3 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -215,236 +215,143 @@ depend: FORCE: # Dependencies for gldns, utils, the extensions and compat functions -const-info.lo const-info.o: $(srcdir)/const-info.c \ - getdns/getdns.h \ - getdns/getdns_extra.h \ - $(srcdir)/const-info.h -context.lo context.o: $(srcdir)/context.c \ - config.h \ - $(srcdir)/debug.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/context.h \ - getdns/getdns.h \ - getdns/getdns_extra.h \ - $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h \ - $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h \ - $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ - $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/list.h $(srcdir)/dict.h \ - $(srcdir)/pubkey-pinning.h -convert.lo convert.o: $(srcdir)/convert.c \ - config.h \ - getdns/getdns.h \ - getdns/getdns_extra.h \ - $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ - $(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \ - $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h \ - $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/wire2str.h \ +const-info.lo const-info.o: $(srcdir)/const-info.c getdns/getdns.h getdns/getdns_extra.h \ + getdns/getdns.h $(srcdir)/const-info.h +context.lo context.o: $(srcdir)/context.c config.h $(srcdir)/debug.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \ + $(srcdir)/gldns/wire2str.h $(srcdir)/context.h getdns/getdns.h getdns/getdns_extra.h \ + getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ + $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ + getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h \ + $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ + $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/list.h $(srcdir)/dict.h $(srcdir)/pubkey-pinning.h +convert.lo convert.o: $(srcdir)/convert.c config.h getdns/getdns.h getdns/getdns_extra.h \ + getdns/getdns.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ + $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ + getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h \ + $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/wire2str.h \ $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/parseutil.h $(srcdir)/const-info.h $(srcdir)/dict.h \ $(srcdir)/list.h $(srcdir)/jsmn/jsmn.h $(srcdir)/convert.h -dict.lo dict.o: $(srcdir)/dict.c \ - config.h \ - $(srcdir)/types-internal.h \ - getdns/getdns.h \ - getdns/getdns_extra.h \ - $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h \ - $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h \ - $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ - $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/const-info.h $(srcdir)/gldns/wire2str.h -dnssec.lo dnssec.o: $(srcdir)/dnssec.c \ - config.h \ - $(srcdir)/debug.h \ - getdns/getdns.h \ - $(srcdir)/context.h \ - getdns/getdns_extra.h \ - $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h \ - $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h \ - $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ - $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \ - $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/parseutil.h $(srcdir)/general.h $(srcdir)/dict.h \ - $(srcdir)/list.h $(srcdir)/util/val_secalgo.h -general.lo general.o: $(srcdir)/general.c \ - config.h \ - $(srcdir)/general.h \ - getdns/getdns.h \ - $(srcdir)/types-internal.h \ - getdns/getdns_extra.h \ - $(srcdir)/util/rbtree.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/gldns/wire2str.h $(srcdir)/context.h \ - $(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \ - $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h \ - $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h \ - $(srcdir)/dict.h $(srcdir)/mdns.h -list.lo list.o: $(srcdir)/list.c $(srcdir)/types-internal.h \ - getdns/getdns.h \ - getdns/getdns_extra.h \ - $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h \ - config.h \ - $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \ - $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h \ - $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/list.h $(srcdir)/dict.h -mdns.lo mdns.o: $(srcdir)/mdns.c \ - config.h \ - $(srcdir)/debug.h $(srcdir)/context.h \ - getdns/getdns.h \ - getdns/getdns_extra.h \ - $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h \ - $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h \ - $(srcdir)/server.h $(srcdir)/general.h $(srcdir)/gldns/pkthdr.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ - $(srcdir)/gldns/gbuffer.h $(srcdir)/mdns.h -pubkey-pinning.lo pubkey-pinning.o: $(srcdir)/pubkey-pinning.c \ - config.h \ - $(srcdir)/debug.h \ - getdns/getdns.h \ - $(srcdir)/context.h \ - getdns/getdns_extra.h \ - $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h \ - $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h \ +dict.lo dict.o: $(srcdir)/dict.c config.h $(srcdir)/types-internal.h getdns/getdns.h \ + getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h \ + $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \ + $(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ + $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ + $(srcdir)/gldns/pkthdr.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/const-info.h $(srcdir)/gldns/wire2str.h +dnssec.lo dnssec.o: $(srcdir)/dnssec.c config.h $(srcdir)/debug.h getdns/getdns.h $(srcdir)/context.h \ + getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ + $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ + getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h \ + $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ + $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h \ + $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/parseutil.h $(srcdir)/general.h $(srcdir)/dict.h $(srcdir)/list.h \ + $(srcdir)/util/val_secalgo.h +general.lo general.o: $(srcdir)/general.c config.h $(srcdir)/general.h getdns/getdns.h $(srcdir)/types-internal.h \ + getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/ub_loop.h $(srcdir)/debug.h \ + $(srcdir)/gldns/wire2str.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \ + $(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ + $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/dict.h $(srcdir)/mdns.h +list.lo list.o: $(srcdir)/list.c $(srcdir)/types-internal.h getdns/getdns.h getdns/getdns_extra.h \ + getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h config.h $(srcdir)/context.h \ + $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ + getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h \ + $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/list.h $(srcdir)/dict.h +mdns.lo mdns.o: $(srcdir)/mdns.c config.h $(srcdir)/debug.h $(srcdir)/context.h getdns/getdns.h \ + getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ + $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ + getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/general.h \ + $(srcdir)/gldns/pkthdr.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ + $(srcdir)/mdns.h +pubkey-pinning.lo pubkey-pinning.o: $(srcdir)/pubkey-pinning.c config.h $(srcdir)/debug.h getdns/getdns.h \ + $(srcdir)/context.h getdns/getdns.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ + $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h config.h \ + $(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ + $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ $(srcdir)/gldns/pkthdr.h -request-internal.lo request-internal.o: $(srcdir)/request-internal.c \ - config.h \ - $(srcdir)/types-internal.h \ - getdns/getdns.h \ - getdns/getdns_extra.h \ - $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h \ - $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h \ - $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ - $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/dict.h $(srcdir)/convert.h -rr-dict.lo rr-dict.o: $(srcdir)/rr-dict.c $(srcdir)/rr-dict.h \ - config.h \ - getdns/getdns.h \ - $(srcdir)/gldns/gbuffer.h $(srcdir)/util-internal.h $(srcdir)/context.h \ - getdns/getdns_extra.h \ - $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h \ - $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h \ - $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dict.h -rr-iter.lo rr-iter.o: $(srcdir)/rr-iter.c $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ - config.h \ - getdns/getdns.h \ +request-internal.lo request-internal.o: $(srcdir)/request-internal.c config.h $(srcdir)/types-internal.h \ + getdns/getdns.h getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \ + $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \ + $(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ + $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ + $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/dict.h \ + $(srcdir)/convert.h +rr-dict.lo rr-dict.o: $(srcdir)/rr-dict.c $(srcdir)/rr-dict.h config.h getdns/getdns.h $(srcdir)/gldns/gbuffer.h \ + $(srcdir)/util-internal.h $(srcdir)/context.h getdns/getdns_extra.h getdns/getdns.h \ + $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h config.h \ + $(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ + $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dict.h +rr-iter.lo rr-iter.o: $(srcdir)/rr-iter.c $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h config.h getdns/getdns.h \ $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h -server.lo server.o: $(srcdir)/server.c \ - config.h \ - getdns/getdns_extra.h \ - getdns/getdns.h \ - $(srcdir)/context.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h \ - $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h \ - $(srcdir)/debug.h $(srcdir)/server.h -stub.lo stub.o: $(srcdir)/stub.c \ - config.h \ - $(srcdir)/debug.h $(srcdir)/stub.h \ - getdns/getdns.h \ - $(srcdir)/types-internal.h \ - getdns/getdns_extra.h \ - $(srcdir)/util/rbtree.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h \ - $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ - $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \ - $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util-internal.h \ - $(srcdir)/general.h $(srcdir)/pubkey-pinning.h -sync.lo sync.o: $(srcdir)/sync.c \ - getdns/getdns.h \ - config.h \ - $(srcdir)/context.h \ - getdns/getdns_extra.h \ - $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h \ - $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h \ - $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/general.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ - $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h \ - $(srcdir)/gldns/wire2str.h -ub_loop.lo ub_loop.o: $(srcdir)/ub_loop.c $(srcdir)/ub_loop.h \ - config.h \ - getdns/getdns.h \ - getdns/getdns_extra.h \ - $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/debug.h -util-internal.lo util-internal.o: $(srcdir)/util-internal.c \ - config.h \ - getdns/getdns.h \ - $(srcdir)/dict.h $(srcdir)/util/rbtree.h $(srcdir)/types-internal.h \ - getdns/getdns_extra.h \ - $(srcdir)/list.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h \ - $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/util/uthash.h $(srcdir)/ub_loop.h \ - $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ - $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h -gbuffer.lo gbuffer.o: $(srcdir)/gldns/gbuffer.c \ - config.h \ +server.lo server.o: $(srcdir)/server.c config.h getdns/getdns_extra.h getdns/getdns.h \ + $(srcdir)/context.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ + $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ + getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h +stub.lo stub.o: $(srcdir)/stub.c config.h $(srcdir)/debug.h $(srcdir)/stub.h getdns/getdns.h $(srcdir)/types-internal.h \ + getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/gldns/gbuffer.h \ + $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \ + $(srcdir)/gldns/wire2str.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/context.h \ + $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ + getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h \ + $(srcdir)/util-internal.h $(srcdir)/general.h $(srcdir)/pubkey-pinning.h +sync.lo sync.o: $(srcdir)/sync.c getdns/getdns.h config.h $(srcdir)/context.h getdns/getdns_extra.h \ + getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ + $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ + getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h \ + $(srcdir)/general.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ + $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/gldns/wire2str.h +ub_loop.lo ub_loop.o: $(srcdir)/ub_loop.c $(srcdir)/ub_loop.h config.h getdns/getdns.h \ + getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ + $(srcdir)/debug.h +util-internal.lo util-internal.o: $(srcdir)/util-internal.c config.h getdns/getdns.h $(srcdir)/dict.h \ + $(srcdir)/util/rbtree.h $(srcdir)/types-internal.h getdns/getdns_extra.h getdns/getdns.h \ + $(srcdir)/list.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \ + $(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ + $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ + $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h +version.lo version.o: version.c +gbuffer.lo gbuffer.o: $(srcdir)/gldns/gbuffer.c config.h $(srcdir)/gldns/gbuffer.h +keyraw.lo keyraw.o: $(srcdir)/gldns/keyraw.c config.h $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/rrdef.h +parse.lo parse.o: $(srcdir)/gldns/parse.c config.h $(srcdir)/gldns/parse.h $(srcdir)/gldns/parseutil.h \ $(srcdir)/gldns/gbuffer.h -keyraw.lo keyraw.o: $(srcdir)/gldns/keyraw.c \ - config.h \ - $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/rrdef.h -parse.lo parse.o: $(srcdir)/gldns/parse.c \ - config.h \ - $(srcdir)/gldns/parse.h $(srcdir)/gldns/parseutil.h $(srcdir)/gldns/gbuffer.h -parseutil.lo parseutil.o: $(srcdir)/gldns/parseutil.c \ - config.h \ - $(srcdir)/gldns/parseutil.h -rrdef.lo rrdef.o: $(srcdir)/gldns/rrdef.c \ - config.h \ - $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/parseutil.h -str2wire.lo str2wire.o: $(srcdir)/gldns/str2wire.c \ - config.h \ - $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/gbuffer.h \ - $(srcdir)/gldns/parse.h $(srcdir)/gldns/parseutil.h -wire2str.lo wire2str.o: $(srcdir)/gldns/wire2str.c \ - config.h \ - $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/pkthdr.h \ - $(srcdir)/gldns/parseutil.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/keyraw.h -arc4_lock.lo arc4_lock.o: $(srcdir)/compat/arc4_lock.c \ - config.h -arc4random.lo arc4random.o: $(srcdir)/compat/arc4random.c \ - config.h \ - $(srcdir)/compat/chacha_private.h -arc4random_uniform.lo arc4random_uniform.o: $(srcdir)/compat/arc4random_uniform.c \ - config.h -explicit_bzero.lo explicit_bzero.o: $(srcdir)/compat/explicit_bzero.c \ - config.h -getentropy_linux.lo getentropy_linux.o: $(srcdir)/compat/getentropy_linux.c \ - config.h -getentropy_osx.lo getentropy_osx.o: $(srcdir)/compat/getentropy_osx.c \ - config.h -getentropy_solaris.lo getentropy_solaris.o: $(srcdir)/compat/getentropy_solaris.c \ - config.h +parseutil.lo parseutil.o: $(srcdir)/gldns/parseutil.c config.h $(srcdir)/gldns/parseutil.h +rrdef.lo rrdef.o: $(srcdir)/gldns/rrdef.c config.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/parseutil.h +str2wire.lo str2wire.o: $(srcdir)/gldns/str2wire.c config.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \ + $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/parse.h $(srcdir)/gldns/parseutil.h +wire2str.lo wire2str.o: $(srcdir)/gldns/wire2str.c config.h $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/str2wire.h \ + $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/parseutil.h $(srcdir)/gldns/gbuffer.h \ + $(srcdir)/gldns/keyraw.h +arc4_lock.lo arc4_lock.o: $(srcdir)/compat/arc4_lock.c config.h +arc4random.lo arc4random.o: $(srcdir)/compat/arc4random.c config.h $(srcdir)/compat/chacha_private.h +arc4random_uniform.lo arc4random_uniform.o: $(srcdir)/compat/arc4random_uniform.c config.h +explicit_bzero.lo explicit_bzero.o: $(srcdir)/compat/explicit_bzero.c config.h +getentropy_linux.lo getentropy_linux.o: $(srcdir)/compat/getentropy_linux.c config.h +getentropy_osx.lo getentropy_osx.o: $(srcdir)/compat/getentropy_osx.c config.h +getentropy_solaris.lo getentropy_solaris.o: $(srcdir)/compat/getentropy_solaris.c config.h getentropy_win.lo getentropy_win.o: $(srcdir)/compat/getentropy_win.c -gettimeofday.lo gettimeofday.o: $(srcdir)/compat/gettimeofday.c \ - config.h -inet_ntop.lo inet_ntop.o: $(srcdir)/compat/inet_ntop.c \ - config.h -inet_pton.lo inet_pton.o: $(srcdir)/compat/inet_pton.c \ - config.h -sha512.lo sha512.o: $(srcdir)/compat/sha512.c \ - config.h -strlcpy.lo strlcpy.o: $(srcdir)/compat/strlcpy.c \ - config.h -rbtree.lo rbtree.o: $(srcdir)/util/rbtree.c \ - config.h \ - $(srcdir)/util/log.h $(srcdir)/debug.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/rbtree.h -val_secalgo.lo val_secalgo.o: $(srcdir)/util/val_secalgo.c \ - config.h \ - $(srcdir)/util/val_secalgo.h $(srcdir)/util/log.h $(srcdir)/debug.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/keyraw.h \ - $(srcdir)/gldns/gbuffer.h +gettimeofday.lo gettimeofday.o: $(srcdir)/compat/gettimeofday.c config.h +inet_ntop.lo inet_ntop.o: $(srcdir)/compat/inet_ntop.c config.h +inet_pton.lo inet_pton.o: $(srcdir)/compat/inet_pton.c config.h +sha512.lo sha512.o: $(srcdir)/compat/sha512.c config.h +strlcpy.lo strlcpy.o: $(srcdir)/compat/strlcpy.c config.h +rbtree.lo rbtree.o: $(srcdir)/util/rbtree.c config.h $(srcdir)/util/log.h $(srcdir)/debug.h config.h \ + $(srcdir)/util/fptr_wlist.h $(srcdir)/util/rbtree.h +val_secalgo.lo val_secalgo.o: $(srcdir)/util/val_secalgo.c config.h $(srcdir)/util/val_secalgo.h $(srcdir)/util/log.h \ + $(srcdir)/debug.h config.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/gbuffer.h jsmn.lo jsmn.o: $(srcdir)/jsmn/jsmn.c $(srcdir)/jsmn/jsmn.h -libev.lo libev.o: $(srcdir)/extension/libev.c \ - config.h \ - $(srcdir)/types-internal.h \ - getdns/getdns.h \ - getdns/getdns_extra.h \ - $(srcdir)/util/rbtree.h $(srcdir)/getdns/getdns_ext_libev.h -libevent.lo libevent.o: $(srcdir)/extension/libevent.c \ - config.h \ - $(srcdir)/types-internal.h \ - getdns/getdns.h \ - getdns/getdns_extra.h \ - $(srcdir)/util/rbtree.h $(srcdir)/getdns/getdns_ext_libevent.h -libuv.lo libuv.o: $(srcdir)/extension/libuv.c \ - config.h \ - $(srcdir)/debug.h $(srcdir)/types-internal.h \ - getdns/getdns.h \ - getdns/getdns_extra.h \ - $(srcdir)/util/rbtree.h $(srcdir)/getdns/getdns_ext_libuv.h -poll_eventloop.lo poll_eventloop.o: $(srcdir)/extension/poll_eventloop.c \ - config.h \ - $(srcdir)/extension/poll_eventloop.h \ - getdns/getdns.h \ - getdns/getdns_extra.h \ - $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/uthash.h $(srcdir)/debug.h -select_eventloop.lo select_eventloop.o: $(srcdir)/extension/select_eventloop.c \ - config.h \ - $(srcdir)/extension/select_eventloop.h \ - getdns/getdns.h \ - getdns/getdns_extra.h \ - $(srcdir)/debug.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h +libev.lo libev.o: $(srcdir)/extension/libev.c config.h $(srcdir)/types-internal.h getdns/getdns.h \ + getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \ + $(srcdir)/getdns/getdns_ext_libev.h getdns/getdns_extra.h +libevent.lo libevent.o: $(srcdir)/extension/libevent.c config.h $(srcdir)/types-internal.h \ + getdns/getdns.h getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \ + $(srcdir)/getdns/getdns_ext_libevent.h getdns/getdns_extra.h +libuv.lo libuv.o: $(srcdir)/extension/libuv.c config.h $(srcdir)/debug.h config.h $(srcdir)/types-internal.h \ + getdns/getdns.h getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \ + $(srcdir)/getdns/getdns_ext_libuv.h getdns/getdns_extra.h +poll_eventloop.lo poll_eventloop.o: $(srcdir)/extension/poll_eventloop.c config.h \ + $(srcdir)/extension/poll_eventloop.h getdns/getdns.h getdns/getdns_extra.h \ + $(srcdir)/types-internal.h getdns/getdns.h getdns/getdns_extra.h $(srcdir)/util/rbtree.h \ + $(srcdir)/debug.h config.h +select_eventloop.lo select_eventloop.o: $(srcdir)/extension/select_eventloop.c config.h \ + $(srcdir)/extension/select_eventloop.h getdns/getdns.h getdns/getdns_extra.h \ + $(srcdir)/debug.h config.h $(srcdir)/types-internal.h getdns/getdns.h getdns/getdns_extra.h \ + $(srcdir)/util/rbtree.h diff --git a/src/extension/poll_eventloop.c b/src/extension/poll_eventloop.c index c55c8ec9..d4cc8727 100644 --- a/src/extension/poll_eventloop.c +++ b/src/extension/poll_eventloop.c @@ -153,20 +153,12 @@ poll_eventloop_schedule(getdns_eventloop *loop, { _getdns_poll_eventloop *poll_loop = (_getdns_poll_eventloop *)loop; - DEBUG_SCHED( "%s(loop: %p, fd: %d, timeout: %"PRIu64", event: %p, max_fds: %d)\n" - , __FUNC__, (void *)loop, fd, timeout, (void *)event, poll_loop->max_fds); + DEBUG_SCHED( "%s(loop: %p, fd: %d, timeout: %"PRIu64", event: %p)\n" + , __FUNC__, (void *)loop, fd, timeout, (void *)event); if (!loop || !event) return GETDNS_RETURN_INVALID_PARAMETER; - -#ifdef HAVE_GETRLIMIT - if (fd >= (int)poll_loop->max_fds) { - DEBUG_SCHED( "ERROR: fd %d >= max_fds: %d!\n" - , fd, poll_loop->max_fds); - return GETDNS_RETURN_GENERIC_ERROR; - } -#endif if (fd >= 0 && !(event->read_cb || event->write_cb)) { DEBUG_SCHED("WARNING: fd event without " "read or write cb!\n"); @@ -492,9 +484,6 @@ poll_eventloop_run(getdns_eventloop *loop) void _getdns_poll_eventloop_init(struct mem_funcs *mf, _getdns_poll_eventloop *loop) { -#ifdef HAVE_GETRLIMIT - struct rlimit rl; -#endif static getdns_eventloop_vmt poll_eventloop_vmt = { poll_eventloop_cleanup, poll_eventloop_schedule, @@ -506,16 +495,6 @@ _getdns_poll_eventloop_init(struct mem_funcs *mf, _getdns_poll_eventloop *loop) loop->loop.vmt = &poll_eventloop_vmt; loop->mf = *mf; -#ifdef HAVE_GETRLIMIT - if (getrlimit(RLIMIT_NOFILE, &rl) == 0) { - loop->max_fds = rl.rlim_cur; - } else { - DEBUG_SCHED("ERROR: could not obtain RLIMIT_NOFILE from getrlimit()\n"); -#endif - loop->max_fds = 0; -#if HAVE_GETRLIMIT - } -#endif loop->to_events_capacity = init_to_events_capacity; if ((loop->to_events = GETDNS_XMALLOC( *mf, _getdns_poll_event, init_to_events_capacity))) diff --git a/src/extension/poll_eventloop.h b/src/extension/poll_eventloop.h index 2643c30e..e4e4bb7e 100644 --- a/src/extension/poll_eventloop.h +++ b/src/extension/poll_eventloop.h @@ -46,7 +46,6 @@ typedef struct _getdns_poll_event { typedef struct _getdns_poll_eventloop { getdns_eventloop loop; struct mem_funcs mf; - unsigned int max_fds; struct pollfd *pfds; size_t fd_events_capacity; diff --git a/src/test/Makefile.in b/src/test/Makefile.in index 758435c1..c481fdab 100644 --- a/src/test/Makefile.in +++ b/src/test/Makefile.in @@ -216,13 +216,10 @@ depend: .PHONY: clean test # Dependencies for the unit tests -check_getdns.lo check_getdns.o: $(srcdir)/check_getdns.c \ - ../getdns/getdns.h \ - $(srcdir)/check_getdns_common.h \ - ../getdns/getdns_extra.h \ - $(srcdir)/check_getdns_address.h $(srcdir)/check_getdns_address_sync.h \ - $(srcdir)/check_getdns_cancel_callback.h $(srcdir)/check_getdns_context_create.h \ - $(srcdir)/check_getdns_context_destroy.h \ +check_getdns.lo check_getdns.o: $(srcdir)/check_getdns.c ../getdns/getdns.h $(srcdir)/check_getdns_common.h \ + ../getdns/getdns_extra.h $(srcdir)/check_getdns_address.h \ + $(srcdir)/check_getdns_address_sync.h $(srcdir)/check_getdns_cancel_callback.h \ + $(srcdir)/check_getdns_context_create.h $(srcdir)/check_getdns_context_destroy.h \ $(srcdir)/check_getdns_context_set_context_update_callback.h \ $(srcdir)/check_getdns_context_set_dns_transport.h \ $(srcdir)/check_getdns_context_set_timeout.h \ @@ -242,58 +239,34 @@ check_getdns.lo check_getdns.o: $(srcdir)/check_getdns.c \ $(srcdir)/check_getdns_list_get_list.h $(srcdir)/check_getdns_pretty_print_dict.h \ $(srcdir)/check_getdns_service.h $(srcdir)/check_getdns_service_sync.h \ $(srcdir)/check_getdns_transport.h -check_getdns_common.lo check_getdns_common.o: $(srcdir)/check_getdns_common.c \ - ../getdns/getdns.h \ - ../config.h \ - $(srcdir)/check_getdns_common.h \ - ../getdns/getdns_extra.h \ +check_getdns_common.lo check_getdns_common.o: $(srcdir)/check_getdns_common.c ../getdns/getdns.h \ + ../config.h $(srcdir)/check_getdns_common.h ../getdns/getdns_extra.h \ $(srcdir)/check_getdns_eventloop.h check_getdns_context_set_timeout.lo check_getdns_context_set_timeout.o: $(srcdir)/check_getdns_context_set_timeout.c \ $(srcdir)/check_getdns_context_set_timeout.h $(srcdir)/check_getdns_common.h \ - ../getdns/getdns.h \ - ../getdns/getdns_extra.h + ../getdns/getdns.h ../getdns/getdns_extra.h check_getdns_libev.lo check_getdns_libev.o: $(srcdir)/check_getdns_libev.c $(srcdir)/check_getdns_eventloop.h \ - ../config.h \ - ../getdns/getdns.h \ - $(srcdir)/../getdns/getdns_ext_libev.h \ - ../getdns/getdns_extra.h \ - $(srcdir)/check_getdns_common.h + ../config.h ../getdns/getdns.h $(srcdir)/../getdns/getdns_ext_libev.h \ + ../getdns/getdns_extra.h $(srcdir)/check_getdns_common.h check_getdns_libevent.lo check_getdns_libevent.o: $(srcdir)/check_getdns_libevent.c $(srcdir)/check_getdns_eventloop.h \ - ../config.h \ - ../getdns/getdns.h \ - $(srcdir)/../getdns/getdns_ext_libevent.h \ - ../getdns/getdns_extra.h \ - $(srcdir)/check_getdns_libevent.h $(srcdir)/check_getdns_common.h + ../config.h ../getdns/getdns.h $(srcdir)/../getdns/getdns_ext_libevent.h \ + ../getdns/getdns_extra.h $(srcdir)/check_getdns_libevent.h $(srcdir)/check_getdns_common.h check_getdns_libuv.lo check_getdns_libuv.o: $(srcdir)/check_getdns_libuv.c $(srcdir)/check_getdns_eventloop.h \ - ../config.h \ - ../getdns/getdns.h \ - $(srcdir)/../getdns/getdns_ext_libuv.h \ - ../getdns/getdns_extra.h \ - $(srcdir)/check_getdns_common.h + ../config.h ../getdns/getdns.h $(srcdir)/../getdns/getdns_ext_libuv.h \ + ../getdns/getdns_extra.h $(srcdir)/check_getdns_common.h check_getdns_selectloop.lo check_getdns_selectloop.o: $(srcdir)/check_getdns_selectloop.c \ - $(srcdir)/check_getdns_eventloop.h \ - ../config.h \ - ../getdns/getdns.h \ + $(srcdir)/check_getdns_eventloop.h ../config.h ../getdns/getdns.h \ ../getdns/getdns_extra.h check_getdns_transport.lo check_getdns_transport.o: $(srcdir)/check_getdns_transport.c \ - $(srcdir)/check_getdns_transport.h $(srcdir)/check_getdns_common.h \ - ../getdns/getdns.h \ + $(srcdir)/check_getdns_transport.h $(srcdir)/check_getdns_common.h ../getdns/getdns.h \ ../getdns/getdns_extra.h -scratchpad.template.lo scratchpad.template.o: scratchpad.template.c \ - ../getdns/getdns.h \ +scratchpad.template.lo scratchpad.template.o: scratchpad.template.c ../getdns/getdns.h \ ../getdns/getdns_extra.h testmessages.lo testmessages.o: $(srcdir)/testmessages.c $(srcdir)/testmessages.h -tests_dict.lo tests_dict.o: $(srcdir)/tests_dict.c $(srcdir)/testmessages.h \ - ../getdns/getdns.h -tests_list.lo tests_list.o: $(srcdir)/tests_list.c $(srcdir)/testmessages.h \ - ../getdns/getdns.h -tests_namespaces.lo tests_namespaces.o: $(srcdir)/tests_namespaces.c $(srcdir)/testmessages.h \ - ../getdns/getdns.h -tests_stub_async.lo tests_stub_async.o: $(srcdir)/tests_stub_async.c \ - ../config.h \ - $(srcdir)/testmessages.h \ - ../getdns/getdns.h \ - ../getdns/getdns_extra.h -tests_stub_sync.lo tests_stub_sync.o: $(srcdir)/tests_stub_sync.c $(srcdir)/testmessages.h \ - ../getdns/getdns.h \ +tests_dict.lo tests_dict.o: $(srcdir)/tests_dict.c $(srcdir)/testmessages.h ../getdns/getdns.h +tests_list.lo tests_list.o: $(srcdir)/tests_list.c $(srcdir)/testmessages.h ../getdns/getdns.h +tests_namespaces.lo tests_namespaces.o: $(srcdir)/tests_namespaces.c $(srcdir)/testmessages.h ../getdns/getdns.h +tests_stub_async.lo tests_stub_async.o: $(srcdir)/tests_stub_async.c ../config.h $(srcdir)/testmessages.h \ + ../getdns/getdns.h ../getdns/getdns_extra.h +tests_stub_sync.lo tests_stub_sync.o: $(srcdir)/tests_stub_sync.c $(srcdir)/testmessages.h ../getdns/getdns.h \ ../getdns/getdns_extra.h diff --git a/src/tools/Makefile.in b/src/tools/Makefile.in index d066e824..d98cf437 100644 --- a/src/tools/Makefile.in +++ b/src/tools/Makefile.in @@ -113,8 +113,5 @@ depend: .PHONY: clean test # Dependencies for getdns_query -getdns_query.lo getdns_query.o: $(srcdir)/getdns_query.c \ - ../config.h \ - $(srcdir)/../debug.h \ - ../getdns/getdns.h \ - ../getdns/getdns_extra.h +getdns_query.lo getdns_query.o: $(srcdir)/getdns_query.c ../config.h $(srcdir)/../debug.h ../config.h \ + ../getdns/getdns.h ../getdns/getdns_extra.h From 91dd991348168a18a377c4ad2325c01e989238e3 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Thu, 16 Feb 2017 22:55:15 +0100 Subject: [PATCH 35/56] Cancel requests without callback --- src/context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/context.c b/src/context.c index 66dcf6f9..b5eaf231 100644 --- a/src/context.c +++ b/src/context.c @@ -2918,7 +2918,7 @@ _getdns_context_cancel_request(getdns_context *context, /* do the cancel */ cancel_dns_req(dnsreq); - if (fire_callback) { + if (fire_callback && dnsreq->user_callback) { context->processing = 1; dnsreq->user_callback(context, GETDNS_CALLBACK_CANCEL, NULL, dnsreq->user_pointer, transaction_id); From df45a2f1c7bd47ef9e91153e6367b20967764c68 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Thu, 16 Feb 2017 23:03:31 +0100 Subject: [PATCH 36/56] Dependencies --- spec/example/Makefile.in | 24 ++- src/Makefile.in | 341 ++++++++++++++++++++++++--------------- src/test/Makefile.in | 71 +++++--- src/tools/Makefile.in | 7 +- 4 files changed, 285 insertions(+), 158 deletions(-) diff --git a/spec/example/Makefile.in b/spec/example/Makefile.in index 7bf5e016..8ff7f2d1 100644 --- a/spec/example/Makefile.in +++ b/spec/example/Makefile.in @@ -149,16 +149,24 @@ depend: # Dependencies for the examples example-all-functions.lo example-all-functions.o: $(srcdir)/example-all-functions.c $(srcdir)/getdns_libevent.h \ - ../../src/config.h ../../src/getdns/getdns.h \ - $(srcdir)/../../src/getdns/getdns_ext_libevent.h ../../src/getdns/getdns_extra.h -example-reverse.lo example-reverse.o: $(srcdir)/example-reverse.c $(srcdir)/getdns_libevent.h ../../src/config.h \ - ../../src/getdns/getdns.h $(srcdir)/../../src/getdns/getdns_ext_libevent.h \ + ../../src/config.h \ + ../../src/getdns/getdns.h \ + $(srcdir)/../../src/getdns/getdns_ext_libevent.h \ + ../../src/getdns/getdns_extra.h +example-reverse.lo example-reverse.o: $(srcdir)/example-reverse.c $(srcdir)/getdns_libevent.h \ + ../../src/config.h \ + ../../src/getdns/getdns.h \ + $(srcdir)/../../src/getdns/getdns_ext_libevent.h \ ../../src/getdns/getdns_extra.h example-simple-answers.lo example-simple-answers.o: $(srcdir)/example-simple-answers.c $(srcdir)/getdns_libevent.h \ - ../../src/config.h ../../src/getdns/getdns.h \ - $(srcdir)/../../src/getdns/getdns_ext_libevent.h ../../src/getdns/getdns_extra.h + ../../src/config.h \ + ../../src/getdns/getdns.h \ + $(srcdir)/../../src/getdns/getdns_ext_libevent.h \ + ../../src/getdns/getdns_extra.h example-synchronous.lo example-synchronous.o: $(srcdir)/example-synchronous.c $(srcdir)/getdns_core_only.h \ ../../src/getdns/getdns.h -example-tree.lo example-tree.o: $(srcdir)/example-tree.c $(srcdir)/getdns_libevent.h ../../src/config.h \ - ../../src/getdns/getdns.h $(srcdir)/../../src/getdns/getdns_ext_libevent.h \ +example-tree.lo example-tree.o: $(srcdir)/example-tree.c $(srcdir)/getdns_libevent.h \ + ../../src/config.h \ + ../../src/getdns/getdns.h \ + $(srcdir)/../../src/getdns/getdns_ext_libevent.h \ ../../src/getdns/getdns_extra.h diff --git a/src/Makefile.in b/src/Makefile.in index 6c5375e3..6f06858a 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -215,143 +215,232 @@ depend: FORCE: # Dependencies for gldns, utils, the extensions and compat functions -const-info.lo const-info.o: $(srcdir)/const-info.c getdns/getdns.h getdns/getdns_extra.h \ - getdns/getdns.h $(srcdir)/const-info.h -context.lo context.o: $(srcdir)/context.c config.h $(srcdir)/debug.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \ - $(srcdir)/gldns/wire2str.h $(srcdir)/context.h getdns/getdns.h getdns/getdns_extra.h \ - getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ - $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ - getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h \ +const-info.lo const-info.o: $(srcdir)/const-info.c \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/const-info.h +context.lo context.o: $(srcdir)/context.c \ + config.h \ + $(srcdir)/debug.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/context.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h \ + $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h \ $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/list.h $(srcdir)/dict.h $(srcdir)/pubkey-pinning.h -convert.lo convert.o: $(srcdir)/convert.c config.h getdns/getdns.h getdns/getdns_extra.h \ - getdns/getdns.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ - $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ - getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h \ - $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/wire2str.h \ - $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/parseutil.h $(srcdir)/const-info.h $(srcdir)/dict.h \ - $(srcdir)/list.h $(srcdir)/jsmn/jsmn.h $(srcdir)/convert.h -dict.lo dict.o: $(srcdir)/dict.c config.h $(srcdir)/types-internal.h getdns/getdns.h \ - getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h \ - $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \ - $(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ - $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ - $(srcdir)/gldns/pkthdr.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/const-info.h $(srcdir)/gldns/wire2str.h -dnssec.lo dnssec.o: $(srcdir)/dnssec.c config.h $(srcdir)/debug.h getdns/getdns.h $(srcdir)/context.h \ - getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ - $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ - getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h \ +convert.lo convert.o: $(srcdir)/convert.c \ + config.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ + $(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \ + $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ + $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/str2wire.h \ + $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/parseutil.h $(srcdir)/const-info.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/jsmn/jsmn.h \ + $(srcdir)/convert.h +dict.lo dict.o: $(srcdir)/dict.c \ + config.h \ + $(srcdir)/types-internal.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h \ + $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h \ + $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dict.h $(srcdir)/list.h \ + $(srcdir)/const-info.h $(srcdir)/gldns/wire2str.h +dnssec.lo dnssec.o: $(srcdir)/dnssec.c \ + config.h \ + $(srcdir)/debug.h \ + getdns/getdns.h \ + $(srcdir)/context.h \ + getdns/getdns_extra.h \ + $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h \ + $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h \ $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h \ $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/parseutil.h $(srcdir)/general.h $(srcdir)/dict.h $(srcdir)/list.h \ $(srcdir)/util/val_secalgo.h -general.lo general.o: $(srcdir)/general.c config.h $(srcdir)/general.h getdns/getdns.h $(srcdir)/types-internal.h \ - getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/ub_loop.h $(srcdir)/debug.h \ - $(srcdir)/gldns/wire2str.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \ - $(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ - $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ - $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/dict.h $(srcdir)/mdns.h -list.lo list.o: $(srcdir)/list.c $(srcdir)/types-internal.h getdns/getdns.h getdns/getdns_extra.h \ - getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h config.h $(srcdir)/context.h \ - $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ - getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h \ - $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/list.h $(srcdir)/dict.h -mdns.lo mdns.o: $(srcdir)/mdns.c config.h $(srcdir)/debug.h $(srcdir)/context.h getdns/getdns.h \ - getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ - $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ - getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/general.h \ +general.lo general.o: $(srcdir)/general.c \ + config.h \ + $(srcdir)/general.h \ + getdns/getdns.h \ + $(srcdir)/types-internal.h \ + getdns/getdns_extra.h \ + $(srcdir)/util/rbtree.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/gldns/wire2str.h $(srcdir)/context.h \ + $(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \ + $(srcdir)/types-internal.h $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ + $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/dict.h \ + $(srcdir)/mdns.h +list.lo list.o: $(srcdir)/list.c $(srcdir)/types-internal.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h \ + config.h \ + $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \ + $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ + $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/list.h $(srcdir)/dict.h +mdns.lo mdns.o: $(srcdir)/mdns.c \ + config.h \ + $(srcdir)/debug.h $(srcdir)/context.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h \ + $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/general.h \ $(srcdir)/gldns/pkthdr.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ $(srcdir)/mdns.h -pubkey-pinning.lo pubkey-pinning.o: $(srcdir)/pubkey-pinning.c config.h $(srcdir)/debug.h getdns/getdns.h \ - $(srcdir)/context.h getdns/getdns.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ - $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h config.h \ - $(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ - $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ - $(srcdir)/gldns/pkthdr.h -request-internal.lo request-internal.o: $(srcdir)/request-internal.c config.h $(srcdir)/types-internal.h \ - getdns/getdns.h getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \ - $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \ - $(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ - $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ - $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/dict.h \ - $(srcdir)/convert.h -rr-dict.lo rr-dict.o: $(srcdir)/rr-dict.c $(srcdir)/rr-dict.h config.h getdns/getdns.h $(srcdir)/gldns/gbuffer.h \ - $(srcdir)/util-internal.h $(srcdir)/context.h getdns/getdns_extra.h getdns/getdns.h \ - $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h config.h \ - $(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ - $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dict.h -rr-iter.lo rr-iter.o: $(srcdir)/rr-iter.c $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h config.h getdns/getdns.h \ +pubkey-pinning.lo pubkey-pinning.o: $(srcdir)/pubkey-pinning.c \ + config.h \ + $(srcdir)/debug.h \ + getdns/getdns.h \ + $(srcdir)/context.h \ + getdns/getdns_extra.h \ + $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h \ + $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h \ + $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h +request-internal.lo request-internal.o: $(srcdir)/request-internal.c \ + config.h \ + $(srcdir)/types-internal.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h \ + $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h \ + $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h \ + $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/dict.h $(srcdir)/convert.h +rr-dict.lo rr-dict.o: $(srcdir)/rr-dict.c $(srcdir)/rr-dict.h \ + config.h \ + getdns/getdns.h \ + $(srcdir)/gldns/gbuffer.h $(srcdir)/util-internal.h $(srcdir)/context.h \ + getdns/getdns_extra.h \ + $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h \ + $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h \ + $(srcdir)/rr-iter.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dict.h +rr-iter.lo rr-iter.o: $(srcdir)/rr-iter.c $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ + config.h \ + getdns/getdns.h \ $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h -server.lo server.o: $(srcdir)/server.c config.h getdns/getdns_extra.h getdns/getdns.h \ - $(srcdir)/context.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ - $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ - getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h -stub.lo stub.o: $(srcdir)/stub.c config.h $(srcdir)/debug.h $(srcdir)/stub.h getdns/getdns.h $(srcdir)/types-internal.h \ - getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/gldns/gbuffer.h \ - $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \ - $(srcdir)/gldns/wire2str.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/context.h \ - $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ - getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h \ - $(srcdir)/util-internal.h $(srcdir)/general.h $(srcdir)/pubkey-pinning.h -sync.lo sync.o: $(srcdir)/sync.c getdns/getdns.h config.h $(srcdir)/context.h getdns/getdns_extra.h \ - getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ - $(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ - getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h \ +server.lo server.o: $(srcdir)/server.c \ + config.h \ + getdns/getdns_extra.h \ + getdns/getdns.h \ + $(srcdir)/context.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h \ + $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h +stub.lo stub.o: $(srcdir)/stub.c \ + config.h \ + $(srcdir)/debug.h $(srcdir)/stub.h \ + getdns/getdns.h \ + $(srcdir)/types-internal.h \ + getdns/getdns_extra.h \ + $(srcdir)/util/rbtree.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h \ + $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ + $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \ + $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/general.h \ + $(srcdir)/pubkey-pinning.h +sync.lo sync.o: $(srcdir)/sync.c \ + getdns/getdns.h \ + config.h \ + $(srcdir)/context.h \ + getdns/getdns_extra.h \ + $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h \ + $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h \ $(srcdir)/general.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/gldns/wire2str.h -ub_loop.lo ub_loop.o: $(srcdir)/ub_loop.c $(srcdir)/ub_loop.h config.h getdns/getdns.h \ - getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ - $(srcdir)/debug.h -util-internal.lo util-internal.o: $(srcdir)/util-internal.c config.h getdns/getdns.h $(srcdir)/dict.h \ - $(srcdir)/util/rbtree.h $(srcdir)/types-internal.h getdns/getdns_extra.h getdns/getdns.h \ - $(srcdir)/list.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \ - $(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ - $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ - $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h -version.lo version.o: version.c -gbuffer.lo gbuffer.o: $(srcdir)/gldns/gbuffer.c config.h $(srcdir)/gldns/gbuffer.h -keyraw.lo keyraw.o: $(srcdir)/gldns/keyraw.c config.h $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/rrdef.h -parse.lo parse.o: $(srcdir)/gldns/parse.c config.h $(srcdir)/gldns/parse.h $(srcdir)/gldns/parseutil.h \ +ub_loop.lo ub_loop.o: $(srcdir)/ub_loop.c $(srcdir)/ub_loop.h \ + config.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/debug.h +util-internal.lo util-internal.o: $(srcdir)/util-internal.c \ + config.h \ + getdns/getdns.h \ + $(srcdir)/dict.h $(srcdir)/util/rbtree.h $(srcdir)/types-internal.h \ + getdns/getdns_extra.h \ + $(srcdir)/list.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h \ + $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h \ + $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/str2wire.h \ + $(srcdir)/gldns/rrdef.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h +gbuffer.lo gbuffer.o: $(srcdir)/gldns/gbuffer.c \ + config.h \ $(srcdir)/gldns/gbuffer.h -parseutil.lo parseutil.o: $(srcdir)/gldns/parseutil.c config.h $(srcdir)/gldns/parseutil.h -rrdef.lo rrdef.o: $(srcdir)/gldns/rrdef.c config.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/parseutil.h -str2wire.lo str2wire.o: $(srcdir)/gldns/str2wire.c config.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \ - $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/parse.h $(srcdir)/gldns/parseutil.h -wire2str.lo wire2str.o: $(srcdir)/gldns/wire2str.c config.h $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/str2wire.h \ - $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/parseutil.h $(srcdir)/gldns/gbuffer.h \ - $(srcdir)/gldns/keyraw.h -arc4_lock.lo arc4_lock.o: $(srcdir)/compat/arc4_lock.c config.h -arc4random.lo arc4random.o: $(srcdir)/compat/arc4random.c config.h $(srcdir)/compat/chacha_private.h -arc4random_uniform.lo arc4random_uniform.o: $(srcdir)/compat/arc4random_uniform.c config.h -explicit_bzero.lo explicit_bzero.o: $(srcdir)/compat/explicit_bzero.c config.h -getentropy_linux.lo getentropy_linux.o: $(srcdir)/compat/getentropy_linux.c config.h -getentropy_osx.lo getentropy_osx.o: $(srcdir)/compat/getentropy_osx.c config.h -getentropy_solaris.lo getentropy_solaris.o: $(srcdir)/compat/getentropy_solaris.c config.h +keyraw.lo keyraw.o: $(srcdir)/gldns/keyraw.c \ + config.h \ + $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/rrdef.h +parse.lo parse.o: $(srcdir)/gldns/parse.c \ + config.h \ + $(srcdir)/gldns/parse.h $(srcdir)/gldns/parseutil.h $(srcdir)/gldns/gbuffer.h +parseutil.lo parseutil.o: $(srcdir)/gldns/parseutil.c \ + config.h \ + $(srcdir)/gldns/parseutil.h +rrdef.lo rrdef.o: $(srcdir)/gldns/rrdef.c \ + config.h \ + $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/parseutil.h +str2wire.lo str2wire.o: $(srcdir)/gldns/str2wire.c \ + config.h \ + $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/gbuffer.h \ + $(srcdir)/gldns/parse.h $(srcdir)/gldns/parseutil.h +wire2str.lo wire2str.o: $(srcdir)/gldns/wire2str.c \ + config.h \ + $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/pkthdr.h \ + $(srcdir)/gldns/parseutil.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/keyraw.h +arc4_lock.lo arc4_lock.o: $(srcdir)/compat/arc4_lock.c \ + config.h +arc4random.lo arc4random.o: $(srcdir)/compat/arc4random.c \ + config.h \ + $(srcdir)/compat/chacha_private.h +arc4random_uniform.lo arc4random_uniform.o: $(srcdir)/compat/arc4random_uniform.c \ + config.h +explicit_bzero.lo explicit_bzero.o: $(srcdir)/compat/explicit_bzero.c \ + config.h +getentropy_linux.lo getentropy_linux.o: $(srcdir)/compat/getentropy_linux.c \ + config.h +getentropy_osx.lo getentropy_osx.o: $(srcdir)/compat/getentropy_osx.c \ + config.h +getentropy_solaris.lo getentropy_solaris.o: $(srcdir)/compat/getentropy_solaris.c \ + config.h getentropy_win.lo getentropy_win.o: $(srcdir)/compat/getentropy_win.c -gettimeofday.lo gettimeofday.o: $(srcdir)/compat/gettimeofday.c config.h -inet_ntop.lo inet_ntop.o: $(srcdir)/compat/inet_ntop.c config.h -inet_pton.lo inet_pton.o: $(srcdir)/compat/inet_pton.c config.h -sha512.lo sha512.o: $(srcdir)/compat/sha512.c config.h -strlcpy.lo strlcpy.o: $(srcdir)/compat/strlcpy.c config.h -rbtree.lo rbtree.o: $(srcdir)/util/rbtree.c config.h $(srcdir)/util/log.h $(srcdir)/debug.h config.h \ - $(srcdir)/util/fptr_wlist.h $(srcdir)/util/rbtree.h -val_secalgo.lo val_secalgo.o: $(srcdir)/util/val_secalgo.c config.h $(srcdir)/util/val_secalgo.h $(srcdir)/util/log.h \ - $(srcdir)/debug.h config.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/gbuffer.h +gettimeofday.lo gettimeofday.o: $(srcdir)/compat/gettimeofday.c \ + config.h +inet_ntop.lo inet_ntop.o: $(srcdir)/compat/inet_ntop.c \ + config.h +inet_pton.lo inet_pton.o: $(srcdir)/compat/inet_pton.c \ + config.h +sha512.lo sha512.o: $(srcdir)/compat/sha512.c \ + config.h +strlcpy.lo strlcpy.o: $(srcdir)/compat/strlcpy.c \ + config.h +rbtree.lo rbtree.o: $(srcdir)/util/rbtree.c \ + config.h \ + $(srcdir)/util/log.h $(srcdir)/debug.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/rbtree.h +val_secalgo.lo val_secalgo.o: $(srcdir)/util/val_secalgo.c \ + config.h \ + $(srcdir)/util/val_secalgo.h $(srcdir)/util/log.h $(srcdir)/debug.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/keyraw.h \ + $(srcdir)/gldns/gbuffer.h jsmn.lo jsmn.o: $(srcdir)/jsmn/jsmn.c $(srcdir)/jsmn/jsmn.h -libev.lo libev.o: $(srcdir)/extension/libev.c config.h $(srcdir)/types-internal.h getdns/getdns.h \ - getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \ - $(srcdir)/getdns/getdns_ext_libev.h getdns/getdns_extra.h -libevent.lo libevent.o: $(srcdir)/extension/libevent.c config.h $(srcdir)/types-internal.h \ - getdns/getdns.h getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \ - $(srcdir)/getdns/getdns_ext_libevent.h getdns/getdns_extra.h -libuv.lo libuv.o: $(srcdir)/extension/libuv.c config.h $(srcdir)/debug.h config.h $(srcdir)/types-internal.h \ - getdns/getdns.h getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \ - $(srcdir)/getdns/getdns_ext_libuv.h getdns/getdns_extra.h -poll_eventloop.lo poll_eventloop.o: $(srcdir)/extension/poll_eventloop.c config.h \ - $(srcdir)/extension/poll_eventloop.h getdns/getdns.h getdns/getdns_extra.h \ - $(srcdir)/types-internal.h getdns/getdns.h getdns/getdns_extra.h $(srcdir)/util/rbtree.h \ - $(srcdir)/debug.h config.h -select_eventloop.lo select_eventloop.o: $(srcdir)/extension/select_eventloop.c config.h \ - $(srcdir)/extension/select_eventloop.h getdns/getdns.h getdns/getdns_extra.h \ - $(srcdir)/debug.h config.h $(srcdir)/types-internal.h getdns/getdns.h getdns/getdns_extra.h \ - $(srcdir)/util/rbtree.h +libev.lo libev.o: $(srcdir)/extension/libev.c \ + config.h \ + $(srcdir)/types-internal.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/util/rbtree.h $(srcdir)/getdns/getdns_ext_libev.h +libevent.lo libevent.o: $(srcdir)/extension/libevent.c \ + config.h \ + $(srcdir)/types-internal.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/util/rbtree.h $(srcdir)/getdns/getdns_ext_libevent.h +libuv.lo libuv.o: $(srcdir)/extension/libuv.c \ + config.h \ + $(srcdir)/debug.h $(srcdir)/types-internal.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/util/rbtree.h $(srcdir)/getdns/getdns_ext_libuv.h +poll_eventloop.lo poll_eventloop.o: $(srcdir)/extension/poll_eventloop.c \ + config.h \ + $(srcdir)/extension/poll_eventloop.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/debug.h +select_eventloop.lo select_eventloop.o: $(srcdir)/extension/select_eventloop.c \ + config.h \ + $(srcdir)/extension/select_eventloop.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/debug.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h diff --git a/src/test/Makefile.in b/src/test/Makefile.in index c481fdab..758435c1 100644 --- a/src/test/Makefile.in +++ b/src/test/Makefile.in @@ -216,10 +216,13 @@ depend: .PHONY: clean test # Dependencies for the unit tests -check_getdns.lo check_getdns.o: $(srcdir)/check_getdns.c ../getdns/getdns.h $(srcdir)/check_getdns_common.h \ - ../getdns/getdns_extra.h $(srcdir)/check_getdns_address.h \ - $(srcdir)/check_getdns_address_sync.h $(srcdir)/check_getdns_cancel_callback.h \ - $(srcdir)/check_getdns_context_create.h $(srcdir)/check_getdns_context_destroy.h \ +check_getdns.lo check_getdns.o: $(srcdir)/check_getdns.c \ + ../getdns/getdns.h \ + $(srcdir)/check_getdns_common.h \ + ../getdns/getdns_extra.h \ + $(srcdir)/check_getdns_address.h $(srcdir)/check_getdns_address_sync.h \ + $(srcdir)/check_getdns_cancel_callback.h $(srcdir)/check_getdns_context_create.h \ + $(srcdir)/check_getdns_context_destroy.h \ $(srcdir)/check_getdns_context_set_context_update_callback.h \ $(srcdir)/check_getdns_context_set_dns_transport.h \ $(srcdir)/check_getdns_context_set_timeout.h \ @@ -239,34 +242,58 @@ check_getdns.lo check_getdns.o: $(srcdir)/check_getdns.c ../getdns/getdns.h $(sr $(srcdir)/check_getdns_list_get_list.h $(srcdir)/check_getdns_pretty_print_dict.h \ $(srcdir)/check_getdns_service.h $(srcdir)/check_getdns_service_sync.h \ $(srcdir)/check_getdns_transport.h -check_getdns_common.lo check_getdns_common.o: $(srcdir)/check_getdns_common.c ../getdns/getdns.h \ - ../config.h $(srcdir)/check_getdns_common.h ../getdns/getdns_extra.h \ +check_getdns_common.lo check_getdns_common.o: $(srcdir)/check_getdns_common.c \ + ../getdns/getdns.h \ + ../config.h \ + $(srcdir)/check_getdns_common.h \ + ../getdns/getdns_extra.h \ $(srcdir)/check_getdns_eventloop.h check_getdns_context_set_timeout.lo check_getdns_context_set_timeout.o: $(srcdir)/check_getdns_context_set_timeout.c \ $(srcdir)/check_getdns_context_set_timeout.h $(srcdir)/check_getdns_common.h \ - ../getdns/getdns.h ../getdns/getdns_extra.h + ../getdns/getdns.h \ + ../getdns/getdns_extra.h check_getdns_libev.lo check_getdns_libev.o: $(srcdir)/check_getdns_libev.c $(srcdir)/check_getdns_eventloop.h \ - ../config.h ../getdns/getdns.h $(srcdir)/../getdns/getdns_ext_libev.h \ - ../getdns/getdns_extra.h $(srcdir)/check_getdns_common.h + ../config.h \ + ../getdns/getdns.h \ + $(srcdir)/../getdns/getdns_ext_libev.h \ + ../getdns/getdns_extra.h \ + $(srcdir)/check_getdns_common.h check_getdns_libevent.lo check_getdns_libevent.o: $(srcdir)/check_getdns_libevent.c $(srcdir)/check_getdns_eventloop.h \ - ../config.h ../getdns/getdns.h $(srcdir)/../getdns/getdns_ext_libevent.h \ - ../getdns/getdns_extra.h $(srcdir)/check_getdns_libevent.h $(srcdir)/check_getdns_common.h + ../config.h \ + ../getdns/getdns.h \ + $(srcdir)/../getdns/getdns_ext_libevent.h \ + ../getdns/getdns_extra.h \ + $(srcdir)/check_getdns_libevent.h $(srcdir)/check_getdns_common.h check_getdns_libuv.lo check_getdns_libuv.o: $(srcdir)/check_getdns_libuv.c $(srcdir)/check_getdns_eventloop.h \ - ../config.h ../getdns/getdns.h $(srcdir)/../getdns/getdns_ext_libuv.h \ - ../getdns/getdns_extra.h $(srcdir)/check_getdns_common.h + ../config.h \ + ../getdns/getdns.h \ + $(srcdir)/../getdns/getdns_ext_libuv.h \ + ../getdns/getdns_extra.h \ + $(srcdir)/check_getdns_common.h check_getdns_selectloop.lo check_getdns_selectloop.o: $(srcdir)/check_getdns_selectloop.c \ - $(srcdir)/check_getdns_eventloop.h ../config.h ../getdns/getdns.h \ + $(srcdir)/check_getdns_eventloop.h \ + ../config.h \ + ../getdns/getdns.h \ ../getdns/getdns_extra.h check_getdns_transport.lo check_getdns_transport.o: $(srcdir)/check_getdns_transport.c \ - $(srcdir)/check_getdns_transport.h $(srcdir)/check_getdns_common.h ../getdns/getdns.h \ + $(srcdir)/check_getdns_transport.h $(srcdir)/check_getdns_common.h \ + ../getdns/getdns.h \ ../getdns/getdns_extra.h -scratchpad.template.lo scratchpad.template.o: scratchpad.template.c ../getdns/getdns.h \ +scratchpad.template.lo scratchpad.template.o: scratchpad.template.c \ + ../getdns/getdns.h \ ../getdns/getdns_extra.h testmessages.lo testmessages.o: $(srcdir)/testmessages.c $(srcdir)/testmessages.h -tests_dict.lo tests_dict.o: $(srcdir)/tests_dict.c $(srcdir)/testmessages.h ../getdns/getdns.h -tests_list.lo tests_list.o: $(srcdir)/tests_list.c $(srcdir)/testmessages.h ../getdns/getdns.h -tests_namespaces.lo tests_namespaces.o: $(srcdir)/tests_namespaces.c $(srcdir)/testmessages.h ../getdns/getdns.h -tests_stub_async.lo tests_stub_async.o: $(srcdir)/tests_stub_async.c ../config.h $(srcdir)/testmessages.h \ - ../getdns/getdns.h ../getdns/getdns_extra.h -tests_stub_sync.lo tests_stub_sync.o: $(srcdir)/tests_stub_sync.c $(srcdir)/testmessages.h ../getdns/getdns.h \ +tests_dict.lo tests_dict.o: $(srcdir)/tests_dict.c $(srcdir)/testmessages.h \ + ../getdns/getdns.h +tests_list.lo tests_list.o: $(srcdir)/tests_list.c $(srcdir)/testmessages.h \ + ../getdns/getdns.h +tests_namespaces.lo tests_namespaces.o: $(srcdir)/tests_namespaces.c $(srcdir)/testmessages.h \ + ../getdns/getdns.h +tests_stub_async.lo tests_stub_async.o: $(srcdir)/tests_stub_async.c \ + ../config.h \ + $(srcdir)/testmessages.h \ + ../getdns/getdns.h \ + ../getdns/getdns_extra.h +tests_stub_sync.lo tests_stub_sync.o: $(srcdir)/tests_stub_sync.c $(srcdir)/testmessages.h \ + ../getdns/getdns.h \ ../getdns/getdns_extra.h diff --git a/src/tools/Makefile.in b/src/tools/Makefile.in index d98cf437..d066e824 100644 --- a/src/tools/Makefile.in +++ b/src/tools/Makefile.in @@ -113,5 +113,8 @@ depend: .PHONY: clean test # Dependencies for getdns_query -getdns_query.lo getdns_query.o: $(srcdir)/getdns_query.c ../config.h $(srcdir)/../debug.h ../config.h \ - ../getdns/getdns.h ../getdns/getdns_extra.h +getdns_query.lo getdns_query.o: $(srcdir)/getdns_query.c \ + ../config.h \ + $(srcdir)/../debug.h \ + ../getdns/getdns.h \ + ../getdns/getdns_extra.h From 990800d9f952911e35fbf9fda089deef626884fe Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Fri, 17 Feb 2017 13:16:06 +0100 Subject: [PATCH 37/56] Bugfix poll_eventloop initialization error --- src/extension/poll_eventloop.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/src/extension/poll_eventloop.c b/src/extension/poll_eventloop.c index d4cc8727..9c151c57 100644 --- a/src/extension/poll_eventloop.c +++ b/src/extension/poll_eventloop.c @@ -51,7 +51,7 @@ static void *get_to_event(_getdns_poll_eventloop *loop, loop->to_events_free * 2); if (!to_events) return NULL; - (void) memset(&loop->to_events[loop->to_events_free], + (void) memset(&to_events[loop->to_events_free], 0, sizeof(_getdns_poll_event) * loop->to_events_free); @@ -78,6 +78,8 @@ static void *get_to_event(_getdns_poll_eventloop *loop, static void *get_fd_event(_getdns_poll_eventloop *loop, int fd, getdns_eventloop_event *event, uint64_t timeout_time) { + size_t i; + if (loop->fd_events_free == loop->fd_events_capacity) { if (loop->fd_events_free) { _getdns_poll_event *fd_events = GETDNS_XREALLOC( @@ -94,12 +96,16 @@ static void *get_fd_event(_getdns_poll_eventloop *loop, int fd, GETDNS_FREE(loop->mf, pfds); return NULL; } - (void) memset(&loop->fd_events[loop->fd_events_free], + (void) memset(&fd_events[loop->fd_events_free], 0, sizeof(_getdns_poll_event) * loop->fd_events_free); - (void) memset(&loop->pfds[loop->fd_events_free], - 0, sizeof(struct pollfd) * loop->fd_events_free); - + for ( i = loop->fd_events_free + ; i < loop->fd_events_free * 2 + ; i++) { + pfds[i].fd = -1; + pfds[i].events = 0; + pfds[i].revents = 0; + } loop->fd_events_capacity = loop->fd_events_free * 2; loop->fd_events = fd_events; loop->pfds = pfds; @@ -114,9 +120,11 @@ static void *get_fd_event(_getdns_poll_eventloop *loop, int fd, (void) memset(loop->fd_events, 0, sizeof(_getdns_poll_event) * init_fd_events_capacity); - (void) memset(loop->pfds, 0, - sizeof(struct pollfd) * init_fd_events_capacity); - + for (i = 0; i < init_fd_events_capacity; i++) { + loop->pfds[i].fd = -1; + loop->pfds[i].events = 0; + loop->pfds[i].revents = 0; + } loop->fd_events_capacity = init_fd_events_capacity; } } @@ -510,10 +518,15 @@ _getdns_poll_eventloop_init(struct mem_funcs *mf, _getdns_poll_eventloop *loop) *mf, _getdns_poll_event, init_fd_events_capacity)) && (loop->pfds = GETDNS_XMALLOC( *mf, struct pollfd, init_fd_events_capacity))) { + size_t i; + (void) memset(loop->fd_events, 0, sizeof(_getdns_poll_event) * init_fd_events_capacity); - (void) memset(loop->pfds, 0, - sizeof(struct pollfd) * init_fd_events_capacity); + for (i = 0; i < init_fd_events_capacity; i++) { + loop->pfds[i].fd = -1; + loop->pfds[i].events = 0; + loop->pfds[i].revents = 0; + } } else { loop->fd_events_capacity = 0; if (loop->fd_events) { From 6ed3d77523c11055dd86e7cc75b11b26d1d90411 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Fri, 17 Feb 2017 23:35:50 +0100 Subject: [PATCH 38/56] Cancel child validation chain dns_reqs on ... parent dns_req cancelation. --- src/context.c | 3 +++ src/dnssec.c | 33 +++++++++++++++++++++++++++++++++ src/dnssec.h | 1 + src/request-internal.c | 1 + src/types-internal.h | 4 ++++ 5 files changed, 42 insertions(+) diff --git a/src/context.c b/src/context.c index b5eaf231..830c4c53 100644 --- a/src/context.c +++ b/src/context.c @@ -2915,6 +2915,9 @@ _getdns_context_cancel_request(getdns_context *context, &context->outbound_requests, &transaction_id))) return GETDNS_RETURN_UNKNOWN_TRANSACTION; + if (dnsreq->chain) + _getdns_cancel_validation_chain(dnsreq); + /* do the cancel */ cancel_dns_req(dnsreq); diff --git a/src/dnssec.c b/src/dnssec.c index 0269fe3d..905f778d 100644 --- a/src/dnssec.c +++ b/src/dnssec.c @@ -3115,6 +3115,38 @@ static void check_chain_complete(chain_head *chain) _getdns_call_user_callback(dnsreq, response_dict); } +void _getdns_cancel_validation_chain(getdns_dns_req *dnsreq) +{ + chain_head *head, *next; + chain_node *node; + size_t node_count; + + for ( head = dnsreq->chain; head ; head = next ) { + next = head->next; + + for ( node_count = head->node_count, node = head->parent + ; node_count + ; node_count--, node = node->parent ) { + + if (node->dnskey_req) + _getdns_context_cancel_request( + node->dnskey_req->owner->context, + node->dnskey_req->owner->trans_id, 0); + + if (node->ds_req) + _getdns_context_cancel_request( + node->ds_req->owner->context, + node->ds_req->owner->trans_id, 0); + + if (node->soa_req) + _getdns_context_cancel_request( + node->soa_req->owner->context, + node->soa_req->owner->trans_id, 0); + } + GETDNS_FREE(head->my_mf, head); + } + dnsreq->chain = NULL; +} void _getdns_get_validation_chain(getdns_dns_req *dnsreq) { @@ -3152,6 +3184,7 @@ void _getdns_get_validation_chain(getdns_dns_req *dnsreq) for (chain_p = chain; chain_p; chain_p = chain_p->next) { if (chain_p->lock) chain_p->lock--; } + dnsreq->chain = chain; check_chain_complete(chain); } else { dnsreq->validating = 0; diff --git a/src/dnssec.h b/src/dnssec.h index 4237f933..b7becfe9 100644 --- a/src/dnssec.h +++ b/src/dnssec.h @@ -46,6 +46,7 @@ /* Do some additional requests to fetch the complete validation chain */ void _getdns_get_validation_chain(getdns_dns_req *dns_req); +void _getdns_cancel_validation_chain(getdns_dns_req *dns_req); uint16_t _getdns_parse_ta_file(time_t *ta_mtime, gldns_buffer *gbuf); diff --git a/src/request-internal.c b/src/request-internal.c index 8193acb7..3f180d56 100644 --- a/src/request-internal.c +++ b/src/request-internal.c @@ -934,6 +934,7 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop, result->finished_next = NULL; result->freed = NULL; result->validating = 0; + result->chain = NULL; network_req_init(result->netreqs[0], result, request_type, dnssec_extension_set, with_opt, diff --git a/src/types-internal.h b/src/types-internal.h index 2ac85581..137892f1 100644 --- a/src/types-internal.h +++ b/src/types-internal.h @@ -267,6 +267,7 @@ typedef struct getdns_network_req static inline int _getdns_netreq_finished(getdns_network_req *req) { return !req || (req->state & NET_REQ_FINISHED); } +struct chain_head; /** * dns request - manages a number of network requests and * the initial data passed to getdns_general @@ -322,6 +323,9 @@ typedef struct getdns_dns_req { unsigned validating : 1; int *freed; + /* Validation chain to be canceled when this request is canceled */ + struct chain_head *chain; + uint16_t tls_query_padding_blocksize; /* internally scheduled request */ From 7e9956b19e1844f75de3b14850e34ba9baa58ce5 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Fri, 17 Feb 2017 23:39:35 +0100 Subject: [PATCH 39/56] Call cancel callbacks only when callback exists --- src/context.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/context.c b/src/context.c index 830c4c53..39f2dbb0 100644 --- a/src/context.c +++ b/src/context.c @@ -3275,9 +3275,11 @@ _getdns_context_request_timed_out(getdns_dns_req *req) /* cancel the req - also clears it from outbound and cleans up*/ _getdns_context_cancel_request(context, trans_id, 0); - context->processing = 1; - cb(context, GETDNS_CALLBACK_TIMEOUT, response, user_arg, trans_id); - context->processing = 0; + if (cb) { + context->processing = 1; + cb(context, GETDNS_CALLBACK_TIMEOUT, response, user_arg, trans_id); + context->processing = 0; + } getdns_context_request_count_changed(context); return GETDNS_RETURN_GOOD; } From a4536780949296f908d36c96c1e6022fceb06fd7 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Sat, 18 Feb 2017 10:07:04 +0100 Subject: [PATCH 40/56] Debug the call to poll --- src/extension/poll_eventloop.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/extension/poll_eventloop.c b/src/extension/poll_eventloop.c index 9c151c57..b59ad64d 100644 --- a/src/extension/poll_eventloop.c +++ b/src/extension/poll_eventloop.c @@ -396,6 +396,11 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) /* turn microseconds into milliseconds */ poll_timeout = (timeout - now) / 1000; } + DEBUG_SCHED( "poll(fd_free: %d, fd_used: %d, to_free: %d, to_used: %d, timeout: %d)\n" + , (int)poll_loop->fd_events_free, (int)poll_loop->fd_events_n_used + , (int)poll_loop->to_events_free, (int)poll_loop->to_events_n_used + , poll_timeout + ); #ifdef USE_WINSOCK if (WSAPoll(poll_loop->pfds, poll_loop->fd_events_free, poll_timeout) < 0) { #else From 74b1f77357beabca1ceb4dd12cc6e2f56c39f529 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Sat, 18 Feb 2017 13:16:25 +0100 Subject: [PATCH 41/56] Cancel get validation chain getdns_dns_reqs And miscellaneous little other scheduling fixes and optimizations --- src/context.c | 238 ++++++++++++++++++++--------------------- src/context.h | 37 +++++-- src/dnssec.c | 39 +++---- src/general.c | 20 ++-- src/request-internal.c | 6 +- src/stub.c | 2 +- src/types-internal.h | 3 - 7 files changed, 168 insertions(+), 177 deletions(-) diff --git a/src/context.c b/src/context.c index 39f2dbb0..39334b82 100644 --- a/src/context.c +++ b/src/context.c @@ -135,8 +135,7 @@ static getdns_return_t create_default_namespaces(struct getdns_context *context) static getdns_return_t create_default_dns_transports(struct getdns_context *context); static int transaction_id_cmp(const void *, const void *); static void dispatch_updated(struct getdns_context *, uint16_t); -static void cancel_dns_req(getdns_dns_req *); -static void cancel_outstanding_requests(struct getdns_context*, int); +static void cancel_outstanding_requests(getdns_context*); /* unbound helpers */ #ifdef HAVE_LIBUNBOUND @@ -682,8 +681,7 @@ _getdns_upstreams_dereference(getdns_upstreams *upstreams) while (upstream->finished_dnsreqs) { dnsreq = upstream->finished_dnsreqs; upstream->finished_dnsreqs = dnsreq->finished_next; - (void) _getdns_context_cancel_request(dnsreq->context, - dnsreq->trans_id, 1); + _getdns_context_cancel_request(dnsreq); } if (upstream->tls_obj != NULL) { if (upstream->tls_session != NULL) @@ -1521,7 +1519,7 @@ getdns_context_destroy(struct getdns_context *context) context->destroying = 1; /* cancel all outstanding requests */ - cancel_outstanding_requests(context, 1); + cancel_outstanding_requests(context); /* Destroy listening addresses */ (void) getdns_context_set_listen_addresses(context, NULL, NULL, NULL); @@ -1705,7 +1703,7 @@ static getdns_return_t rebuild_ub_ctx(struct getdns_context* context) { if (context->unbound_ctx != NULL) { /* cancel all requests and delete */ - cancel_outstanding_requests(context, 1); + cancel_outstanding_requests(context); ub_ctx_delete(context->unbound_ctx); context->unbound_ctx = NULL; } @@ -2882,28 +2880,68 @@ getdns_context_set_memory_functions(struct getdns_context *context, context, MF_PLAIN, mf.ext.malloc, mf.ext.realloc, mf.ext.free); } /* getdns_context_set_memory_functions*/ -/* cancel the request */ -static void -cancel_dns_req(getdns_dns_req *req) +void +_getdns_context_track_outbound_request(getdns_dns_req *dnsreq) +{ + /* Called only by getdns_general_ns() after successful allocation */ + assert(dnsreq); + + dnsreq->node.key = &(dnsreq->trans_id); + if (_getdns_rbtree_insert( + &dnsreq->context->outbound_requests, &dnsreq->node)) + getdns_context_request_count_changed(dnsreq->context); +} + +void +_getdns_context_clear_outbound_request(getdns_dns_req *dnsreq) +{ + if (!dnsreq) return; + + if (dnsreq->loop && dnsreq->loop->vmt && dnsreq->timeout.timeout_cb) { + dnsreq->loop->vmt->clear(dnsreq->loop, &dnsreq->timeout); + dnsreq->timeout.timeout_cb = NULL; + } + /* delete the node from the tree */ + if (_getdns_rbtree_delete( + &dnsreq->context->outbound_requests, &dnsreq->trans_id)) + getdns_context_request_count_changed(dnsreq->context); + + if (dnsreq->chain) + _getdns_cancel_validation_chain(dnsreq); +} + +void +_getdns_context_cancel_request(getdns_dns_req *dnsreq) { getdns_network_req *netreq, **netreq_p; - for (netreq_p = req->netreqs; (netreq = *netreq_p); netreq_p++) + DEBUG_SCHED("%s(%p)\n", __FUNC__, (void *)dnsreq); + if (!dnsreq) return; + + _getdns_context_clear_outbound_request(dnsreq); + + /* cancel network requests */ + for (netreq_p = dnsreq->netreqs; (netreq = *netreq_p); netreq_p++) #ifdef HAVE_LIBUNBOUND if (netreq->unbound_id != -1) { - ub_cancel(req->context->unbound_ctx, + ub_cancel(dnsreq->context->unbound_ctx, netreq->unbound_id); netreq->unbound_id = -1; } else #endif _getdns_cancel_stub_request(netreq); - req->canceled = 1; + /* clean up */ + _getdns_dns_req_free(dnsreq); } +/* + * getdns_cancel_callback + * + */ getdns_return_t -_getdns_context_cancel_request(getdns_context *context, - getdns_transaction_t transaction_id, int fire_callback) +getdns_cancel_callback(getdns_context *context, + getdns_transaction_t transaction_id) { getdns_dns_req *dnsreq; @@ -2915,40 +2953,69 @@ _getdns_context_cancel_request(getdns_context *context, &context->outbound_requests, &transaction_id))) return GETDNS_RETURN_UNKNOWN_TRANSACTION; - if (dnsreq->chain) - _getdns_cancel_validation_chain(dnsreq); - - /* do the cancel */ - cancel_dns_req(dnsreq); - - if (fire_callback && dnsreq->user_callback) { - context->processing = 1; - dnsreq->user_callback(context, GETDNS_CALLBACK_CANCEL, - NULL, dnsreq->user_pointer, transaction_id); - context->processing = 0; - } - - /* clean up */ - _getdns_dns_req_free(dnsreq); - return GETDNS_RETURN_GOOD; -} - -/* - * getdns_cancel_callback - * - */ -getdns_return_t -getdns_cancel_callback(getdns_context *context, - getdns_transaction_t transaction_id) -{ - if (!context) - return GETDNS_RETURN_INVALID_PARAMETER; - - getdns_return_t r = _getdns_context_cancel_request(context, transaction_id, 1); getdns_context_request_count_changed(context); - return r; + + if (dnsreq->user_callback) { + dnsreq->context->processing = 1; + dnsreq->user_callback(dnsreq->context, GETDNS_CALLBACK_CANCEL, + NULL, dnsreq->user_pointer, dnsreq->trans_id); + dnsreq->context->processing = 0; + } + _getdns_context_cancel_request(dnsreq); + return GETDNS_RETURN_GOOD; } /* getdns_cancel_callback */ +void +_getdns_context_request_timed_out(getdns_dns_req *dnsreq) +{ + DEBUG_SCHED("%s(%p)\n", __FUNC__, (void *)dnsreq); + + if (dnsreq->user_callback) { + dnsreq->context->processing = 1; + dnsreq->user_callback(dnsreq->context, GETDNS_CALLBACK_TIMEOUT, + _getdns_create_getdns_response(dnsreq), + dnsreq->user_pointer, dnsreq->trans_id); + dnsreq->context->processing = 0; + } + _getdns_context_cancel_request(dnsreq); +} + +static void +accumulate_outstanding_transactions(_getdns_rbnode_t *node, void* arg) +{ + *(*(getdns_dns_req ***)arg)++ = (getdns_dns_req *)node; +} + +static void +cancel_outstanding_requests(getdns_context* context) +{ + getdns_dns_req **dnsreqs, **dnsreq_a, **dnsreq_i; + + if (context->outbound_requests.count == 0) + return; + + dnsreq_i = dnsreq_a = dnsreqs = GETDNS_XMALLOC(context->my_mf, + getdns_dns_req *, context->outbound_requests.count); + + _getdns_traverse_postorder(&context->outbound_requests, + accumulate_outstanding_transactions, &dnsreq_a); + + while (dnsreq_i < dnsreq_a) { + getdns_dns_req *dnsreq = *dnsreq_i; + + if (dnsreq->user_callback) { + dnsreq->context->processing = 1; + dnsreq->user_callback(dnsreq->context, + GETDNS_CALLBACK_CANCEL, NULL, + dnsreq->user_pointer, dnsreq->trans_id); + dnsreq->context->processing = 0; + } + _getdns_context_cancel_request(dnsreq); + + dnsreq_i += 1; + } + GETDNS_FREE(context->my_mf, dnsreqs); +} #ifndef STUB_NATIVE_DNSSEC @@ -3234,56 +3301,6 @@ _getdns_context_prepare_for_resolution(struct getdns_context *context, return r; } /* _getdns_context_prepare_for_resolution */ -getdns_return_t -_getdns_context_track_outbound_request(getdns_dns_req *dnsreq) -{ - if (!dnsreq) - return GETDNS_RETURN_INVALID_PARAMETER; - - dnsreq->node.key = &(dnsreq->trans_id); - if (!_getdns_rbtree_insert( - &dnsreq->context->outbound_requests, &dnsreq->node)) - return GETDNS_RETURN_GENERIC_ERROR; - - getdns_context_request_count_changed(dnsreq->context); - return GETDNS_RETURN_GOOD; -} - -getdns_return_t -_getdns_context_clear_outbound_request(getdns_dns_req *dnsreq) -{ - if (!dnsreq) - return GETDNS_RETURN_INVALID_PARAMETER; - - if (!_getdns_rbtree_delete( - &dnsreq->context->outbound_requests, &dnsreq->trans_id)) - return GETDNS_RETURN_GENERIC_ERROR; - - getdns_context_request_count_changed(dnsreq->context); - return GETDNS_RETURN_GOOD; -} - -getdns_return_t -_getdns_context_request_timed_out(getdns_dns_req *req) -{ - /* Don't use req after callback */ - getdns_context* context = req->context; - getdns_transaction_t trans_id = req->trans_id; - getdns_callback_t cb = req->user_callback; - void *user_arg = req->user_pointer; - getdns_dict *response = _getdns_create_getdns_response(req); - - /* cancel the req - also clears it from outbound and cleans up*/ - _getdns_context_cancel_request(context, trans_id, 0); - if (cb) { - context->processing = 1; - cb(context, GETDNS_CALLBACK_TIMEOUT, response, user_arg, trans_id); - context->processing = 0; - } - getdns_context_request_count_changed(context); - return GETDNS_RETURN_GOOD; -} - char * _getdns_strdup(const struct mem_funcs *mfs, const char *s) { @@ -3365,33 +3382,6 @@ getdns_context_run(getdns_context *context) context->extension->vmt->run(context->extension); } -typedef struct timeout_accumulator { - getdns_transaction_t* ids; - int idx; -} timeout_accumulator; - -static void -accumulate_outstanding_transactions(_getdns_rbnode_t* node, void* arg) { - timeout_accumulator* acc = (timeout_accumulator*) arg; - acc->ids[acc->idx] = *((getdns_transaction_t*) node->key); - acc->idx++; -} - -static void -cancel_outstanding_requests(struct getdns_context* context, int fire_callback) { - if (context->outbound_requests.count > 0) { - timeout_accumulator acc; - int i; - acc.idx = 0; - acc.ids = GETDNS_XMALLOC(context->my_mf, getdns_transaction_t, context->outbound_requests.count); - _getdns_traverse_postorder(&context->outbound_requests, accumulate_outstanding_transactions, &acc); - for (i = 0; i < acc.idx; ++i) { - _getdns_context_cancel_request(context, acc.ids[i], fire_callback); - } - GETDNS_FREE(context->my_mf, acc.ids); - } -} - getdns_return_t getdns_context_detach_eventloop(struct getdns_context* context) { @@ -3405,7 +3395,7 @@ getdns_context_detach_eventloop(struct getdns_context* context) * and they may destroy the context ) */ /* cancel all outstanding requests */ - cancel_outstanding_requests(context, 1); + cancel_outstanding_requests(context); context->extension->vmt->cleanup(context->extension); context->extension = &context->default_eventloop.loop; _getdns_default_eventloop_init(&context->mf, &context->default_eventloop); @@ -3423,7 +3413,7 @@ getdns_context_set_eventloop(getdns_context* context, getdns_eventloop* loop) return GETDNS_RETURN_INVALID_PARAMETER; if (context->extension) { - cancel_outstanding_requests(context, 1); + cancel_outstanding_requests(context); context->extension->vmt->cleanup(context->extension); } context->extension = loop; diff --git a/src/context.h b/src/context.h index b89a5876..e6ed49fb 100644 --- a/src/context.h +++ b/src/context.h @@ -349,19 +349,34 @@ struct getdns_context { getdns_return_t _getdns_context_prepare_for_resolution(struct getdns_context *context, int usenamespaces); -/* track an outbound request */ -getdns_return_t _getdns_context_track_outbound_request(struct getdns_dns_req - *req); -/* clear the outbound request from being tracked - does not cancel it */ -getdns_return_t _getdns_context_clear_outbound_request(struct getdns_dns_req - *req); +/* Register a getdns_dns_req with context. + * - Without pluggable unbound event API, + * ub_fd() is scheduled when this was the first request. + */ +void _getdns_context_track_outbound_request(getdns_dns_req *dnsreq); -getdns_return_t _getdns_context_request_timed_out(struct getdns_dns_req - *req); +/* Deregister getdns_dns_req from the context. + * - Without pluggable unbound event API, + * ub_fd() is scheduled when this was the first request. + * - Potential timeout events will be cleared. + * - All associated getdns_dns_reqs (to get the validation chain) + * will be canceled. + */ +void _getdns_context_clear_outbound_request(getdns_dns_req *dnsreq); -/* cancel callback internal - flag to indicate if req should be freed and callback fired */ -getdns_return_t _getdns_context_cancel_request(struct getdns_context *context, - getdns_transaction_t transaction_id, int fire_callback); +/* Cancels and frees a getdns_dns_req (without calling user callbacks) + * - Deregisters getdns_dns_req with _getdns_context_clear_outbound_request() + * - Cancels associated getdns_network_reqs + * (by calling ub_cancel() or _getdns_cancel_stub_request()) + * - Frees the getdns_dns_req + */ +void _getdns_context_cancel_request(getdns_dns_req *dnsreq); + + +/* Calls user callback (with GETDNS_CALLBACK_TIMEOUT + response dict), then + * cancels and frees the getdns_dns_req with _getdns_context_cancel_request() + */ +void _getdns_context_request_timed_out(getdns_dns_req *dnsreq); char *_getdns_strdup(const struct mem_funcs *mfs, const char *str); diff --git a/src/dnssec.c b/src/dnssec.c index 905f778d..0396f045 100644 --- a/src/dnssec.c +++ b/src/dnssec.c @@ -1044,7 +1044,6 @@ static void val_chain_node_cb(getdns_dns_req *dnsreq) _getdns_rrsig_iter *rrsig, rrsig_spc; size_t n_signers; - _getdns_context_clear_outbound_request(dnsreq); switch (netreq->request_type) { case GETDNS_RRTYPE_DS : node->ds.pkt = netreq->response; node->ds.pkt_len = netreq->response_len; @@ -1094,7 +1093,6 @@ static void val_chain_node_soa_cb(getdns_dns_req *dnsreq) _getdns_rrset_iter i_spc, *i; _getdns_rrset *rrset; - _getdns_context_clear_outbound_request(dnsreq); /* A SOA query is always scheduled with a node as the user argument. */ assert(node != NULL); @@ -1121,8 +1119,10 @@ static void val_chain_node_soa_cb(getdns_dns_req *dnsreq) } else { /* SOA for a different name */ node = (chain_node *)dnsreq->user_pointer; - node->lock++; - val_chain_sched_soa_node(node->parent); + if (node->parent) { + node->lock++; + val_chain_sched_soa_node(node->parent); + } } } else if (node->parent) { @@ -3049,7 +3049,10 @@ static void check_chain_complete(chain_head *chain) val_chain_list = dnsreq->dnssec_return_validation_chain ? getdns_list_create_with_context(context) : NULL; - /* Walk chain to add values to val_chain_list and to cleanup */ + /* Walk chain to add values to val_chain_list. We do not cleanup yet. + * The chain will eventually be freed when the dns request is descheduled + * with getdns_context_clear_outbound_request(). + */ for ( head = chain; head ; head = next ) { next = head->next; if (dnsreq->dnssec_return_full_validation_chain && @@ -3076,7 +3079,6 @@ static void check_chain_complete(chain_head *chain) context, val_chain_list, node->dnskey_req, node->dnskey_signer); - _getdns_dns_req_free(node->dnskey_req->owner); } if (node->ds_req) { if (val_chain_list) @@ -3094,13 +3096,8 @@ static void check_chain_complete(chain_head *chain) context, val_chain_list, &node->ds); } - _getdns_dns_req_free(node->ds_req->owner); - } - if (node->soa_req) { - _getdns_dns_req_free(node->soa_req->owner); } } - GETDNS_FREE(head->my_mf, head); } response_dict = _getdns_create_getdns_response(dnsreq); @@ -3117,11 +3114,12 @@ static void check_chain_complete(chain_head *chain) void _getdns_cancel_validation_chain(getdns_dns_req *dnsreq) { - chain_head *head, *next; + chain_head *head = dnsreq->chain, *next; chain_node *node; size_t node_count; - for ( head = dnsreq->chain; head ; head = next ) { + dnsreq->chain = NULL; + while (head) { next = head->next; for ( node_count = head->node_count, node = head->parent @@ -3130,22 +3128,19 @@ void _getdns_cancel_validation_chain(getdns_dns_req *dnsreq) if (node->dnskey_req) _getdns_context_cancel_request( - node->dnskey_req->owner->context, - node->dnskey_req->owner->trans_id, 0); + node->dnskey_req->owner); if (node->ds_req) _getdns_context_cancel_request( - node->ds_req->owner->context, - node->ds_req->owner->trans_id, 0); - - if (node->soa_req) + node->ds_req->owner); + + if (node->soa_req) _getdns_context_cancel_request( - node->soa_req->owner->context, - node->soa_req->owner->trans_id, 0); + node->soa_req->owner); } GETDNS_FREE(head->my_mf, head); + head = next; } - dnsreq->chain = NULL; } void _getdns_get_validation_chain(getdns_dns_req *dnsreq) diff --git a/src/general.c b/src/general.c index 97a97dcf..b31e2405 100644 --- a/src/general.c +++ b/src/general.c @@ -54,14 +54,6 @@ #include "dict.h" #include "mdns.h" -/* cancel, cleanup and send timeout to callback */ -static void -ub_resolve_timeout(void *arg) -{ - getdns_dns_req *dns_req = (getdns_dns_req *) arg; - (void) _getdns_context_request_timed_out(dns_req); -} - void _getdns_call_user_callback(getdns_dns_req *dns_req, struct getdns_dict *response) { @@ -72,13 +64,14 @@ void _getdns_call_user_callback(getdns_dns_req *dns_req, /* clean up */ _getdns_context_clear_outbound_request(dns_req); - _getdns_dns_req_free(dns_req); context->processing = 1; cb(context, (response ? GETDNS_CALLBACK_COMPLETE : GETDNS_CALLBACK_ERROR), response, user_arg, trans_id); context->processing = 0; + + _getdns_dns_req_free(dns_req); } static int @@ -186,9 +179,10 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req) return; } } - if (dns_req->internal_cb) + if (dns_req->internal_cb) { + _getdns_context_clear_outbound_request(dns_req); dns_req->internal_cb(dns_req); - else if (! results_found) + } else if (! results_found) _getdns_call_user_callback(dns_req, NULL); else if (dns_req->dnssec_return_validation_chain #ifdef DNSSEC_ROADBLOCK_AVOIDANCE @@ -290,7 +284,9 @@ _getdns_submit_netreq(getdns_network_req *netreq) dns_req->timeout.userarg = dns_req; dns_req->timeout.read_cb = NULL; dns_req->timeout.write_cb = NULL; - dns_req->timeout.timeout_cb = ub_resolve_timeout; + dns_req->timeout.timeout_cb = + (getdns_eventloop_callback) + _getdns_context_request_timed_out; dns_req->timeout.ev = NULL; if ((r = dns_req->loop->vmt->schedule(dns_req->loop, -1, dns_req->context->timeout, &dns_req->timeout))) diff --git a/src/request-internal.c b/src/request-internal.c index 3f180d56..eae467e9 100644 --- a/src/request-internal.c +++ b/src/request-internal.c @@ -644,7 +644,7 @@ _getdns_dns_req_free(getdns_dns_req * req) network_req_cleanup(*net_req); /* clear timeout event */ - if (req->timeout.timeout_cb) { + if (req->loop && req->loop->vmt && req->timeout.timeout_cb) { req->loop->vmt->clear(req->loop, &req->timeout); req->timeout.timeout_cb = NULL; } @@ -896,9 +896,7 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop, } result->context = context; result->loop = loop; - result->canceled = 0; - result->trans_id = (((uint64_t)arc4random()) << 32) | - ((uint64_t)arc4random()); + result->trans_id = (uint64_t) (intptr_t) result; result->dnssec_return_status = dnssec_return_status; result->dnssec_return_only_secure = dnssec_return_only_secure; result->dnssec_return_all_statuses = dnssec_return_all_statuses; diff --git a/src/stub.c b/src/stub.c index 9421f5d8..a377228f 100644 --- a/src/stub.c +++ b/src/stub.c @@ -602,7 +602,7 @@ stub_timeout_cb(void *userarg) if (netreq->owner->user_callback) { netreq->debug_end_time = _getdns_get_time_as_uintt64(); /* Note this calls cancel_request which calls stub_cleanup again....!*/ - (void) _getdns_context_request_timed_out(netreq->owner); + _getdns_context_request_timed_out(netreq->owner); } else _getdns_check_dns_req_complete(netreq->owner); } diff --git a/src/types-internal.h b/src/types-internal.h index 137892f1..78f1935a 100644 --- a/src/types-internal.h +++ b/src/types-internal.h @@ -290,9 +290,6 @@ typedef struct getdns_dns_req { size_t suffix_len; unsigned suffix_appended : 1; - /* canceled flag */ - unsigned canceled : 1; - /* request extensions */ unsigned dnssec_return_status : 1; unsigned dnssec_return_only_secure : 1; From 09a727eadb44e56b8860ac097ab744c4973396be Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Sat, 18 Feb 2017 13:18:14 +0100 Subject: [PATCH 42/56] git ignore tpkg tests cruft --- .gitignore | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 7bbbdebd..d9315494 100644 --- a/.gitignore +++ b/.gitignore @@ -55,6 +55,13 @@ m4/ltsugar.m4 m4/ltversion.m4 m4/lt~obsolete.m4 src/config.h.in -build/ getdns.pc getdns_ext_event.pc +/src/test/tpkg/result.* +/src/test/tpkg/.done-* +/src/test/tpkg/.tpkg.var.master +/src/test/tpkg/scan-build-reports/ +/src/test/tpkg/install/ +/src/test/tpkg/build/ +/src/test/tpkg/build-stub-only/ +/src/test/tpkg/build-event-loops/ From ba7dfbeec0615f4ab46175cf3d6f2af5c8186a0a Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Sat, 18 Feb 2017 15:56:06 +0100 Subject: [PATCH 43/56] Misplaced event clear in stub.c --- src/stub.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/stub.c b/src/stub.c index a377228f..37c025a8 100644 --- a/src/stub.c +++ b/src/stub.c @@ -1299,8 +1299,6 @@ stub_udp_read_cb(void *userarg) DEBUG_STUB("%s %-35s: MSG: %p \n", STUB_DEBUG_READ, __FUNC__, (void*)netreq); - GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event); - read = recvfrom(netreq->fd, (void *)netreq->response, netreq->max_udp_payload_size + 1, /* If read == max_udp_payload_size * then all is good. If read == @@ -1322,6 +1320,8 @@ stub_udp_read_cb(void *userarg) upstream, netreq->response, read)) return; /* Client cookie didn't match? */ + GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event); + #ifdef USE_WINSOCK closesocket(netreq->fd); #else From 8fccd668136ce6d0f4dcb2567bc54f91a6bedf28 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Sun, 19 Feb 2017 09:39:10 +0100 Subject: [PATCH 44/56] cancel_outstanding_requests by transaction_id to prevent double frees as side effect of getdns_dns_req being canceled by user callbacks. --- src/context.c | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/src/context.c b/src/context.c index 39334b82..5421fd81 100644 --- a/src/context.c +++ b/src/context.c @@ -2983,38 +2983,34 @@ _getdns_context_request_timed_out(getdns_dns_req *dnsreq) static void accumulate_outstanding_transactions(_getdns_rbnode_t *node, void* arg) { - *(*(getdns_dns_req ***)arg)++ = (getdns_dns_req *)node; + *(*(getdns_transaction_t**)arg)++ = ((getdns_dns_req*)node)->trans_id; } static void cancel_outstanding_requests(getdns_context* context) { - getdns_dns_req **dnsreqs, **dnsreq_a, **dnsreq_i; + getdns_transaction_t *trans_ids, *tids_a, *tids_i; if (context->outbound_requests.count == 0) return; - dnsreq_i = dnsreq_a = dnsreqs = GETDNS_XMALLOC(context->my_mf, - getdns_dns_req *, context->outbound_requests.count); + tids_i = tids_a = trans_ids = GETDNS_XMALLOC(context->my_mf, + getdns_transaction_t, context->outbound_requests.count); _getdns_traverse_postorder(&context->outbound_requests, - accumulate_outstanding_transactions, &dnsreq_a); + accumulate_outstanding_transactions, &tids_a); - while (dnsreq_i < dnsreq_a) { - getdns_dns_req *dnsreq = *dnsreq_i; + while (tids_i < tids_a) { - if (dnsreq->user_callback) { - dnsreq->context->processing = 1; - dnsreq->user_callback(dnsreq->context, - GETDNS_CALLBACK_CANCEL, NULL, - dnsreq->user_pointer, dnsreq->trans_id); - dnsreq->context->processing = 0; - } - _getdns_context_cancel_request(dnsreq); - - dnsreq_i += 1; + /* We have to cancel by transaction_id because we do not know + * what happens when the user_callback is called. It might + * delete getdns_dns_req's that were scheduled to be canceled. + * The extra lookup with transaction_id makes sure we do not + * access freed memory. + */ + (void) getdns_cancel_callback(context, *tids_i++); } - GETDNS_FREE(context->my_mf, dnsreqs); + GETDNS_FREE(context->my_mf, trans_ids); } #ifndef STUB_NATIVE_DNSSEC From b3a06f1944fbdc6b2f76b8afe45be3eae6a16f55 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Sun, 19 Feb 2017 09:47:41 +0100 Subject: [PATCH 45/56] A bit more consistency in user_callback usage --- src/general.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/src/general.c b/src/general.c index b31e2405..69dc7462 100644 --- a/src/general.c +++ b/src/general.c @@ -54,24 +54,19 @@ #include "dict.h" #include "mdns.h" -void _getdns_call_user_callback(getdns_dns_req *dns_req, - struct getdns_dict *response) +void _getdns_call_user_callback(getdns_dns_req *dnsreq, getdns_dict *response) { - struct getdns_context *context = dns_req->context; - getdns_transaction_t trans_id = dns_req->trans_id; - getdns_callback_t cb = dns_req->user_callback; - void *user_arg = dns_req->user_pointer; + _getdns_context_clear_outbound_request(dnsreq); - /* clean up */ - _getdns_context_clear_outbound_request(dns_req); - - context->processing = 1; - cb(context, - (response ? GETDNS_CALLBACK_COMPLETE : GETDNS_CALLBACK_ERROR), - response, user_arg, trans_id); - context->processing = 0; - - _getdns_dns_req_free(dns_req); + if (dnsreq->user_callback) { + dnsreq->context->processing = 1; + dnsreq->user_callback(dnsreq->context, + (response ? GETDNS_CALLBACK_COMPLETE + : GETDNS_CALLBACK_ERROR), + response, dnsreq->user_pointer, dnsreq->trans_id); + dnsreq->context->processing = 0; + } + _getdns_dns_req_free(dnsreq); } static int From 4b6962cd9aa16c3675def2d04a2bd7d25f91248f Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Sun, 19 Feb 2017 09:55:10 +0100 Subject: [PATCH 46/56] Use __FUNC__ instead of function for protability It is #defined to __FUNCTION__ or to __func__ depending on what configure detected. --- src/mdns.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/mdns.c b/src/mdns.c index 36950f36..253bf972 100644 --- a/src/mdns.c +++ b/src/mdns.c @@ -83,7 +83,7 @@ static void mdns_cleanup(getdns_network_req *netreq) { DEBUG_MDNS("%s %-35s: MSG: %p\n", - MDNS_DEBUG_CLEANUP, __FUNCTION__, netreq); + MDNS_DEBUG_CLEANUP, __FUNC__, netreq); getdns_dns_req *dnsreq = netreq->owner; GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event); @@ -109,7 +109,7 @@ mdns_timeout_cb(void *userarg) { getdns_network_req *netreq = (getdns_network_req *)userarg; DEBUG_MDNS("%s %-35s: MSG: %p\n", - MDNS_DEBUG_CLEANUP, __FUNCTION__, netreq); + MDNS_DEBUG_CLEANUP, __FUNC__, netreq); /* TODO: do we need a retry logic here? */ @@ -143,7 +143,7 @@ mdns_udp_read_cb(void *userarg) getdns_dns_req *dnsreq = netreq->owner; ssize_t read; DEBUG_MDNS("%s %-35s: MSG: %p \n", MDNS_DEBUG_READ, - __FUNCTION__, netreq); + __FUNC__, netreq); GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event); @@ -197,7 +197,7 @@ mdns_udp_write_cb(void *userarg) int r; DEBUG_MDNS("%s %-35s: MSG: %p \n", MDNS_DEBUG_WRITE, - __FUNCTION__, netreq); + __FUNC__, netreq); GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event); @@ -245,7 +245,7 @@ mdns_udp_write_cb(void *userarg) getdns_return_t _getdns_submit_mdns_request(getdns_network_req *netreq) { - DEBUG_MDNS("%s %-35s: MSG: %p TYPE: %d\n", MDNS_DEBUG_ENTRY, __FUNCTION__, + DEBUG_MDNS("%s %-35s: MSG: %p TYPE: %d\n", MDNS_DEBUG_ENTRY, __FUNC__, netreq, netreq->request_type); int fd = -1; getdns_dns_req *dnsreq = netreq->owner; From 09df4e2d5dfea4715f3376da77a7e5dd7b206cf8 Mon Sep 17 00:00:00 2001 From: Sara Dickinson Date: Wed, 22 Feb 2017 13:00:27 +0000 Subject: [PATCH 47/56] Fix spacing error in stubby help output --- src/tools/getdns_query.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/getdns_query.c b/src/tools/getdns_query.c index 61825f1b..bb452929 100644 --- a/src/tools/getdns_query.c +++ b/src/tools/getdns_query.c @@ -215,7 +215,7 @@ print_usage(FILE *out, const char *progname) fprintf(out, "\t\tThe file must be in json dict format.\n"); if (i_am_stubby) { fprintf(out, "\t\tBy default, configuration is first read from"); - fprintf(out, "\t\t\"/etc/stubby.conf\" and then from \"$HOME/.stubby.conf\""); + fprintf(out, "\n\t\t\"/etc/stubby.conf\" and then from \"$HOME/.stubby.conf\"\n"); } fprintf(out, "\t-D\tSet edns0 do bit\n"); fprintf(out, "\t-d\tclear edns0 do bit\n"); From 356408955db7ea8caaac56c017e627ebb882e785 Mon Sep 17 00:00:00 2001 From: Sara Dickinson Date: Wed, 22 Feb 2017 13:08:32 +0000 Subject: [PATCH 48/56] Update the SPKI pin in the stubby.conf file for the Sinodun/Surfnet servers. --- src/tools/stubby.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/stubby.conf b/src/tools/stubby.conf index 5deb03db..e562e49d 100644 --- a/src/tools/stubby.conf +++ b/src/tools/stubby.conf @@ -5,14 +5,14 @@ , tls_auth_name: "dnsovertls.sinodun.com" , tls_pubkey_pinset: [ { digest: "sha256" - , value: 0xA132D34D34C181765337C70B83E3697B9524DDDB05A7118B43C0284033D5A0CC + , value: 0xEB694ABBD1EC0D56F288F7A70299DCE2C7E64984C73957C580BDE9C81F9C04BE } ] }, { address_data: 145.100.185.16 , tls_auth_name: "dnsovertls1.sinodun.com" , tls_pubkey_pinset: [ { digest: "sha256" - , value: 0x659B41EB08DCC70EE9D624E6219C76EE31954DA1548B0C8519EAE5228CB24150 + , value: 0x704D9E7002DE13907EBAB2610EB26554599FDFC7092C0BEA7A438DBE3BE9A940 } ] }, { address_data: 185.49.141.38 From 1b7aef5a882b39f04ca12e325d66a7d03d580519 Mon Sep 17 00:00:00 2001 From: Sara Dickinson Date: Thu, 23 Feb 2017 14:49:17 +0000 Subject: [PATCH 49/56] Add a new GETDNS_RETURN code for the case where no upstream is considered valid and hence a query cannot even be scheduled. Only applies when using purely stateful transports. This can happen when using Stubby if there are problems with connections to upstreams. --- src/const-info.c | 2 ++ src/getdns/getdns_extra.h.in | 2 ++ src/stub.c | 5 ++--- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/const-info.c b/src/const-info.c index a71f928a..0022a768 100644 --- a/src/const-info.c +++ b/src/const-info.c @@ -24,6 +24,7 @@ static struct const_info consts_info[] = { { 310, "GETDNS_RETURN_MEMORY_ERROR", GETDNS_RETURN_MEMORY_ERROR_TEXT }, { 311, "GETDNS_RETURN_INVALID_PARAMETER", GETDNS_RETURN_INVALID_PARAMETER_TEXT }, { 312, "GETDNS_RETURN_NOT_IMPLEMENTED", GETDNS_RETURN_NOT_IMPLEMENTED_TEXT }, + { 398, "GETDNS_RETURN_NO_UPSTREAM_AVAILABLE", GETDNS_RETURN_NO_UPSTREAM_AVAILABLE_TEXT }, { 399, "GETDNS_RETURN_NEED_MORE_SPACE", GETDNS_RETURN_NEED_MORE_SPACE_TEXT }, { 400, "GETDNS_DNSSEC_SECURE", GETDNS_DNSSEC_SECURE_TEXT }, { 401, "GETDNS_DNSSEC_BOGUS", GETDNS_DNSSEC_BOGUS_TEXT }, @@ -218,6 +219,7 @@ static struct const_name_info consts_name_info[] = { { "GETDNS_RETURN_GOOD", 0 }, { "GETDNS_RETURN_INVALID_PARAMETER", 311 }, { "GETDNS_RETURN_MEMORY_ERROR", 310 }, + { "GETDNS_RETURN_NO_UPSTREAM_AVAILABLE", 398}, { "GETDNS_RETURN_NEED_MORE_SPACE", 399 }, { "GETDNS_RETURN_NOT_IMPLEMENTED", 312 }, { "GETDNS_RETURN_NO_SUCH_DICT_NAME", 305 }, diff --git a/src/getdns/getdns_extra.h.in b/src/getdns/getdns_extra.h.in index 5abf39e7..a76564eb 100644 --- a/src/getdns/getdns_extra.h.in +++ b/src/getdns/getdns_extra.h.in @@ -56,6 +56,8 @@ extern "C" { * \defgroup Ureturnvaluesandtext Additional return values and texts * @{ */ +#define GETDNS_RETURN_NO_UPSTREAM_AVAILABLE ((getdns_return_t) 398 ) +#define GETDNS_RETURN_NO_UPSTREAM_AVAILABLE_TEXT "None of the configured upstreams could be used to send queries on the specified transports" #define GETDNS_RETURN_NEED_MORE_SPACE ((getdns_return_t) 399 ) #define GETDNS_RETURN_NEED_MORE_SPACE_TEXT "The buffer was too small" /** @} diff --git a/src/stub.c b/src/stub.c index 37c025a8..369c0d38 100644 --- a/src/stub.c +++ b/src/stub.c @@ -520,7 +520,7 @@ stub_cleanup(getdns_network_req *netreq) static void upstream_failed(getdns_upstream *upstream, int during_setup) { - DEBUG_STUB("%s %-35s: FD: %d During setup = %d\n", + DEBUG_STUB("%s %-35s: FD: %d Failure during connection setup = %d\n", STUB_DEBUG_CLEANUP, __FUNC__, upstream->fd, during_setup); /* Fallback code should take care of queue queries and then close conn when idle.*/ @@ -2023,8 +2023,7 @@ _getdns_submit_stub_request(getdns_network_req *netreq) * All other set up is done async*/ fd = upstream_find_for_netreq(netreq); if (fd == -1) - /* Handle better, will give unhelpful error is some cases */ - return GETDNS_RETURN_GENERIC_ERROR; + return GETDNS_RETURN_NO_UPSTREAM_AVAILABLE; getdns_transport_list_t transport = netreq->transports[netreq->transport_current]; From ff4ecd5b39997fb1e2650243aa0c66aa5765e9dc Mon Sep 17 00:00:00 2001 From: Sara Dickinson Date: Thu, 23 Feb 2017 15:38:45 +0000 Subject: [PATCH 50/56] Couple of extra output messages so Stubby users in strict mode know why the authentication failed --- src/stub.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/stub.c b/src/stub.c index 369c0d38..c40d518e 100644 --- a/src/stub.c +++ b/src/stub.c @@ -872,9 +872,16 @@ tls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx) /* First deal with the hostname authentication done by OpenSSL. */ #ifdef X509_V_ERR_HOSTNAME_MISMATCH /*Report if error is hostname mismatch*/ - if (err == X509_V_ERR_HOSTNAME_MISMATCH && upstream->tls_fallback_ok) - DEBUG_STUB("%s %-35s: FD: %d WARNING: Proceeding even though hostname validation failed!\n", - STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->fd); + if (err == X509_V_ERR_HOSTNAME_MISMATCH) { + if (upstream->tls_fallback_ok) + DEBUG_STUB("%s %-35s: FD: %d WARNING: Proceeding even though hostname validation failed!\n", + STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->fd); +#if defined(DAEMON_DEBUG) && DAEMON_DEBUG + else + DEBUG_DAEMON("%s %s : Conn failed : Transport=TLS - *Failure* - Hostname mismatch\n", + STUB_DEBUG_DAEMON, upstream->addr_str); +#endif + } #else /* if we weren't built against OpenSSL with hostname matching we * could not have matched the hostname, so this would be an automatic @@ -897,9 +904,15 @@ tls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx) if (upstream->tls_fallback_ok) DEBUG_STUB("%s %-35s: FD: %d, WARNING: Proceeding even though pinset validation failed!\n", STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->fd); +#if defined(DAEMON_DEBUG) && DAEMON_DEBUG + else + DEBUG_DAEMON("%s %s : Conn failed : Transport=TLS - *Failure* - Pinset validation failure\n", + STUB_DEBUG_DAEMON, upstream->addr_str); +#endif } else { /* If we _only_ had a pinset and it is good then force succesful - authentication when the cert self-signed */ + authentication when the cert self-signed + TODO: We need to check for other error cases here, not blindly accept the cert!! */ if ((upstream->tls_pubkey_pinset && upstream->tls_auth_name[0] == '\0') && (err == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN || err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT)) { @@ -915,6 +928,7 @@ tls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx) else if (upstream->tls_auth_state == GETDNS_AUTH_NONE && (upstream->tls_pubkey_pinset || upstream->tls_auth_name[0])) upstream->tls_auth_state = GETDNS_AUTH_OK; + /* If fallback is allowed, proceed regardless of what the auth error is (might not be hostname or pinset related) */ return (upstream->tls_fallback_ok) ? 1 : preverify_ok; From ebdf657fd784bc6a7e6f53f0bb8937653eef659c Mon Sep 17 00:00:00 2001 From: Sara Dickinson Date: Thu, 23 Feb 2017 16:48:16 +0000 Subject: [PATCH 51/56] Change pins for IPv6 addresses for Sinodun privacy servers! Improve logging of auth failure --- src/stub.c | 15 +++++++-------- src/tools/stubby.conf | 4 ++-- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/stub.c b/src/stub.c index c40d518e..148c1a2b 100644 --- a/src/stub.c +++ b/src/stub.c @@ -868,20 +868,19 @@ tls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx) STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->fd, err, X509_verify_cert_error_string(err)); #endif +#if defined(DAEMON_DEBUG) && DAEMON_DEBUG + if (!preverify_ok && !upstream->tls_fallback_ok) + DEBUG_DAEMON("%s %s : Conn failed : Transport=TLS - *Failure* - (%d) \"%s\"\n", + STUB_DEBUG_DAEMON, upstream->addr_str, err, + X509_verify_cert_error_string(err)); +#endif /* First deal with the hostname authentication done by OpenSSL. */ #ifdef X509_V_ERR_HOSTNAME_MISMATCH /*Report if error is hostname mismatch*/ - if (err == X509_V_ERR_HOSTNAME_MISMATCH) { - if (upstream->tls_fallback_ok) + if (err == X509_V_ERR_HOSTNAME_MISMATCH && upstream->tls_fallback_ok) DEBUG_STUB("%s %-35s: FD: %d WARNING: Proceeding even though hostname validation failed!\n", STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->fd); -#if defined(DAEMON_DEBUG) && DAEMON_DEBUG - else - DEBUG_DAEMON("%s %s : Conn failed : Transport=TLS - *Failure* - Hostname mismatch\n", - STUB_DEBUG_DAEMON, upstream->addr_str); -#endif - } #else /* if we weren't built against OpenSSL with hostname matching we * could not have matched the hostname, so this would be an automatic diff --git a/src/tools/stubby.conf b/src/tools/stubby.conf index e562e49d..054a9256 100644 --- a/src/tools/stubby.conf +++ b/src/tools/stubby.conf @@ -26,14 +26,14 @@ , tls_auth_name: "dnsovertls.sinodun.com" , tls_pubkey_pinset: [ { digest: "sha256" - , value: 0xA132D34D34C181765337C70B83E3697B9524DDDB05A7118B43C0284033D5A0CC + , value: 0xEB694ABBD1EC0D56F288F7A70299DCE2C7E64984C73957C580BDE9C81F9C04BE } ] }, { address_data: 2001:610:1:40ba:145:100:185:16 , tls_auth_name: "dnsovertls1.sinodun.com" , tls_pubkey_pinset: [ { digest: "sha256" - , value: 0x659B41EB08DCC70EE9D624E6219C76EE31954DA1548B0C8519EAE5228CB24150 + , value: 0x704D9E7002DE13907EBAB2610EB26554599FDFC7092C0BEA7A438DBE3BE9A940 } ] }, { address_data: 2a04:b900:0:100::38 From f71dd2bf7121070720950897959aaa1ad183dd66 Mon Sep 17 00:00:00 2001 From: Sara Dickinson Date: Thu, 23 Feb 2017 16:50:29 +0000 Subject: [PATCH 52/56] Re-order so checks pass! --- src/const-info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/const-info.c b/src/const-info.c index 0022a768..473f7a45 100644 --- a/src/const-info.c +++ b/src/const-info.c @@ -219,12 +219,12 @@ static struct const_name_info consts_name_info[] = { { "GETDNS_RETURN_GOOD", 0 }, { "GETDNS_RETURN_INVALID_PARAMETER", 311 }, { "GETDNS_RETURN_MEMORY_ERROR", 310 }, - { "GETDNS_RETURN_NO_UPSTREAM_AVAILABLE", 398}, { "GETDNS_RETURN_NEED_MORE_SPACE", 399 }, { "GETDNS_RETURN_NOT_IMPLEMENTED", 312 }, { "GETDNS_RETURN_NO_SUCH_DICT_NAME", 305 }, { "GETDNS_RETURN_NO_SUCH_EXTENSION", 307 }, { "GETDNS_RETURN_NO_SUCH_LIST_ITEM", 304 }, + { "GETDNS_RETURN_NO_UPSTREAM_AVAILABLE", 398}, { "GETDNS_RETURN_UNKNOWN_TRANSACTION", 303 }, { "GETDNS_RETURN_WRONG_TYPE_REQUESTED", 306 }, { "GETDNS_RRCLASS_ANY", 255 }, From 7c8605c3b133d6739045b5e0cae834c76c21c183 Mon Sep 17 00:00:00 2001 From: Sara Dickinson Date: Thu, 23 Feb 2017 17:03:00 +0000 Subject: [PATCH 53/56] And fix the whitespace... --- src/const-info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/const-info.c b/src/const-info.c index 473f7a45..4556634a 100644 --- a/src/const-info.c +++ b/src/const-info.c @@ -224,7 +224,7 @@ static struct const_name_info consts_name_info[] = { { "GETDNS_RETURN_NO_SUCH_DICT_NAME", 305 }, { "GETDNS_RETURN_NO_SUCH_EXTENSION", 307 }, { "GETDNS_RETURN_NO_SUCH_LIST_ITEM", 304 }, - { "GETDNS_RETURN_NO_UPSTREAM_AVAILABLE", 398}, + { "GETDNS_RETURN_NO_UPSTREAM_AVAILABLE", 398 }, { "GETDNS_RETURN_UNKNOWN_TRANSACTION", 303 }, { "GETDNS_RETURN_WRONG_TYPE_REQUESTED", 306 }, { "GETDNS_RRCLASS_ANY", 255 }, From bbd2fb8cf05a39eb42a688ed8b3f7ac0ffa400a3 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Mon, 27 Feb 2017 14:30:44 -0800 Subject: [PATCH 54/56] Although safe, a bit scary --- src/stub.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/stub.c b/src/stub.c index 148c1a2b..e905f600 100644 --- a/src/stub.c +++ b/src/stub.c @@ -877,10 +877,12 @@ tls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx) /* First deal with the hostname authentication done by OpenSSL. */ #ifdef X509_V_ERR_HOSTNAME_MISMATCH +# if defined(STUB_DEBUG) && STUB_DEBUG /*Report if error is hostname mismatch*/ if (err == X509_V_ERR_HOSTNAME_MISMATCH && upstream->tls_fallback_ok) DEBUG_STUB("%s %-35s: FD: %d WARNING: Proceeding even though hostname validation failed!\n", STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->fd); +# endif #else /* if we weren't built against OpenSSL with hostname matching we * could not have matched the hostname, so this would be an automatic From 6a9e2f4a56894a8b6d66c4cc5668a08d6981ff58 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Mon, 27 Feb 2017 16:22:52 -0800 Subject: [PATCH 55/56] Base64 primitive in json input --- src/convert.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 65 insertions(+), 3 deletions(-) diff --git a/src/convert.c b/src/convert.c index 11919107..6e05bdfe 100644 --- a/src/convert.c +++ b/src/convert.c @@ -1204,6 +1204,66 @@ static int _jsmn_get_ipdict(struct mem_funcs *mf, const char *js, jsmntok_t *t, return *value != NULL; } +static int _jsmn_get_base64_data(struct mem_funcs *mf, const char *js, jsmntok_t *t, + getdns_bindata **value) +{ + int e, i; + int size = t->end - t->start; + char value_str_buf[1025]; + char *value_str; + size_t target_buf_size; + + assert(size >= 4); + + if (size % 4 != 0) + return 0; + + e = t->end; + if (js[e - 1] == '=') e -= 1; + if (js[e - 1] == '=') e -= 1; + + for (i = t->start; i < e; i++) + if (!((js[i] >= '0' && js[i] <= '9') + ||(js[i] >= 'a' && js[i] <= 'z') + ||(js[i] >= 'A' && js[i] <= 'Z') + || js[i] == '+' || js[i] == '/')) + return 0; + + target_buf_size = gldns_b64_pton_calculate_size(size); + if (!(*value = GETDNS_MALLOC(*mf, getdns_bindata))) + return 0; + + else if (!((*value)->data = GETDNS_XMALLOC( + *mf, uint8_t, target_buf_size))) { + GETDNS_FREE(*mf, *value); + return 0; + } + if (size <= 0 || size >= (int)sizeof(value_str) || js[t->end - 1] != '.') + return 0; + + if ((size_t)size >= sizeof(value_str_buf)) + value_str = GETDNS_XMALLOC(*mf, char, size + 1); + else value_str = value_str_buf; + + if (value_str) { + (void) memcpy(value_str, js + t->start, size); + value_str[size] = '\0'; + + e = gldns_b64_pton(value_str, (*value)->data, target_buf_size); + + if (value_str != value_str_buf) + GETDNS_FREE(*mf, value_str); + + if (e > 0) { + (*value)->size = e; + return 1; + } + } + GETDNS_FREE(*mf, (*value)->data); + GETDNS_FREE(*mf, *value); + return 0; +} + static int _jsmn_get_data(struct mem_funcs *mf, const char *js, jsmntok_t *t, getdns_bindata **value) { @@ -1211,15 +1271,17 @@ static int _jsmn_get_data(struct mem_funcs *mf, const char *js, jsmntok_t *t, size_t j; uint8_t h, l; - if ((t->end - t->start) < 4 || (t->end - t->start) % 2 == 1 || - js[t->start] != '0' || js[t->start + 1] != 'x') + if ((t->end - t->start) < 4 || (t->end - t->start) % 2 == 1) return 0; + if (js[t->start] != '0' || js[t->start + 1] != 'x') + return _jsmn_get_base64_data(mf, js, t, value); + for (i = t->start + 2; i < t->end; i++) if (!((js[i] >= '0' && js[i] <= '9') ||(js[i] >= 'a' && js[i] <= 'f') ||(js[i] >= 'A' && js[i] <= 'F'))) - return 0; + return _jsmn_get_base64_data(mf, js, t, value); if (!(*value = GETDNS_MALLOC(*mf, getdns_bindata))) return 0; From 09baade01693063fdc21dd600b959be9bb36cc7e Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Tue, 28 Feb 2017 07:28:18 -0800 Subject: [PATCH 56/56] Print pinsets Bas64 too + bugfix in reading base64 + base64 pinsets in stubby.conf --- src/convert.c | 3 --- src/dict.c | 38 ++++++++++++++++++++++++++++++++++++++ src/tools/stubby.conf | 16 ++++++++-------- 3 files changed, 46 insertions(+), 11 deletions(-) diff --git a/src/convert.c b/src/convert.c index 6e05bdfe..6417c6d1 100644 --- a/src/convert.c +++ b/src/convert.c @@ -1238,9 +1238,6 @@ static int _jsmn_get_base64_data(struct mem_funcs *mf, const char *js, jsmntok_t GETDNS_FREE(*mf, *value); return 0; } - if (size <= 0 || size >= (int)sizeof(value_str) || js[t->end - 1] != '.') - return 0; - if ((size_t)size >= sizeof(value_str_buf)) value_str = GETDNS_XMALLOC(*mf, char, size + 1); else value_str = value_str_buf; diff --git a/src/dict.c b/src/dict.c index 23b42531..b8c9db99 100644 --- a/src/dict.c +++ b/src/dict.c @@ -51,6 +51,7 @@ #include "const-info.h" #include "gldns/gbuffer.h" #include "gldns/wire2str.h" +#include "gldns/parseutil.h" static char *_json_ptr_first(const struct mem_funcs *mf, @@ -731,6 +732,33 @@ _getdns_bindata_is_dname(getdns_bindata *bindata) bindata->data[bindata->size - 1] == 0; } +static int +getdns_pp_base64(gldns_buffer *buf, getdns_bindata *bindata) +{ + size_t p = gldns_buffer_position(buf); + size_t base64str_sz; + char *target; + size_t avail; + + if (gldns_buffer_printf(buf, " size); + target = (char *)gldns_buffer_current(buf); + avail = gldns_buffer_remaining(buf); + if (avail >= base64str_sz) + gldns_buffer_skip(buf, gldns_b64_ntop( + bindata->data, bindata->size, + target, base64str_sz)); + else + gldns_buffer_skip(buf, base64str_sz); + + if (gldns_buffer_printf(buf, ">") < 0) + return -1; + + return gldns_buffer_position(buf) - p; +} + /*---------------------------------------- getdns_pp_bindata */ /** * private function to pretty print bindata to a gldns_buffer @@ -1094,6 +1122,16 @@ getdns_pp_dict(gldns_buffer * buf, size_t indent, )) < 0) return -1; + } else if (!json && + (strcmp(item->node.key, "pin-sha256") == 0 || + strcmp(item->node.key, "value") == 0) && + item->i.data.bindata->size > 0 && + item->i.data.bindata->size % 4 == 0) { + + if (getdns_pp_base64(buf, + item->i.data.bindata) < 0) + return -1; + } else if (getdns_pp_bindata( buf, item->i.data.bindata, (strcmp(item->node.key, "rdata_raw") == 0), diff --git a/src/tools/stubby.conf b/src/tools/stubby.conf index 054a9256..1055e277 100644 --- a/src/tools/stubby.conf +++ b/src/tools/stubby.conf @@ -5,54 +5,54 @@ , tls_auth_name: "dnsovertls.sinodun.com" , tls_pubkey_pinset: [ { digest: "sha256" - , value: 0xEB694ABBD1EC0D56F288F7A70299DCE2C7E64984C73957C580BDE9C81F9C04BE + , value: 62lKu9HsDVbyiPenApnc4sfmSYTHOVfFgL3pyB+cBL4= } ] }, { address_data: 145.100.185.16 , tls_auth_name: "dnsovertls1.sinodun.com" , tls_pubkey_pinset: [ { digest: "sha256" - , value: 0x704D9E7002DE13907EBAB2610EB26554599FDFC7092C0BEA7A438DBE3BE9A940 + , value: cE2ecALeE5B+urJhDrJlVFmf38cJLAvqekONvjvpqUA= } ] }, { address_data: 185.49.141.38 , tls_auth_name: "getdnsapi.net" , tls_pubkey_pinset: [ { digest: "sha256" - , value: 0x7e8c59467221f606695a797ecc488a6b4109dab7421aba0c5a6d3681ac5273d4 + , value: foxZRnIh9gZpWnl+zEiKa0EJ2rdCGroMWm02gaxSc9Q= } ] }, { address_data: 2001:610:1:40ba:145:100:185:15 , tls_auth_name: "dnsovertls.sinodun.com" , tls_pubkey_pinset: [ { digest: "sha256" - , value: 0xEB694ABBD1EC0D56F288F7A70299DCE2C7E64984C73957C580BDE9C81F9C04BE + , value: 62lKu9HsDVbyiPenApnc4sfmSYTHOVfFgL3pyB+cBL4= } ] }, { address_data: 2001:610:1:40ba:145:100:185:16 , tls_auth_name: "dnsovertls1.sinodun.com" , tls_pubkey_pinset: [ { digest: "sha256" - , value: 0x704D9E7002DE13907EBAB2610EB26554599FDFC7092C0BEA7A438DBE3BE9A940 + , value: cE2ecALeE5B+urJhDrJlVFmf38cJLAvqekONvjvpqUA= } ] }, { address_data: 2a04:b900:0:100::38 , tls_auth_name: "getdnsapi.net" , tls_pubkey_pinset: [ { digest: "sha256" - , value: 0x7e8c59467221f606695a797ecc488a6b4109dab7421aba0c5a6d3681ac5273d4 + , value: foxZRnIh9gZpWnl+zEiKa0EJ2rdCGroMWm02gaxSc9Q= } ] }, { address_data: 184.105.193.78 , tls_pubkey_pinset: [ { digest: "sha256" - , value: 0xA4E5EBA54B7D9203E06D6C411457014DB447DA17A8DB01F05E9D5F7780045572 + , value: pOXrpUt9kgPgbWxBFFcBTbRH2heo2wHwXp1fd4AEVXI= } ] }, { address_data: 2620:ff:c000:0:1::64:25 , tls_pubkey_pinset: [ { digest: "sha256" - , value: 0xA4E5EBA54B7D9203E06D6C411457014DB447DA17A8DB01F05E9D5F7780045572 + , value: pOXrpUt9kgPgbWxBFFcBTbRH2heo2wHwXp1fd4AEVXI= } ] } ]