diff --git a/configure.ac b/configure.ac index b6c2a655..939941cb 100644 --- a/configure.ac +++ b/configure.ac @@ -20,7 +20,7 @@ found_all_libs=1 AC_MSG_NOTICE([Checking for dependencies ldns and libevent]) AC_CHECK_LIB([event_core], [event_base_new], [], [found_all_libs=0]) AC_CHECK_LIB([ldns], [ldns_dname_new_frm_str], [], [found_all_libs=0]) - +AC_CHECK_LIB([pthread], [pthread_create], [], [found_all_libs=0]) if test $found_all_libs == 0 then AC_MSG_ERROR([One more dependencies is missing]) diff --git a/src/example/Makefile.am b/src/example/Makefile.am index 396f89eb..6d2ddceb 100644 --- a/src/example/Makefile.am +++ b/src/example/Makefile.am @@ -1,5 +1,5 @@ AM_CPPFLAGS = -Wall -Werror -g -fPIC -I$(srcdir)/ -I/usr/local/include -I$(top_srcdir)/src -std=c99 -AM_LDFLAGS =-L$(top_srcdir)/src -L/usr/local/lib -lgetdns -lldns -levent +AM_LDFLAGS =-L$(top_srcdir)/src -L/usr/local/lib -lgetdns -lldns -levent -lpthread bin_PROGRAMS = example_all_functions example_synchronous \ example_simple_answers example_tree example_all_functions_SOURCES = example_all_functions.c diff --git a/src/getdns/getdns.h b/src/getdns/getdns.h index c33a816d..4787ed0a 100644 --- a/src/getdns/getdns.h +++ b/src/getdns/getdns.h @@ -740,7 +740,7 @@ getdns_general_sync( uint16_t request_type, struct getdns_dict *extensions, uint32_t *response_length, - struct getdns_dict *response + struct getdns_dict **response ); /** @@ -758,7 +758,7 @@ getdns_address_sync( const char *name, struct getdns_dict *extensions, uint32_t *response_length, - struct getdns_dict *response + struct getdns_dict **response ); /** @@ -776,7 +776,7 @@ getdns_hostname_sync( struct getdns_dict *address, struct getdns_dict *extensions, uint32_t *response_length, - struct getdns_dict *response + struct getdns_dict **response ); /** @@ -794,7 +794,7 @@ getdns_service_sync( const char *name, struct getdns_dict *extensions, uint32_t *response_length, - struct getdns_dict *response + struct getdns_dict **response ); void diff --git a/src/sync.c b/src/sync.c index ae26f56a..6f029286 100644 --- a/src/sync.c +++ b/src/sync.c @@ -28,10 +28,48 @@ */ #include +#include +#include "types-internal.h" /* stuff to make it compile pedantically */ #define UNUSED_PARAM(x) ((void)(x)) +/* struct used for the request */ +typedef struct sync_request_data { + getdns_context_t context; + const char* name; + uint16_t request_type; + getdns_dict *extensions; + getdns_return_t response_status; + getdns_dict **response; +} sync_request_data; + +static void sync_callback_func(getdns_context_t context, + uint16_t callback_type, + struct getdns_dict *response, + void *userarg, + getdns_transaction_t transaction_id) { + sync_request_data* req_data = userarg; + *(req_data->response) = response; +} + +static void * request_thread_start(void *arg) { + struct sync_request_data *req_data = arg; + struct event_base *event_base = event_base_new(); + + getdns_extension_set_libevent_base(req_data->context, event_base); + req_data->response_status = getdns_general(req_data->context, + req_data->name, + req_data->request_type, + req_data->extensions, + req_data, + NULL, + sync_callback_func); + + event_base_dispatch(event_base); + return NULL; +} + getdns_return_t getdns_general_sync( @@ -40,10 +78,44 @@ getdns_general_sync( uint16_t request_type, struct getdns_dict *extensions, uint32_t *response_length, - struct getdns_dict *response + struct getdns_dict **response ) -{ UNUSED_PARAM(context); UNUSED_PARAM(name); UNUSED_PARAM(request_type); UNUSED_PARAM(extensions); -UNUSED_PARAM(response_length); UNUSED_PARAM(response); return GETDNS_RETURN_GOOD; } +{ + /* we will cheat and spawn a thread */ + /* get the old event base */ + struct event_base* orig_base = context->event_base; + pthread_t thread; + pthread_attr_t attr; + sync_request_data req_data = { + context, name, request_type, + extensions, + GETDNS_RETURN_GOOD, + response + }; + + /* create the thread */ + int ret = pthread_attr_init(&attr); + if (ret != 0) { + return GETDNS_RETURN_GENERIC_ERROR; + } + ret = pthread_create(&thread, &attr, request_thread_start, &req_data); + if (ret != 0) { + pthread_attr_destroy(&attr); + return GETDNS_RETURN_GENERIC_ERROR; + } + /* wait for the thread */ + ret = pthread_join(thread, NULL); + /* delete attr */ + pthread_attr_destroy(&attr); + if (ret != 0) { + return GETDNS_RETURN_GENERIC_ERROR; + } + + /* set the old event loop */ + getdns_extension_set_libevent_base(context, orig_base); + + return req_data.response_status; +} getdns_return_t getdns_address_sync( @@ -51,10 +123,26 @@ getdns_address_sync( const char *name, struct getdns_dict *extensions, uint32_t *response_length, - struct getdns_dict *response + struct getdns_dict **response ) -{ UNUSED_PARAM(context); UNUSED_PARAM(name); UNUSED_PARAM(extensions); -UNUSED_PARAM(response_length); UNUSED_PARAM(response); return GETDNS_RETURN_GOOD; } +{ + int cleanup_extensions = 0; + if (!extensions) { + extensions = getdns_dict_create(); + cleanup_extensions = 1; + } + getdns_dict_set_int(extensions, + GETDNS_STR_EXTENSION_RETURN_BOTH_V4_AND_V6, + GETDNS_EXTENSION_TRUE); + + getdns_return_t result = + getdns_general_sync(context, name, GETDNS_RRTYPE_A, + extensions, response_length, response); + if (cleanup_extensions) { + getdns_dict_destroy(extensions); + } + return result; +} getdns_return_t getdns_hostname_sync( @@ -62,7 +150,7 @@ getdns_hostname_sync( struct getdns_dict *address, struct getdns_dict *extensions, uint32_t *response_length, - struct getdns_dict *response + struct getdns_dict **response ) { UNUSED_PARAM(context); UNUSED_PARAM(address); UNUSED_PARAM(extensions); UNUSED_PARAM(response_length); UNUSED_PARAM(response); return GETDNS_RETURN_GOOD; } @@ -73,10 +161,14 @@ getdns_service_sync( const char *name, struct getdns_dict *extensions, uint32_t *response_length, - struct getdns_dict *response + struct getdns_dict **response ) -{ UNUSED_PARAM(context); UNUSED_PARAM(name); UNUSED_PARAM(extensions); -UNUSED_PARAM(response_length); UNUSED_PARAM(response); return GETDNS_RETURN_GOOD; } +{ + + return getdns_general_sync(context, name, GETDNS_RRTYPE_SRV, extensions, + response_length, response); + +} void getdns_free_sync_request_memory( diff --git a/src/test/Makefile.am b/src/test/Makefile.am index f04d506d..d53b95e8 100644 --- a/src/test/Makefile.am +++ b/src/test/Makefile.am @@ -1,6 +1,7 @@ AM_CPPFLAGS = -Wall -Werror -g -fPIC -I$(srcdir)/ -I/usr/local/include -I$(top_srcdir)/src -std=c99 -AM_LDFLAGS =-L$(top_srcdir)/src -L/usr/local/lib -lgetdns -noinst_PROGRAMS = tests_list tests_dict tests_stub_async +AM_LDFLAGS =-L$(top_srcdir)/src -L/usr/local/lib -lgetdns -lldns -lpthread -levent +noinst_PROGRAMS = tests_list tests_dict tests_stub_async tests_stub_sync tests_list_SOURCES = tests_list.c testmessages.c tests_dict_SOURCES = tests_dict.c testmessages.c tests_stub_async_SOURCES = tests_stub_async.c testmessages.c +tests_stub_sync_SOURCES = tests_stub_sync.c diff --git a/src/test/tests_stub_async.c b/src/test/tests_stub_async.c index 4005d4cf..71728c23 100644 --- a/src/test/tests_stub_async.c +++ b/src/test/tests_stub_async.c @@ -44,11 +44,10 @@ void this_callbackfn(struct getdns_context_t *this_context, getdns_bindata* bindata = NULL; getdns_dict_get_bindata(this_response, "pkt", &bindata); if (bindata) { - char* data = malloc(1 + bindata->size); + char* data = (char*) bindata->data; data[bindata->size] = 0; memcpy(data, bindata->data, bindata->size); fprintf(stdout, "The packet %s\n", data); - free(data); } } else if (this_callback_type == GETDNS_CALLBACK_CANCEL) diff --git a/src/test/tests_stub_sync.c b/src/test/tests_stub_sync.c new file mode 100644 index 00000000..fec2aa5b --- /dev/null +++ b/src/test/tests_stub_sync.c @@ -0,0 +1,84 @@ +/** + * \file + * unit tests for getdns_dict helper routines, these should be used to + * perform regression tests, output must be unchanged from canonical output + * stored with the sources + */ +/* The MIT License (MIT) + * Copyright (c) 2013 Verisign, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include +#include "testmessages.h" +#include + +static void print_response(getdns_dict* response) { + getdns_bindata* bindata = NULL; + getdns_dict_get_bindata(response, "pkt", &bindata); + if (bindata) { + char* data = (char*) bindata->data; + data[bindata->size] = 0; + memcpy(data, bindata->data, bindata->size); + fprintf(stdout, "The packet %s\n", data); + } +} + +int main() +{ + /* Create the DNS context for this call */ + struct getdns_context_t *this_context = NULL; + getdns_return_t context_create_return = getdns_context_create(&this_context, true); + if (context_create_return != GETDNS_RETURN_GOOD) + { + fprintf(stderr, "Trying to create the context failed: %d", context_create_return); + return(GETDNS_RETURN_GENERIC_ERROR); + } + getdns_context_set_resolution_type(this_context, GETDNS_CONTEXT_STUB); + + getdns_dict* response = NULL; + uint32_t responseLen = 0; + getdns_return_t ret = getdns_address_sync(this_context, "www.google.com", NULL, &responseLen, &response); + + if (ret != GETDNS_RETURN_GOOD || response == NULL) { + fprintf(stderr, "Address sync returned error.\n"); + exit(EXIT_FAILURE); + } + print_response(response); + getdns_dict_destroy(response); + + ret = getdns_service_sync(this_context, "www.google.com", NULL, &responseLen, &response); + if (ret != GETDNS_RETURN_GOOD || response == NULL) { + fprintf(stderr, "Service sync returned error.\n"); + exit(EXIT_FAILURE); + } + print_response(response); + getdns_dict_destroy(response); + + /* Clean up */ + getdns_context_destroy(this_context); + /* Assuming we get here, leave gracefully */ + exit(EXIT_SUCCESS); +} /* main */ + +/* example-simple-answers.c */ +