From cf387ca3f2a9a4f89718e98822773fef149cbd75 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Thu, 7 Jan 2016 15:32:23 +0100 Subject: [PATCH 01/23] Fixes for cross compiling --- configure.ac | 26 +++++++++++++----------- src/compat/arc4random.c | 36 ++------------------------------- src/compat/getentropy_linux.c | 29 ++++++++++++++++++-------- src/compat/getentropy_solaris.c | 6 ++++++ src/compat/sha512.c | 2 +- src/util-internal.c | 2 +- 6 files changed, 45 insertions(+), 56 deletions(-) diff --git a/configure.ac b/configure.ac index 1a57f475..8ad29b90 100644 --- a/configure.ac +++ b/configure.ac @@ -1019,14 +1019,25 @@ AC_SUBST(C99COMPATFLAGS) AH_BOTTOM([ +#include +#include +#include +#include +#include + +#ifdef HAVE_BSD_STRING_H +#include +#endif + /* the version of the windows API enabled */ -#undef WINVER -#undef _WIN32_WINNT +#ifndef WINVER #define WINVER 0x0600 // 0x0502 +#endif +#ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0600 // 0x0502 +#endif #ifdef HAVE_WINSOCK2_H #include -#include #endif #ifdef HAVE_WS2TCPIP_H @@ -1047,15 +1058,6 @@ AH_BOTTOM([ #endif -#include -#include -#include -#include -#include - -#ifdef HAVE_BSD_STRING_H -#include -#endif #ifdef __cplusplus extern "C" { diff --git a/src/compat/arc4random.c b/src/compat/arc4random.c index 890699cd..2c78818f 100644 --- a/src/compat/arc4random.c +++ b/src/compat/arc4random.c @@ -26,7 +26,9 @@ #include #include #include +#ifdef HAVE_STDINT_H #include +#endif #include #include #include @@ -35,40 +37,6 @@ #include #ifndef GETDNS_ON_WINDOWS #include -#else -#include -#include - -int getentropy(void *buf, size_t len); - -/* -* On Windows, CryptGenRandom is supposed to be a well-seeded -* cryptographically strong random number generator. -*/ -int -getentropy(void *buf, size_t len) -{ - HCRYPTPROV provider; - - if (len > 256) { - errno = EIO; - return -1; - } - - if (CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL, - CRYPT_VERIFYCONTEXT) == 0) - goto fail; - if (CryptGenRandom(provider, len, buf) == 0) { - CryptReleaseContext(provider, 0); - goto fail; - } - CryptReleaseContext(provider, 0); - return (0); - -fail: - errno = EIO; - return (-1); -} #endif #define KEYSTREAM_ONLY diff --git a/src/compat/getentropy_linux.c b/src/compat/getentropy_linux.c index 6c642a96..37d86a8f 100644 --- a/src/compat/getentropy_linux.c +++ b/src/compat/getentropy_linux.c @@ -16,10 +16,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ - #include "config.h" -#ifndef GETDNS_ON_WINDOWS - /* #define _POSIX_C_SOURCE 199309L @@ -49,7 +46,12 @@ #include #include #include + +#if defined(HAVE_SSL) #include +#elif defined(HAVE_NETTLE) +#include +#endif #include #include @@ -70,9 +72,21 @@ HD(b); \ } while (0) +#if defined(HAVE_SSL) +#define CRYPTO_SHA512_CTX SHA512_CTX +#define CRYPTO_SHA512_INIT(x) SHA512_Init(x) +#define CRYPTO_SHA512_FINAL(r, c) SHA512_Final(r, c) #define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l))) #define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x))) #define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*))) +#elif defined(HAVE_NETTLE) +#define CRYPTO_SHA512_CTX struct sha512_ctx +#define CRYPTO_SHA512_INIT(x) sha512_init(x) +#define CRYPTO_SHA512_FINAL(r, c) sha512_digest(c, SHA512_DIGEST_SIZE, r) +#define HR(x, l) (sha512_update(&ctx, (l), (uint8_t *)(x))) +#define HD(x) (sha512_update(&ctx, sizeof (x), (uint8_t *)&(x))) +#define HF(x) (sha512_update(&ctx, sizeof (void*), (uint8_t *)&(x))) +#endif int getentropy(void *buf, size_t len); @@ -125,7 +139,7 @@ getentropy(void *buf, size_t len) * Try to use sysctl CTL_KERN, KERN_RANDOM, RANDOM_UUID. * sysctl is a failsafe API, so it guarantees a result. This * should work inside a chroot, or when file descriptors are - * exhuasted. + * exhausted. * * However this can fail if the Linux kernel removes support * for sysctl. Starting in 2007, there have been efforts to @@ -340,7 +354,7 @@ getentropy_fallback(void *buf, size_t len) struct rusage ru; sigset_t sigset; struct stat st; - SHA512_CTX ctx; + CRYPTO_SHA512_CTX ctx; static pid_t lastpid; pid_t pid; size_t i, ii, m; @@ -357,7 +371,7 @@ getentropy_fallback(void *buf, size_t len) } for (i = 0; i < len; ) { int j; - SHA512_Init(&ctx); + CRYPTO_SHA512_INIT(&ctx); for (j = 0; j < repeat; j++) { HX((e = gettimeofday(&tv, NULL)) == -1, tv); if (e != -1) { @@ -529,7 +543,7 @@ getentropy_fallback(void *buf, size_t len) # endif #endif /* HAVE_GETAUXVAL */ - SHA512_Final(results, &ctx); + CRYPTO_SHA512_FINAL(results, &ctx); memcpy((char*)buf + i, results, min(sizeof(results), len - i)); i += min(sizeof(results), len - i); } @@ -541,4 +555,3 @@ getentropy_fallback(void *buf, size_t len) errno = EIO; return -1; } -#endif \ No newline at end of file diff --git a/src/compat/getentropy_solaris.c b/src/compat/getentropy_solaris.c index 83895738..810098a8 100644 --- a/src/compat/getentropy_solaris.c +++ b/src/compat/getentropy_solaris.c @@ -30,7 +30,9 @@ #include #include #include +#ifdef HAVE_STDINT_H #include +#endif #include #include #include @@ -39,10 +41,14 @@ #include #include #include +#ifdef HAVE_SYS_SHA2_H #include #define SHA512_Init SHA512Init #define SHA512_Update SHA512Update #define SHA512_Final SHA512Final +#else +#include "openssl/sha.h" +#endif #include #include diff --git a/src/compat/sha512.c b/src/compat/sha512.c index ac046abb..744b7ac7 100644 --- a/src/compat/sha512.c +++ b/src/compat/sha512.c @@ -70,7 +70,7 @@ unsigned char *SHA512(void *data, unsigned int data_len, unsigned char *digest); * Please make sure that your system defines BYTE_ORDER. If your * architecture is little-endian, make sure it also defines * LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are - * equivilent. + * equivalent. * * If your system does not define the above, then you can do so by * hand like this: diff --git a/src/util-internal.c b/src/util-internal.c index dd4e816c..fe41bea6 100644 --- a/src/util-internal.c +++ b/src/util-internal.c @@ -271,7 +271,7 @@ _getdns_rr_iter2rr_dict(struct mem_funcs *mf, _getdns_rr_iter *i) } else if (rdf->rdd_pos->type == GETDNS_RDF_SPECIAL) val_type = wf_special; else - assert(0); + assert(((val_type = wf_int), 0)); if (! rdf->rdd_repeat) { switch (val_type) { From 6d7645705a81a26bf2c3a6283662dd1d4c03fb50 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Sun, 10 Jan 2016 12:28:30 +0100 Subject: [PATCH 02/23] Increase FD_SETSIZE on windows --- configure.ac | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/configure.ac b/configure.ac index 8ad29b90..422db4b9 100644 --- a/configure.ac +++ b/configure.ac @@ -1019,6 +1019,14 @@ AC_SUBST(C99COMPATFLAGS) AH_BOTTOM([ +#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 + */ +#define FD_SETSIZE 1024 +#endif + #include #include #include From a970dd420fc50615adf63e9a09ef1717411911ce Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Sun, 10 Jan 2016 12:29:37 +0100 Subject: [PATCH 03/23] Deal with Windows vsnprintf behaviour + a better situated DEBUG_STUB statement in getdns_query --- src/gldns/gbuffer.c | 7 ++++--- src/gldns/gbuffer.h | 15 +++++++++++++++ src/gldns/wire2str.c | 2 +- src/test/getdns_query.c | 5 +++-- 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/gldns/gbuffer.c b/src/gldns/gbuffer.c index a73281c5..ac70415d 100644 --- a/src/gldns/gbuffer.c +++ b/src/gldns/gbuffer.c @@ -120,8 +120,8 @@ gldns_buffer_printf(gldns_buffer *buffer, const char *format, ...) remaining = gldns_buffer_remaining(buffer); va_start(args, format); - written = vsnprintf((char *) gldns_buffer_current(buffer), remaining, - format, args); + written = _gldns_vsnprintf((char*)gldns_buffer_current(buffer), + remaining, format, args); va_end(args); if (written == -1) { buffer->_status_err = 1; @@ -132,7 +132,8 @@ gldns_buffer_printf(gldns_buffer *buffer, const char *format, ...) return -1; } va_start(args, format); - written = vsnprintf((char *) gldns_buffer_current(buffer), + written = _gldns_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 745bb8eb..3d3190ed 100644 --- a/src/gldns/gbuffer.h +++ b/src/gldns/gbuffer.h @@ -27,6 +27,21 @@ 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). diff --git a/src/gldns/wire2str.c b/src/gldns/wire2str.c index f15631b0..b9a979eb 100644 --- a/src/gldns/wire2str.c +++ b/src/gldns/wire2str.c @@ -278,7 +278,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 = vsnprintf(*str, *slen, format, args); + int w = _gldns_vsnprintf(*str, *slen, format, args); if(w < 0) { /* error in printout */ return 0; diff --git a/src/test/getdns_query.c b/src/test/getdns_query.c index 837ed61d..73e2c11c 100644 --- a/src/test/getdns_query.c +++ b/src/test/getdns_query.c @@ -68,12 +68,13 @@ my_eventloop_schedule(getdns_eventloop *loop, my_eventloop *my_loop = (my_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); + assert(loop); assert(event); assert(fd < FD_SETSIZE); - DEBUG_SCHED( "%s(loop: %p, fd: %d, timeout: %"PRIu64", event: %p)\n" - , __FUNCTION__, loop, fd, timeout, event); if (fd >= 0 && (event->read_cb || event->write_cb)) { assert(my_loop->fd_events[fd] == NULL); From 39f7e87f1a2babfd8576344418fee2899180058b Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Mon, 11 Jan 2016 12:11:17 +0100 Subject: [PATCH 04/23] Get rid of unkown format specifiers on windows --- configure.ac | 4 ++++ src/context.c | 8 ++++---- src/debug.h | 4 ++-- src/dnssec.c | 16 ++++++++-------- src/pubkey-pinning.c | 6 +++--- src/test/getdns_query.c | 20 ++++++++++---------- 6 files changed, 31 insertions(+), 27 deletions(-) diff --git a/configure.ac b/configure.ac index 422db4b9..41f28349 100644 --- a/configure.ac +++ b/configure.ac @@ -1025,6 +1025,10 @@ AH_BOTTOM([ * See: https://support.microsoft.com/en-us/kb/111855 */ #define FD_SETSIZE 1024 + +#define PRIsz "%Iu" +#else +#define PRIsz "%zu" #endif #include diff --git a/src/context.c b/src/context.c index c47d4992..c325d982 100644 --- a/src/context.c +++ b/src/context.c @@ -1761,15 +1761,15 @@ getdns_context_set_dns_root_servers( else if (addr_bd->size == 16 && inet_ntop(AF_INET6, addr_bd->data, dst, sizeof(dst))) - fprintf(fh, ". NS %zu.root-servers.getdnsapi.net.\n" - "%zu.root-servers.getdnsapi.net. AAAA %s\n", + fprintf(fh,". NS "PRIsz".root-servers.getdnsapi.net.\n" + PRIsz".root-servers.getdnsapi.net. AAAA %s\n", i, i, dst); else if (addr_bd->size == 4 && inet_ntop(AF_INET, addr_bd->data, dst, sizeof(dst))) - fprintf(fh, ". NS %zu.root-servers.getdnsapi.net.\n" - "%zu.root-servers.getdnsapi.net. A %s\n", + fprintf(fh,". NS "PRIsz".root-servers.getdnsapi.net.\n" + PRIsz".root-servers.getdnsapi.net. A %s\n", i, i, dst); } fclose(fh); diff --git a/src/debug.h b/src/debug.h index 4381757d..cee9475d 100644 --- a/src/debug.h +++ b/src/debug.h @@ -44,7 +44,7 @@ \ gettimeofday(&tv, NULL); \ gmtime_r(&tv.tv_sec, &tm); \ - strftime(buf, 10, "%T", &tm); \ + strftime(buf, 10, "%H:%M:%S", &tm); \ fprintf(stderr, "[%s.%.6d] ", buf, (int)tv.tv_usec); \ fprintf(stderr, __VA_ARGS__); \ } while (0) @@ -56,7 +56,7 @@ \ gettimeofday(&tv, NULL); \ gmtime_r(&tv.tv_sec, &tm); \ - strftime(buf, 10, "%T", &tm); \ + strftime(buf, 10, "%H:%M:%S", &tm); \ fprintf(stderr, "[%s.%.6d] ", buf, (int)tv.tv_usec); \ fprintf(stderr, __VA_ARGS__); \ fprintf(stderr, "\n"); \ diff --git a/src/dnssec.c b/src/dnssec.c index 94cf8cfd..7cf54ec7 100644 --- a/src/dnssec.c +++ b/src/dnssec.c @@ -839,7 +839,7 @@ static chain_head *add_rrset2val_chain(struct mem_funcs *mf, dname_len = *labels - last_label[-1] + 1; head_sz = (sizeof(chain_head) + dname_len + 7) / 8 * 8; node_count = last_label - labels - max_labels; - DEBUG_SEC( "%zu labels in common. %zu labels to allocate\n" + DEBUG_SEC( PRIsz" labels in common. "PRIsz" labels to allocate\n" , max_labels, node_count); if (! (region = GETDNS_XMALLOC(*mf, uint8_t, head_sz + @@ -1627,7 +1627,7 @@ static int _getdns_verify_rrsig(struct mem_funcs *mf, /* More space needed for val_rrset */ val_rrset = GETDNS_XMALLOC(*mf, _getdns_rr_iter, n_rrs); } - DEBUG_SEC( "sizes: %zu rrs, %zu bytes for validation buffer\n" + DEBUG_SEC( "sizes: "PRIsz" rrs, "PRIsz" bytes for validation buffer\n" , n_rrs, valbuf_sz); qsort(val_rrset, n_rrs, sizeof(_getdns_rr_iter), _rr_iter_rdata_cmp); @@ -1686,7 +1686,7 @@ static int _getdns_verify_rrsig(struct mem_funcs *mf, gldns_buffer_write_u16_at(&valbuf, pos, (uint16_t)(gldns_buffer_position(&valbuf) - pos - 2)); } - DEBUG_SEC( "written to valbuf: %zu bytes\n" + DEBUG_SEC( "written to valbuf: "PRIsz" bytes\n" , gldns_buffer_position(&valbuf)); assert(gldns_buffer_position(&valbuf) <= valbuf_sz); @@ -2107,7 +2107,7 @@ static int ds_authenticates_keys(struct mem_funcs *mf, if (digest_buf != digest_buf_spc) GETDNS_FREE(*mf, digest_buf); - DEBUG_SEC("HASH length mismatch %zu != %zu\n", + DEBUG_SEC("HASH length mismatch "PRIsz" != "PRIsz"\n", digest_len, ds->rr_i.nxt - ds->rr_i.rr_type-14); continue; } @@ -2130,7 +2130,7 @@ static int ds_authenticates_keys(struct mem_funcs *mf, max_supported_result = SIGNATURE_VERIFIED | keytag; } } - DEBUG_SEC("valid_dsses: %zu, supported_dsses: %zu\n", + DEBUG_SEC("valid_dsses: "PRIsz", supported_dsses: "PRIsz"\n", valid_dsses, supported_dsses); if (valid_dsses && !supported_dsses) return NO_SUPPORTED_ALGORITHMS; @@ -3135,7 +3135,7 @@ static void check_chain_complete(chain_head *chain) rrset_iter tas_iter; if ((o = count_outstanding_requests(chain)) > 0) { - DEBUG_SEC("%zu outstanding requests\n", o); + DEBUG_SEC(PRIsz" outstanding requests\n", o); return; } DEBUG_SEC("Chain done!\n"); @@ -3410,7 +3410,7 @@ getdns_validate_dnssec(getdns_list *records_to_validate, for (i = 0; !getdns_list_get_dict(records_to_validate,i,&reply); i++) { - DEBUG_SEC("REPLY %zu, r: %d\n", i, r); + DEBUG_SEC("REPLY "PRIsz", r: %d\n", i, r); if (to_val != to_val_buf) GETDNS_FREE(*mf, to_val); to_val_len = sizeof(to_val_buf); @@ -3437,7 +3437,7 @@ getdns_validate_dnssec(getdns_list *records_to_validate, break; } } - DEBUG_SEC("REPLY %zu, r: %d\n", i, r); + DEBUG_SEC("REPLY "PRIsz", r: %d\n", i, r); exit_free_to_val: if (to_val != to_val_buf) diff --git a/src/pubkey-pinning.c b/src/pubkey-pinning.c index 2f685ad3..6281f2f8 100644 --- a/src/pubkey-pinning.c +++ b/src/pubkey-pinning.c @@ -415,13 +415,13 @@ _getdns_verify_pinset_match(const sha256_pin_t *pinset, /* digest the cert with sha256 */ len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), NULL); if (len > sizeof(raw)) { - DEBUG_STUB("--- %s: pubkey %d is larger than %ld octets\n", + DEBUG_STUB("--- %s: pubkey %d is larger than "PRIsz" octets\n", __FUNCTION__, i, sizeof(raw)); continue; } i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &next); if (next - raw != len) { - DEBUG_STUB("--- %s: pubkey %d claimed it needed %d octets, really needed %ld\n", + DEBUG_STUB("--- %s: pubkey %d claimed it needed %d octets, really needed "PRIsz"\n", __FUNCTION__, i, len, next - raw); continue; } @@ -430,7 +430,7 @@ _getdns_verify_pinset_match(const sha256_pin_t *pinset, /* compare it */ for (p = pinset; p; p = p->next) if (0 == memcmp(buf, p->pin, sizeof(p->pin))) { - DEBUG_STUB("--- %s: pubkey %d matched pin %p (%ld)!\n", + DEBUG_STUB("--- %s: pubkey %d matched pin %p ("PRIsz")!\n", __FUNCTION__, i, p, sizeof(p->pin)); return GETDNS_RETURN_GOOD; } else diff --git a/src/test/getdns_query.c b/src/test/getdns_query.c index 73e2c11c..2e665cef 100644 --- a/src/test/getdns_query.c +++ b/src/test/getdns_query.c @@ -588,7 +588,7 @@ static getdns_return_t validate_chain(getdns_dict *response) if ((r = getdns_list_set_dict(to_validate, 0, reply))) goto error; - printf("reply %u, dnssec_status: ", (unsigned)i); + printf("reply "PRIsz", dnssec_status: ", i); switch ((s = getdns_validate_dnssec( to_validate, validation_chain, trust_anchor))) { @@ -646,7 +646,7 @@ void callback(getdns_context *context, getdns_callback_type_t callback_type, else { fprintf(stderr, "An error occurred: The callback got a callback_type of %d. Exiting.\n", - callback_type); + (int)callback_type); fprintf(stderr, "Error : '%s'\n", getdns_get_errorstr_by_id(callback_type)); @@ -737,7 +737,7 @@ getdns_return_t parse_args(int argc, char **argv) (arg[4] == '=' || arg[4] == '\0')) { if ((r = set_cookie(extensions, arg+4))) { fprintf(stderr, "Could not set cookie:" - " %d", r); + " %d", (int)r); break; } } else if (strncmp(arg+1, "specify_class=", 14) == 0) { @@ -777,7 +777,7 @@ getdns_return_t parse_args(int argc, char **argv) } else if ((r = getdns_dict_set_int(extensions, arg+1, GETDNS_EXTENSION_TRUE))) { fprintf(stderr, "Could not set extension " - "\"%s\": %d\n", argv[i], r); + "\"%s\": %d\n", argv[i], (int)r); break; } continue; @@ -912,7 +912,7 @@ getdns_return_t parse_args(int argc, char **argv) if (r = getdns_list_set_dict(pubkey_pinset, pincount++, pubkey_pin), r) { fprintf(stderr, "Failed to add pin to pinset (error %d: %s)\n", - r, getdns_get_errorstr_by_id(r)); + (int)r, getdns_get_errorstr_by_id(r)); getdns_dict_destroy(pubkey_pin); pubkey_pin = NULL; return GETDNS_RETURN_GENERIC_ERROR; @@ -1122,11 +1122,11 @@ next: ; /* apply the accumulated pubkey pinset to all upstreams: */ for (i = 0; i < upstream_count; i++) { if (r = getdns_list_get_dict(upstream_list, i, &upstream), r) { - fprintf(stderr, "Failed to get upstream %lu when adding pinset\n", (long unsigned int)i); + fprintf(stderr, "Failed to get upstream "PRIsz" when adding pinset\n", i); return r; } if (r = getdns_dict_set_list(upstream, "tls_pubkey_pinset", pubkey_pinset), r) { - fprintf(stderr, "Failed to set pubkey pinset on upstream %lu\n", (long unsigned int)i); + fprintf(stderr, "Failed to set pubkey pinset on upstream "PRIsz"\n", i); return r; } } @@ -1191,7 +1191,7 @@ getdns_return_t do_the_call(void) if (r == GETDNS_RETURN_GOOD && !batch_mode) getdns_context_run(context); if (r != GETDNS_RETURN_GOOD) - fprintf(stderr, "An error occurred: %d '%s'\n", r, + fprintf(stderr, "An error occurred: %d '%s'\n", (int)r, getdns_get_errorstr_by_id(r)); } else { switch (calltype) { @@ -1216,7 +1216,7 @@ getdns_return_t do_the_call(void) break; } if (r != GETDNS_RETURN_GOOD) { - fprintf(stderr, "An error occurred: %d '%s'\n", r, + fprintf(stderr, "An error occurred: %d '%s'\n", (int)r, getdns_get_errorstr_by_id(r)); return r; } @@ -1301,7 +1301,7 @@ main(int argc, char **argv) name = the_root; if ((r = getdns_context_create(&context, 1))) { - fprintf(stderr, "Create context failed: %d\n", r); + fprintf(stderr, "Create context failed: %d\n", (int)r); return r; } my_eventloop_init(&my_loop); From 4fd8d3dddd9fbf018ffc9340c7b3efc2ab4cdb3c Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Tue, 12 Jan 2016 15:52:14 +0100 Subject: [PATCH 05/23] Replace mini_event extension by default_eventloop * default_eventloop was prototyped in getdns_query and is still in there as my_eventloop * It interfaces directly with the scheduling primitives of getdns. * It can operate entirely from stack and does not have to do any memory allocations or deallocations. * Adapted configure.ac to allow libunbound to be linked with Windows (with the removal of winsock_event.c we have no symbol clashed anymore) * Added STUB_TCP_WOULDBLOCK return code in stub_resolving helper functions, to anticipate dealing with edge triggered event loops (versus level triggered). (i.e. Windows) --- configure.ac | 70 +- spec/example/Makefile.in | 24 +- src/Makefile.in | 236 ++--- src/context.c | 59 +- src/context.h | 8 +- src/extension/default_eventloop.c | 281 ++++++ .../{libmini_event.h => default_eventloop.h} | 52 +- src/extension/libmini_event.c | 238 ----- src/stub.c | 104 ++- src/sync.c | 6 +- src/test/Makefile.in | 96 +- src/util/import.sh | 2 +- src/util/mini_event.c | 394 -------- src/util/mini_event.h | 178 ---- src/util/winsock_event.c | 844 ------------------ src/util/winsock_event.h | 295 ------ 16 files changed, 640 insertions(+), 2247 deletions(-) create mode 100644 src/extension/default_eventloop.c rename src/extension/{libmini_event.h => default_eventloop.h} (65%) delete mode 100644 src/extension/libmini_event.c delete mode 100644 src/util/mini_event.c delete mode 100644 src/util/mini_event.h delete mode 100644 src/util/winsock_event.c delete mode 100644 src/util/winsock_event.h diff --git a/configure.ac b/configure.ac index 41f28349..ab0d917b 100644 --- a/configure.ac +++ b/configure.ac @@ -453,45 +453,39 @@ if test "$USE_WINSOCK" = 1; then AC_DEFINE_UNQUOTED([GETDNS_ON_WINDOWS], [1], [Define this to enable Windows build.]) AC_DEFINE_UNQUOTED([STUB_NATIVE_DNSSEC], [1]) LIBS="$LIBS -lgdi32 -liphlpapi" - my_with_libunbound=0 - my_with_libidn=0 -else - my_with_libidn=1 fi -if test $my_with_libidn = 1 -then - AC_ARG_WITH(libidn, AS_HELP_STRING([--with-libidn=pathname], - [path to libidn (default: search /usr/local ..)]), - [], [withval="yes"]) - if test x_$withval = x_yes; then - for dir in /usr/local /opt/local /usr/pkg /usr/sfw; do - if test -f "$dir/include/idna.h"; then - CFLAGS="$CFLAGS -I$dir/include" - LDFLAGS="$LDFLAGS -L$dir/lib" - AC_MSG_NOTICE([Found libidn in $dir]) - break - fi - if test -f "$dir/include/idn/idna.h"; then - CFLAGS="$CFLAGS -I$dir/include/idn" - LDFLAGS="$LDFLAGS -L$dir/lib" - AC_MSG_NOTICE([Found libidn in $dir]) - break - fi - done - if test -f "/usr/include/idn/idna.h"; then - CFLAGS="$CFLAGS -I/usr/include/idn" - #LDFLAGS="$LDFLAGS -L/usr/lib" - AC_MSG_NOTICE([Found libidn in /usr]) +my_with_libidn=1 +AC_ARG_WITH(libidn, AS_HELP_STRING([--with-libidn=pathname], + [path to libidn (default: search /usr/local ..)]), + [], [withval="yes"]) +if test x_$withval = x_yes; then + for dir in /usr/local /opt/local /usr/pkg /usr/sfw; do + if test -f "$dir/include/idna.h"; then + CFLAGS="$CFLAGS -I$dir/include" + LDFLAGS="$LDFLAGS -L$dir/lib" + AC_MSG_NOTICE([Found libidn in $dir]) + break fi + if test -f "$dir/include/idn/idna.h"; then + CFLAGS="$CFLAGS -I$dir/include/idn" + LDFLAGS="$LDFLAGS -L$dir/lib" + AC_MSG_NOTICE([Found libidn in $dir]) + break + fi + done + if test -f "/usr/include/idn/idna.h"; then + CFLAGS="$CFLAGS -I/usr/include/idn" + #LDFLAGS="$LDFLAGS -L/usr/lib" + AC_MSG_NOTICE([Found libidn in /usr]) + fi +else + if test x_$withval != x_no; then + CFLAGS="$CFLAGS -I$withval/include" + LDFLAGS="$LDFLAGS -L$withval/lib" else - if test x_$withval != x_no; then - CFLAGS="$CFLAGS -I$withval/include" - LDFLAGS="$LDFLAGS -L$withval/lib" - else - my_with_libidn=0 - fi + my_with_libidn=0 fi fi @@ -1161,6 +1155,14 @@ const char *inet_ntop(int af, const void *src, char *dst, size_t size); #include #endif +#ifdef HAVE_INTTYPES_H +#include +#endif + +#ifndef PRIu64 +#define PRIu64 "llu" +#endif + #ifdef HAVE_ATTR_FORMAT # define ATTR_FORMAT(archetype, string_index, first_to_check) \ __attribute__ ((format (archetype, string_index, first_to_check))) 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 a20a9b18..f51a0ab4 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -74,9 +74,9 @@ LIBOBJDIR= LIBOBJS=@LIBOBJS@ COMPAT_OBJ=$(LIBOBJS:.o=.lo) -UTIL_OBJ=mini_event.lo winsock_event.lo rbtree.lo val_secalgo.lo +UTIL_OBJ=rbtree.lo val_secalgo.lo -EXTENSION_OBJ=libmini_event.lo libevent.lo libev.lo +EXTENSION_OBJ=default_eventloop.lo libevent.lo libev.lo NON_C99_OBJS=context.lo libuv.lo @@ -144,8 +144,8 @@ libgetdns_ext_ev.la: libgetdns.la libev.lo $(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) -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 libmini_event.lo $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) - $(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) -o $@ $(GETDNS_OBJ) version.lo context.lo libmini_event.lo $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(LDFLAGS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/libgetdns.symbols +libgetdns.la: $(GETDNS_OBJ) version.lo context.lo default_eventloop.lo $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) + $(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) -o $@ $(GETDNS_OBJ) version.lo context.lo default_eventloop.lo $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(LDFLAGS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/libgetdns.symbols test: all @@ -225,114 +225,136 @@ 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/libmini_event.h \ - config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h $(srcdir)/types-internal.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)/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/libmini_event.h config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \ - $(srcdir)/types-internal.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)/dict.h $(srcdir)/list.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/libmini_event.h config.h $(srcdir)/util/mini_event.h \ - $(srcdir)/util/rbtree.h $(srcdir)/types-internal.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/libmini_event.h config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \ - $(srcdir)/types-internal.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/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)/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/libmini_event.h config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \ - $(srcdir)/types-internal.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)/stub.h $(srcdir)/general.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/libmini_event.h config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \ - $(srcdir)/types-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ - $(srcdir)/list.h $(srcdir)/dict.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/libmini_event.h config.h $(srcdir)/util/mini_event.h \ - $(srcdir)/util/rbtree.h $(srcdir)/types-internal.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/libmini_event.h config.h \ - $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h $(srcdir)/types-internal.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 \ +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)/util-internal.h $(srcdir)/rr-iter.h \ + $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.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)/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)/dict.h $(srcdir)/list.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)/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)/util-internal.h $(srcdir)/rr-iter.h \ + $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.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)/gldns/wire2str.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.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)/stub.h \ + $(srcdir)/dict.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)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ + $(srcdir)/gldns/pkthdr.h $(srcdir)/list.h $(srcdir)/dict.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 +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)/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)/debug.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/libmini_event.h config.h \ - $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h $(srcdir)/types-internal.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 getdns/getdns.h $(srcdir)/rr-dict.h config.h \ - $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.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/libmini_event.h \ - config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h $(srcdir)/types-internal.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/libmini_event.h \ - config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h $(srcdir)/types-internal.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)/stub.h $(srcdir)/gldns/wire2str.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/libmini_event.h config.h \ - $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h $(srcdir)/types-internal.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 -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 \ +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)/rr-iter.h $(srcdir)/gldns/pkthdr.h \ + $(srcdir)/dict.h +rr-iter.lo rr-iter.o: $(srcdir)/rr-iter.c $(srcdir)/rr-iter.h \ + getdns/getdns.h $(srcdir)/rr-dict.h \ + config.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ + $(srcdir)/gldns/rrdef.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)/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)/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)/stub.h \ + $(srcdir)/gldns/wire2str.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)/rr-iter.h \ + $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/str2wire.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 +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 +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 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 -mini_event.lo mini_event.o: $(srcdir)/util/mini_event.c config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \ - $(srcdir)/util/fptr_wlist.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 -winsock_event.lo winsock_event.o: $(srcdir)/util/winsock_event.c config.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 -libmini_event.lo libmini_event.o: $(srcdir)/extension/libmini_event.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)/extension/libmini_event.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.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 +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 +default_eventloop.lo default_eventloop.o: $(srcdir)/extension/default_eventloop.c \ + $(srcdir)/extension/default_eventloop.h config.h \ + getdns/getdns.h \ + getdns/getdns_extra.h $(srcdir)/debug.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 diff --git a/src/context.c b/src/context.c index c325d982..0dd7ec79 100644 --- a/src/context.c +++ b/src/context.c @@ -966,6 +966,9 @@ getdns_context_create_with_extended_memory_functions( struct getdns_context *result = NULL; mf_union mf; gldns_buffer gbuf; +#ifdef USE_WINSOCK + WORD wVersionRequested; +#endif if (!context || !malloc || !realloc || !free) return GETDNS_RETURN_INVALID_PARAMETER; @@ -979,6 +982,14 @@ getdns_context_create_with_extended_memory_functions( if (!result) return GETDNS_RETURN_MEMORY_ERROR; +#ifdef USE_WINSOCK + /* We need to run WSAStartup() to be able to use getaddrinfo() */ + wVersionRequested = MAKEWORD(2, 2); + if (WSAStartup(wVersionRequested, &result->wsaData)) { + r = GETDNS_RETURN_GENERIC_ERROR; + goto error; + } +#endif result->processing = 0; result->destroying = 0; result->my_mf.mf_arg = userarg; @@ -1050,9 +1061,8 @@ getdns_context_create_with_extended_memory_functions( result->tls_query_padding_blocksize = 1; /* default is to not try to pad */ result-> tls_ctx = NULL; - result->extension = &result->mini_event.loop; - if ((r = _getdns_mini_event_init(result, &result->mini_event))) - goto error; + result->extension = &result->default_eventloop.loop; + _getdns_default_eventloop_init(&result->default_eventloop); result->fchg_resolvconf = NULL; result->fchg_hosts = NULL; @@ -1198,6 +1208,9 @@ getdns_context_destroy(struct getdns_context *context) _getdns_traverse_postorder(&context->local_hosts, destroy_local_host, context); +#ifdef USE_WINSOCK + WSACleanup(); +#endif GETDNS_FREE(context->my_mf, context); } /* getdns_context_destroy */ @@ -2798,55 +2811,36 @@ _getdns_bindata_destroy(struct mem_funcs *mfs, /* TODO: Remove next_timeout argument from getdns_context_get_num_pending_requests */ -void _getdns_handle_timeouts(struct _getdns_event_base* base, struct timeval* now, - struct timeval* wait); uint32_t -getdns_context_get_num_pending_requests(struct getdns_context* context, +getdns_context_get_num_pending_requests(getdns_context* context, struct timeval* next_timeout) { - struct timeval dispose; + (void)next_timeout; - RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER); + if (!context) + return GETDNS_RETURN_INVALID_PARAMETER; if (context->outbound_requests.count) context->extension->vmt->run_once(context->extension, 0); - /* TODO: Remove this when next_timeout is gone */ - if (context->extension == &context->mini_event.loop) - _getdns_handle_timeouts(context->mini_event.base, - &context->mini_event.time_tv, - next_timeout ? next_timeout : &dispose); - return context->outbound_requests.count; } /* process async reqs */ getdns_return_t -getdns_context_process_async(struct getdns_context* context) +getdns_context_process_async(getdns_context *context) { - RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER); + if (!context) + return GETDNS_RETURN_INVALID_PARAMETER; -#ifdef HAVE_LIBUNBOUND - if (ub_poll(context->unbound_ctx) && ub_process(context->unbound_ctx)){ - /* need an async return code? */ - return GETDNS_RETURN_GENERIC_ERROR; - } -#endif context->extension->vmt->run_once(context->extension, 0); - return GETDNS_RETURN_GOOD; } void getdns_context_run(getdns_context *context) { - if (context->extension == &context->mini_event.loop) { - if (getdns_context_get_num_pending_requests(context, NULL) > 0 && - !getdns_context_process_async(context)) - context->extension->vmt->run(context->extension); - } - else - context->extension->vmt->run(context->extension); + context->extension->vmt->run(context->extension); } typedef struct timeout_accumulator { @@ -2891,8 +2885,9 @@ getdns_context_detach_eventloop(struct getdns_context* context) /* cancel all outstanding requests */ cancel_outstanding_requests(context, 1); context->extension->vmt->cleanup(context->extension); - context->extension = &context->mini_event.loop; - return _getdns_mini_event_init(context, &context->mini_event); + context->extension = &context->default_eventloop.loop; + _getdns_default_eventloop_init(&context->default_eventloop); + return GETDNS_RETURN_GOOD; } getdns_return_t diff --git a/src/context.h b/src/context.h index 340ac375..8547673c 100644 --- a/src/context.h +++ b/src/context.h @@ -41,7 +41,7 @@ #include "getdns/getdns_extra.h" #include "config.h" #include "types-internal.h" -#include "extension/libmini_event.h" +#include "extension/default_eventloop.h" #include "util/rbtree.h" struct getdns_dns_req; @@ -245,7 +245,7 @@ struct getdns_context { #endif /* The default extension */ - _getdns_mini_event mini_event; + _getdns_default_eventloop default_eventloop; /* * state data used to detect changes to the system config files @@ -255,6 +255,10 @@ struct getdns_context { uint8_t trust_anchors_spc[1024]; +#ifdef USE_WINSOCK + /* We need to run WSAStartup() to be able to use getaddrinfo() */ + WSADATA wsaData; +#endif }; /* getdns_context */ /** internal functions **/ diff --git a/src/extension/default_eventloop.c b/src/extension/default_eventloop.c new file mode 100644 index 00000000..d44cfb6a --- /dev/null +++ b/src/extension/default_eventloop.c @@ -0,0 +1,281 @@ +/* + * 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 "extension/default_eventloop.h" +#include "debug.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 : -1; +} + +static getdns_return_t +default_eventloop_schedule(getdns_eventloop *loop, + int fd, uint64_t timeout, getdns_eventloop_event *event) +{ + _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); + + if (!loop || !event) + return GETDNS_RETURN_INVALID_PARAMETER; + + if (fd >= FD_SETSIZE) { + DEBUG_SCHED( "ERROR: fd %d >= FD_SETSIZE: %d!\n" + , fd, FD_SETSIZE); + return GETDNS_RETURN_GENERIC_ERROR; + } + if (fd >= 0) { + if (!(event->read_cb || event->write_cb)) { + DEBUG_SCHED("ERROR: fd event without " + "read or write cb!\n"); + return GETDNS_RETURN_GENERIC_ERROR; + } +#if defined(SCHED_DEBUG) && SCHED_DEBUG + if (default_loop->fd_events[fd]) { + DEBUG_SCHED( "ERROR: Event present at fd slot: %p!\n" + , default_loop->fd_events[fd]); + } +#endif + default_loop->fd_events[fd] = event; + default_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 (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; + + 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 +default_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) +{ + _getdns_default_eventloop *default_loop = (_getdns_default_eventloop *)loop; + ssize_t i; + + if (!loop || !event) + return GETDNS_RETURN_INVALID_PARAMETER; + + DEBUG_SCHED( "%s(loop: %p, event: %p)\n", __FUNCTION__, loop, 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 (default_loop->timeout_events[i] != event) + DEBUG_SCHED( "ERROR: Different/wrong event present at " + "timeout slot: %p!\n" + , default_loop->timeout_events[i]); +#endif + default_loop->timeout_events[i] = NULL; + } else { +#if defined(SCHED_DEBUG) && SCHED_DEBUG + if (default_loop->fd_events[i] != event) + DEBUG_SCHED( "ERROR: Different/wrong event present at " + "fd slot: %p!\n" + , default_loop->fd_events[i]); +#endif + default_loop->fd_events[i] = NULL; + } + event->ev = NULL; + return GETDNS_RETURN_GOOD; +} + +static void +default_eventloop_cleanup(getdns_eventloop *loop) +{ +} + +static void +default_read_cb(int fd, getdns_eventloop_event *event) +{ + DEBUG_SCHED( "%s(fd: %d, event: %p)\n", __FUNCTION__, fd, event); + event->read_cb(event->userarg); +} + +static void +default_write_cb(int fd, getdns_eventloop_event *event) +{ + DEBUG_SCHED( "%s(fd: %d, event: %p)\n", __FUNCTION__, fd, event); + event->write_cb(event->userarg); +} + +static void +default_timeout_cb(int fd, getdns_eventloop_event *event) +{ + DEBUG_SCHED( "%s(fd: %d, event: %p)\n", __FUNCTION__, fd, event); + event->timeout_cb(event->userarg); +} + +static void +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 = (uint64_t)-1; + 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 (!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]; + } + for (fd = 0; fd < FD_SETSIZE; 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 (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 == (uint64_t)-1) + return; + + if (! blocking || now > timeout) { + tv.tv_sec = 0; + tv.tv_usec = 0; + } else { + tv.tv_sec = (timeout - now) / 1000000; + tv.tv_usec = (timeout - now) % 1000000; + } + if (select(max_fd + 1, &readfds, &writefds, NULL, + (timeout == ((uint64_t)-1) ? NULL : &tv)) < 0) { + perror("select() failed"); + exit(EXIT_FAILURE); + } + now = get_now_plus(0); + for (fd = 0; fd < FD_SETSIZE; fd++) { + if (default_loop->fd_events[fd] && + default_loop->fd_events[fd]->read_cb && + FD_ISSET(fd, &readfds)) + 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)) + default_write_cb(fd, default_loop->fd_events[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]); + } +} + +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 < MAX_TIMEOUTS) { + if (default_loop->fd_events[i] || default_loop->timeout_events[i]) { + default_eventloop_run_once(loop, 1); + i = 0; + } else { + i++; + } + } +} + +void +_getdns_default_eventloop_init(_getdns_default_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 + }; + + (void) memset(loop, 0, sizeof(_getdns_default_eventloop)); + loop->loop.vmt = &default_eventloop_vmt; +} diff --git a/src/extension/libmini_event.h b/src/extension/default_eventloop.h similarity index 65% rename from src/extension/libmini_event.h rename to src/extension/default_eventloop.h index c3f5b19a..7f6b78f0 100644 --- a/src/extension/libmini_event.h +++ b/src/extension/default_eventloop.h @@ -1,11 +1,10 @@ -/** - * - * \file libmini_event.h +/* + * \file default_eventloop.h * @brief Build in default eventloop extension that uses select. * */ /* - * Copyright (c) 2013, NLnet Labs, Verisign, Inc. + * Copyright (c) 2013, NLNet Labs, Verisign, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -30,34 +29,31 @@ * (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 _GETDNS_LIBMINI_EVENT_H_ -#define _GETDNS_LIBMINI_EVENT_H_ - +#ifndef DEFAULT_EVENTLOOP_H_ +#define DEFAULT_EVENTLOOP_H_ #include "config.h" -#ifndef USE_WINSOCK -#include "util/mini_event.h" -#else -#include "util/winsock_event.h" -#endif -#include "types-internal.h" +#include "getdns/getdns.h" +#include "getdns/getdns_extra.h" -typedef struct _getdns_mini_event { - getdns_eventloop loop; - time_t time_secs; - struct timeval time_tv; - struct _getdns_event_base *base; - size_t n_events; - struct mem_funcs mf; -} _getdns_mini_event; +/* 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 -getdns_return_t -_getdns_mini_event_init(getdns_context *context, _getdns_mini_event *mini_event); +/* Eventloop based on select */ +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_default_eventloop; -getdns_return_t -_getdns_mini_event_create(getdns_context *ctxt, _getdns_mini_event **mini_event); void -_getdns_mini_event_destroy(_getdns_mini_event *mini_event); +_getdns_default_eventloop_init(_getdns_default_eventloop *loop); + +#endif -#endif /* _GETDNS_LIBMINI_EVENT_H_ */ diff --git a/src/extension/libmini_event.c b/src/extension/libmini_event.c deleted file mode 100644 index def10027..00000000 --- a/src/extension/libmini_event.c +++ /dev/null @@ -1,238 +0,0 @@ -/** - * - * \file libmini_event.c - * @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. - */ - -#include "config.h" -#include "debug.h" -#include "types-internal.h" -#include "extension/libmini_event.h" -#if defined(SCHED_DEBUG) && SCHED_DEBUG -#include -#endif - -static void -_getdns_mini_event_cleanup(getdns_eventloop *loop) -{ - _getdns_mini_event *ext = (_getdns_mini_event *)loop; - _getdns_event_base_free(ext->base); -} - -void -_getdns_mini_event_destroy(_getdns_mini_event *ext) -{ - assert(ext); - ext->loop.vmt->cleanup(&ext->loop); - GETDNS_FREE(ext->mf, ext); -} - -void _getdns_handle_timeouts(struct _getdns_event_base* base, - struct timeval* now, struct timeval* wait); -int _getdns_handle_select(struct _getdns_event_base* base, struct timeval* wait); - -static int -_getdns_mini_event_settime(_getdns_mini_event *ext) -{ - if (gettimeofday(&ext->time_tv, NULL) < 0) - return -1; - ext->time_secs = (time_t)ext->time_tv.tv_sec; - return 0; -} - -static void -_getdns_mini_event_run(getdns_eventloop *loop) -{ - _getdns_mini_event *ext = (_getdns_mini_event *)loop; - struct timeval wait; - - if (ext->n_events == 0 || _getdns_mini_event_settime(ext) < 0) - return; - - do { - (void) _getdns_handle_timeouts(ext->base, &ext->time_tv, &wait); - - if (!ext->n_events) - break; - - if (_getdns_handle_select(ext->base, &wait)) - break; - - } while (ext->n_events); -} - -static void -_getdns_mini_event_run_once(getdns_eventloop *loop, int blocking) -{ - static struct timeval immediately = { 0, 0 }; - _getdns_mini_event *ext = (_getdns_mini_event *)loop; - struct timeval wait; - - if (blocking) { - if (_getdns_mini_event_settime(ext) < 0) - return; - _getdns_handle_timeouts(ext->base, &ext->time_tv, &wait); - if (_getdns_handle_select(ext->base, &wait) < 0) - return; - - } else if (_getdns_handle_select(ext->base, &immediately) < 0) - return; - - _getdns_handle_timeouts(ext->base, &ext->time_tv, &wait); -} - -static getdns_return_t -_getdns_mini_event_clear(getdns_eventloop *loop, getdns_eventloop_event *el_ev) -{ - getdns_return_t r = GETDNS_RETURN_GOOD; - _getdns_mini_event *ext = (_getdns_mini_event *)loop; - - assert(el_ev->ev); - DEBUG_SCHED("1. _getdns_mini_event_clear(loop: %p, el_ev: %p[userarg: %p, r: %p, w: %p, t: %p, ev: %p]); n_events: %d, times: %d\n", loop, el_ev, el_ev->userarg, el_ev->read_cb, el_ev->write_cb, el_ev->timeout_cb, el_ev->ev, (int)ext->n_events, (int)ext->base->times->count); - - if (_getdns_event_del(el_ev->ev) != 0) - r = GETDNS_RETURN_GENERIC_ERROR; - - GETDNS_FREE(ext->mf, el_ev->ev); - el_ev->ev = NULL; - - ext->n_events--; - DEBUG_SCHED("2. %d <- _getdns_mini_event_clear(loop: %p, el_ev: %p[userarg: %p, r: %p, w: %p, t: %p, ev: %p]); n_events: %d, times: %d\n", r, loop, el_ev, el_ev->userarg, el_ev->read_cb, el_ev->write_cb, el_ev->timeout_cb, el_ev->ev, (int)ext->n_events, (int)ext->base->times->count); - - return r; -} - -static void -_getdns_mini_event_callback(int fd, short bits, void *arg) -{ - getdns_eventloop_event *el_ev = (getdns_eventloop_event *)arg; - DEBUG_SCHED("1. _getdns_mini_event_callback(fd: %d, bits: %d, el_ev: %p[userarg: %p, r: %p, w: %p, t: %p, ev: %p])\n", fd, (int)bits, el_ev, el_ev->userarg, el_ev->read_cb, el_ev->write_cb, el_ev->timeout_cb, el_ev->ev); - if (bits & EV_READ) { - assert(el_ev->read_cb); - el_ev->read_cb(el_ev->userarg); - } else if (bits & EV_WRITE) { - assert(el_ev->write_cb); - el_ev->write_cb(el_ev->userarg); - } else if (bits & EV_TIMEOUT) { - assert(el_ev->timeout_cb); - el_ev->timeout_cb(el_ev->userarg); - } else - assert(ASSERT_UNREACHABLE); -} - -static getdns_return_t -_getdns_mini_event_schedule(getdns_eventloop *loop, - int fd, uint64_t timeout, getdns_eventloop_event *el_ev) -{ - _getdns_mini_event *ext = (_getdns_mini_event *)loop; - struct _getdns_event *my_ev; - struct timeval tv = { timeout / 1000, (timeout % 1000) * 1000 }; - - assert(el_ev); - assert(!(el_ev->read_cb || el_ev->write_cb) || fd >= 0); - assert( el_ev->read_cb || el_ev->write_cb || el_ev->timeout_cb); - - if (!(my_ev = GETDNS_MALLOC(ext->mf, struct _getdns_event))) - return GETDNS_RETURN_MEMORY_ERROR; - - el_ev->ev = my_ev; - DEBUG_SCHED("1. _getdns_mini_event_schedule(loop: %p, fd: %d, timeout: %"PRId64", el_ev: %p[userarg: %p, r: %p, w: %p, t: %p, ev: %p]); n_events: %d\n", loop, fd, timeout, el_ev, el_ev->userarg, el_ev->read_cb, el_ev->write_cb, el_ev->timeout_cb, el_ev->ev, (int)ext->n_events); - _getdns_event_set(my_ev, fd, ( - (el_ev->read_cb ? EV_READ|EV_PERSIST : 0) | - (el_ev->write_cb ? EV_WRITE|EV_PERSIST : 0) | - (el_ev->timeout_cb ? EV_TIMEOUT : 0)), - _getdns_mini_event_callback, el_ev); - - if (_getdns_mini_event_settime(ext)) - goto error; - - (void) _getdns_event_base_set(ext->base, my_ev); - if (_getdns_event_add(my_ev, el_ev->timeout_cb ? &tv : NULL)) - goto error; - - ext->n_events++; - DEBUG_SCHED("2. _getdns_mini_event_schedule(loop: %p, fd: %d, timeout: %"PRId64", el_ev: %p[userarg: %p, r: %p, w: %p, t: %p, ev: %p]); n_events: %d\n", loop, fd, timeout, el_ev, el_ev->userarg, el_ev->read_cb, el_ev->write_cb, el_ev->timeout_cb, el_ev->ev, (int)ext->n_events); - - return GETDNS_RETURN_GOOD; -error: - GETDNS_FREE(ext->mf, my_ev); - el_ev->ev = NULL; - - DEBUG_SCHED("3. _getdns_mini_event_schedule(loop: %p, fd: %d, timeout: %"PRId64", el_ev: %p[userarg: %p, r: %p, w: %p, t: %p, ev: %p]); n_events: %d\n", loop, fd, timeout, el_ev, el_ev->userarg, el_ev->read_cb, el_ev->write_cb, el_ev->timeout_cb, el_ev->ev, (int)ext->n_events); - return GETDNS_RETURN_GENERIC_ERROR; -} - -getdns_return_t -_getdns_mini_event_init(getdns_context *context, _getdns_mini_event *ext) -{ - static getdns_eventloop_vmt _getdns_mini_event_vmt = { - _getdns_mini_event_cleanup, - _getdns_mini_event_schedule, - _getdns_mini_event_clear, - _getdns_mini_event_run, - _getdns_mini_event_run_once - }; - - if (!context) - return GETDNS_RETURN_BAD_CONTEXT; - if (!ext) - return GETDNS_RETURN_INVALID_PARAMETER; - -#ifdef USE_WINSOCK - int r; - WSADATA wsa_data; - - if ((r = WSAStartup(MAKEWORD(2, 2), &wsa_data)) != 0) { - printf("could not init winsock. WSAStartup: %s", - wsa_strerror(r)); - return GETDNS_RETURN_GENERIC_ERROR; - } -#endif - - ext->n_events = 0; - ext->loop.vmt = &_getdns_mini_event_vmt; - ext->base = _getdns_event_init(&ext->time_secs, &ext->time_tv); - if (!ext->base) - return GETDNS_RETURN_MEMORY_ERROR; - - ext->mf = *priv_getdns_context_mf(context); - return GETDNS_RETURN_GOOD; -} - -getdns_return_t -_getdns_mini_event_create(getdns_context *context, _getdns_mini_event **ext) -{ - if (!context) return GETDNS_RETURN_BAD_CONTEXT; - if (!ext) return GETDNS_RETURN_INVALID_PARAMETER; - - *ext = GETDNS_MALLOC(*priv_getdns_context_mf(context), _getdns_mini_event); - return _getdns_mini_event_init(context, *ext); -} diff --git a/src/stub.c b/src/stub.c index 719efc97..c09e98ed 100644 --- a/src/stub.c +++ b/src/stub.c @@ -50,12 +50,20 @@ #include "pubkey-pinning.h" #ifdef USE_WINSOCK -#define EINPROGRESS 112 -#define EWOULDBLOCK 140 typedef u_short sa_family_t; -#include "util/winsock_event.h" +#define _getdns_EWOULDBLOCK (WSAGetLastError() == WSATRY_AGAIN ||\ + WSAGetLastError() == WSAEWOULDBLOCK) +#define _getdns_EINPROGRESS (WSAGetLastError() == WSAEINPROGRESS) +#else +#define _getdns_EWOULDBLOCK (errno == EAGAIN || errno == EWOULDBLOCK) +#define _getdns_EINPROGRESS (errno == EINPROGRESS) #endif +/* WSA TODO: + * STUB_TCP_WOULDBLOCK added to deal with edge triggered event loops (versus + * level triggered). See also lines containing WSA TODO below... + */ +#define STUB_TCP_WOULDBLOCK -6 #define STUB_OUT_OF_OPTIONS -5 /* upstream options exceeded MAXIMUM_UPSTREAM_OPTION_SPACE */ #define STUB_TLS_SETUP_ERROR -4 #define STUB_TCP_AGAIN -3 @@ -402,10 +410,21 @@ tcp_connected(getdns_upstream *upstream) { int error = 0; socklen_t len = (socklen_t)sizeof(error); getsockopt(upstream->fd, SOL_SOCKET, SO_ERROR, (void*)&error, &len); - if (error == EINPROGRESS || error == EWOULDBLOCK) - return STUB_TCP_AGAIN; /* try again */ +#ifdef USE_WINSOCK + if (error == WSAEINPROGRESS) + return STUB_TCP_WOULDBLOCK; + else if (error == WSAEWOULDBLOCK) + return STUB_TCP_WOULDBLOCK; else if (error != 0) return STUB_TCP_ERROR; +#else + if (error == EINPROGRESS) + return STUB_TCP_WOULDBLOCK; + else if (error == EWOULDBLOCK || error == EAGAIN) + return STUB_TCP_WOULDBLOCK; + else if (error != 0) + return STUB_TCP_ERROR; +#endif return 0; } @@ -625,7 +644,7 @@ stub_tls_timeout_cb(void *userarg) /****************************/ static int -stub_tcp_read(int fd, getdns_tcp_state *tcp, struct mem_funcs *mf, getdns_eventloop_event* event) +stub_tcp_read(int fd, getdns_tcp_state *tcp, struct mem_funcs *mf) { ssize_t read; uint8_t *buf; @@ -642,33 +661,21 @@ stub_tcp_read(int fd, getdns_tcp_state *tcp, struct mem_funcs *mf, getdns_eventl } read = recv(fd, (void *)tcp->read_pos, tcp->to_read, 0); if (read == -1) { -#ifdef USE_WINSOCK - printf("read (in tcp ) %s\n", - wsa_strerror(WSAGetLastError())); - if (WSAGetLastError() == WSAECONNRESET) - return STUB_TCP_AGAIN; - if (WSAGetLastError() == WSAEINPROGRESS) - return STUB_TCP_AGAIN; - if (WSAGetLastError() == WSAEWOULDBLOCK) { - winsock_tcp_wouldblock(event->ev, EV_READ); - return STUB_TCP_AGAIN; - } - -#else - if (errno == EAGAIN || errno == EWOULDBLOCK) - return STUB_TCP_AGAIN; + if (_getdns_EWOULDBLOCK) + return STUB_TCP_WOULDBLOCK; else return STUB_TCP_ERROR; -#endif } else if (read == 0) { /* Remote end closed the socket */ /* TODO: Try to reconnect */ return STUB_TCP_ERROR; + } else if (read> tcp->to_read) { + return STUB_TCP_ERROR; } tcp->to_read -= read; tcp->read_pos += read; - if ((int)tcp->to_read > 0) + if (tcp->to_read > 0) return STUB_TCP_AGAIN; read = tcp->read_pos - tcp->read_buf; @@ -721,7 +728,7 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq) if (! tcp->write_buf) { /* No, this is an initial write. Try to send */ - do { + do { query_id = arc4random(); query_id_intptr = (intptr_t)query_id; netreq->node.key = (void *)query_id_intptr; @@ -754,8 +761,8 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq) /* We have an initialized packet buffer. * Lets see how much of it we can write */ -#ifdef USE_TCP_FASTOPEN /* We use sendto() here which will do both a connect and send */ +#ifdef USE_TCP_FASTOPEN written = sendto(fd, netreq->query - 2, pkt_len + 2, MSG_FASTOPEN, (struct sockaddr *)&(netreq->upstream->addr), netreq->upstream->addr_len); @@ -763,29 +770,19 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq) just fall back to a 'normal' write. */ if (written == -1 && errno == EISCONN) written = write(fd, netreq->query - 2, pkt_len + 2); - - if ((written == -1 && (errno == EAGAIN || - errno == EWOULDBLOCK || - /* Add the error case where the connection is in progress which is when - a cookie is not available (e.g. when doing the first request to an - upstream). We must let the handshake complete since non-blocking. */ - errno == EINPROGRESS)) || - written < pkt_len + 2) { #else - -#ifdef USE_WINSOCK written = sendto(fd, (const char *)(netreq->query - 2), pkt_len + 2, 0, (struct sockaddr *)&(netreq->upstream->addr), netreq->upstream->addr_len); - -#else - written = write(fd, netreq->query - 2, pkt_len + 2); #endif - if ((written == -1 && (errno == EAGAIN || - errno == EWOULDBLOCK)) || + if ((written == -1 && (_getdns_EWOULDBLOCK || + /* Add the error case where the connection is in progress which is when + a cookie is not available (e.g. when doing the first request to an + upstream). We must let the handshake complete since non-blocking. */ + _getdns_EINPROGRESS)) || written < pkt_len + 2) { -#endif + /* We couldn't write the whole packet. * We have to return with STUB_TCP_AGAIN. * Setup tcp to track the state. @@ -794,7 +791,7 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq) tcp->write_buf_len = pkt_len + 2; tcp->written = written >= 0 ? written : 0; - return STUB_TCP_AGAIN; + return STUB_TCP_WOULDBLOCK; } else if (written == -1) return STUB_TCP_ERROR; @@ -809,8 +806,8 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq) written = write(fd, tcp->write_buf + tcp->written, tcp->write_buf_len - tcp->written); if (written == -1) { - if (errno == EAGAIN || errno == EWOULDBLOCK) - return STUB_TCP_AGAIN; + if (_getdns_EWOULDBLOCK) + return STUB_TCP_WOULDBLOCK; else return STUB_TCP_ERROR; } @@ -1304,7 +1301,7 @@ stub_udp_read_cb(void *userarg) * i.e. overflow */ 0, NULL, NULL); - if (read == -1 && (errno = EAGAIN || errno == EWOULDBLOCK)) + if (read == -1 && _getdns_EWOULDBLOCK) return; if (read < GLDNS_HEADER_SIZE) @@ -1405,13 +1402,16 @@ upstream_read_cb(void *userarg) if (tls_should_read(upstream)) q = stub_tls_read(upstream, &upstream->tcp, - &upstream->upstreams->mf); + &upstream->upstreams->mf); else q = stub_tcp_read(upstream->fd, &upstream->tcp, - &upstream->upstreams->mf, &upstream->event); + &upstream->upstreams->mf); switch (q) { case STUB_TCP_AGAIN: + /* WSA TODO: if callback is still upstream_read_cb, do it again + */ + case STUB_TCP_WOULDBLOCK: return; case STUB_TCP_ERROR: @@ -1463,6 +1463,10 @@ upstream_read_cb(void *userarg) upstream_reschedule_netreq_events(upstream, netreq); _getdns_check_dns_req_complete(netreq->owner); + + /* WSA TODO: if callback is still upstream_read_cb, do it again + */ + return; } } @@ -1499,6 +1503,10 @@ upstream_write_cb(void *userarg) switch (q) { case STUB_TCP_AGAIN: + /* WSA TODO: if callback is still upstream_write_cb, do it again + */ + + case STUB_TCP_WOULDBLOCK: return; case STUB_TCP_ERROR: @@ -1553,6 +1561,8 @@ upstream_write_cb(void *userarg) netreq_upstream_write_cb : NULL), stub_timeout_cb)); } + /* WSA TODO: if callback is still upstream_write_cb, do it again + */ return; } } diff --git a/src/sync.c b/src/sync.c index ae063f87..cfc43df6 100644 --- a/src/sync.c +++ b/src/sync.c @@ -46,7 +46,7 @@ #include "gldns/wire2str.h" typedef struct getdns_sync_loop { - _getdns_mini_event loop; + _getdns_default_eventloop loop; #ifdef HAVE_LIBUNBOUND getdns_eventloop_event ub_event; #endif @@ -61,14 +61,12 @@ getdns_sync_loop_init(getdns_context *context, getdns_sync_loop *loop) #ifdef HAVE_LIBUNBOUND getdns_eventloop *ext = &loop->loop.loop; #endif - getdns_return_t r; loop->response = NULL; loop->to_run = 1; loop->context = context; - if ((r = _getdns_mini_event_init(context, &loop->loop))) - return r; + _getdns_default_eventloop_init(&loop->loop); #ifdef HAVE_LIBUNBOUND loop->ub_event.userarg = loop->context; diff --git a/src/test/Makefile.in b/src/test/Makefile.in index 016b9e22..b2c6c22d 100644 --- a/src/test/Makefile.in +++ b/src/test/Makefile.in @@ -232,21 +232,24 @@ 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_general.h \ - $(srcdir)/check_getdns_general_sync.h $(srcdir)/check_getdns_address.h \ - $(srcdir)/check_getdns_address_sync.h $(srcdir)/check_getdns_hostname.h \ - $(srcdir)/check_getdns_hostname_sync.h $(srcdir)/check_getdns_context_create.h \ - $(srcdir)/check_getdns_context_destroy.h $(srcdir)/check_getdns_cancel_callback.h \ - $(srcdir)/check_getdns_list_get_length.h $(srcdir)/check_getdns_list_get_data_type.h \ - $(srcdir)/check_getdns_list_get_dict.h $(srcdir)/check_getdns_list_get_list.h \ - $(srcdir)/check_getdns_list_get_int.h $(srcdir)/check_getdns_list_get_bindata.h \ - $(srcdir)/check_getdns_dict_get_names.h $(srcdir)/check_getdns_dict_get_data_type.h \ - $(srcdir)/check_getdns_dict_get_dict.h $(srcdir)/check_getdns_dict_get_list.h \ - $(srcdir)/check_getdns_dict_get_bindata.h $(srcdir)/check_getdns_dict_get_int.h \ - $(srcdir)/check_getdns_dict_destroy.h $(srcdir)/check_getdns_dict_set_dict.h \ - $(srcdir)/check_getdns_dict_set_list.h $(srcdir)/check_getdns_dict_set_bindata.h \ - $(srcdir)/check_getdns_dict_set_int.h $(srcdir)/check_getdns_convert_ulabel_to_alabel.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_general.h $(srcdir)/check_getdns_general_sync.h \ + $(srcdir)/check_getdns_address.h $(srcdir)/check_getdns_address_sync.h \ + $(srcdir)/check_getdns_hostname.h $(srcdir)/check_getdns_hostname_sync.h \ + $(srcdir)/check_getdns_context_create.h $(srcdir)/check_getdns_context_destroy.h \ + $(srcdir)/check_getdns_cancel_callback.h $(srcdir)/check_getdns_list_get_length.h \ + $(srcdir)/check_getdns_list_get_data_type.h $(srcdir)/check_getdns_list_get_dict.h \ + $(srcdir)/check_getdns_list_get_list.h $(srcdir)/check_getdns_list_get_int.h \ + $(srcdir)/check_getdns_list_get_bindata.h $(srcdir)/check_getdns_dict_get_names.h \ + $(srcdir)/check_getdns_dict_get_data_type.h $(srcdir)/check_getdns_dict_get_dict.h \ + $(srcdir)/check_getdns_dict_get_list.h $(srcdir)/check_getdns_dict_get_bindata.h \ + $(srcdir)/check_getdns_dict_get_int.h $(srcdir)/check_getdns_dict_destroy.h \ + $(srcdir)/check_getdns_dict_set_dict.h $(srcdir)/check_getdns_dict_set_list.h \ + $(srcdir)/check_getdns_dict_set_bindata.h $(srcdir)/check_getdns_dict_set_int.h \ + $(srcdir)/check_getdns_convert_ulabel_to_alabel.h \ $(srcdir)/check_getdns_convert_alabel_to_ulabel.h $(srcdir)/check_getdns_pretty_print_dict.h \ $(srcdir)/check_getdns_display_ip_address.h \ $(srcdir)/check_getdns_context_set_context_update_callback.h \ @@ -254,36 +257,59 @@ check_getdns.lo check_getdns.o: $(srcdir)/check_getdns.c ../getdns/getdns.h $(sr $(srcdir)/check_getdns_context_set_upstream_recursive_servers.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 -getdns_query.lo getdns_query.o: $(srcdir)/getdns_query.c ../config.h $(srcdir)/../debug.h ../config.h \ - ../getdns/getdns.h ../getdns/getdns_extra.h -scratchpad.template.lo scratchpad.template.o: scratchpad.template.c ../getdns/getdns.h \ +getdns_query.lo getdns_query.o: $(srcdir)/getdns_query.c \ + ../config.h $(srcdir)/../debug.h \ + ../getdns/getdns.h \ + ../getdns/getdns_extra.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/util/import.sh b/src/util/import.sh index 44eabe3a..08cad0af 100755 --- a/src/util/import.sh +++ b/src/util/import.sh @@ -4,7 +4,7 @@ mkdir ub || true cd ub -for f in mini_event.c mini_event.h rbtree.c rbtree.h +for f in rbtree.c rbtree.h do wget http://unbound.net/svn/trunk/util/$f || \ ftp http://unbound.net/svn/trunk/util/$f || continue diff --git a/src/util/mini_event.c b/src/util/mini_event.c deleted file mode 100644 index 1e25f8ee..00000000 --- a/src/util/mini_event.c +++ /dev/null @@ -1,394 +0,0 @@ -/* - * mini_event.c - implementation of part of libevent api, portably. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * 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 name of the NLNET LABS 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 THE COPYRIGHT - * HOLDER 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. - * - */ - -/** - * \file - * fake libevent implementation. Less broad in functionality, and only - * supports select(2). - */ - -#include "config.h" -#ifdef HAVE_TIME_H -#include -#endif -#include - -#if defined(USE_MINI_EVENT) && !defined(USE_WINSOCK) -#include -#include "util/mini_event.h" -#include "util/fptr_wlist.h" - -/** compare events in tree, based on timevalue, ptr for uniqueness */ -int _getdns_mini_ev_cmp(const void* a, const void* b) -{ - const struct _getdns_event *e = (const struct _getdns_event*)a; - const struct _getdns_event *f = (const struct _getdns_event*)b; - if(e->ev_timeout.tv_sec < f->ev_timeout.tv_sec) - return -1; - if(e->ev_timeout.tv_sec > f->ev_timeout.tv_sec) - return 1; - if(e->ev_timeout.tv_usec < f->ev_timeout.tv_usec) - return -1; - if(e->ev_timeout.tv_usec > f->ev_timeout.tv_usec) - return 1; - if(e < f) - return -1; - if(e > f) - return 1; - return 0; -} - -/** set time */ -static int -settime(struct _getdns_event_base* base) -{ - if(gettimeofday(base->time_tv, NULL) < 0) { - return -1; - } -#ifndef S_SPLINT_S - *base->time_secs = (time_t)base->time_tv->tv_sec; -#endif - return 0; -} - -/** create event base */ -void *_getdns_event_init(time_t* time_secs, struct timeval* time_tv) -{ - struct _getdns_event_base* base = (struct _getdns_event_base*)malloc( - sizeof(struct _getdns_event_base)); - if(!base) - return NULL; - memset(base, 0, sizeof(*base)); - base->time_secs = time_secs; - base->time_tv = time_tv; - if(settime(base) < 0) { - _getdns_event_base_free(base); - return NULL; - } - base->times = _getdns_rbtree_create(_getdns_mini_ev_cmp); - if(!base->times) { - _getdns_event_base_free(base); - return NULL; - } - base->capfd = MAX_FDS; -#ifdef FD_SETSIZE - if((int)FD_SETSIZE < base->capfd) - base->capfd = (int)FD_SETSIZE; -#endif - base->fds = (struct _getdns_event**)calloc((size_t)base->capfd, - sizeof(struct _getdns_event*)); - if(!base->fds) { - _getdns_event_base_free(base); - return NULL; - } - base->signals = (struct _getdns_event**)calloc(MAX_SIG, sizeof(struct _getdns_event*)); - if(!base->signals) { - _getdns_event_base_free(base); - return NULL; - } -#ifndef S_SPLINT_S - FD_ZERO(&base->reads); - FD_ZERO(&base->writes); -#endif - return base; -} - -/** get version */ -const char *_getdns_event_get_version(void) -{ - return "mini-event-"PACKAGE_VERSION; -} - -/** get polling method, select */ -const char *_getdns_event_get_method(void) -{ - return "select"; -} - -/** call timeouts handlers, and return how long to wait for next one or -1 */ -void _getdns_handle_timeouts(struct _getdns_event_base* base, struct timeval* now, - struct timeval* wait) -{ - struct _getdns_event* p; -#ifndef S_SPLINT_S - wait->tv_sec = (time_t)-1; -#endif - - while((_getdns_rbnode_t*)(p = (struct _getdns_event*)_getdns_rbtree_first(base->times)) - !=RBTREE_NULL) { -#ifndef S_SPLINT_S - if(p->ev_timeout.tv_sec > now->tv_sec || - (p->ev_timeout.tv_sec==now->tv_sec && - p->ev_timeout.tv_usec > now->tv_usec)) { - /* there is a next larger timeout. wait for it */ - wait->tv_sec = p->ev_timeout.tv_sec - now->tv_sec; - if(now->tv_usec > p->ev_timeout.tv_usec) { - wait->tv_sec--; - wait->tv_usec = 1000000 - (now->tv_usec - - p->ev_timeout.tv_usec); - } else { - wait->tv_usec = p->ev_timeout.tv_usec - - now->tv_usec; - } - return; - } -#endif - /* event times out, remove it */ - (void)_getdns_rbtree_delete(base->times, p); - p->ev_events &= ~EV_TIMEOUT; - fptr_ok(fptr_whitelist_event(p->ev_callback)); - (*p->ev_callback)(p->ev_fd, EV_TIMEOUT, p->ev_arg); - } -} - -/** call select and callbacks for that */ -int _getdns_handle_select(struct _getdns_event_base* base, struct timeval* wait) -{ - fd_set r, w; - int ret, i; - -#ifndef S_SPLINT_S - if(wait->tv_sec==(time_t)-1) - wait = NULL; -#endif - memmove(&r, &base->reads, sizeof(fd_set)); - memmove(&w, &base->writes, sizeof(fd_set)); - memmove(&base->ready, &base->content, sizeof(fd_set)); - - if((ret = select(base->maxfd+1, &r, &w, NULL, wait)) == -1) { - ret = errno; - if(settime(base) < 0) - return -1; - errno = ret; - if(ret == EAGAIN || ret == EINTR) - return 0; - return -1; - } - if(settime(base) < 0) - return -1; - - for(i=0; imaxfd+1; i++) { - short bits = 0; - if(!base->fds[i] || !(FD_ISSET(i, &base->ready))) { - continue; - } - if(FD_ISSET(i, &r)) { - bits |= EV_READ; - ret--; - } - if(FD_ISSET(i, &w)) { - bits |= EV_WRITE; - ret--; - } - bits &= base->fds[i]->ev_events; - if(bits) { - fptr_ok(fptr_whitelist_event( - base->fds[i]->ev_callback)); - (*base->fds[i]->ev_callback)(base->fds[i]->ev_fd, - bits, base->fds[i]->ev_arg); - if(ret==0) - break; - } - } - return 0; -} - -/** run select in a loop */ -int _getdns_event_base_dispatch(struct _getdns_event_base* base) -{ - struct timeval wait; - if(settime(base) < 0) - return -1; - while(!base->need_to_exit) - { - /* see if timeouts need handling */ - _getdns_handle_timeouts(base, base->time_tv, &wait); - if(base->need_to_exit) - return 0; - /* do select */ - if(_getdns_handle_select(base, &wait) < 0) { - if(base->need_to_exit) - return 0; - return -1; - } - } - return 0; -} - -/** exit that loop */ -int _getdns_event_base_loopexit(struct _getdns_event_base* base, - struct timeval* ATTR_UNUSED(tv)) -{ - base->need_to_exit = 1; - return 0; -} - -/* free event base, free events yourself */ -void _getdns_event_base_free(struct _getdns_event_base* base) -{ - if(!base) - return; - if(base->times) - free(base->times); - if(base->fds) - free(base->fds); - if(base->signals) - free(base->signals); - free(base); -} - -/** set content of event */ -void _getdns_event_set(struct _getdns_event* ev, int fd, short bits, - void (*cb)(int, short, void *), void* arg) -{ - ev->node.key = ev; - ev->ev_fd = fd; - ev->ev_events = bits; - ev->ev_callback = cb; - fptr_ok(fptr_whitelist_event(ev->ev_callback)); - ev->ev_arg = arg; - ev->added = 0; -} - -/* add event to a base */ -int _getdns_event_base_set(struct _getdns_event_base* base, struct _getdns_event* ev) -{ - ev->ev_base = base; - ev->added = 0; - return 0; -} - -/* add event to make it active, you may not change it with _getdns_event_set anymore */ -int _getdns_event_add(struct _getdns_event* ev, struct timeval* tv) -{ - if(ev->added) - _getdns_event_del(ev); - if(ev->ev_fd != -1 && ev->ev_fd >= ev->ev_base->capfd) - return -1; - if( (ev->ev_events&(EV_READ|EV_WRITE)) && ev->ev_fd != -1) { - ev->ev_base->fds[ev->ev_fd] = ev; - if(ev->ev_events&EV_READ) { - FD_SET(FD_SET_T ev->ev_fd, &ev->ev_base->reads); - } - if(ev->ev_events&EV_WRITE) { - FD_SET(FD_SET_T ev->ev_fd, &ev->ev_base->writes); - } - FD_SET(FD_SET_T ev->ev_fd, &ev->ev_base->content); - FD_CLR(FD_SET_T ev->ev_fd, &ev->ev_base->ready); - if(ev->ev_fd > ev->ev_base->maxfd) - ev->ev_base->maxfd = ev->ev_fd; - } - if(tv && (ev->ev_events&EV_TIMEOUT)) { -#ifndef S_SPLINT_S - struct timeval *now = ev->ev_base->time_tv; - ev->ev_timeout.tv_sec = tv->tv_sec + now->tv_sec; - ev->ev_timeout.tv_usec = tv->tv_usec + now->tv_usec; - while(ev->ev_timeout.tv_usec > 1000000) { - ev->ev_timeout.tv_usec -= 1000000; - ev->ev_timeout.tv_sec++; - } -#endif - (void)_getdns_rbtree_insert(ev->ev_base->times, &ev->node); - } - ev->added = 1; - return 0; -} - -/* remove event, you may change it again */ -int _getdns_event_del(struct _getdns_event* ev) -{ - if(ev->ev_fd != -1 && ev->ev_fd >= ev->ev_base->capfd) - return -1; - if((ev->ev_events&EV_TIMEOUT)) - (void)_getdns_rbtree_delete(ev->ev_base->times, &ev->node); - if((ev->ev_events&(EV_READ|EV_WRITE)) && ev->ev_fd != -1) { - ev->ev_base->fds[ev->ev_fd] = NULL; - FD_CLR(FD_SET_T ev->ev_fd, &ev->ev_base->reads); - FD_CLR(FD_SET_T ev->ev_fd, &ev->ev_base->writes); - FD_CLR(FD_SET_T ev->ev_fd, &ev->ev_base->ready); - FD_CLR(FD_SET_T ev->ev_fd, &ev->ev_base->content); - } - ev->added = 0; - return 0; -} - -/** which base gets to handle signals */ -static struct _getdns_event_base* signal_base = NULL; -/** signal handler */ -static RETSIGTYPE sigh(int sig) -{ - struct _getdns_event* ev; - if(!signal_base || sig < 0 || sig >= MAX_SIG) - return; - ev = signal_base->signals[sig]; - if(!ev) - return; - fptr_ok(fptr_whitelist_event(ev->ev_callback)); - (*ev->ev_callback)(sig, EV_SIGNAL, ev->ev_arg); -} - -/** install signal handler */ -int _getdns_signal_add(struct _getdns_event* ev, struct timeval* ATTR_UNUSED(tv)) -{ - if(ev->ev_fd == -1 || ev->ev_fd >= MAX_SIG) - return -1; - signal_base = ev->ev_base; - ev->ev_base->signals[ev->ev_fd] = ev; - ev->added = 1; - if(signal(ev->ev_fd, sigh) == SIG_ERR) { - return -1; - } - return 0; -} - -/** remove signal handler */ -int _getdns_signal_del(struct _getdns_event* ev) -{ - if(ev->ev_fd == -1 || ev->ev_fd >= MAX_SIG) - return -1; - ev->ev_base->signals[ev->ev_fd] = NULL; - ev->added = 0; - return 0; -} - -#else /* USE_MINI_EVENT */ -#ifndef USE_WINSOCK -int _getdns_mini_ev_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b)) -{ - return 0; -} -#endif /* not USE_WINSOCK */ -#endif /* USE_MINI_EVENT */ diff --git a/src/util/mini_event.h b/src/util/mini_event.h deleted file mode 100644 index ff675f15..00000000 --- a/src/util/mini_event.h +++ /dev/null @@ -1,178 +0,0 @@ -/* - * mini-event.h - micro implementation of libevent api, using select() only. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * 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 name of the NLNET LABS 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 THE COPYRIGHT - * HOLDER 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. - */ - -/** - * \file - * This file implements part of the event(3) libevent api. - * The back end is only select. Max number of fds is limited. - * Max number of signals is limited, one handler per signal only. - * And one handler per fd. - * - * Although limited to select() and a max (1024) open fds, it - * is efficient: - * o dispatch call caches fd_sets to use. - * o handler calling takes time ~ to the number of fds. - * o timeouts are stored in a redblack tree, sorted, so take log(n). - * Timeouts are only accurate to the second (no subsecond accuracy). - * To avoid cpu hogging, fractional timeouts are rounded up to a whole second. - */ - -#ifndef MINI_EVENT_H -#define MINI_EVENT_H - -#if defined(USE_MINI_EVENT) && !defined(USE_WINSOCK) - -#ifndef HAVE_EVENT_BASE_FREE -#define HAVE_EVENT_BASE_FREE -#endif - - -/** event timeout */ -#define EV_TIMEOUT 0x01 -/** event fd readable */ -#define EV_READ 0x02 -/** event fd writable */ -#define EV_WRITE 0x04 -/** event signal */ -#define EV_SIGNAL 0x08 -/** event must persist */ -#define EV_PERSIST 0x10 - -/* needs our redblack tree */ -#include "util/rbtree.h" - -/** max number of file descriptors to support */ -#define MAX_FDS 1024 -/** max number of signals to support */ -#define MAX_SIG 32 - -/** event base */ -struct _getdns_event_base -{ - /** sorted by timeout (absolute), ptr */ - _getdns_rbtree_t* times; - /** array of 0 - maxfd of ptr to event for it */ - struct _getdns_event** fds; - /** max fd in use */ - int maxfd; - /** capacity - size of the fds array */ - int capfd; - /* fdset for read write, for fds ready, and added */ - fd_set - /** fds for reading */ - reads, - /** fds for writing */ - writes, - /** fds determined ready for use */ - ready, - /** ready plus newly added events. */ - content; - /** array of 0 - maxsig of ptr to event for it */ - struct _getdns_event** signals; - /** if we need to exit */ - int need_to_exit; - /** where to store time in seconds */ - time_t* time_secs; - /** where to store time in microseconds */ - struct timeval* time_tv; -}; - -/** - * Event structure. Has some of the event elements. - */ -struct _getdns_event { - /** node in timeout rbtree */ - _getdns_rbnode_t node; - /** is event already added */ - int added; - - /** event base it belongs to */ - struct _getdns_event_base *ev_base; - /** fd to poll or -1 for timeouts. signal number for sigs. */ - int ev_fd; - /** what events this event is interested in, see EV_.. above. */ - short ev_events; - /** timeout value */ - struct timeval ev_timeout; - - /** callback to call: fd, eventbits, userarg */ - void (*ev_callback)(int, short, void *arg); - /** callback user arg */ - void *ev_arg; -}; - -/* function prototypes (some are as they appear in event.h) */ -/** create event base */ -void *_getdns_event_init(time_t* time_secs, struct timeval* time_tv); -/** get version */ -const char *_getdns_event_get_version(void); -/** get polling method, select */ -const char *_getdns_event_get_method(void); -/** run select in a loop */ -int _getdns_event_base_dispatch(struct _getdns_event_base *); -/** exit that loop */ -int _getdns_event_base_loopexit(struct _getdns_event_base *, struct timeval *); -/** free event base. Free events yourself */ -void _getdns_event_base_free(struct _getdns_event_base *); -/** set content of event */ -void _getdns_event_set(struct _getdns_event *, int, short, void (*)(int, short, void *), void *); -/** add event to a base. You *must* call this for every event. */ -int _getdns_event_base_set(struct _getdns_event_base *, struct _getdns_event *); -/** add event to make it active. You may not change it with _getdns_event_set anymore */ -int _getdns_event_add(struct _getdns_event *, struct timeval *); -/** remove event. You may change it again */ -int _getdns_event_del(struct _getdns_event *); - -/** add a timer */ -#define _getdns_evtimer_add(ev, tv) _getdns_event_add(ev, tv) -/** remove a timer */ -#define _getdns_evtimer_del(ev) _getdns_event_del(ev) - -/* uses different implementation. Cannot mix fd/timeouts and signals inside - * the same struct _getdns_event. create several event structs for that. */ -/** install signal handler */ -int _getdns_signal_add(struct _getdns_event *, struct timeval *); -/** set signal event contents */ -#define _getdns_signal_set(ev, x, cb, arg) \ - _getdns_event_set(ev, x, EV_SIGNAL|EV_PERSIST, cb, arg) -/** remove signal handler */ -int _getdns_signal_del(struct _getdns_event *); - -#endif /* USE_MINI_EVENT and not USE_WINSOCK */ - -/** compare events in tree, based on timevalue, ptr for uniqueness */ -int _getdns_mini_ev_cmp(const void* a, const void* b); - -#endif /* MINI_EVENT_H */ diff --git a/src/util/winsock_event.c b/src/util/winsock_event.c deleted file mode 100644 index 2df44558..00000000 --- a/src/util/winsock_event.c +++ /dev/null @@ -1,844 +0,0 @@ -/* - * util/winsock_event.c - implementation of the getdns winsock event handler. - * - * Copyright (c) 2015, Verisign/NLnet Labs. All rights reserved. - * - * This software is open source. - * - * 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 name of the NLNET LABS/Verisign 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 THE COPYRIGHT - * HOLDER 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. - */ -/** - * \file - * Implementation of the getdns WinSock2 API event notification handler - * for the getdns Windows port. - * Code is originally from the Unbound source for Windows. - */ - -#include "config.h" -#ifdef USE_WINSOCK // only included for Windows builds -#include -#ifdef HAVE_TIME_H -#include -#endif -#include -#include "util/winsock_event.h" -#include "util/fptr_wlist.h" - -/** -* implementation of log_err -* @param format: format string printf-style. -*/ -void -log_err(const char *format, ...) -{ - va_list args; - va_start(args, format); - fprintf(stderr, "error "); - fprintf(stderr, format, args); - va_end(args); -} - - -char* wsa_strerror(DWORD err) -{ - static char unknown[32]; - - switch (err) { - case WSA_INVALID_HANDLE: return "Specified event object handle is invalid."; - case WSA_NOT_ENOUGH_MEMORY: return "Insufficient memory available."; - case WSA_INVALID_PARAMETER: return "One or more parameters are invalid."; - case WSA_OPERATION_ABORTED: return "Overlapped operation aborted."; - case WSA_IO_INCOMPLETE: return "Overlapped I/O event object not in signaled state."; - case WSA_IO_PENDING: return "Overlapped operations will complete later."; - case WSAEINTR: return "Interrupted function call."; - case WSAEBADF: return "File handle is not valid."; - case WSAEACCES: return "Permission denied."; - case WSAEFAULT: return "Bad address."; - case WSAEINVAL: return "Invalid argument."; - case WSAEMFILE: return "Too many open files."; - case WSAEWOULDBLOCK: return "Resource temporarily unavailable."; - case WSAEINPROGRESS: return "Operation now in progress."; - case WSAEALREADY: return "Operation already in progress."; - case WSAENOTSOCK: return "Socket operation on nonsocket."; - case WSAEDESTADDRREQ: return "Destination address required."; - case WSAEMSGSIZE: return "Message too long."; - case WSAEPROTOTYPE: return "Protocol wrong type for socket."; - case WSAENOPROTOOPT: return "Bad protocol option."; - case WSAEPROTONOSUPPORT: return "Protocol not supported."; - case WSAESOCKTNOSUPPORT: return "Socket type not supported."; - case WSAEOPNOTSUPP: return "Operation not supported."; - case WSAEPFNOSUPPORT: return "Protocol family not supported."; - case WSAEAFNOSUPPORT: return "Address family not supported by protocol family."; - case WSAEADDRINUSE: return "Address already in use."; - case WSAEADDRNOTAVAIL: return "Cannot assign requested address."; - case WSAENETDOWN: return "Network is down."; - case WSAENETUNREACH: return "Network is unreachable."; - case WSAENETRESET: return "Network dropped connection on reset."; - case WSAECONNABORTED: return "Software caused connection abort."; - case WSAECONNRESET: return "Connection reset by peer."; - case WSAENOBUFS: return "No buffer space available."; - case WSAEISCONN: return "Socket is already connected."; - case WSAENOTCONN: return "Socket is not connected."; - case WSAESHUTDOWN: return "Cannot send after socket shutdown."; - case WSAETOOMANYREFS: return "Too many references."; - case WSAETIMEDOUT: return "Connection timed out."; - case WSAECONNREFUSED: return "Connection refused."; - case WSAELOOP: return "Cannot translate name."; - case WSAENAMETOOLONG: return "Name too long."; - case WSAEHOSTDOWN: return "Host is down."; - case WSAEHOSTUNREACH: return "No route to host."; - case WSAENOTEMPTY: return "Directory not empty."; - case WSAEPROCLIM: return "Too many processes."; - case WSAEUSERS: return "User quota exceeded."; - case WSAEDQUOT: return "Disk quota exceeded."; - case WSAESTALE: return "Stale file handle reference."; - case WSAEREMOTE: return "Item is remote."; - case WSASYSNOTREADY: return "Network subsystem is unavailable."; - case WSAVERNOTSUPPORTED: return "Winsock.dll version out of range."; - case WSANOTINITIALISED: return "Successful WSAStartup not yet performed."; - case WSAEDISCON: return "Graceful shutdown in progress."; - case WSAENOMORE: return "No more results."; - case WSAECANCELLED: return "Call has been canceled."; - case WSAEINVALIDPROCTABLE: return "Procedure call table is invalid."; - case WSAEINVALIDPROVIDER: return "Service provider is invalid."; - case WSAEPROVIDERFAILEDINIT: return "Service provider failed to initialize."; - case WSASYSCALLFAILURE: return "System call failure."; - case WSASERVICE_NOT_FOUND: return "Service not found."; - case WSATYPE_NOT_FOUND: return "Class type not found."; - case WSA_E_NO_MORE: return "No more results."; - case WSA_E_CANCELLED: return "Call was canceled."; - case WSAEREFUSED: return "Database query was refused."; - case WSAHOST_NOT_FOUND: return "Host not found."; - case WSATRY_AGAIN: return "Nonauthoritative host not found."; - case WSANO_RECOVERY: return "This is a nonrecoverable error."; - case WSANO_DATA: return "Valid name, no data record of requested type."; - case WSA_QOS_RECEIVERS: return "QOS receivers."; - case WSA_QOS_SENDERS: return "QOS senders."; - case WSA_QOS_NO_SENDERS: return "No QOS senders."; - case WSA_QOS_NO_RECEIVERS: return "QOS no receivers."; - case WSA_QOS_REQUEST_CONFIRMED: return "QOS request confirmed."; - case WSA_QOS_ADMISSION_FAILURE: return "QOS admission error."; - case WSA_QOS_POLICY_FAILURE: return "QOS policy failure."; - case WSA_QOS_BAD_STYLE: return "QOS bad style."; - case WSA_QOS_BAD_OBJECT: return "QOS bad object."; - case WSA_QOS_TRAFFIC_CTRL_ERROR: return "QOS traffic control error."; - case WSA_QOS_GENERIC_ERROR: return "QOS generic error."; - case WSA_QOS_ESERVICETYPE: return "QOS service type error."; - case WSA_QOS_EFLOWSPEC: return "QOS flowspec error."; - case WSA_QOS_EPROVSPECBUF: return "Invalid QOS provider buffer."; - case WSA_QOS_EFILTERSTYLE: return "Invalid QOS filter style."; - case WSA_QOS_EFILTERTYPE: return "Invalid QOS filter type."; - case WSA_QOS_EFILTERCOUNT: return "Incorrect QOS filter count."; - case WSA_QOS_EOBJLENGTH: return "Invalid QOS object length."; - case WSA_QOS_EFLOWCOUNT: return "Incorrect QOS flow count."; - /*case WSA_QOS_EUNKOWNPSOBJ: return "Unrecognized QOS object.";*/ - case WSA_QOS_EPOLICYOBJ: return "Invalid QOS policy object."; - case WSA_QOS_EFLOWDESC: return "Invalid QOS flow descriptor."; - case WSA_QOS_EPSFLOWSPEC: return "Invalid QOS provider-specific flowspec."; - case WSA_QOS_EPSFILTERSPEC: return "Invalid QOS provider-specific filterspec."; - case WSA_QOS_ESDMODEOBJ: return "Invalid QOS shape discard mode object."; - case WSA_QOS_ESHAPERATEOBJ: return "Invalid QOS shaping rate object."; - case WSA_QOS_RESERVED_PETYPE: return "Reserved policy QOS element type."; - default: - snprintf(unknown, sizeof(unknown), - "unknown WSA error code %d", (int)err); - return unknown; - } -} - -int _getdns_mini_ev_cmp(const void* a, const void* b) -{ - const struct _getdns_event *e = (const struct _getdns_event*)a; - const struct _getdns_event *f = (const struct _getdns_event*)b; - if(e->ev_timeout.tv_sec < f->ev_timeout.tv_sec) - return -1; - if(e->ev_timeout.tv_sec > f->ev_timeout.tv_sec) - return 1; - if(e->ev_timeout.tv_usec < f->ev_timeout.tv_usec) - return -1; - if(e->ev_timeout.tv_usec > f->ev_timeout.tv_usec) - return 1; - if(e < f) - return -1; - if(e > f) - return 1; - return 0; -} - -/** set time */ -static int -settime(struct _getdns_event_base* base) -{ - if(gettimeofday(base->time_tv, NULL) < 0) { - return -1; - } -#ifndef S_SPLINT_S - *base->time_secs = (time_t)base->time_tv->tv_sec; -#endif - return 0; -} - -#ifdef WINSOCK_DEBUG -/** - * Find a fd in the list of items. - * Note that not all items have a fd associated (those are -1). - * Signals are stored separately, and not searched. - * @param base: event base to look in. - * @param fd: what socket to look for. - * @return the index in the array, or -1 on failure. - */ -static int -find_fd(struct _getdns_event_base* base, int fd) -{ - int i; - for(i=0; imax; i++) { - if(base->items[i]->ev_fd == fd) - return i; - } - return -1; -} -#endif - -/** Find ptr in base array */ -static void -zero_waitfor(WSAEVENT waitfor[], WSAEVENT x) -{ - int i; - for(i=0; itime_secs = time_secs; - base->time_tv = time_tv; - if(settime(base) < 0) { - _getdns_event_base_free(base); - return NULL; - } - base->items = (struct _getdns_event**)calloc(WSK_MAX_ITEMS, - sizeof(struct _getdns_event*)); - if(!base->items) { - _getdns_event_base_free(base); - return NULL; - } - base->cap = WSK_MAX_ITEMS; - base->max = 0; - base->times = _getdns_rbtree_create(_getdns_mini_ev_cmp); - if(!base->times) { - _getdns_event_base_free(base); - return NULL; - } - base->signals = (struct _getdns_event**)calloc(MAX_SIG, - sizeof(struct _getdns_event*)); - if(!base->signals) { - _getdns_event_base_free(base); - return NULL; - } - base->tcp_stickies = 0; - base->tcp_reinvigorated = 0; - - return base; -} - -const char *_getdns_event_get_version(void) -{ - return "winsock-event-"PACKAGE_VERSION; -} - -const char *_getdns_event_get_method(void) -{ - return "WSAWaitForMultipleEvents"; -} - -/** call timeouts handlers, and return how long to wait for next one or -1 */ -void _getdns_handle_timeouts(struct _getdns_event_base* base, struct timeval* now, - struct timeval* wait) -{ - struct _getdns_event* p; -#ifndef S_SPLINT_S - wait->tv_sec = (time_t)-1; -#endif - - while((_getdns_rbnode_t*)(p = (struct _getdns_event*)_getdns_rbtree_first(base->times)) - !=RBTREE_NULL) { -#ifndef S_SPLINT_S - if(p->ev_timeout.tv_sec > now->tv_sec || - (p->ev_timeout.tv_sec==now->tv_sec && - p->ev_timeout.tv_usec > now->tv_usec)) { - /* there is a next larger timeout. wait for it */ - wait->tv_sec = p->ev_timeout.tv_sec - now->tv_sec; - if(now->tv_usec > p->ev_timeout.tv_usec) { - wait->tv_sec--; - wait->tv_usec = 1000000 - (now->tv_usec - - p->ev_timeout.tv_usec); - } else { - wait->tv_usec = p->ev_timeout.tv_usec - - now->tv_usec; - } - return; - } -#endif - /* event times out, remove it */ - (void)_getdns_rbtree_delete(base->times, p); - p->ev_events &= ~EV_TIMEOUT; - fptr_ok(fptr_whitelist_event(p->ev_callback)); - (*p->ev_callback)(p->ev_fd, EV_TIMEOUT, p->ev_arg); - } -} - -/** handle is_signal events and see if signalled */ -static void _getdns_handle_signal(struct _getdns_event* ev) -{ - printf("In _getdns_handle_signal\n"); - DWORD ret; - //log_assert(ev->is_signal && ev->hEvent); - /* see if the event is signalled */ - ret = WSAWaitForMultipleEvents(1, &ev->hEvent, 0 /* any object */, - 0 /* return immediately */, 0 /* not alertable for IOcomple*/); - if(ret == WSA_WAIT_IO_COMPLETION || ret == WSA_WAIT_FAILED) { - log_err("getdns: WSAWaitForMultipleEvents(signal) failed: %s", - wsa_strerror(WSAGetLastError())); - return; - } - if(ret == WSA_WAIT_TIMEOUT) { - /* not signalled */ - return; - } - - /* reset the signal */ - if(!WSAResetEvent(ev->hEvent)) - log_err("getdns: WSAResetEvent failed: %s", - wsa_strerror(WSAGetLastError())); - /* do the callback (which may set the signal again) */ - fptr_ok(fptr_whitelist_event(ev->ev_callback)); - (*ev->ev_callback)(ev->ev_fd, ev->ev_events, ev->ev_arg); -} - -/** call select and callbacks for that */ -int _getdns_handle_select(struct _getdns_event_base* base, struct timeval* wait) -{ - DWORD timeout = 0; /* in milliseconds */ - DWORD ret; - WSANETWORKEVENTS netev; - struct _getdns_event* eventlist[WSK_MAX_ITEMS]; - int i, numwait = 0, startidx = 0; - int newstickies = 0; - struct timeval nultm; - -#ifndef S_SPLINT_S - if(wait->tv_sec==(time_t)-1) - wait = NULL; - if (wait) - // timeout = 10 + wait->tv_usec / 1000; - timeout = wait->tv_sec * 1000 + wait->tv_usec / 1000; - if(base->tcp_stickies) { - wait = &nultm; - nultm.tv_sec = 0; - nultm.tv_usec = 0; - timeout = 0; /* no waiting, we have sticky events */ - } -#endif - - /* prepare event array */ - for(i=0; imax; i++) { - if(base->items[i]->ev_fd == -1 && !base->items[i]->is_signal) - continue; /* skip timer only events */ - eventlist[numwait] = base->items[i]; - base->waitfor[numwait++] = base->items[i]->hEvent; - printf("winsock_event bmax=%d numwait=%d wait=%x " - "timeout=%d hEvent %d\n", base->max, numwait, (int)wait, - (int)timeout, (int)base->items[i]->hEvent); - if (numwait == WSK_MAX_ITEMS) - break; /* sanity check */ - } - //log_assert(numwait <= WSA_MAXIMUM_WAIT_EVENTS); - - /* do the wait */ - if(numwait == 0) { - /* WSAWaitFor.. doesn't like 0 event objects */ - if(wait) { - Sleep(timeout); - } - } - else { - //gv: do not schedule udp write - for (i = 0; imax; i++) { - if (!base->items[i]->is_tcp && base->items[i]->ev_events&EV_WRITE) { - printf("skip UDP sched\n"); - (*eventlist[i]->ev_callback)(eventlist[i]->ev_fd, - EV_WRITE & eventlist[i]->ev_events, - eventlist[i]->ev_arg); - return 0; - } - } - printf("before wait %d\n", base->items[0]->ev_events); - ret = WSAWaitForMultipleEvents(numwait, base->waitfor, - 0 /* do not wait for all, just one will do */, - wait?timeout:WSA_INFINITE, - 0); /* we are not alertable (IO completion events) */ - printf("after wait %d %d\n", (int)ret, numwait); - if(ret == WSA_WAIT_IO_COMPLETION) { - //printf("getdns: WSAWaitForMultipleEvents failed: WSA_WAIT_IO_COMPLETION"); - return -1; - } else if(ret == WSA_WAIT_FAILED) { - //printf("getdns: WSAWaitForMultipleEvents failed: %s", - // wsa_strerror(WSAGetLastError())); - return -1; - } else if(ret == WSA_WAIT_TIMEOUT) { - printf("timeout\n"); - } else - startidx = ret - WSA_WAIT_EVENT_0; - } - ////verbose(VERB_CLIENT, "winsock_event wake was_timeout=%d startidx=%d", - // was_timeout, startidx); - - /* get new time after wait */ - if(settime(base) < 0) - return -1; - - /* callbacks */ - if(base->tcp_stickies) - startidx = 0; /* process all events, some are sticky */ - for(i=startidx; ijust_checked = 1; - - //verbose(VERB_CLIENT, "winsock_event signals"); - for(i=startidx; iwaitfor[i]) - continue; /* was deleted */ - if(eventlist[i]->is_signal) { - eventlist[i]->just_checked = 0; - _getdns_handle_signal(eventlist[i]); - } - } - /* early exit - do not process network, exit quickly */ - if(base->need_to_exit) - return 0; - - //verbose(VERB_CLIENT, "winsock_event net"); - for(i=startidx; iwaitfor[i]) - continue; /* was deleted */ - if(!eventlist[i]->just_checked) - continue; /* added by other callback */ - if(eventlist[i]->is_signal) - continue; /* not a network event at all */ - eventlist[i]->just_checked = 0; - - if(WSAEnumNetworkEvents(eventlist[i]->ev_fd, - base->waitfor[i], /* reset the event handle */ - /*NULL,*/ /* do not reset the event handle */ - &netev) != 0) { - log_err("getdns: WSAEnumNetworkEvents failed: %s", - wsa_strerror(WSAGetLastError())); - return -1; - } - if((netev.lNetworkEvents & FD_READ)) { - if(netev.iErrorCode[FD_READ_BIT] != 0) - printf("FD_READ_BIT error: %s\n", - wsa_strerror(netev.iErrorCode[FD_READ_BIT])); - bits |= EV_READ; - printf("FD_READ_BIT\n"); - } - if((netev.lNetworkEvents & FD_WRITE)) { - if(netev.iErrorCode[FD_WRITE_BIT] != 0) - printf("FD_WRITE_BIT error: %s\n", - wsa_strerror(netev.iErrorCode[FD_WRITE_BIT])); - bits |= EV_WRITE; - printf("FD_WRITE_BIT\n"); - } - if((netev.lNetworkEvents & FD_CONNECT)) { - if(netev.iErrorCode[FD_CONNECT_BIT] != 0) - printf("FD_CONNECT_BIT error: %s\n", - wsa_strerror(netev.iErrorCode[FD_CONNECT_BIT])); - bits |= EV_READ; - bits |= EV_WRITE; - printf("FD_CONNECT_BIT\n"); - } - if((netev.lNetworkEvents & FD_ACCEPT)) { - if(netev.iErrorCode[FD_ACCEPT_BIT] != 0) - printf("FD_ACCEPT_BIT error: %s\n", - wsa_strerror(netev.iErrorCode[FD_ACCEPT_BIT])); - bits |= EV_READ; - printf("FD_ACCEPT_BIT\n"); - } - if((netev.lNetworkEvents & FD_CLOSE)) { - if(netev.iErrorCode[FD_CLOSE_BIT] != 0) - printf("FD_CLOSE_BIT error: %s\n", - wsa_strerror(netev.iErrorCode[FD_CLOSE_BIT])); - //g bits |= EV_READ; - //g bits |= EV_WRITE; - printf("FD_CLOSE_BIT\n"); - } - if(eventlist[i]->is_tcp && eventlist[i]->stick_events) { - - printf("winsock %d pass sticky %s%s\n", - eventlist[i]->ev_fd, - (eventlist[i]->old_events&EV_READ)?"EV_READ":"", - (eventlist[i]->old_events&EV_WRITE)?"EV_WRITE":""); - - bits |= eventlist[i]->old_events; - } - if(eventlist[i]->is_tcp && bits) { - eventlist[i]->old_events = bits; - eventlist[i]->stick_events = 1; - if((eventlist[i]->ev_events & bits)) { - newstickies = 1; - } - - printf("winsock %d store sticky %s%s", - eventlist[i]->ev_fd, - (eventlist[i]->old_events&EV_READ)?"EV_READ":"", - (eventlist[i]->old_events&EV_WRITE) ? "EV_WRITE" : ""); - - } - if((bits & eventlist[i]->ev_events)) { - printf( "winsock event callback %p fd=%d " - "%s%s%s%s%s ; %s%s%s\n", - eventlist[i], eventlist[i]->ev_fd, - (netev.lNetworkEvents&FD_READ)?" FD_READ":"", - (netev.lNetworkEvents&FD_WRITE)?" FD_WRITE":"", - (netev.lNetworkEvents&FD_CONNECT)? - " FD_CONNECT":"", - (netev.lNetworkEvents&FD_ACCEPT)? - " FD_ACCEPT":"", - (netev.lNetworkEvents&FD_CLOSE)?" FD_CLOSE":"", - (bits&EV_READ)?" EV_READ":"", - (bits&EV_WRITE)?" EV_WRITE":"", - (bits&EV_TIMEOUT)?" EV_TIMEOUT":""); - - fptr_ok(fptr_whitelist_event( - eventlist[i]->ev_callback)); - (*eventlist[i]->ev_callback)(eventlist[i]->ev_fd, - bits & eventlist[i]->ev_events, - eventlist[i]->ev_arg); - } - - if(eventlist[i]->is_tcp && bits) - printf( "winsock %d got sticky %s%s\n", - eventlist[i]->ev_fd, - (eventlist[i]->old_events&EV_READ)?"EV_READ":"", - (eventlist[i]->old_events&EV_WRITE)?"EV_WRITE":""); - - } - //verbose(VERB_CLIENT, "winsock_event net"); - if(base->tcp_reinvigorated) { - printf("winsock_event reinvigorated\n"); - base->tcp_reinvigorated = 0; - newstickies = 1; - } - base->tcp_stickies = newstickies; - //gprintf("winsock_event handle_select end\n"); - return 0; -} - -int _getdns_event_base_dispatch(struct _getdns_event_base *base) -{ - struct timeval wait; - if(settime(base) < 0) - return -1; - while(!base->need_to_exit) - { - /* see if timeouts need handling */ - _getdns_handle_timeouts(base, base->time_tv, &wait); - if(base->need_to_exit) - return 0; - /* do select */ - if(_getdns_handle_select(base, &wait) < 0) { - if(base->need_to_exit) - return 0; - return -1; - } - } - return 0; -} - -int _getdns_event_base_loopexit(struct _getdns_event_base *base, - struct timeval * ATTR_UNUSED(tv)) -{ - base->need_to_exit = 1; - return 0; -} - -void _getdns_event_base_free(struct _getdns_event_base *base) -{ - if(!base) - return; - if(base->items) - free(base->items); - if(base->times) - free(base->times); - if(base->signals) - free(base->signals); - free(base); -} - -void _getdns_event_set(struct _getdns_event *ev, int fd, short bits, - void (*cb)(int, short, void *), void *arg) -{ - ev->node.key = ev; - ev->ev_fd = fd; - ev->ev_events = bits; - ev->ev_callback = cb; - fptr_ok(fptr_whitelist_event(ev->ev_callback)); - ev->ev_arg = arg; - ev->just_checked = 0; - ev->added = 0; -} - -int _getdns_event_base_set(struct _getdns_event_base *base, struct _getdns_event *ev) -{ - ev->ev_base = base; - ev->old_events = 0; - ev->stick_events = 0; - ev->added = 0; - return 0; -} - -int _getdns_event_add(struct _getdns_event *ev, struct timeval *tv) -{ - printf( "event_add %p added=%d fd=%d tv=" ARG_LL "d %s%s%s\n", - ev, ev->added, ev->ev_fd, - (tv?(long long)tv->tv_sec*1000+(long long)tv->tv_usec/1000:-1), - (ev->ev_events&EV_READ)?" EV_READ":"", - (ev->ev_events&EV_WRITE)?" EV_WRITE":"", - (ev->ev_events&EV_TIMEOUT)?" EV_TIMEOUT":""); - - if(ev->added) - _getdns_event_del(ev); - - ev->is_tcp = 0; - ev->is_signal = 0; - ev->just_checked = 0; - - if ((ev->ev_events&(EV_READ | EV_WRITE)) && ev->ev_fd != -1) { - BOOL b = 0; - int t, l; - long events = 0; - //gprintf("\getdns_event_add %d %d\n", ev->ev_fd, events); - - if (ev->ev_base->max == ev->ev_base->cap) - return -1; - ev->idx = ev->ev_base->max++; - ev->ev_base->items[ev->idx] = ev; - - if ((ev->ev_events&EV_READ)) - events |= FD_READ; - if ((ev->ev_events&EV_WRITE)) - { - events |= FD_CONNECT; - events |= FD_WRITE; - } - - //printf("\getdns_event_add %d read = %d write = %d %d\n", ev->ev_fd, ev->ev_events&EV_READ, ev->ev_events&EV_WRITE, events); - - l = sizeof(t); - if(getsockopt(ev->ev_fd, SOL_SOCKET, SO_TYPE, - (void*)&t, &l) != 0) - log_err("getdns: getsockopt(SO_TYPE) failed: %s", - wsa_strerror(WSAGetLastError())); - if(t == SOCK_STREAM) { - /* TCP socket */ - ev->is_tcp = 1; - events |= FD_CLOSE; - if( (ev->ev_events&EV_WRITE) ) - events |= FD_CONNECT; - l = sizeof(b); - if(getsockopt(ev->ev_fd, SOL_SOCKET, SO_ACCEPTCONN, - (void*)&b, &l) != 0) - log_err("getdns: getsockopt(SO_ACCEPTCONN) failed: %s", - wsa_strerror(WSAGetLastError())); - if(b) /* TCP accept socket */ - events |= FD_ACCEPT; - } - ev->hEvent = WSACreateEvent(); - if(ev->hEvent == WSA_INVALID_EVENT) - log_err("getdns: WSACreateEvent failed: %s", - wsa_strerror(WSAGetLastError())); - /* automatically sets fd to nonblocking mode. - * nonblocking cannot be disabled, until wsaES(fd, NULL, 0) */ - printf("\nWSAEventSelect %d events %d hEvent %d\n", ev->ev_fd, (int)events, (int)ev->hEvent); - if (WSAEventSelect(ev->ev_fd, ev->hEvent, events) != 0) { - log_err("getdns: WSAEventSelect in getdns failed: %s", - wsa_strerror(WSAGetLastError())); - } - if(ev->is_tcp && ev->stick_events && - (ev->ev_events & ev->old_events)) { - /* go to processing the sticky event right away */ - printf("\nWSAEventSelect sticky %d events %d hEvent %d\n", ev->ev_fd, (int)events, (int)ev->hEvent); - ev->ev_base->tcp_reinvigorated = 1; - } - } - - if(tv && (ev->ev_events&EV_TIMEOUT)) { - printf("\nWSAEventSelect timeout %d hEvent %d\n", ev->ev_fd, (int)ev->hEvent); - -#ifndef S_SPLINT_S - struct timeval *now = ev->ev_base->time_tv; - ev->ev_timeout.tv_sec = tv->tv_sec + now->tv_sec; - ev->ev_timeout.tv_usec = tv->tv_usec + now->tv_usec; - while(ev->ev_timeout.tv_usec > 1000000) { - ev->ev_timeout.tv_usec -= 1000000; - ev->ev_timeout.tv_sec++; - } -#endif - (void)_getdns_rbtree_insert(ev->ev_base->times, &ev->node); - } - ev->added = 1; - return 0; -} - -int _getdns_event_del(struct _getdns_event *ev) -{ - //verbose(VERB_ALGO, "event_del %p added=%d fd=%d tv=" ARG_LL "d %s%s%s", - // ev, ev->added, ev->ev_fd, - // (ev->ev_events&EV_TIMEOUT)?(long long)ev->ev_timeout.tv_sec*1000+ - // (long long)ev->ev_timeout.tv_usec/1000:-1, - // (ev->ev_events&EV_READ)?" EV_READ":"", - // (ev->ev_events&EV_WRITE)?" EV_WRITE":"", - // (ev->ev_events&EV_TIMEOUT)?" EV_TIMEOUT":""); - if(!ev->added) - return 0; - //log_assert(ev->added); - if((ev->ev_events&EV_TIMEOUT)) - (void)_getdns_rbtree_delete(ev->ev_base->times, &ev->node); - if((ev->ev_events&(EV_READ|EV_WRITE)) && ev->ev_fd != -1) { - //log_assert(ev->ev_base->max > 0); - /* remove item and compact the list */ - ev->ev_base->items[ev->idx] = - ev->ev_base->items[ev->ev_base->max-1]; - ev->ev_base->items[ev->ev_base->max-1] = NULL; - ev->ev_base->max--; - if(ev->idx < ev->ev_base->max) - ev->ev_base->items[ev->idx]->idx = ev->idx; - zero_waitfor(ev->ev_base->waitfor, ev->hEvent); - - if(WSAEventSelect(ev->ev_fd, ev->hEvent, 0) != 0) - log_err("getdns: WSAEventSelect(disable) failed: %s", - wsa_strerror(WSAGetLastError())); - if(!WSACloseEvent(ev->hEvent)) - log_err("getdns: WSACloseEvent failed: %s", - wsa_strerror(WSAGetLastError())); - } - ev->just_checked = 0; - ev->added = 0; - return 0; -} - -/** which base gets to handle signals */ -static struct _getdns_event_base* signal_base = NULL; -/** signal handler */ -static RETSIGTYPE sigh(int sig) -{ - if(!signal_base || sig < 0 || sig >= MAX_SIG) - return; -} - -int _getdns_signal_add(struct _getdns_event *ev, struct timeval * ATTR_UNUSED(tv)) -{ - if(ev->ev_fd == -1 || ev->ev_fd >= MAX_SIG) - return -1; - signal_base = ev->ev_base; - ev->ev_base->signals[ev->ev_fd] = ev; - ev->added = 1; - if(signal(ev->ev_fd, sigh) == SIG_ERR) { - return -1; - } - return 0; -} - -int _getdns_signal_del(struct _getdns_event *ev) -{ - if(ev->ev_fd == -1 || ev->ev_fd >= MAX_SIG) - return -1; - ev->ev_base->signals[ev->ev_fd] = NULL; - ev->added = 0; - return 0; -} - -void winsock_tcp_wouldblock(struct _getdns_event* ev, int eventbits) -{ - printf("winsock: tcp wouldblock %s\n", - eventbits==EV_READ?"EV_READ":"EV_WRITE"); - ev->old_events &= (~eventbits); - if(ev->old_events == 0) - ev->stick_events = 0; - /* in case this is the last sticky event, we could - * possibly run an empty handler loop to reset the base - * tcp_stickies variable - */ -} - -int winsock_register_wsaevent(struct _getdns_event_base* base, struct _getdns_event* ev, - WSAEVENT wsaevent, void (*cb)(int, short, void*), void* arg) -{ - if(base->max == base->cap) - return 0; - memset(ev, 0, sizeof(*ev)); - ev->ev_fd = -1; - ev->ev_events = EV_READ; - ev->ev_callback = cb; - ev->ev_arg = arg; - ev->is_signal = 1; - ev->hEvent = wsaevent; - ev->added = 1; - ev->ev_base = base; - ev->idx = ev->ev_base->max++; - ev->ev_base->items[ev->idx] = ev; - return 1; -} - -void winsock_unregister_wsaevent(struct _getdns_event* ev) -{ - if(!ev || !ev->added) return; - //log_assert(ev->added && ev->ev_base->max > 0) - /* remove item and compact the list */ - ev->ev_base->items[ev->idx] = ev->ev_base->items[ev->ev_base->max-1]; - ev->ev_base->items[ev->ev_base->max-1] = NULL; - ev->ev_base->max--; - if(ev->idx < ev->ev_base->max) - ev->ev_base->items[ev->idx]->idx = ev->idx; - ev->added = 0; -} - -#else /* USE_WINSOCK */ -/** symbol so this codefile defines symbols. pleasing ranlib on OSX 10.5 */ -int winsock_unused_symbol = 1; -#endif /* USE_WINSOCK */ diff --git a/src/util/winsock_event.h b/src/util/winsock_event.h deleted file mode 100644 index e9bb5982..00000000 --- a/src/util/winsock_event.h +++ /dev/null @@ -1,295 +0,0 @@ -/* - * util/winsock_event.h - getdns event handling for winsock on windows - * extracted from Unbound source code and modified for getdns - * - * Copyright (c) 2015, NLnet Labs/Verisign. All rights reserved. - * - * This software is open source. - * - * 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 name of the NLNET LABS or Verisign 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 THE COPYRIGHT - * HOLDER 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. - */ - -/** - * \file - * - * This file contains interface functions with the WinSock2 API on Windows. - * It uses the winsock WSAWaitForMultipleEvents interface on a number of - * sockets. - * Code is originally from the Unbound source for Windows. - * - * Note that windows can only wait for max 64 events at one time. - * - * Also, file descriptors cannot be waited for. - * - * Named pipes are not easily available (and are not usable in select() ). - * For interprocess communication, it is possible to wait for a hEvent to - * be signaled by another thread. - * - * When a socket becomes readable, then it will not be flagged as - * readable again until you have gotten WOULDBLOCK from a recv routine. - * That means the event handler must store the readability (edge notify) - * and process the incoming data until it blocks. - * The function performing recv then has to inform the event handler that - * the socket has blocked, and the event handler can mark it as such. - * Thus, this file transforms the edge notify from windows to a level notify - * that is compatible with UNIX. - * The WSAEventSelect page says that it does do level notify, as long - * as you call a recv/write/accept at least once when it is signalled. - * This last bit is not true, even though documented in server2008 api docs - * from microsoft, it does not happen at all. Instead you have to test for - * WSAEWOULDBLOCK on a tcp stream, and only then retest the socket. - * And before that remember the previous result as still valid. - * - * To stay 'fair', instead of emptying a socket completely, the event handler - * can test the other (marked as blocking) sockets for new events. - * - * Additionally, TCP accept sockets get special event support. - * - * Socket numbers are not starting small, they can be any number (say 33060). - * Therefore, bitmaps are not used, but arrays. - * - * on winsock, you must use recv() and send() for TCP reads and writes, - * not read() and write(), those work only on files. - * - * Also fseek and fseeko do not work if a FILE is not fopen-ed in binary mode. - * - * When under a high load windows gives out lots of errors, from recvfrom - * on udp sockets for example (WSAECONNRESET). Even though the udp socket - * has no connection per se. - */ - -#ifndef UTIL_WINSOCK_EVENT_H -#define UTIL_WINSOCK_EVENT_H - -// Only enabled for Windows -#ifdef USE_WINSOCK - -#ifndef HAVE_EVENT_BASE_FREE -#define HAVE_EVENT_BASE_FREE -#endif - -/* redefine the calls to different names so that there is no name - * collision with other code that uses libevent names. (that uses libunbound)*/ -#define _getdns_event_init winsockevent_init -#define event_get_version winsockevent_get_version -#define event_get_method winsockevent_get_method -#define _getdns_event_base_dispatch winsockevent_base_dispatch -#define event_base_loopexit winsockevent_base_loopexit -#define _getdns_event_base_free winsockevent_base_free -#define _getdns_event_set winsockevent_set -#define _getdns_event_base_set winsockevent_base_set -#define _getdns_event_add winsockevent_add -#define _getdns_event_del winsockevent_del -#define signal_add winsocksignal_add -#define signal_del winsocksignal_del - -/** event timeout */ -#define EV_TIMEOUT 0x01 -/** event fd readable */ -#define EV_READ 0x02 -/** event fd writable */ -#define EV_WRITE 0x04 -/** event signal */ -#define EV_SIGNAL 0x08 -/** event must persist */ -#define EV_PERSIST 0x10 - -/* needs our redblack tree */ -#include "util/rbtree.h" - -/** max number of signals to support */ -#define MAX_SIG 32 - -/** The number of items that the winsock event handler can service. - * Windows cannot handle more anyway */ -#define WSK_MAX_ITEMS 64 - -/** - * event base for winsock event handler - */ -struct _getdns_event_base -{ - /** sorted by timeout (absolute), ptr */ - _getdns_rbtree_t* times; - /** array (first part in use) of handles to work on */ - struct _getdns_event** items; - /** number of items in use in array */ - int max; - /** capacity of array, size of array in items */ - int cap; - /** array of 0 - maxsig of ptr to event for it */ - struct _getdns_event** signals; - /** if we need to exit */ - int need_to_exit; - /** where to store time in seconds */ - time_t* time_secs; - /** where to store time in microseconds */ - struct timeval* time_tv; - /** - * TCP streams have sticky events to them, these are not - * reported by the windows event system anymore, we have to - * keep reporting those events as present until wouldblock() is - * signalled by the handler back to use. - */ - int tcp_stickies; - /** - * should next cycle process reinvigorated stickies, - * these are stickies that have been stored, but due to a new - * event_add a sudden interest in the event has incepted. - */ - int tcp_reinvigorated; - /** The list of events that is currently being processed. */ - WSAEVENT waitfor[WSK_MAX_ITEMS]; - - /* fdset for read write, for fds ready, and added */ - fd_set - /** fds for reading */ - reads, - /** fds for writing */ - writes, - /** fds determined ready for use */ - ready, - /** ready plus newly added events. */ - content; -}; - -/** - * Event structure. Has some of the event elements. - */ -struct _getdns_event { - /** node in timeout rbtree */ - _getdns_rbnode_t node; - /** is event already added */ - int added; - - /** event base it belongs to */ - struct _getdns_event_base *ev_base; - /** fd to poll or -1 for timeouts. signal number for sigs. */ - int ev_fd; - /** what events this event is interested in, see EV_.. above. */ - short ev_events; - /** timeout value */ - struct timeval ev_timeout; - - /** callback to call: fd, eventbits, userarg */ - void (*ev_callback)(int, short, void *); - /** callback user arg */ - void *ev_arg; - - /* ----- nonpublic part, for winsock_event only ----- */ - /** index of this event in the items array (if added) */ - int idx; - /** the event handle to wait for new events to become ready */ - WSAEVENT hEvent; - /** true if this filedes is a TCP socket and needs special attention */ - int is_tcp; - /** remembered EV_ values */ - short old_events; - /** should remembered EV_ values be used for TCP streams. - * Reset after WOULDBLOCK is signaled using the function. */ - int stick_events; - - /** true if this event is a signaling WSAEvent by the user. - * User created and user closed WSAEvent. Only signaled/unsigneled, - * no read/write/distinctions needed. */ - int is_signal; - /** used during callbacks to see which events were just checked */ - int just_checked; -}; - -char* wsa_strerror(DWORD err); -void log_err(const char *format, ...); -/** create event base */ -void *_getdns_event_init(time_t* time_secs, struct timeval* time_tv); -/** get version */ -const char *event_get_version(void); -/** get polling method (select,epoll) */ -const char *event_get_method(void); -/** run select in a loop */ -int _getdns_event_base_dispatch(struct _getdns_event_base *); -/** exit that loop */ -int event_base_loopexit(struct _getdns_event_base *, struct timeval *); -/** free event base. Free events yourself */ -void _getdns_event_base_free(struct _getdns_event_base *); -/** set content of event */ -void _getdns_event_set(struct _getdns_event *, int, short, void (*)(int, short, void *), void *); - -/** add event to a base. You *must* call this for every event. */ -int _getdns_event_base_set(struct _getdns_event_base *, struct _getdns_event *); -/** add event to make it active. You may not change it with event_set anymore */ -int _getdns_event_add(struct _getdns_event *, struct timeval *); -/** remove event. You may change it again */ -int _getdns_event_del(struct _getdns_event *); - -#define evtimer_add(ev, tv) event_add(ev, tv) -#define evtimer_del(ev) event_del(ev) - -/* uses different implementation. Cannot mix fd/timeouts and signals inside - * the same struct event. create several event structs for that. */ -/** install signal handler */ -int signal_add(struct _getdns_event *, struct timeval *); -/** set signal event contents */ -#define signal_set(ev, x, cb, arg) \ - event_set(ev, x, EV_SIGNAL|EV_PERSIST, cb, arg) -/** remove signal handler */ -int signal_del(struct _getdns_event *); - -/** compare events in tree, based on timevalue, ptr for uniqueness */ -int getdns_mini_ev_cmp(const void* a, const void* b); - -/** - * Routine for windows only, where the handling layer can signal that - * a TCP stream encountered WSAEWOULDBLOCK for a stream and thus needs - * retesting the event. - * Pass if EV_READ or EV_WRITE gave wouldblock. - */ -void winsock_tcp_wouldblock(struct _getdns_event* ev, int eventbit); - -/** - * Routine for windows only. where you pass a signal WSAEvent that - * you wait for. When the event is signaled, the callback gets called. - * The callback has to WSAResetEvent to disable the signal. - * @param base: the event base. - * @param ev: the event structure for data storage - * can be passed uninitialised. - * @param wsaevent: the WSAEvent that gets signaled. - * @param cb: callback routine. - * @param arg: user argument to callback routine. - * @return false on error. - */ -int winsock_register_wsaevent(struct _getdns_event_base* base, struct _getdns_event* ev, - WSAEVENT wsaevent, void (*cb)(int, short, void*), void* arg); - -/** - * Unregister a wsaevent. User has to close the WSAEVENT itself. - * @param ev: event data storage. - */ -void winsock_unregister_wsaevent(struct _getdns_event* ev); - -#endif /* USE_WINSOCK */ -#endif /* UTIL_WINSOCK_EVENT_H */ From 2a6318afd20dd317588b0db0e53cb62d024b14d8 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Tue, 12 Jan 2016 16:38:10 +0100 Subject: [PATCH 06/23] Disable scheduling ub_fd() --- src/context.c | 4 ++++ src/sync.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/context.c b/src/context.c index 0dd7ec79..8ddf2c9a 100644 --- a/src/context.c +++ b/src/context.c @@ -1280,17 +1280,21 @@ getdns_context_request_count_changed(getdns_context *context) DEBUG_SCHED("gc_request_count_changed " "-> ub schedule(el_ev = %p, el_ev->ev = %p)\n", &context->ub_event, context->ub_event.ev); +#ifndef USE_WINSOCK context->extension->vmt->schedule( context->extension, ub_fd(context->unbound_ctx), TIMEOUT_FOREVER, &context->ub_event); +#endif } else if (context->ub_event.ev) /* Only test if count == 0! */ { DEBUG_SCHED("gc_request_count_changed " "-> ub clear(el_ev = %p, el_ev->ev = %p)\n", &context->ub_event, context->ub_event.ev); +#ifndef USE_WINSOCK context->extension->vmt->clear( context->extension, &context->ub_event); +#endif } } diff --git a/src/sync.c b/src/sync.c index cfc43df6..b6524d02 100644 --- a/src/sync.c +++ b/src/sync.c @@ -68,7 +68,7 @@ getdns_sync_loop_init(getdns_context *context, getdns_sync_loop *loop) _getdns_default_eventloop_init(&loop->loop); -#ifdef HAVE_LIBUNBOUND +#if defined(HAVE_LIBUNBOUND) && !defined(USE_WINSOCK) loop->ub_event.userarg = loop->context; loop->ub_event.read_cb = _getdns_context_ub_read_cb; loop->ub_event.write_cb = NULL; From 61c0a51ec560e08c79391387cb986346045fd73b Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Tue, 12 Jan 2016 16:43:25 +0100 Subject: [PATCH 07/23] Disable clearing ub_fd too (for windows) --- src/sync.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sync.c b/src/sync.c index b6524d02..714a6b87 100644 --- a/src/sync.c +++ b/src/sync.c @@ -87,7 +87,7 @@ getdns_sync_loop_cleanup(getdns_sync_loop *loop) { getdns_eventloop *ext = &loop->loop.loop; -#ifdef HAVE_LIBUNBOUND +#if defined(HAVE_LIBUNBOUND) && !defined(USE_WINSOCK) ext->vmt->clear(ext, &loop->ub_event); #endif ext->vmt->cleanup(ext); From fed8cc51ed8ae5af84a25bebbe0faea69fa8176f Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Tue, 12 Jan 2016 16:54:42 +0100 Subject: [PATCH 08/23] Initial TCP support for Windows --- src/stub.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/stub.c b/src/stub.c index c09e98ed..3e44730e 100644 --- a/src/stub.c +++ b/src/stub.c @@ -390,12 +390,16 @@ tcp_connect(getdns_upstream *upstream, getdns_transport_list_t transport) } return fd; #endif + printf("fd: %d\n",fd); if (connect(fd, (struct sockaddr *)&upstream->addr, upstream->addr_len) == -1) { - if (errno != EINPROGRESS) { - close(fd); - return -1; - } +#if USE_WINSOCK + printf("WSAGetLastError(): %d\n", WSAGetLastError()); +#endif + if (_getdns_EINPROGRESS || _getdns_EWOULDBLOCK) + return fd; + close(fd); + return -1; } return fd; } From 0c0868517c2b043686eee61ce92fef1489cd07a9 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Tue, 12 Jan 2016 16:57:17 +0100 Subject: [PATCH 09/23] Remove leftover debugging printfs --- src/stub.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/stub.c b/src/stub.c index 3e44730e..cc2f0da8 100644 --- a/src/stub.c +++ b/src/stub.c @@ -390,12 +390,8 @@ tcp_connect(getdns_upstream *upstream, getdns_transport_list_t transport) } return fd; #endif - printf("fd: %d\n",fd); if (connect(fd, (struct sockaddr *)&upstream->addr, upstream->addr_len) == -1) { -#if USE_WINSOCK - printf("WSAGetLastError(): %d\n", WSAGetLastError()); -#endif if (_getdns_EINPROGRESS || _getdns_EWOULDBLOCK) return fd; close(fd); From ae2b16665b422222c3c1c4b501ece9c65a918ff4 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Tue, 19 Jan 2016 16:52:11 +0100 Subject: [PATCH 10/23] Setup getdns eventloop in libunbound When unbound supports this --- configure.ac | 15 +++++++++++++-- src/context.c | 40 +++++++++++++++++++++++++++++++++------- src/context.h | 3 +++ src/general.c | 40 +++++++++++++++++++++++++++++++++++----- src/sync.c | 20 +++++++++++++++----- src/test/getdns_query.c | 6 ++++-- src/util-internal.c | 28 +++++++++++----------------- src/util-internal.h | 3 ++- 8 files changed, 116 insertions(+), 39 deletions(-) diff --git a/configure.ac b/configure.ac index ab0d917b..df56589c 100644 --- a/configure.ac +++ b/configure.ac @@ -526,7 +526,15 @@ fi if test $my_with_libunbound = 1 then AC_MSG_NOTICE([Checking for dependency libunbound]) - AC_CHECK_LIB([unbound], [ub_fd], [], [found_all_libs=0]) + AC_CHECK_LIB([unbound], [ub_fd], [ + AC_DEFINE_UNQUOTED([HAVE_LIBUNBOUND], [1], [Define to 1 if you have the `unbound' library (-lunbound).]) + LIBS="$LIBS -lunbound" + AC_CHECK_HEADER([unbound-event.h],[ + AC_CHECK_FUNC([ub_event_get_version], [ + AC_DEFINE_UNQUOTED([HAVE_UNBOUND_EVENT_API], [1], [Define this when libunbound is compiled with the --enable-event-api option.]) + ]) + ],,[AC_INCLUDES_DEFAULT]) + ], [found_all_libs=0]) fi if test $found_all_libs = 0 @@ -1192,7 +1200,10 @@ const char *inet_ntop(int af, const void *src, char *dst, size_t size); #endif #ifdef HAVE_LIBUNBOUND -#include +# include +# ifdef HAVE_UNBOUND_EVENT_API +# include +# endif #endif ]) diff --git a/src/context.c b/src/context.c index 8ddf2c9a..3ea960e6 100644 --- a/src/context.c +++ b/src/context.c @@ -1281,9 +1281,12 @@ getdns_context_request_count_changed(getdns_context *context) "-> ub schedule(el_ev = %p, el_ev->ev = %p)\n", &context->ub_event, context->ub_event.ev); #ifndef USE_WINSOCK - context->extension->vmt->schedule( - context->extension, ub_fd(context->unbound_ctx), - TIMEOUT_FOREVER, &context->ub_event); +#ifdef HAVE_UNBOUND_EVENT_API + if (!context->unbound_event_api) +#endif + context->extension->vmt->schedule( + context->extension, ub_fd(context->unbound_ctx), + TIMEOUT_FOREVER, &context->ub_event); #endif } else if (context->ub_event.ev) /* Only test if count == 0! */ { @@ -1292,8 +1295,11 @@ getdns_context_request_count_changed(getdns_context *context) &context->ub_event, context->ub_event.ev); #ifndef USE_WINSOCK - context->extension->vmt->clear( - context->extension, &context->ub_event); +#ifdef HAVE_UNBOUND_EVENT_API + if (!context->unbound_event_api) +#endif + context->extension->vmt->clear( + context->extension, &context->ub_event); #endif } } @@ -1324,8 +1330,18 @@ rebuild_ub_ctx(struct getdns_context* context) { context->unbound_ctx = NULL; } /* setup */ - context->unbound_ctx = ub_ctx_create(); - (void) ub_ctx_async(context->unbound_ctx, 1); +#ifdef HAVE_UNBOUND_EVENT_API + context->unbound_event_api = + strncmp(ub_event_get_version(), "getdns-event", 12) == 0; + if (context->unbound_event_api) { + context->unbound_ctx = ub_ctx_create_event((void *)context->extension); + } else { +#endif + context->unbound_ctx = ub_ctx_create(); + (void) ub_ctx_async(context->unbound_ctx, 1); +#ifdef HAVE_UNBOUND_EVENT_API + } +#endif context->unbound_ta_set = 0; if (!context->unbound_ctx) { return GETDNS_RETURN_MEMORY_ERROR; @@ -2891,6 +2907,11 @@ getdns_context_detach_eventloop(struct getdns_context* context) context->extension->vmt->cleanup(context->extension); context->extension = &context->default_eventloop.loop; _getdns_default_eventloop_init(&context->default_eventloop); +#ifdef HAVE_UNBOUND_EVENT_API + if (context->unbound_event_api) + (void) ub_ctx_set_event( + context->unbound_ctx, (void *)context->extension); +#endif return GETDNS_RETURN_GOOD; } @@ -2905,6 +2926,11 @@ getdns_context_set_eventloop(getdns_context* context, getdns_eventloop* loop) context->extension->vmt->cleanup(context->extension); } context->extension = loop; +#ifdef HAVE_UNBOUND_EVENT_API + if (context->unbound_event_api) + (void) ub_ctx_set_event( + context->unbound_ctx, (void *)context->extension); +#endif return GETDNS_RETURN_GOOD; } diff --git a/src/context.h b/src/context.h index 8547673c..2ba134f9 100644 --- a/src/context.h +++ b/src/context.h @@ -220,6 +220,9 @@ struct getdns_context { /* The underlying contexts that do the real work */ struct ub_ctx *unbound_ctx; int unbound_ta_set; +#ifdef HAVE_UNBOUND_EVENT_API + int unbound_event_api; +#endif #endif /* A tree to hold local host information*/ diff --git a/src/general.c b/src/general.c index 777774e6..af156c05 100644 --- a/src/general.c +++ b/src/general.c @@ -256,6 +256,26 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req) } #ifdef HAVE_LIBUNBOUND +#ifdef HAVE_UNBOUND_EVENT_API +static void +ub_resolve_event_callback(void* arg, int rcode, void *pkt, int pkt_len, + int sec, char* why_bogus) +{ + getdns_network_req *netreq = (getdns_network_req *) arg; + getdns_dns_req *dns_req = netreq->owner; + + netreq->state = NET_REQ_FINISHED; + /* parse */ + if (getdns_apply_network_result( + netreq, rcode, pkt, pkt_len, sec, why_bogus)) { + _getdns_call_user_callback(dns_req, NULL); + return; + } + _getdns_check_dns_req_complete(dns_req); + +} /* ub_resolve_event_callback */ +#endif + static void ub_resolve_callback(void* arg, int err, struct ub_result* ub_res) { @@ -268,7 +288,9 @@ ub_resolve_callback(void* arg, int err, struct ub_result* ub_res) return; } /* parse */ - if (getdns_apply_network_result(netreq, ub_res)) { + if (getdns_apply_network_result(netreq, ub_res->rcode, + ub_res->answer_packet, ub_res->answer_len, + (ub_res->secure ? 2 : ub_res->bogus ? 1 : 0), ub_res->why_bogus)) { ub_resolve_free(ub_res); _getdns_call_user_callback(dns_req, NULL); return; @@ -319,10 +341,18 @@ _getdns_submit_netreq(getdns_network_req *netreq) dns_req->name_len, name, sizeof(name)); #ifdef HAVE_LIBUNBOUND - return ub_resolve_async(dns_req->context->unbound_ctx, - name, netreq->request_type, netreq->owner->request_class, - netreq, ub_resolve_callback, &(netreq->unbound_id)) ? - GETDNS_RETURN_GENERIC_ERROR : GETDNS_RETURN_GOOD; +#ifdef HAVE_UNBOUND_EVENT_API + if (dns_req->context->unbound_event_api) + return ub_resolve_event(dns_req->context->unbound_ctx, + name, netreq->request_type, netreq->owner->request_class, + netreq, ub_resolve_event_callback, &(netreq->unbound_id)) ? + GETDNS_RETURN_GENERIC_ERROR : GETDNS_RETURN_GOOD; + else +#endif + return ub_resolve_async(dns_req->context->unbound_ctx, + name, netreq->request_type, netreq->owner->request_class, + netreq, ub_resolve_callback, &(netreq->unbound_id)) ? + GETDNS_RETURN_GENERIC_ERROR : GETDNS_RETURN_GOOD; #else return GETDNS_RETURN_NOT_IMPLEMENTED; #endif diff --git a/src/sync.c b/src/sync.c index 714a6b87..dffff203 100644 --- a/src/sync.c +++ b/src/sync.c @@ -75,11 +75,15 @@ getdns_sync_loop_init(getdns_context *context, getdns_sync_loop *loop) loop->ub_event.timeout_cb = NULL; loop->ub_event.ev = NULL; - return ext->vmt->schedule(ext, ub_fd(context->unbound_ctx), - TIMEOUT_FOREVER, &loop->ub_event); -#else - return GETDNS_RETURN_GOOD; +# ifdef HAVE_UNBOUND_EVENT_API + if (context->unbound_event_api) { + (void) ub_ctx_set_event(context->unbound_ctx, (void *)ext); + } else +# endif + return ext->vmt->schedule(ext, ub_fd(context->unbound_ctx), + TIMEOUT_FOREVER, &loop->ub_event); #endif + return GETDNS_RETURN_GOOD; } static void @@ -88,7 +92,13 @@ getdns_sync_loop_cleanup(getdns_sync_loop *loop) getdns_eventloop *ext = &loop->loop.loop; #if defined(HAVE_LIBUNBOUND) && !defined(USE_WINSOCK) - ext->vmt->clear(ext, &loop->ub_event); +# ifdef HAVE_UNBOUND_EVENT_API + if (loop->context->unbound_event_api) { + (void) ub_ctx_set_event(loop->context->unbound_ctx, + (void *)loop->context->extension); + } else +# endif + ext->vmt->clear(ext, &loop->ub_event); #endif ext->vmt->cleanup(ext); } diff --git a/src/test/getdns_query.c b/src/test/getdns_query.c index 2e665cef..a17a4bec 100644 --- a/src/test/getdns_query.c +++ b/src/test/getdns_query.c @@ -1305,8 +1305,6 @@ main(int argc, char **argv) return r; } my_eventloop_init(&my_loop); - if ((r = getdns_context_set_eventloop(context, &my_loop.base))) - goto done_destroy_context; if ((r = getdns_context_set_use_threads(context, 1))) goto done_destroy_context; extensions = getdns_dict_create(); @@ -1329,10 +1327,14 @@ main(int argc, char **argv) /* Make the call */ if (interactive) { + getdns_eventloop_event read_line_ev = { &read_line_ev, read_line_cb, NULL, NULL, NULL }; (void) my_eventloop_schedule( &my_loop.base, fileno(fp), -1, &read_line_ev); + if ((r = getdns_context_set_eventloop(context, &my_loop.base))) + goto done_destroy_context; + if (!query_file) { printf("> "); fflush(stdout); diff --git a/src/util-internal.c b/src/util-internal.c index fe41bea6..2498306b 100644 --- a/src/util-internal.c +++ b/src/util-internal.c @@ -1020,30 +1020,24 @@ error_free_result: #ifdef HAVE_LIBUNBOUND getdns_return_t getdns_apply_network_result(getdns_network_req* netreq, - struct ub_result* ub_res) + int rcode, void *pkt, int pkt_len, int sec, char* why_bogus) { - if (ub_res->bogus) - netreq->dnssec_status = GETDNS_DNSSEC_BOGUS; - else if (ub_res->secure) - netreq->dnssec_status = GETDNS_DNSSEC_SECURE; - else if (netreq->owner->context->trust_anchors) - netreq->dnssec_status = GETDNS_DNSSEC_INSECURE; + netreq->dnssec_status = sec == 0 ? GETDNS_DNSSEC_INSECURE + : sec == 2 ? GETDNS_DNSSEC_SECURE + : GETDNS_DNSSEC_BOGUS; - if (ub_res == NULL) /* Timeout */ - return GETDNS_RETURN_GOOD; - - if (ub_res->answer_packet) { - if (netreq->max_udp_payload_size < ub_res->answer_len) + if (pkt) { + if (netreq->max_udp_payload_size < pkt_len) netreq->response = GETDNS_XMALLOC( netreq->owner->context->mf, - uint8_t, ub_res->answer_len + uint8_t, pkt_len ); - (void) memcpy(netreq->response, ub_res->answer_packet, - (netreq->response_len = ub_res->answer_len)); + (void) memcpy(netreq->response, pkt, + (netreq->response_len = pkt_len)); return GETDNS_RETURN_GOOD; } - if (ub_res->rcode == GETDNS_RCODE_SERVFAIL) { + if (rcode == GETDNS_RCODE_SERVFAIL) { /* Likely to be caused by timeout from a synchronous * lookup. Don't forge a packet. */ @@ -1064,7 +1058,7 @@ getdns_apply_network_result(getdns_network_req* netreq, GLDNS_QR_SET(netreq->response); GLDNS_RD_SET(netreq->response); GLDNS_RA_SET(netreq->response); - GLDNS_RCODE_SET(netreq->response, ub_res->rcode); + GLDNS_RCODE_SET(netreq->response, rcode); (void) memcpy( netreq->response + GLDNS_HEADER_SIZE , netreq->owner->name, netreq->owner->name_len); diff --git a/src/util-internal.h b/src/util-internal.h index 7a826b95..8aeeb397 100644 --- a/src/util-internal.h +++ b/src/util-internal.h @@ -56,7 +56,8 @@ struct ub_result; struct getdns_network_req; -getdns_return_t getdns_apply_network_result(getdns_network_req* netreq, struct ub_result* result); +getdns_return_t getdns_apply_network_result(getdns_network_req* netreq, + int rcode, void *pkt, int pkt_len, int sec, char* why_bogus); #define GETDNS_MAX_DNAME_LEN 255 #define GETDNS_MAX_LABEL_LEN 63 From ca36c879a07e27cacda2287cddf1a1d1d5ac1f95 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 20 Jan 2016 10:21:05 +0100 Subject: [PATCH 11/23] Set unbound target fetch policy to on demand only --- src/context.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/context.c b/src/context.c index 3ea960e6..6527333e 100644 --- a/src/context.c +++ b/src/context.c @@ -1343,9 +1343,11 @@ rebuild_ub_ctx(struct getdns_context* context) { } #endif context->unbound_ta_set = 0; - if (!context->unbound_ctx) { + if (!context->unbound_ctx) return GETDNS_RETURN_MEMORY_ERROR; - } + + ub_ctx_set_option(context->unbound_ctx, + "target-fetch-policy:", "0 0 0 0 0"); set_ub_dnssec_allowed_skew(context, context->dnssec_allowed_skew); set_ub_edns_maximum_udp_payload_size(context, From d50860c0899ad0faa942380c23b3352cae071aef Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 20 Jan 2016 11:10:53 +0100 Subject: [PATCH 12/23] Run context's event loop when doing sync requests --- src/sync.c | 176 ++++++++++++++--------------------------------------- 1 file changed, 46 insertions(+), 130 deletions(-) diff --git a/src/sync.c b/src/sync.c index dffff203..17fd8d28 100644 --- a/src/sync.c +++ b/src/sync.c @@ -33,197 +33,113 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include -#include "getdns/getdns.h" #include "config.h" -#include "context.h" -#include "general.h" -#include "types-internal.h" -#include "util-internal.h" -#include "dnssec.h" +#include "getdns/getdns.h" +#include "getdns/getdns_extra.h" -#include "stub.h" -#include "gldns/wire2str.h" -typedef struct getdns_sync_loop { - _getdns_default_eventloop loop; -#ifdef HAVE_LIBUNBOUND - getdns_eventloop_event ub_event; -#endif - getdns_context *context; - int to_run; - getdns_dict *response; -} getdns_sync_loop; - -static getdns_return_t -getdns_sync_loop_init(getdns_context *context, getdns_sync_loop *loop) -{ -#ifdef HAVE_LIBUNBOUND - getdns_eventloop *ext = &loop->loop.loop; -#endif - - loop->response = NULL; - loop->to_run = 1; - loop->context = context; - - _getdns_default_eventloop_init(&loop->loop); - -#if defined(HAVE_LIBUNBOUND) && !defined(USE_WINSOCK) - loop->ub_event.userarg = loop->context; - loop->ub_event.read_cb = _getdns_context_ub_read_cb; - loop->ub_event.write_cb = NULL; - loop->ub_event.timeout_cb = NULL; - loop->ub_event.ev = NULL; - -# ifdef HAVE_UNBOUND_EVENT_API - if (context->unbound_event_api) { - (void) ub_ctx_set_event(context->unbound_ctx, (void *)ext); - } else -# endif - return ext->vmt->schedule(ext, ub_fd(context->unbound_ctx), - TIMEOUT_FOREVER, &loop->ub_event); -#endif - return GETDNS_RETURN_GOOD; -} - -static void -getdns_sync_loop_cleanup(getdns_sync_loop *loop) -{ - getdns_eventloop *ext = &loop->loop.loop; - -#if defined(HAVE_LIBUNBOUND) && !defined(USE_WINSOCK) -# ifdef HAVE_UNBOUND_EVENT_API - if (loop->context->unbound_event_api) { - (void) ub_ctx_set_event(loop->context->unbound_ctx, - (void *)loop->context->extension); - } else -# endif - ext->vmt->clear(ext, &loop->ub_event); -#endif - ext->vmt->cleanup(ext); -} - -static void -getdns_sync_loop_run(getdns_sync_loop *loop) -{ - getdns_eventloop *ext = &loop->loop.loop; - - while (loop->to_run) - ext->vmt->run_once(ext, 1); - - getdns_sync_loop_cleanup(loop); -} +typedef struct getdns_sync_data { + int to_run; + getdns_callback_type_t callback_type; + getdns_dict *response; + getdns_transaction_t transaction_id; +} getdns_sync_data; static void getdns_sync_cb(getdns_context *context, getdns_callback_type_t callback_type, getdns_dict *response, void *userarg, getdns_transaction_t transaction_id) { - getdns_sync_loop *loop = (getdns_sync_loop *)userarg; + getdns_sync_data *data = (getdns_sync_data *)userarg; - assert(loop); + assert(data); + assert(data->transaction_id == transaction_id); - loop->response = response; - loop->to_run = 0; + data->callback_type = callback_type; + data->response = response; + data->to_run = 0; +} + +static getdns_return_t +_getdns_sync_run( + getdns_context *context, getdns_sync_data *data, getdns_dict **response) +{ + data->to_run = 1; + data->callback_type = (getdns_callback_type_t)0; + data->response = NULL; + + while (data->to_run) + getdns_context_process_async(context); + + return (*response = data->response) ? + GETDNS_RETURN_GOOD : GETDNS_RETURN_GENERIC_ERROR; } getdns_return_t getdns_general_sync(getdns_context *context, const char *name, uint16_t request_type, getdns_dict *extensions, getdns_dict **response) { - getdns_sync_loop loop; + getdns_sync_data data; getdns_return_t r; if (!context || !name || !response) return GETDNS_RETURN_INVALID_PARAMETER; - if ((r = getdns_sync_loop_init(context, &loop))) + if ((r = getdns_general(context, name, request_type, + extensions, &data, &data.transaction_id, getdns_sync_cb))) return r; - if ((r = _getdns_general_loop(context, &loop.loop.loop, name, - request_type, extensions, &loop, NULL, getdns_sync_cb, NULL))) { - - getdns_sync_loop_cleanup(&loop); - return r; - } - getdns_sync_loop_run(&loop); - - return (*response = loop.response) ? - GETDNS_RETURN_GOOD : GETDNS_RETURN_GENERIC_ERROR; + return _getdns_sync_run(context, &data, response); } getdns_return_t getdns_address_sync(getdns_context *context, const char *name, getdns_dict *extensions, getdns_dict **response) { - getdns_sync_loop loop; + getdns_sync_data data; getdns_return_t r; if (!context || !name || !response) return GETDNS_RETURN_INVALID_PARAMETER; - if ((r = getdns_sync_loop_init(context, &loop))) + if ((r = getdns_address(context, name, + extensions, &data, &data.transaction_id, getdns_sync_cb))) return r; - if ((r = _getdns_address_loop(context, &loop.loop.loop, name, - extensions, &loop, NULL, getdns_sync_cb))) { - - getdns_sync_loop_cleanup(&loop); - return r; - } - getdns_sync_loop_run(&loop); - - return (*response = loop.response) ? - GETDNS_RETURN_GOOD : GETDNS_RETURN_GENERIC_ERROR; + return _getdns_sync_run(context, &data, response); } getdns_return_t getdns_hostname_sync(getdns_context *context, getdns_dict *address, getdns_dict *extensions, getdns_dict **response) { - getdns_sync_loop loop; + getdns_sync_data data; getdns_return_t r; - if (!context || !address || !response) + if (!context || !address|| !response) return GETDNS_RETURN_INVALID_PARAMETER; - if ((r = getdns_sync_loop_init(context, &loop))) + if ((r = getdns_hostname(context, address, + extensions, &data, &data.transaction_id, getdns_sync_cb))) return r; - if ((r = _getdns_hostname_loop(context, &loop.loop.loop, address, - extensions, &loop, NULL, getdns_sync_cb))) { - - getdns_sync_loop_cleanup(&loop); - return r; - } - getdns_sync_loop_run(&loop); - - return (*response = loop.response) ? - GETDNS_RETURN_GOOD : GETDNS_RETURN_GENERIC_ERROR; + return _getdns_sync_run(context, &data, response); } getdns_return_t getdns_service_sync(getdns_context *context, const char *name, getdns_dict *extensions, getdns_dict **response) { - getdns_sync_loop loop; + getdns_sync_data data; getdns_return_t r; if (!context || !name || !response) return GETDNS_RETURN_INVALID_PARAMETER; - if ((r = getdns_sync_loop_init(context, &loop))) + if ((r = getdns_service(context, name, + extensions, &data, &data.transaction_id, getdns_sync_cb))) return r; - if ((r = _getdns_service_loop(context, &loop.loop.loop, name, - extensions, &loop, NULL, getdns_sync_cb))) { - - getdns_sync_loop_cleanup(&loop); - return r; - } - getdns_sync_loop_run(&loop); - - return (*response = loop.response) ? - GETDNS_RETURN_GOOD : GETDNS_RETURN_GENERIC_ERROR; + return _getdns_sync_run(context, &data, response); } /* getdns_core_sync.c */ From 24b58074bff76de26b292ba9c737008bb4b08cb0 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 20 Jan 2016 13:09:18 +0100 Subject: [PATCH 13/23] Prevent chain checks to be performed too early --- src/dnssec.c | 43 +++++++++++++++++++++++++++---------------- src/general.c | 42 +++++++++++++++++++++--------------------- src/general.h | 2 +- 3 files changed, 49 insertions(+), 38 deletions(-) diff --git a/src/dnssec.c b/src/dnssec.c index 7cf54ec7..b4e55ac5 100644 --- a/src/dnssec.c +++ b/src/dnssec.c @@ -749,6 +749,8 @@ struct chain_head { struct chain_node { chain_node *parent; + + size_t lock; getdns_rrset dnskey; getdns_network_req *dnskey_req; @@ -878,6 +880,7 @@ static chain_head *add_rrset2val_chain(struct mem_funcs *mf, ; node_count ; node_count--, node = node->parent =&node[1], dname += *dname + 1) { + node->lock = 0; node->ds.name = dname; node->dnskey.name = dname; node->ds.rr_class = head->rrset.rr_class; @@ -1135,7 +1138,6 @@ static void val_chain_sched_soa_node(chain_node *node) { getdns_context *context; getdns_eventloop *loop; - getdns_dns_req *dnsreq; char name[1024]; context = node->chains->netreq->owner->context; @@ -1147,12 +1149,15 @@ static void val_chain_sched_soa_node(chain_node *node) DEBUG_SEC("schedule SOA lookup for %s\n", name); + node->lock++; if (! node->soa_req && - ! _getdns_general_loop(context, loop, name, GETDNS_RRTYPE_SOA, - CD_extension(node->chains->netreq->owner), node, &dnsreq, NULL, - val_chain_node_soa_cb)) + _getdns_general_loop(context, loop, name, GETDNS_RRTYPE_SOA, + CD_extension(node->chains->netreq->owner), node, &node->soa_req, + NULL, val_chain_node_soa_cb)) - node->soa_req = dnsreq->netreqs[0]; + node->soa_req = NULL; + + node->lock--; } /* A SOA lookup is scheduled as a last resort. No signatures were found and @@ -1183,7 +1188,6 @@ static void val_chain_sched_node(chain_node *node) { getdns_context *context; getdns_eventloop *loop; - getdns_dns_req *dnsreq; char name[1024]; context = node->chains->netreq->owner->context; @@ -1195,19 +1199,22 @@ static void val_chain_sched_node(chain_node *node) DEBUG_SEC("schedule DS & DNSKEY lookup for %s\n", name); + node->lock++; if (! node->dnskey_req /* not scheduled */ && - ! _getdns_general_loop(context, loop, name, GETDNS_RRTYPE_DNSKEY, + _getdns_general_loop(context, loop, name, GETDNS_RRTYPE_DNSKEY, CD_extension(node->chains->netreq->owner), - node, &dnsreq, NULL, val_chain_node_cb)) + node, &node->dnskey_req, NULL, val_chain_node_cb)) - node->dnskey_req = dnsreq->netreqs[0]; + node->dnskey_req = NULL; if (! node->ds_req && node->parent /* not root */ && - ! _getdns_general_loop(context, loop, name, GETDNS_RRTYPE_DS, + _getdns_general_loop(context, loop, name, GETDNS_RRTYPE_DS, CD_extension(node->chains->netreq->owner), - node, &dnsreq, NULL, val_chain_node_cb)) + node, &node->ds_req, NULL, val_chain_node_cb)) - node->ds_req = dnsreq->netreqs[0]; + node->ds_req = NULL; + + node->lock--; } static void val_chain_sched(chain_head *head, const uint8_t *dname) @@ -1228,7 +1235,6 @@ static void val_chain_sched_ds_node(chain_node *node) { getdns_context *context; getdns_eventloop *loop; - getdns_dns_req *ds_req; char name[1024]; context = node->chains->netreq->owner->context; @@ -1241,12 +1247,15 @@ static void val_chain_sched_ds_node(chain_node *node) DEBUG_SEC("schedule DS lookup for %s\n", name); + node->lock++; if (! node->ds_req && node->parent /* not root */ && - ! _getdns_general_loop(context, loop, name, GETDNS_RRTYPE_DS, + _getdns_general_loop(context, loop, name, GETDNS_RRTYPE_DS, CD_extension(node->chains->netreq->owner), - node, &ds_req, NULL, val_chain_node_cb)) + node, &node->ds_req, NULL, val_chain_node_cb)) - node->ds_req = ds_req->netreqs[0]; + node->ds_req = NULL; + + node->lock--; } static void val_chain_sched_ds(chain_head *head, const uint8_t *dname) @@ -2998,6 +3007,8 @@ static size_t count_outstanding_requests(chain_head *head) ; node ; node = node->parent) { + count += node->lock; + if (node->dnskey_req && node->dnskey_req->state != NET_REQ_FINISHED && node->dnskey_req->state != NET_REQ_CANCELED) diff --git a/src/general.c b/src/general.c index af156c05..43cd8724 100644 --- a/src/general.c +++ b/src/general.c @@ -442,7 +442,7 @@ validate_extensions(struct getdns_dict * extensions) static getdns_return_t getdns_general_ns(getdns_context *context, getdns_eventloop *loop, const char *name, uint16_t request_type, getdns_dict *extensions, - void *userarg, getdns_dns_req **dnsreq_p, + void *userarg, getdns_network_req **return_netreq_p, getdns_callback_t callbackfn, internal_cb_t internal_cb, int usenamespaces) { getdns_return_t r = GETDNS_RETURN_GOOD; @@ -473,8 +473,8 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop, req->user_callback = callbackfn; req->internal_cb = internal_cb; - if (dnsreq_p) - *dnsreq_p = req; + if (return_netreq_p) + *return_netreq_p = req->netreqs[0]; _getdns_context_track_outbound_request(req); @@ -523,12 +523,12 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop, getdns_return_t _getdns_general_loop(getdns_context *context, getdns_eventloop *loop, const char *name, uint16_t request_type, getdns_dict *extensions, - void *userarg, getdns_dns_req **dnsreq_p, + void *userarg, getdns_network_req **netreq_p, getdns_callback_t callback, internal_cb_t internal_cb) { return getdns_general_ns(context, loop, name, request_type, extensions, - userarg, dnsreq_p, callback, internal_cb, 0); + userarg, netreq_p, callback, internal_cb, 0); } /* getdns_general_loop */ @@ -540,7 +540,7 @@ _getdns_address_loop(getdns_context *context, getdns_eventloop *loop, getdns_dict *my_extensions = extensions; getdns_return_t r; uint32_t value; - getdns_dns_req *dnsreq = NULL; + getdns_network_req *netreq = NULL; if (!my_extensions) { if (!(my_extensions=getdns_dict_create_with_context(context))) @@ -556,9 +556,9 @@ _getdns_address_loop(getdns_context *context, getdns_eventloop *loop, r = getdns_general_ns(context, loop, name, GETDNS_RRTYPE_AAAA, my_extensions, - userarg, &dnsreq, callback, NULL, 1); - if (dnsreq && transaction_id) - *transaction_id = dnsreq->trans_id; + userarg, &netreq, callback, NULL, 1); + if (netreq && transaction_id) + *transaction_id = netreq->owner->trans_id; if (my_extensions != extensions) getdns_dict_destroy(my_extensions); @@ -576,7 +576,7 @@ _getdns_hostname_loop(getdns_context *context, getdns_eventloop *loop, uint16_t req_type; char name[1024]; getdns_return_t retval; - getdns_dns_req *dnsreq = NULL; + getdns_network_req *netreq= NULL; if ((retval = getdns_dict_get_bindata(address, "address_data", @@ -650,9 +650,9 @@ _getdns_hostname_loop(getdns_context *context, getdns_eventloop *loop, return GETDNS_RETURN_INVALID_PARAMETER; } retval = _getdns_general_loop(context, loop, name, req_type, - extensions, userarg, &dnsreq, callback, NULL); - if (dnsreq && transaction_id) - *transaction_id = dnsreq->trans_id; + extensions, userarg, &netreq, callback, NULL); + if (netreq && transaction_id) + *transaction_id = netreq->owner->trans_id; return retval; } /* getdns_hostname_loop */ @@ -662,11 +662,11 @@ _getdns_service_loop(getdns_context *context, getdns_eventloop *loop, getdns_transaction_t * transaction_id, getdns_callback_t callback) { getdns_return_t r; - getdns_dns_req *dnsreq = NULL; + getdns_network_req *netreq = NULL; r = getdns_general_ns(context, loop, name, GETDNS_RRTYPE_SRV, - extensions, userarg, &dnsreq, callback, NULL, 1); - if (dnsreq && transaction_id) - *transaction_id = dnsreq->trans_id; + extensions, userarg, &netreq, callback, NULL, 1); + if (netreq && transaction_id) + *transaction_id = netreq->owner->trans_id; return r; } /* getdns_service_loop */ @@ -680,14 +680,14 @@ getdns_general(getdns_context *context, getdns_callback_t callback) { getdns_return_t r; - getdns_dns_req *dnsreq = NULL; + getdns_network_req *netreq = NULL; if (!context) return GETDNS_RETURN_INVALID_PARAMETER; r = _getdns_general_loop(context, context->extension, name, request_type, extensions, - userarg, &dnsreq, callback, NULL); - if (dnsreq && transaction_id) - *transaction_id = dnsreq->trans_id; + userarg, &netreq, callback, NULL); + if (netreq && transaction_id) + *transaction_id = netreq->owner->trans_id; return r; } /* getdns_general */ diff --git a/src/general.h b/src/general.h index 58201056..e9a4529e 100644 --- a/src/general.h +++ b/src/general.h @@ -50,7 +50,7 @@ getdns_return_t _getdns_submit_netreq(getdns_network_req *netreq); getdns_return_t _getdns_general_loop(getdns_context *context, getdns_eventloop *loop, const char *name, uint16_t request_type, getdns_dict *extensions, - void *userarg, getdns_dns_req **dnsreq, + void *userarg, getdns_network_req **netreq_p, getdns_callback_t callbackfn, internal_cb_t internal_cb); getdns_return_t From 7fe2d5b346dbda319d04c0aad345ca254529d9ca Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 20 Jan 2016 15:16:03 +0100 Subject: [PATCH 14/23] Linking order matters on Windows --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index df56589c..c63cacac 100644 --- a/configure.ac +++ b/configure.ac @@ -528,7 +528,7 @@ then AC_MSG_NOTICE([Checking for dependency libunbound]) AC_CHECK_LIB([unbound], [ub_fd], [ AC_DEFINE_UNQUOTED([HAVE_LIBUNBOUND], [1], [Define to 1 if you have the `unbound' library (-lunbound).]) - LIBS="$LIBS -lunbound" + LIBS="-lunbound $LIBS" AC_CHECK_HEADER([unbound-event.h],[ AC_CHECK_FUNC([ub_event_get_version], [ AC_DEFINE_UNQUOTED([HAVE_UNBOUND_EVENT_API], [1], [Define this when libunbound is compiled with the --enable-event-api option.]) From a0896ac4bfdd5f3433b37ccf282e205ba05ba283 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Thu, 4 Feb 2016 15:25:01 +0100 Subject: [PATCH 15/23] Rearange link lib order for mingw --- configure.ac | 9 +++++---- m4/acx_openssl.m4 | 8 ++++---- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/configure.ac b/configure.ac index c63cacac..21f5a32a 100644 --- a/configure.ac +++ b/configure.ac @@ -201,6 +201,11 @@ case "$enable_native_stub_dnssec" in ;; esac +# search to set include and library paths right +# find libidn (no libidn on windows though) +AC_CHECK_HEADERS([windows.h winsock.h stdio.h winsock2.h ws2tcpip.h],,, [AC_INCLUDES_DEFAULT]) +ACX_CHECK_GETADDRINFO_WITH_INCLUDES + USE_NSS="no" # openssl if test $USE_NSS = "no"; then @@ -444,10 +449,6 @@ case "$enable_stub_only" in ;; esac -# search to set include and library paths right -# find libidn (no libidn on windows though) -AC_CHECK_HEADERS([windows.h winsock.h stdio.h winsock2.h ws2tcpip.h],,, [AC_INCLUDES_DEFAULT]) -ACX_CHECK_GETADDRINFO_WITH_INCLUDES if test "$USE_WINSOCK" = 1; then AC_MSG_NOTICE([ Building on Windows ... YES! ]) AC_DEFINE_UNQUOTED([GETDNS_ON_WINDOWS], [1], [Define this to enable Windows build.]) diff --git a/m4/acx_openssl.m4 b/m4/acx_openssl.m4 index 0b2885f7..485f6599 100644 --- a/m4/acx_openssl.m4 +++ b/m4/acx_openssl.m4 @@ -48,8 +48,8 @@ AC_DEFUN([ACX_SSL_CHECKS], [ fi AC_MSG_CHECKING([for HMAC_CTX_init in -lcrypto]) - LIBS="$LIBS -lssl -lcrypto" - LIBSSL_LIBS="$LIBSSL_LIBS -lssl -lcrypto" + LIBS="-lssl -lcrypto $LIBS" + LIBSSL_LIBS="-lssl -lcrypto $LIBSSL_LIBS" AC_TRY_LINK(, [ int HMAC_CTX_init(void); (void)HMAC_CTX_init(); @@ -101,11 +101,11 @@ AC_CHECK_HEADERS([openssl/err.h],,, [AC_INCLUDES_DEFAULT]) AC_CHECK_HEADERS([openssl/rand.h],,, [AC_INCLUDES_DEFAULT]) dnl TLS v1.2 requires OpenSSL 1.0.1 -AC_CHECK_LIB(ssl, TLSv1_2_client_method,AC_DEFINE([HAVE_TLS_v1_2], [1], +AC_CHECK_FUNC(TLSv1_2_client_method,AC_DEFINE([HAVE_TLS_v1_2], [1], [Define if you have libssl with tls 1.2]),[AC_MSG_WARN([Cannot find TLSv1_2_client_method in libssl library. TLS will not be available.])]) dnl Native OpenSSL hostname verification requires OpenSSL 1.0.2 -AC_CHECK_LIB(ssl, SSL_CTX_get0_param,AC_DEFINE([HAVE_SSL_HN_AUTH], [1], +AC_CHECK_FUNC(SSL_CTX_get0_param,AC_DEFINE([HAVE_SSL_HN_AUTH], [1], [Define if you have libssl with host name verification]),[AC_MSG_WARN([Cannot find SSL_CTX_get0_param in libssl library. TLS hostname verification will not be available.])]) ]) From 4230961e9fd92d558be6629d3f84f783a5e7a93e Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Tue, 1 Mar 2016 16:29:37 +0100 Subject: [PATCH 16/23] Basic usage of unbound pluggable event loop --- configure.ac | 17 +- spec/example/Makefile.in | 24 +-- src/Makefile.in | 219 +++++++++++-------------- src/context.c | 24 +-- src/context.h | 4 +- src/general.c | 8 +- src/test/Makefile.in | 96 ++++------- src/ub_loop.c | 341 +++++++++++++++++++++++++++++++++++++++ src/ub_loop.h | 70 ++++++++ 9 files changed, 581 insertions(+), 222 deletions(-) create mode 100644 src/ub_loop.c create mode 100644 src/ub_loop.h diff --git a/configure.ac b/configure.ac index 21f5a32a..1d4d24db 100644 --- a/configure.ac +++ b/configure.ac @@ -526,15 +526,14 @@ fi if test $my_with_libunbound = 1 then + AC_CHECK_HEADERS([unbound-event.h],,, [AC_INCLUDES_DEFAULT]) AC_MSG_NOTICE([Checking for dependency libunbound]) AC_CHECK_LIB([unbound], [ub_fd], [ AC_DEFINE_UNQUOTED([HAVE_LIBUNBOUND], [1], [Define to 1 if you have the `unbound' library (-lunbound).]) LIBS="-lunbound $LIBS" - AC_CHECK_HEADER([unbound-event.h],[ - AC_CHECK_FUNC([ub_event_get_version], [ - AC_DEFINE_UNQUOTED([HAVE_UNBOUND_EVENT_API], [1], [Define this when libunbound is compiled with the --enable-event-api option.]) - ]) - ],,[AC_INCLUDES_DEFAULT]) + AC_CHECK_FUNC([ub_ctx_create_ub_event], [ + AC_DEFINE_UNQUOTED([HAVE_UNBOUND_EVENT_API], [1], [Define this when libunbound is compiled with the --enable-event-api option.]) + ]) ], [found_all_libs=0]) fi @@ -1202,8 +1201,14 @@ const char *inet_ntop(int af, const void *src, char *dst, size_t size); #ifdef HAVE_LIBUNBOUND # include -# ifdef HAVE_UNBOUND_EVENT_API +# ifdef HAVE_UNBOUND_EVENT_H # include +# else +struct ub_event_base; +struct ub_ctx* ub_ctx_create_ub_event(struct ub_event_base* base); +typedef void (*ub_event_callback_t)(void*, int, void*, int, int, char*); +int ub_resolve_event(struct ub_ctx* ctx, const char* name, int rrtype, + int rrclass, void* mydata, ub_event_callback_t callback, int* async_id); # endif #endif ]) 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 f51a0ab4..ad04c7f6 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -65,7 +65,7 @@ C99COMPATFLAGS=@C99COMPATFLAGS@ 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 stub.lo sync.lo util-internal.lo + rr-iter.lo stub.lo sync.lo ub_loop.lo util-internal.lo GLDNS_OBJ=keyraw.lo gbuffer.lo wire2str.lo parse.lo parseutil.lo rrdef.lo \ str2wire.lo @@ -225,136 +225,107 @@ 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)/util-internal.h $(srcdir)/rr-iter.h \ - $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.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 \ +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 getdns/getdns_extra.h $(srcdir)/ub_loop.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)/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)/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)/dict.h $(srcdir)/list.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)/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)/util-internal.h $(srcdir)/rr-iter.h \ - $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.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)/gldns/wire2str.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.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)/stub.h \ - $(srcdir)/dict.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)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ - $(srcdir)/gldns/pkthdr.h $(srcdir)/list.h $(srcdir)/dict.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 -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)/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)/debug.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)/rr-iter.h $(srcdir)/gldns/pkthdr.h \ - $(srcdir)/dict.h -rr-iter.lo rr-iter.o: $(srcdir)/rr-iter.c $(srcdir)/rr-iter.h \ - getdns/getdns.h $(srcdir)/rr-dict.h \ - config.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ - $(srcdir)/gldns/rrdef.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)/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)/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)/stub.h \ - $(srcdir)/gldns/wire2str.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)/rr-iter.h \ - $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h -gbuffer.lo gbuffer.o: $(srcdir)/gldns/gbuffer.c config.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)/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)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ + $(srcdir)/dnssec.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)/gldns/wire2str.h \ + $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h \ + $(srcdir)/ub_loop.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)/stub.h $(srcdir)/dict.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)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/list.h $(srcdir)/dict.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 +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)/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)/debug.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)/rr-iter.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dict.h +rr-iter.lo rr-iter.o: $(srcdir)/rr-iter.c $(srcdir)/rr-iter.h getdns/getdns.h $(srcdir)/rr-dict.h config.h \ + $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.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)/util-internal.h $(srcdir)/general.h $(srcdir)/pubkey-pinning.h +sync.lo sync.o: $(srcdir)/sync.c config.h getdns/getdns.h getdns/getdns_extra.h \ + getdns/getdns.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 +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)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ + $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/str2wire.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 +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 +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 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 +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 default_eventloop.lo default_eventloop.o: $(srcdir)/extension/default_eventloop.c \ - $(srcdir)/extension/default_eventloop.h config.h \ - getdns/getdns.h \ - getdns/getdns_extra.h $(srcdir)/debug.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 + $(srcdir)/extension/default_eventloop.h config.h getdns/getdns.h \ + getdns/getdns_extra.h $(srcdir)/debug.h config.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 diff --git a/src/context.c b/src/context.c index 342ac485..784a966f 100644 --- a/src/context.c +++ b/src/context.c @@ -63,6 +63,9 @@ typedef unsigned short in_port_t; #include #include "config.h" +#ifdef HAVE_LIBUNBOUND +#include +#endif #include "debug.h" #include "gldns/str2wire.h" #include "gldns/wire2str.h" @@ -1372,7 +1375,7 @@ getdns_context_request_count_changed(getdns_context *context) &context->ub_event, context->ub_event.ev); #ifndef USE_WINSOCK #ifdef HAVE_UNBOUND_EVENT_API - if (!context->unbound_event_api) + if (!_getdns_ub_loop_enabled(&context->ub_loop)) #endif context->extension->vmt->schedule( context->extension, ub_fd(context->unbound_ctx), @@ -1386,7 +1389,7 @@ getdns_context_request_count_changed(getdns_context *context) #ifndef USE_WINSOCK #ifdef HAVE_UNBOUND_EVENT_API - if (!context->unbound_event_api) + if (!_getdns_ub_loop_enabled(&context->ub_loop)) #endif context->extension->vmt->clear( context->extension, &context->ub_event); @@ -1421,10 +1424,9 @@ rebuild_ub_ctx(struct getdns_context* context) { } /* setup */ #ifdef HAVE_UNBOUND_EVENT_API - context->unbound_event_api = - strncmp(ub_event_get_version(), "getdns-event", 12) == 0; - if (context->unbound_event_api) { - context->unbound_ctx = ub_ctx_create_event((void *)context->extension); + _getdns_ub_loop_init(&context->ub_loop, &context->mf, context->extension); + if (_getdns_ub_loop_enabled(&context->ub_loop)) { + context->unbound_ctx = ub_ctx_create_ub_event(&context->ub_loop.super); } else { #endif context->unbound_ctx = ub_ctx_create(); @@ -3006,9 +3008,8 @@ getdns_context_detach_eventloop(struct getdns_context* context) context->extension = &context->default_eventloop.loop; _getdns_default_eventloop_init(&context->default_eventloop); #ifdef HAVE_UNBOUND_EVENT_API - if (context->unbound_event_api) - (void) ub_ctx_set_event( - context->unbound_ctx, (void *)context->extension); + if (_getdns_ub_loop_enabled(&context->ub_loop)) + context->ub_loop.extension = context->extension; #endif return GETDNS_RETURN_GOOD; } @@ -3025,9 +3026,8 @@ getdns_context_set_eventloop(getdns_context* context, getdns_eventloop* loop) } context->extension = loop; #ifdef HAVE_UNBOUND_EVENT_API - if (context->unbound_event_api) - (void) ub_ctx_set_event( - context->unbound_ctx, (void *)context->extension); + if (_getdns_ub_loop_enabled(&context->ub_loop)) + context->ub_loop.extension = loop; #endif return GETDNS_RETURN_GOOD; } diff --git a/src/context.h b/src/context.h index 2ba134f9..d3bff070 100644 --- a/src/context.h +++ b/src/context.h @@ -43,6 +43,7 @@ #include "types-internal.h" #include "extension/default_eventloop.h" #include "util/rbtree.h" +#include "ub_loop.h" struct getdns_dns_req; struct ub_ctx; @@ -221,10 +222,9 @@ struct getdns_context { struct ub_ctx *unbound_ctx; int unbound_ta_set; #ifdef HAVE_UNBOUND_EVENT_API - int unbound_event_api; + _getdns_ub_loop ub_loop; #endif #endif - /* A tree to hold local host information*/ _getdns_rbtree_t local_hosts; diff --git a/src/general.c b/src/general.c index 43cd8724..f5f1abf1 100644 --- a/src/general.c +++ b/src/general.c @@ -39,6 +39,12 @@ #include #include "config.h" #include "general.h" +#ifdef HAVE_LIBUNBOUND +#include +#endif +#ifdef HAVE_UNBOUND_EVENT_API +#include "ub_loop.h" +#endif #include "gldns/wire2str.h" #include "context.h" #include "types-internal.h" @@ -342,7 +348,7 @@ _getdns_submit_netreq(getdns_network_req *netreq) #ifdef HAVE_LIBUNBOUND #ifdef HAVE_UNBOUND_EVENT_API - if (dns_req->context->unbound_event_api) + if (_getdns_ub_loop_enabled(&dns_req->context->ub_loop)) return ub_resolve_event(dns_req->context->unbound_ctx, name, netreq->request_type, netreq->owner->request_class, netreq, ub_resolve_event_callback, &(netreq->unbound_id)) ? diff --git a/src/test/Makefile.in b/src/test/Makefile.in index b2c6c22d..016b9e22 100644 --- a/src/test/Makefile.in +++ b/src/test/Makefile.in @@ -232,24 +232,21 @@ 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_general.h $(srcdir)/check_getdns_general_sync.h \ - $(srcdir)/check_getdns_address.h $(srcdir)/check_getdns_address_sync.h \ - $(srcdir)/check_getdns_hostname.h $(srcdir)/check_getdns_hostname_sync.h \ - $(srcdir)/check_getdns_context_create.h $(srcdir)/check_getdns_context_destroy.h \ - $(srcdir)/check_getdns_cancel_callback.h $(srcdir)/check_getdns_list_get_length.h \ - $(srcdir)/check_getdns_list_get_data_type.h $(srcdir)/check_getdns_list_get_dict.h \ - $(srcdir)/check_getdns_list_get_list.h $(srcdir)/check_getdns_list_get_int.h \ - $(srcdir)/check_getdns_list_get_bindata.h $(srcdir)/check_getdns_dict_get_names.h \ - $(srcdir)/check_getdns_dict_get_data_type.h $(srcdir)/check_getdns_dict_get_dict.h \ - $(srcdir)/check_getdns_dict_get_list.h $(srcdir)/check_getdns_dict_get_bindata.h \ - $(srcdir)/check_getdns_dict_get_int.h $(srcdir)/check_getdns_dict_destroy.h \ - $(srcdir)/check_getdns_dict_set_dict.h $(srcdir)/check_getdns_dict_set_list.h \ - $(srcdir)/check_getdns_dict_set_bindata.h $(srcdir)/check_getdns_dict_set_int.h \ - $(srcdir)/check_getdns_convert_ulabel_to_alabel.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_general.h \ + $(srcdir)/check_getdns_general_sync.h $(srcdir)/check_getdns_address.h \ + $(srcdir)/check_getdns_address_sync.h $(srcdir)/check_getdns_hostname.h \ + $(srcdir)/check_getdns_hostname_sync.h $(srcdir)/check_getdns_context_create.h \ + $(srcdir)/check_getdns_context_destroy.h $(srcdir)/check_getdns_cancel_callback.h \ + $(srcdir)/check_getdns_list_get_length.h $(srcdir)/check_getdns_list_get_data_type.h \ + $(srcdir)/check_getdns_list_get_dict.h $(srcdir)/check_getdns_list_get_list.h \ + $(srcdir)/check_getdns_list_get_int.h $(srcdir)/check_getdns_list_get_bindata.h \ + $(srcdir)/check_getdns_dict_get_names.h $(srcdir)/check_getdns_dict_get_data_type.h \ + $(srcdir)/check_getdns_dict_get_dict.h $(srcdir)/check_getdns_dict_get_list.h \ + $(srcdir)/check_getdns_dict_get_bindata.h $(srcdir)/check_getdns_dict_get_int.h \ + $(srcdir)/check_getdns_dict_destroy.h $(srcdir)/check_getdns_dict_set_dict.h \ + $(srcdir)/check_getdns_dict_set_list.h $(srcdir)/check_getdns_dict_set_bindata.h \ + $(srcdir)/check_getdns_dict_set_int.h $(srcdir)/check_getdns_convert_ulabel_to_alabel.h \ $(srcdir)/check_getdns_convert_alabel_to_ulabel.h $(srcdir)/check_getdns_pretty_print_dict.h \ $(srcdir)/check_getdns_display_ip_address.h \ $(srcdir)/check_getdns_context_set_context_update_callback.h \ @@ -257,59 +254,36 @@ check_getdns.lo check_getdns.o: $(srcdir)/check_getdns.c \ $(srcdir)/check_getdns_context_set_upstream_recursive_servers.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 -getdns_query.lo getdns_query.o: $(srcdir)/getdns_query.c \ - ../config.h $(srcdir)/../debug.h \ - ../getdns/getdns.h \ - ../getdns/getdns_extra.h -scratchpad.template.lo scratchpad.template.o: scratchpad.template.c \ - ../getdns/getdns.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 +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/ub_loop.c b/src/ub_loop.c new file mode 100644 index 00000000..ee02986a --- /dev/null +++ b/src/ub_loop.c @@ -0,0 +1,341 @@ +/** + * + * \file ub_loop.c + * @brief Interface to the unbound pluggable event API + * + * These routines are not intended to be used by applications calling into + * the library. + * + */ + +/* + * 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 "ub_loop.h" +#ifdef HAVE_UNBOUND_EVENT_API + +#ifndef HAVE_UNBOUND_EVENT_H +/** event timeout */ +#define UB_EV_TIMEOUT 0x01 +/** event fd readable */ +#define UB_EV_READ 0x02 +/** event fd writable */ +#define UB_EV_WRITE 0x04 +/** event signal */ +#define UB_EV_SIGNAL 0x08 +/** event must persist */ +#define UB_EV_PERSIST 0x10 + +struct ub_event_base_vmt { + void (*event_base_free)(struct ub_event_base*); + int (*event_base_dispatch)(struct ub_event_base*); + int (*event_base_loopexit)(struct ub_event_base*, struct timeval*); + struct ub_event* (*event_new)(struct ub_event_base*, + int fd, short bits, void (*cb)(int, short, void*), void* arg); + struct ub_event* (*signal_new)(struct ub_event_base*, int fd, + void (*cb)(int, short, void*), void* arg); + struct ub_event* (*winsock_register_wsaevent)(struct ub_event_base*, + void* wsaevent, void (*cb)(int, short, void*), void* arg); +}; + +struct ub_event_vmt { + void (*event_add_bits)(struct ub_event*, short); + void (*event_del_bits)(struct ub_event*, short); + void (*event_set_fd)(struct ub_event*, int); + void (*event_free)(struct ub_event*); + int (*event_add)(struct ub_event*, struct timeval*); + int (*event_del)(struct ub_event*); + int (*timer_add)(struct ub_event*, struct ub_event_base*, + void (*cb)(int, short, void*), void* arg, struct timeval*); + int (*timer_del)(struct ub_event*); + int (*signal_add)(struct ub_event*, struct timeval*); + int (*signal_del)(struct ub_event*); + void (*winsock_unregister_wsaevent)(struct ub_event* ev); + void (*winsock_tcp_wouldblock)(struct ub_event*, int eventbit); +}; + +struct ub_event { + struct ub_event_vmt* vmt; +}; +#endif + +typedef struct my_event { + struct ub_event super; + /** event in the getdns event loop */ + getdns_eventloop_event gev; + /** is event already added */ + int added; + + /** event loop it belongs to */ + _getdns_ub_loop *loop; + /** fd to poll or -1 for timeouts. signal number for sigs. */ + int fd; + /** what events this event is interested in, see EV_.. above. */ + short bits; + /** timeout value */ + uint64_t timeout; + /** callback to call: fd, eventbits, userarg */ + void (*cb)(int, short, void *arg); + /** callback user arg */ + void *arg; +} my_event; + +#define AS_UB_LOOP(x) \ + (((union {struct ub_event_base* a; _getdns_ub_loop* b;})x).b) +#define AS_MY_EVENT(x) \ + (((union {struct ub_event* a; my_event* b;})x).b) + +static void my_event_base_free(struct ub_event_base* base) +{ + (void)base; + return; +} + +static int my_event_base_dispatch(struct ub_event_base* base) +{ + (void)base; + /* We don't run the pluggable event base ourselfs */ + return -1; +} + +static int my_event_base_loopexit(struct ub_event_base* base, struct timeval* tv) +{ + (void)tv; + AS_UB_LOOP(base)->running = 0; + return 0; +} + +#define CLEAR_MY_EVENT(ev) \ + do { (ev)->loop->extension->vmt->clear((ev)->loop->extension, \ + &(ev)->gev); (ev)->added = 0; } while(0) + +#define SCHEDULE_MY_EVENT(ev) \ + do { if ((ev)->gev.read_cb||(ev)->gev.write_cb||(ev)->gev.timeout_cb){\ + (ev)->loop->extension->vmt->schedule((ev)->loop->extension, \ + (ev)->fd, (uint64_t)-1, &(ev)->gev); (ev)->added=1; }}while(0) + +static void read_cb(void *userarg) +{ + struct my_event *ev = (struct my_event *)userarg; + (*ev->cb)(ev->fd, UB_EV_READ, ev->arg); + if ((ev->bits & UB_EV_PERSIST) == 0) + CLEAR_MY_EVENT(ev); +} + +static void write_cb(void *userarg) +{ + struct my_event *ev = (struct my_event *)userarg; + (*ev->cb)(ev->fd, UB_EV_WRITE, ev->arg); + if ((ev->bits & UB_EV_PERSIST) == 0) + CLEAR_MY_EVENT(ev); +} + +static void timeout_cb(void *userarg) +{ + struct my_event *ev = (struct my_event *)userarg; + (*ev->cb)(ev->fd, UB_EV_TIMEOUT, ev->arg); + if ((ev->bits & UB_EV_PERSIST) == 0) + CLEAR_MY_EVENT(ev); +} + +static void set_gev_callbacks(my_event* ev, short bits) +{ + int added = ev->added; + + if (ev->bits != bits) { + if (added) + CLEAR_MY_EVENT(ev); + + ev->gev.read_cb = bits & UB_EV_READ ? read_cb : NULL; + ev->gev.write_cb = bits & UB_EV_WRITE ? write_cb : NULL; + ev->gev.timeout_cb = bits & UB_EV_TIMEOUT ? timeout_cb : NULL; + ev->bits = bits; + + if (added) + SCHEDULE_MY_EVENT(ev); + } +} + +static void my_event_add_bits(struct ub_event* ev, short bits) +{ + set_gev_callbacks(AS_MY_EVENT(ev), AS_MY_EVENT(ev)->bits | bits); +} + +static void my_event_del_bits(struct ub_event* ev, short bits) +{ + set_gev_callbacks(AS_MY_EVENT(ev), AS_MY_EVENT(ev)->bits & ~bits); +} + +static void my_event_set_fd(struct ub_event* ub_ev, int fd) +{ + my_event *ev = AS_MY_EVENT(ub_ev); + + if (ev->fd != fd) { + if (ev->added) { + CLEAR_MY_EVENT(ev); + ev->fd = fd; + SCHEDULE_MY_EVENT(ev); + } else + ev->fd = fd; + } +} + +static void my_event_free(struct ub_event* ev) +{ + GETDNS_FREE(AS_MY_EVENT(ev)->loop->mf, ev); +} + +static int my_event_del(struct ub_event* ev) +{ + if (AS_MY_EVENT(ev)->added) + CLEAR_MY_EVENT(AS_MY_EVENT(ev)); + return 0; +} + +static int my_event_add(struct ub_event* ev, struct timeval* tv) +{ + if (AS_MY_EVENT(ev)->added) + my_event_del(ev); + if (tv && (AS_MY_EVENT(ev)->bits & UB_EV_TIMEOUT) != 0) + AS_MY_EVENT(ev)->timeout = (tv->tv_sec * 1000) + (tv->tv_usec / 1000); + SCHEDULE_MY_EVENT(AS_MY_EVENT(ev)); + return 0; +} + +static int my_timer_add(struct ub_event* ub_ev, struct ub_event_base* base, + void (*cb)(int, short, void*), void* arg, struct timeval* tv) +{ + my_event *ev = AS_MY_EVENT(ub_ev); + + if (!base || !cb || !tv || AS_UB_LOOP(base) != ev->loop) + return -1; + + if (ev->added) + CLEAR_MY_EVENT(ev); + + ev->cb = cb; + ev->arg = arg; + return my_event_add(ub_ev, tv); +} + +static int my_timer_del(struct ub_event* ev) +{ + return my_event_del(ev); +} + + +static int my_signal_add(struct ub_event* ub_ev, struct timeval* tv) +{ + return -1; +} + +static int my_signal_del(struct ub_event* ub_ev) +{ + return -1; +} + +static void my_winsock_unregister_wsaevent(struct ub_event* ev) +{ + (void)ev; +} + +static void my_winsock_tcp_wouldblock(struct ub_event* ev, int bits) +{ + (void)ev; (void)bits; +} + +static struct ub_event* my_event_new(struct ub_event_base* base, int fd, + short bits, void (*cb)(int, short, void*), void* arg) +{ + static struct ub_event_vmt vmt = { + my_event_add_bits, + my_event_del_bits, + my_event_set_fd, + my_event_free, + my_event_add, + my_event_del, + my_timer_add, + my_timer_del, + my_signal_add, + my_signal_del, + my_winsock_unregister_wsaevent, + my_winsock_tcp_wouldblock + }; + my_event *ev; + + if (!base || !cb) + return NULL; + + ev = GETDNS_MALLOC(AS_UB_LOOP(base)->mf, my_event); + ev->super.vmt = &vmt; + ev->loop = AS_UB_LOOP(base); + ev->added = 0; + ev->fd = fd; + ev->bits = bits; + ev->timeout = (uint64_t)-1; + ev->cb = cb; + ev->arg = arg; + ev->gev.userarg = ev; + ev->gev.read_cb = bits & UB_EV_READ ? read_cb : NULL; + ev->gev.write_cb = bits & UB_EV_WRITE ? write_cb : NULL; + ev->gev.timeout_cb = bits & UB_EV_TIMEOUT ? timeout_cb : NULL; + return &ev->super; +} + +static struct ub_event* my_signal_new(struct ub_event_base* base, int fd, + void (*cb)(int, short, void*), void* arg) +{ + return my_event_new(base, fd, UB_EV_SIGNAL | UB_EV_PERSIST, cb, arg); +} + +static struct ub_event* my_winsock_register_wsaevent(struct ub_event_base *b, + void* wsaevent, void (*cb)(int, short, void*), void* arg) +{ + /* Not applicable, because in unbound used for tubes only */ + (void)b; (void)wsaevent; (void)cb; (void)arg; + return NULL; +} + +void _getdns_ub_loop_init(_getdns_ub_loop *loop, struct mem_funcs *mf, getdns_eventloop *extension) +{ + static struct ub_event_base_vmt vmt = { + my_event_base_free, + my_event_base_dispatch, + my_event_base_loopexit, + my_event_new, + my_signal_new, + my_winsock_register_wsaevent + }; + + loop->super.vmt = &vmt; + loop->mf = *mf; + loop->extension = extension; + loop->running = 1; +} + +#endif +/* ub_loop.c */ diff --git a/src/ub_loop.h b/src/ub_loop.h new file mode 100644 index 00000000..abc2e773 --- /dev/null +++ b/src/ub_loop.h @@ -0,0 +1,70 @@ +/** + * + * \file ub_loop.h + * /brief Interface for the pluggable unbound event API + * + */ + +/* + * Copyright (c) 2015, 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 UB_LOOP_H +#define UB_LOOP_H + +#include "config.h" +#ifdef HAVE_UNBOUND_EVENT_API +#include "getdns/getdns.h" +#include "getdns/getdns_extra.h" +#include "types-internal.h" + +#ifndef HAVE_UNBOUND_EVENT_H +struct ub_event_base_vmt; +struct ub_event_base { + struct ub_event_base_vmt* vmt; +}; +struct ub_event_base; +struct ub_ctx* ub_ctx_create_ub_event(struct ub_event_base* base); +typedef void (*ub_event_callback_t)(void*, int, void*, int, int, char*); +int ub_resolve_event(struct ub_ctx* ctx, const char* name, int rrtype, + int rrclass, void* mydata, ub_event_callback_t callback, int* async_id); +#endif + +typedef struct _getdns_ub_loop { + struct ub_event_base super; + struct mem_funcs mf; + getdns_eventloop *extension; + int running; +} _getdns_ub_loop; + +void _getdns_ub_loop_init(_getdns_ub_loop *loop, struct mem_funcs *mf, getdns_eventloop *extension); + +inline static int _getdns_ub_loop_enabled(_getdns_ub_loop *loop) +{ return loop->super.vmt ? 1 : 0; } + +#endif /* HAVE_UNBOUND_EVENT_API */ +#endif +/* ub_loop.h */ From 8e4dd05379c4d3cff0c206f1abe9b7dbdc6fcdbf Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 2 Mar 2016 12:38:29 +0100 Subject: [PATCH 17/23] Anticipate magic number --- src/ub_loop.c | 36 +++++++++++++++++++++--------------- src/ub_loop.h | 1 + 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/ub_loop.c b/src/ub_loop.c index ee02986a..e2bdc8a4 100644 --- a/src/ub_loop.c +++ b/src/ub_loop.c @@ -38,6 +38,8 @@ #include "ub_loop.h" #ifdef HAVE_UNBOUND_EVENT_API +#define UB_EVENT_API_MAGIC 0x44d74d78 + #ifndef HAVE_UNBOUND_EVENT_H /** event timeout */ #define UB_EV_TIMEOUT 0x01 @@ -51,38 +53,40 @@ #define UB_EV_PERSIST 0x10 struct ub_event_base_vmt { - void (*event_base_free)(struct ub_event_base*); - int (*event_base_dispatch)(struct ub_event_base*); - int (*event_base_loopexit)(struct ub_event_base*, struct timeval*); - struct ub_event* (*event_new)(struct ub_event_base*, + void (*free)(struct ub_event_base*); + int (*dispatch)(struct ub_event_base*); + int (*loopexit)(struct ub_event_base*, struct timeval*); + struct ub_event* (*new_event)(struct ub_event_base*, int fd, short bits, void (*cb)(int, short, void*), void* arg); - struct ub_event* (*signal_new)(struct ub_event_base*, int fd, + struct ub_event* (*new_signal)(struct ub_event_base*, int fd, void (*cb)(int, short, void*), void* arg); struct ub_event* (*winsock_register_wsaevent)(struct ub_event_base*, void* wsaevent, void (*cb)(int, short, void*), void* arg); }; struct ub_event_vmt { - void (*event_add_bits)(struct ub_event*, short); - void (*event_del_bits)(struct ub_event*, short); - void (*event_set_fd)(struct ub_event*, int); - void (*event_free)(struct ub_event*); - int (*event_add)(struct ub_event*, struct timeval*); - int (*event_del)(struct ub_event*); - int (*timer_add)(struct ub_event*, struct ub_event_base*, + void (*add_bits)(struct ub_event*, short); + void (*del_bits)(struct ub_event*, short); + void (*set_fd)(struct ub_event*, int); + void (*free)(struct ub_event*); + int (*add)(struct ub_event*, struct timeval*); + int (*del)(struct ub_event*); + int (*add_timer)(struct ub_event*, struct ub_event_base*, void (*cb)(int, short, void*), void* arg, struct timeval*); - int (*timer_del)(struct ub_event*); - int (*signal_add)(struct ub_event*, struct timeval*); - int (*signal_del)(struct ub_event*); + int (*del_timer)(struct ub_event*); + int (*add_signal)(struct ub_event*, struct timeval*); + int (*del_signal)(struct ub_event*); void (*winsock_unregister_wsaevent)(struct ub_event* ev); void (*winsock_tcp_wouldblock)(struct ub_event*, int eventbit); }; struct ub_event { + unsigned long magic; struct ub_event_vmt* vmt; }; #endif + typedef struct my_event { struct ub_event super; /** event in the getdns event loop */ @@ -291,6 +295,7 @@ static struct ub_event* my_event_new(struct ub_event_base* base, int fd, return NULL; ev = GETDNS_MALLOC(AS_UB_LOOP(base)->mf, my_event); + ev->super.magic = UB_EVENT_API_MAGIC; ev->super.vmt = &vmt; ev->loop = AS_UB_LOOP(base); ev->added = 0; @@ -331,6 +336,7 @@ void _getdns_ub_loop_init(_getdns_ub_loop *loop, struct mem_funcs *mf, getdns_ev my_winsock_register_wsaevent }; + loop->super.magic = UB_EVENT_API_MAGIC; loop->super.vmt = &vmt; loop->mf = *mf; loop->extension = extension; diff --git a/src/ub_loop.h b/src/ub_loop.h index abc2e773..b9199e06 100644 --- a/src/ub_loop.h +++ b/src/ub_loop.h @@ -44,6 +44,7 @@ #ifndef HAVE_UNBOUND_EVENT_H struct ub_event_base_vmt; struct ub_event_base { + unsigned long magic; struct ub_event_base_vmt* vmt; }; struct ub_event_base; From 75ee40b98fb8b3bac03efbbb3fdf0c2f429affbc Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Fri, 4 Mar 2016 11:52:50 +0100 Subject: [PATCH 18/23] Small improvements for ub_loop's --- src/ub_loop.c | 41 ++++++++++++++++++++++++++++++----------- src/ub_loop.h | 4 +++- 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/src/ub_loop.c b/src/ub_loop.c index e2bdc8a4..49c57115 100644 --- a/src/ub_loop.c +++ b/src/ub_loop.c @@ -115,6 +115,7 @@ typedef struct my_event { static void my_event_base_free(struct ub_event_base* base) { + /* We don't allocate our event base, so no need to free */ (void)base; return; } @@ -122,13 +123,18 @@ static void my_event_base_free(struct ub_event_base* base) static int my_event_base_dispatch(struct ub_event_base* base) { (void)base; - /* We don't run the pluggable event base ourselfs */ + /* We run the event loop extension for which this ub_event_base is an + * interface ourselfs, so no need to let libunbound call dispatch. + */ return -1; } static int my_event_base_loopexit(struct ub_event_base* base, struct timeval* tv) { (void)tv; + /* Not sure when this will be called. But it is of no influence as we + * run the event loop ourself. + */ AS_UB_LOOP(base)->running = 0; return 0; } @@ -137,10 +143,18 @@ static int my_event_base_loopexit(struct ub_event_base* base, struct timeval* tv do { (ev)->loop->extension->vmt->clear((ev)->loop->extension, \ &(ev)->gev); (ev)->added = 0; } while(0) -#define SCHEDULE_MY_EVENT(ev) \ - do { if ((ev)->gev.read_cb||(ev)->gev.write_cb||(ev)->gev.timeout_cb){\ - (ev)->loop->extension->vmt->schedule((ev)->loop->extension, \ - (ev)->fd, (uint64_t)-1, &(ev)->gev); (ev)->added=1; }}while(0) +static inline getdns_return_t schedule_my_event(my_event *ev) +{ + getdns_return_t r; + + if (ev->gev.read_cb || ev->gev.write_cb || ev->gev.write_cb) { + if ((r = ev->loop->extension->vmt->schedule( + ev->loop->extension, ev->fd, ev->timeout, &ev->gev))) + return r; + ev->added = 1; + } + return GETDNS_RETURN_GOOD; +} static void read_cb(void *userarg) { @@ -166,7 +180,7 @@ static void timeout_cb(void *userarg) CLEAR_MY_EVENT(ev); } -static void set_gev_callbacks(my_event* ev, short bits) +static getdns_return_t set_gev_callbacks(my_event* ev, short bits) { int added = ev->added; @@ -180,18 +194,19 @@ static void set_gev_callbacks(my_event* ev, short bits) ev->bits = bits; if (added) - SCHEDULE_MY_EVENT(ev); + return schedule_my_event(ev); } + return GETDNS_RETURN_GOOD; } static void my_event_add_bits(struct ub_event* ev, short bits) { - set_gev_callbacks(AS_MY_EVENT(ev), AS_MY_EVENT(ev)->bits | bits); + (void) set_gev_callbacks(AS_MY_EVENT(ev), AS_MY_EVENT(ev)->bits | bits); } static void my_event_del_bits(struct ub_event* ev, short bits) { - set_gev_callbacks(AS_MY_EVENT(ev), AS_MY_EVENT(ev)->bits & ~bits); + (void) set_gev_callbacks(AS_MY_EVENT(ev), AS_MY_EVENT(ev)->bits & ~bits); } static void my_event_set_fd(struct ub_event* ub_ev, int fd) @@ -202,7 +217,7 @@ static void my_event_set_fd(struct ub_event* ub_ev, int fd) if (ev->added) { CLEAR_MY_EVENT(ev); ev->fd = fd; - SCHEDULE_MY_EVENT(ev); + (void) schedule_my_event(ev); } else ev->fd = fd; } @@ -226,7 +241,8 @@ static int my_event_add(struct ub_event* ev, struct timeval* tv) my_event_del(ev); if (tv && (AS_MY_EVENT(ev)->bits & UB_EV_TIMEOUT) != 0) AS_MY_EVENT(ev)->timeout = (tv->tv_sec * 1000) + (tv->tv_usec / 1000); - SCHEDULE_MY_EVENT(AS_MY_EVENT(ev)); + if (schedule_my_event(AS_MY_EVENT(ev))) + return -1; return 0; } @@ -254,16 +270,19 @@ static int my_timer_del(struct ub_event* ev) static int my_signal_add(struct ub_event* ub_ev, struct timeval* tv) { + /* Only unbound daaemon workers use signals */ return -1; } static int my_signal_del(struct ub_event* ub_ev) { + /* Only unbound daaemon workers use signals */ return -1; } static void my_winsock_unregister_wsaevent(struct ub_event* ev) { + /* wsa events don't get registered with libunbound */ (void)ev; } diff --git a/src/ub_loop.h b/src/ub_loop.h index b9199e06..cb816aec 100644 --- a/src/ub_loop.h +++ b/src/ub_loop.h @@ -41,7 +41,9 @@ #include "getdns/getdns_extra.h" #include "types-internal.h" -#ifndef HAVE_UNBOUND_EVENT_H +#ifdef HAVE_UNBOUND_EVENT_H +#include +#else struct ub_event_base_vmt; struct ub_event_base { unsigned long magic; From ebb892def1d14ac22895a64fd5f68fb9e1d345d6 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Fri, 4 Mar 2016 12:08:46 +0100 Subject: [PATCH 19/23] Revert "Run context's event loop when doing sync requests" This reverts commit d50860c0899ad0faa942380c23b3352cae071aef. --- src/sync.c | 176 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 130 insertions(+), 46 deletions(-) diff --git a/src/sync.c b/src/sync.c index 17fd8d28..dffff203 100644 --- a/src/sync.c +++ b/src/sync.c @@ -33,113 +33,197 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" +#include #include "getdns/getdns.h" -#include "getdns/getdns_extra.h" +#include "config.h" +#include "context.h" +#include "general.h" +#include "types-internal.h" +#include "util-internal.h" +#include "dnssec.h" +#include "stub.h" +#include "gldns/wire2str.h" -typedef struct getdns_sync_data { - int to_run; - getdns_callback_type_t callback_type; - getdns_dict *response; - getdns_transaction_t transaction_id; -} getdns_sync_data; +typedef struct getdns_sync_loop { + _getdns_default_eventloop loop; +#ifdef HAVE_LIBUNBOUND + getdns_eventloop_event ub_event; +#endif + getdns_context *context; + int to_run; + getdns_dict *response; +} getdns_sync_loop; + +static getdns_return_t +getdns_sync_loop_init(getdns_context *context, getdns_sync_loop *loop) +{ +#ifdef HAVE_LIBUNBOUND + getdns_eventloop *ext = &loop->loop.loop; +#endif + + loop->response = NULL; + loop->to_run = 1; + loop->context = context; + + _getdns_default_eventloop_init(&loop->loop); + +#if defined(HAVE_LIBUNBOUND) && !defined(USE_WINSOCK) + loop->ub_event.userarg = loop->context; + loop->ub_event.read_cb = _getdns_context_ub_read_cb; + loop->ub_event.write_cb = NULL; + loop->ub_event.timeout_cb = NULL; + loop->ub_event.ev = NULL; + +# ifdef HAVE_UNBOUND_EVENT_API + if (context->unbound_event_api) { + (void) ub_ctx_set_event(context->unbound_ctx, (void *)ext); + } else +# endif + return ext->vmt->schedule(ext, ub_fd(context->unbound_ctx), + TIMEOUT_FOREVER, &loop->ub_event); +#endif + return GETDNS_RETURN_GOOD; +} + +static void +getdns_sync_loop_cleanup(getdns_sync_loop *loop) +{ + getdns_eventloop *ext = &loop->loop.loop; + +#if defined(HAVE_LIBUNBOUND) && !defined(USE_WINSOCK) +# ifdef HAVE_UNBOUND_EVENT_API + if (loop->context->unbound_event_api) { + (void) ub_ctx_set_event(loop->context->unbound_ctx, + (void *)loop->context->extension); + } else +# endif + ext->vmt->clear(ext, &loop->ub_event); +#endif + ext->vmt->cleanup(ext); +} + +static void +getdns_sync_loop_run(getdns_sync_loop *loop) +{ + getdns_eventloop *ext = &loop->loop.loop; + + while (loop->to_run) + ext->vmt->run_once(ext, 1); + + getdns_sync_loop_cleanup(loop); +} static void getdns_sync_cb(getdns_context *context, getdns_callback_type_t callback_type, getdns_dict *response, void *userarg, getdns_transaction_t transaction_id) { - getdns_sync_data *data = (getdns_sync_data *)userarg; + getdns_sync_loop *loop = (getdns_sync_loop *)userarg; - assert(data); - assert(data->transaction_id == transaction_id); + assert(loop); - data->callback_type = callback_type; - data->response = response; - data->to_run = 0; -} - -static getdns_return_t -_getdns_sync_run( - getdns_context *context, getdns_sync_data *data, getdns_dict **response) -{ - data->to_run = 1; - data->callback_type = (getdns_callback_type_t)0; - data->response = NULL; - - while (data->to_run) - getdns_context_process_async(context); - - return (*response = data->response) ? - GETDNS_RETURN_GOOD : GETDNS_RETURN_GENERIC_ERROR; + loop->response = response; + loop->to_run = 0; } getdns_return_t getdns_general_sync(getdns_context *context, const char *name, uint16_t request_type, getdns_dict *extensions, getdns_dict **response) { - getdns_sync_data data; + getdns_sync_loop loop; getdns_return_t r; if (!context || !name || !response) return GETDNS_RETURN_INVALID_PARAMETER; - if ((r = getdns_general(context, name, request_type, - extensions, &data, &data.transaction_id, getdns_sync_cb))) + if ((r = getdns_sync_loop_init(context, &loop))) return r; - return _getdns_sync_run(context, &data, response); + if ((r = _getdns_general_loop(context, &loop.loop.loop, name, + request_type, extensions, &loop, NULL, getdns_sync_cb, NULL))) { + + getdns_sync_loop_cleanup(&loop); + return r; + } + getdns_sync_loop_run(&loop); + + return (*response = loop.response) ? + GETDNS_RETURN_GOOD : GETDNS_RETURN_GENERIC_ERROR; } getdns_return_t getdns_address_sync(getdns_context *context, const char *name, getdns_dict *extensions, getdns_dict **response) { - getdns_sync_data data; + getdns_sync_loop loop; getdns_return_t r; if (!context || !name || !response) return GETDNS_RETURN_INVALID_PARAMETER; - if ((r = getdns_address(context, name, - extensions, &data, &data.transaction_id, getdns_sync_cb))) + if ((r = getdns_sync_loop_init(context, &loop))) return r; - return _getdns_sync_run(context, &data, response); + if ((r = _getdns_address_loop(context, &loop.loop.loop, name, + extensions, &loop, NULL, getdns_sync_cb))) { + + getdns_sync_loop_cleanup(&loop); + return r; + } + getdns_sync_loop_run(&loop); + + return (*response = loop.response) ? + GETDNS_RETURN_GOOD : GETDNS_RETURN_GENERIC_ERROR; } getdns_return_t getdns_hostname_sync(getdns_context *context, getdns_dict *address, getdns_dict *extensions, getdns_dict **response) { - getdns_sync_data data; + getdns_sync_loop loop; getdns_return_t r; - if (!context || !address|| !response) + if (!context || !address || !response) return GETDNS_RETURN_INVALID_PARAMETER; - if ((r = getdns_hostname(context, address, - extensions, &data, &data.transaction_id, getdns_sync_cb))) + if ((r = getdns_sync_loop_init(context, &loop))) return r; - return _getdns_sync_run(context, &data, response); + if ((r = _getdns_hostname_loop(context, &loop.loop.loop, address, + extensions, &loop, NULL, getdns_sync_cb))) { + + getdns_sync_loop_cleanup(&loop); + return r; + } + getdns_sync_loop_run(&loop); + + return (*response = loop.response) ? + GETDNS_RETURN_GOOD : GETDNS_RETURN_GENERIC_ERROR; } getdns_return_t getdns_service_sync(getdns_context *context, const char *name, getdns_dict *extensions, getdns_dict **response) { - getdns_sync_data data; + getdns_sync_loop loop; getdns_return_t r; if (!context || !name || !response) return GETDNS_RETURN_INVALID_PARAMETER; - if ((r = getdns_service(context, name, - extensions, &data, &data.transaction_id, getdns_sync_cb))) + if ((r = getdns_sync_loop_init(context, &loop))) return r; - return _getdns_sync_run(context, &data, response); + if ((r = _getdns_service_loop(context, &loop.loop.loop, name, + extensions, &loop, NULL, getdns_sync_cb))) { + + getdns_sync_loop_cleanup(&loop); + return r; + } + getdns_sync_loop_run(&loop); + + return (*response = loop.response) ? + GETDNS_RETURN_GOOD : GETDNS_RETURN_GENERIC_ERROR; } /* getdns_core_sync.c */ From aeeadde2993ea4a76fae56ba0ced6d0382b66066 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Mon, 7 Mar 2016 16:35:43 +0100 Subject: [PATCH 20/23] Synchronous with pluggable event APIs again --- src/sync.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/sync.c b/src/sync.c index dffff203..3dd4af86 100644 --- a/src/sync.c +++ b/src/sync.c @@ -68,20 +68,28 @@ getdns_sync_loop_init(getdns_context *context, getdns_sync_loop *loop) _getdns_default_eventloop_init(&loop->loop); -#if defined(HAVE_LIBUNBOUND) && !defined(USE_WINSOCK) +#ifdef HAVE_LIBUNBOUND +# ifndef USE_WINSOCK loop->ub_event.userarg = loop->context; loop->ub_event.read_cb = _getdns_context_ub_read_cb; loop->ub_event.write_cb = NULL; loop->ub_event.timeout_cb = NULL; loop->ub_event.ev = NULL; - +# endif # ifdef HAVE_UNBOUND_EVENT_API - if (context->unbound_event_api) { - (void) ub_ctx_set_event(context->unbound_ctx, (void *)ext); + if (_getdns_ub_loop_enabled(&context->ub_loop)) { + context->ub_loop.extension = ext; } else # endif +# ifndef USE_WINSOCK return ext->vmt->schedule(ext, ub_fd(context->unbound_ctx), TIMEOUT_FOREVER, &loop->ub_event); +# else + /* No sync full recursion requests on windows without + * UNBOUND_EVENT_API because ub_fd() doesn't work on windows. + */ + ; /* pass */ +# endif #endif return GETDNS_RETURN_GOOD; } @@ -93,9 +101,8 @@ getdns_sync_loop_cleanup(getdns_sync_loop *loop) #if defined(HAVE_LIBUNBOUND) && !defined(USE_WINSOCK) # ifdef HAVE_UNBOUND_EVENT_API - if (loop->context->unbound_event_api) { - (void) ub_ctx_set_event(loop->context->unbound_ctx, - (void *)loop->context->extension); + if (_getdns_ub_loop_enabled(&loop->context->ub_loop)) { + loop->context->ub_loop.extension = loop->context->extension; } else # endif ext->vmt->clear(ext, &loop->ub_event); From 70cc65f7865ca67dc84f041eda00122d980202ff Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 9 Mar 2016 10:37:05 +0100 Subject: [PATCH 21/23] Replace default append_name setting to GETDNS_APPEND_NAME_ONLY_TO_SINGLE_LABEL_AFTER_FAILURE --- src/context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/context.c b/src/context.c index 784a966f..8501f730 100644 --- a/src/context.c +++ b/src/context.c @@ -1117,7 +1117,7 @@ getdns_context_create_with_extended_memory_functions( result->follow_redirects = GETDNS_REDIRECTS_FOLLOW; result->dns_root_servers = NULL; result->root_servers_fn[0] = 0; - result->append_name = GETDNS_APPEND_NAME_ALWAYS; + result->append_name = GETDNS_APPEND_NAME_ONLY_TO_SINGLE_LABEL_AFTER_FAILURE; result->suffixes = no_suffixes; result->suffixes_len = sizeof(no_suffixes); From a83c54387dcc7cb80594965bdb05d5380d6405e7 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 9 Mar 2016 11:16:19 +0100 Subject: [PATCH 22/23] Reuse sync eventloop per context So recursive resolution can depend on and continue with outstanding queries it depends on --- src/context.c | 5 ++- src/context.h | 1 + src/sync.c | 116 +++++++++++++++++++++++--------------------------- 3 files changed, 58 insertions(+), 64 deletions(-) diff --git a/src/context.c b/src/context.c index 8501f730..89af5673 100644 --- a/src/context.c +++ b/src/context.c @@ -1156,6 +1156,7 @@ getdns_context_create_with_extended_memory_functions( result->extension = &result->default_eventloop.loop; _getdns_default_eventloop_init(&result->default_eventloop); + _getdns_default_eventloop_init(&result->sync_eventloop); result->fchg_resolvconf = NULL; result->fchg_hosts = NULL; @@ -1260,13 +1261,13 @@ getdns_context_destroy(struct getdns_context *context) */ _getdns_upstreams_dereference(context->upstreams); + context->sync_eventloop.loop.vmt->cleanup(&context->sync_eventloop.loop); + context->extension->vmt->cleanup(context->extension); #ifdef HAVE_LIBUNBOUND if (context->unbound_ctx) ub_ctx_delete(context->unbound_ctx); #endif - context->extension->vmt->cleanup(context->extension); - if (context->namespaces) GETDNS_FREE(context->my_mf, context->namespaces); diff --git a/src/context.h b/src/context.h index d3bff070..51457632 100644 --- a/src/context.h +++ b/src/context.h @@ -249,6 +249,7 @@ struct getdns_context { /* The default extension */ _getdns_default_eventloop default_eventloop; + _getdns_default_eventloop sync_eventloop; /* * state data used to detect changes to the system config files diff --git a/src/sync.c b/src/sync.c index 3dd4af86..2b15c445 100644 --- a/src/sync.c +++ b/src/sync.c @@ -45,36 +45,33 @@ #include "stub.h" #include "gldns/wire2str.h" -typedef struct getdns_sync_loop { - _getdns_default_eventloop loop; +typedef struct getdns_sync_data { #ifdef HAVE_LIBUNBOUND getdns_eventloop_event ub_event; #endif getdns_context *context; int to_run; getdns_dict *response; -} getdns_sync_loop; +} getdns_sync_data; static getdns_return_t -getdns_sync_loop_init(getdns_context *context, getdns_sync_loop *loop) +getdns_sync_data_init(getdns_context *context, getdns_sync_data *data) { #ifdef HAVE_LIBUNBOUND - getdns_eventloop *ext = &loop->loop.loop; + getdns_eventloop *ext = &context->sync_eventloop.loop; #endif - loop->response = NULL; - loop->to_run = 1; - loop->context = context; - - _getdns_default_eventloop_init(&loop->loop); + data->context = context; + data->to_run = 1; + data->response = NULL; #ifdef HAVE_LIBUNBOUND # ifndef USE_WINSOCK - loop->ub_event.userarg = loop->context; - loop->ub_event.read_cb = _getdns_context_ub_read_cb; - loop->ub_event.write_cb = NULL; - loop->ub_event.timeout_cb = NULL; - loop->ub_event.ev = NULL; + data->ub_event.userarg = data->context; + data->ub_event.read_cb = _getdns_context_ub_read_cb; + data->ub_event.write_cb = NULL; + data->ub_event.timeout_cb = NULL; + data->ub_event.ev = NULL; # endif # ifdef HAVE_UNBOUND_EVENT_API if (_getdns_ub_loop_enabled(&context->ub_loop)) { @@ -83,7 +80,7 @@ getdns_sync_loop_init(getdns_context *context, getdns_sync_loop *loop) # endif # ifndef USE_WINSOCK return ext->vmt->schedule(ext, ub_fd(context->unbound_ctx), - TIMEOUT_FOREVER, &loop->ub_event); + TIMEOUT_FOREVER, &data->ub_event); # else /* No sync full recursion requests on windows without * UNBOUND_EVENT_API because ub_fd() doesn't work on windows. @@ -95,66 +92,61 @@ getdns_sync_loop_init(getdns_context *context, getdns_sync_loop *loop) } static void -getdns_sync_loop_cleanup(getdns_sync_loop *loop) +getdns_sync_data_cleanup(getdns_sync_data *data) { - getdns_eventloop *ext = &loop->loop.loop; - #if defined(HAVE_LIBUNBOUND) && !defined(USE_WINSOCK) # ifdef HAVE_UNBOUND_EVENT_API - if (_getdns_ub_loop_enabled(&loop->context->ub_loop)) { - loop->context->ub_loop.extension = loop->context->extension; + if (_getdns_ub_loop_enabled(&data->context->ub_loop)) { + data->context->ub_loop.extension = data->context->extension; } else # endif - ext->vmt->clear(ext, &loop->ub_event); + data->context->sync_eventloop.loop.vmt->clear( + &data->context->sync_eventloop.loop, &data->ub_event); #endif - ext->vmt->cleanup(ext); } static void -getdns_sync_loop_run(getdns_sync_loop *loop) +getdns_sync_loop_run(getdns_sync_data *data) { - getdns_eventloop *ext = &loop->loop.loop; - - while (loop->to_run) - ext->vmt->run_once(ext, 1); - - getdns_sync_loop_cleanup(loop); + while (data->to_run) + data->context->sync_eventloop.loop.vmt->run_once( + &data->context->sync_eventloop.loop, 1); } static void getdns_sync_cb(getdns_context *context, getdns_callback_type_t callback_type, getdns_dict *response, void *userarg, getdns_transaction_t transaction_id) { - getdns_sync_loop *loop = (getdns_sync_loop *)userarg; + getdns_sync_data *data = (getdns_sync_data *)userarg; - assert(loop); + assert(data); - loop->response = response; - loop->to_run = 0; + data->response = response; + data->to_run = 0; } getdns_return_t getdns_general_sync(getdns_context *context, const char *name, uint16_t request_type, getdns_dict *extensions, getdns_dict **response) { - getdns_sync_loop loop; + getdns_sync_data data; getdns_return_t r; if (!context || !name || !response) return GETDNS_RETURN_INVALID_PARAMETER; - if ((r = getdns_sync_loop_init(context, &loop))) + if ((r = getdns_sync_data_init(context, &data))) return r; - if ((r = _getdns_general_loop(context, &loop.loop.loop, name, - request_type, extensions, &loop, NULL, getdns_sync_cb, NULL))) { + if ((r = _getdns_general_loop(context, &context->sync_eventloop.loop, + name, request_type, extensions, &data, NULL, getdns_sync_cb, NULL))) { - getdns_sync_loop_cleanup(&loop); + getdns_sync_data_cleanup(&data); return r; } - getdns_sync_loop_run(&loop); + getdns_sync_loop_run(&data); - return (*response = loop.response) ? + return (*response = data.response) ? GETDNS_RETURN_GOOD : GETDNS_RETURN_GENERIC_ERROR; } @@ -162,24 +154,24 @@ getdns_return_t getdns_address_sync(getdns_context *context, const char *name, getdns_dict *extensions, getdns_dict **response) { - getdns_sync_loop loop; + getdns_sync_data data; getdns_return_t r; if (!context || !name || !response) return GETDNS_RETURN_INVALID_PARAMETER; - if ((r = getdns_sync_loop_init(context, &loop))) + if ((r = getdns_sync_data_init(context, &data))) return r; - if ((r = _getdns_address_loop(context, &loop.loop.loop, name, - extensions, &loop, NULL, getdns_sync_cb))) { + if ((r = _getdns_address_loop(context, &context->sync_eventloop.loop, + name, extensions, &data, NULL, getdns_sync_cb))) { - getdns_sync_loop_cleanup(&loop); + getdns_sync_data_cleanup(&data); return r; } - getdns_sync_loop_run(&loop); + getdns_sync_loop_run(&data); - return (*response = loop.response) ? + return (*response = data.response) ? GETDNS_RETURN_GOOD : GETDNS_RETURN_GENERIC_ERROR; } @@ -187,24 +179,24 @@ getdns_return_t getdns_hostname_sync(getdns_context *context, getdns_dict *address, getdns_dict *extensions, getdns_dict **response) { - getdns_sync_loop loop; + getdns_sync_data data; getdns_return_t r; if (!context || !address || !response) return GETDNS_RETURN_INVALID_PARAMETER; - if ((r = getdns_sync_loop_init(context, &loop))) + if ((r = getdns_sync_data_init(context, &data))) return r; - if ((r = _getdns_hostname_loop(context, &loop.loop.loop, address, - extensions, &loop, NULL, getdns_sync_cb))) { + if ((r = _getdns_hostname_loop(context, &context->sync_eventloop.loop, + address, extensions, &data, NULL, getdns_sync_cb))) { - getdns_sync_loop_cleanup(&loop); + getdns_sync_data_cleanup(&data); return r; } - getdns_sync_loop_run(&loop); + getdns_sync_loop_run(&data); - return (*response = loop.response) ? + return (*response = data.response) ? GETDNS_RETURN_GOOD : GETDNS_RETURN_GENERIC_ERROR; } @@ -212,24 +204,24 @@ getdns_return_t getdns_service_sync(getdns_context *context, const char *name, getdns_dict *extensions, getdns_dict **response) { - getdns_sync_loop loop; + getdns_sync_data data; getdns_return_t r; if (!context || !name || !response) return GETDNS_RETURN_INVALID_PARAMETER; - if ((r = getdns_sync_loop_init(context, &loop))) + if ((r = getdns_sync_data_init(context, &data))) return r; - if ((r = _getdns_service_loop(context, &loop.loop.loop, name, - extensions, &loop, NULL, getdns_sync_cb))) { + if ((r = _getdns_service_loop(context, &context->sync_eventloop.loop, + name, extensions, &data, NULL, getdns_sync_cb))) { - getdns_sync_loop_cleanup(&loop); + getdns_sync_data_cleanup(&data); return r; } - getdns_sync_loop_run(&loop); + getdns_sync_loop_run(&data); - return (*response = loop.response) ? + return (*response = data.response) ? GETDNS_RETURN_GOOD : GETDNS_RETURN_GENERIC_ERROR; } From 36e620d7693112445230cb6f1aab64d25f75b32e Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 9 Mar 2016 15:37:47 +0100 Subject: [PATCH 23/23] TCP handling on windows --- src/ub_loop.c | 111 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 95 insertions(+), 16 deletions(-) diff --git a/src/ub_loop.c b/src/ub_loop.c index 49c57115..e0755cd5 100644 --- a/src/ub_loop.c +++ b/src/ub_loop.c @@ -106,6 +106,12 @@ typedef struct my_event { void (*cb)(int, short, void *arg); /** callback user arg */ void *arg; +#ifdef USE_WINSOCK + int is_tcp; + int read_wouldblock; + int write_wouldblock; +#endif + int *active; } my_event; #define AS_UB_LOOP(x) \ @@ -141,9 +147,10 @@ static int my_event_base_loopexit(struct ub_event_base* base, struct timeval* tv #define CLEAR_MY_EVENT(ev) \ do { (ev)->loop->extension->vmt->clear((ev)->loop->extension, \ - &(ev)->gev); (ev)->added = 0; } while(0) + &(ev)->gev); (ev)->added = 0; if ((ev)->active) { \ + *(ev)->active = 0; (ev)->active = NULL; }} while(0) -static inline getdns_return_t schedule_my_event(my_event *ev) +static getdns_return_t schedule_my_event(my_event *ev) { getdns_return_t r; @@ -159,25 +166,66 @@ static inline getdns_return_t schedule_my_event(my_event *ev) static void read_cb(void *userarg) { struct my_event *ev = (struct my_event *)userarg; - (*ev->cb)(ev->fd, UB_EV_READ, ev->arg); - if ((ev->bits & UB_EV_PERSIST) == 0) - CLEAR_MY_EVENT(ev); + + int active = 1; + ev->active = &active; + +#ifdef USE_WINSOCK + if (ev->is_tcp) { + ev->read_wouldblock = 0; + do { + (*ev->cb)(ev->fd, UB_EV_READ, ev->arg); + } while (active && !ev->read_wouldblock && (ev->bits & UB_EV_PERSIST)); + } else + (*ev->cb)(ev->fd, UB_EV_READ, ev->arg); +#else + (*ev->cb)(ev->fd, UB_EV_READ, ev->arg); +#endif + if (active) { + ev->active = NULL; + if ((ev->bits & UB_EV_PERSIST) == 0) + CLEAR_MY_EVENT(ev); + } } static void write_cb(void *userarg) { struct my_event *ev = (struct my_event *)userarg; - (*ev->cb)(ev->fd, UB_EV_WRITE, ev->arg); - if ((ev->bits & UB_EV_PERSIST) == 0) - CLEAR_MY_EVENT(ev); + + int active = 1; + ev->active = &active; + +#ifdef USE_WINSOCK + if (ev->is_tcp) { + ev->write_wouldblock = 0; + do { + (*ev->cb)(ev->fd, UB_EV_WRITE, ev->arg); + } while (active && !ev->write_wouldblock && (ev->bits & UB_EV_PERSIST)); + } else + (*ev->cb)(ev->fd, UB_EV_WRITE, ev->arg); +#else + (*ev->cb)(ev->fd, UB_EV_WRITE, ev->arg); +#endif + if (active) { + ev->active = NULL; + if ((ev->bits & UB_EV_PERSIST) == 0) + CLEAR_MY_EVENT(ev); + } } static void timeout_cb(void *userarg) { struct my_event *ev = (struct my_event *)userarg; + + int active = 1; + ev->active = &active; + (*ev->cb)(ev->fd, UB_EV_TIMEOUT, ev->arg); - if ((ev->bits & UB_EV_PERSIST) == 0) - CLEAR_MY_EVENT(ev); + if (active) { + ev->active = NULL; + if ((ev->bits & UB_EV_PERSIST) == 0) + CLEAR_MY_EVENT(ev); + } } static getdns_return_t set_gev_callbacks(my_event* ev, short bits) @@ -235,12 +283,28 @@ static int my_event_del(struct ub_event* ev) return 0; } -static int my_event_add(struct ub_event* ev, struct timeval* tv) +static int my_event_add(struct ub_event* ub_ev, struct timeval* tv) { - if (AS_MY_EVENT(ev)->added) - my_event_del(ev); - if (tv && (AS_MY_EVENT(ev)->bits & UB_EV_TIMEOUT) != 0) - AS_MY_EVENT(ev)->timeout = (tv->tv_sec * 1000) + (tv->tv_usec / 1000); + my_event *ev = AS_MY_EVENT(ub_ev); +#ifdef USE_WINSOCK + int t, l = sizeof(t); +#endif + + if (ev->added) + my_event_del(&ev->super); + if (tv && (ev->bits & UB_EV_TIMEOUT) != 0) + ev->timeout = (tv->tv_sec * 1000) + (tv->tv_usec / 1000); +#ifdef USE_WINSOCK + if ((ev->bits & (UB_EV_READ|UB_EV_WRITE)) && ev->fd != -1 && + getsockopt(ev->fd, SOL_SOCKET, SO_TYPE, (void *)&t, &l) == 0 && + t == SOCK_STREAM) { + + ev->is_tcp = 1; + ev->read_wouldblock = 0; + ev->write_wouldblock = 0; + } else + ev->is_tcp = 0; +#endif if (schedule_my_event(AS_MY_EVENT(ev))) return -1; return 0; @@ -288,7 +352,14 @@ static void my_winsock_unregister_wsaevent(struct ub_event* ev) static void my_winsock_tcp_wouldblock(struct ub_event* ev, int bits) { +#ifndef USE_WINSOCK (void)ev; (void)bits; +#else + if (bits & UB_EV_READ) + AS_MY_EVENT(ev)->read_wouldblock = 1; + if (bits & UB_EV_WRITE) + AS_MY_EVENT(ev)->write_wouldblock = 1; +#endif } static struct ub_event* my_event_new(struct ub_event_base* base, int fd, @@ -323,6 +394,12 @@ static struct ub_event* my_event_new(struct ub_event_base* base, int fd, ev->timeout = (uint64_t)-1; ev->cb = cb; ev->arg = arg; +#ifdef USE_WINSOCK + ev->is_tcp = 0; + ev->read_wouldblock = 0; + ev->write_wouldblock = 0; +#endif + ev->active = NULL; ev->gev.userarg = ev; ev->gev.read_cb = bits & UB_EV_READ ? read_cb : NULL; ev->gev.write_cb = bits & UB_EV_WRITE ? write_cb : NULL; @@ -333,7 +410,9 @@ static struct ub_event* my_event_new(struct ub_event_base* base, int fd, static struct ub_event* my_signal_new(struct ub_event_base* base, int fd, void (*cb)(int, short, void*), void* arg) { - return my_event_new(base, fd, UB_EV_SIGNAL | UB_EV_PERSIST, cb, arg); + /* Not applicable, because in unbound used in the daemon only */ + (void)base; (void)fd; (void)cb; (void)arg; + return NULL; } static struct ub_event* my_winsock_register_wsaevent(struct ub_event_base *b,