26 #include <arpa/nameser.h>
27 #include <arpa/inet.h>
52 static void query_set_data_destructor(
void *obj)
56 ast_mutex_destroy(&qsdata->lock);
57 ast_cond_destroy(&qsdata->cond);
64 qsdata = ao2_alloc(
sizeof(*qsdata), query_set_data_destructor);
69 ast_mutex_init(&qsdata->lock);
70 ast_cond_init(&qsdata->cond, NULL);
75 #define DNS_ANSWER "Yes sirree"
76 #define DNS_ANSWER_SIZE strlen(DNS_ANSWER)
89 static void *resolution_thread(
void *dns_query)
95 ast_assert(qsdata != NULL);
115 pthread_t resolver_thread;
122 return ast_pthread_create_detached(&resolver_thread, NULL, resolution_thread,
ao2_bump(query));
152 .resolve = query_set_resolve,
153 .cancel = query_set_cancel,
165 ast_mutex_lock(&qsdata->lock);
167 ast_cond_signal(&qsdata->cond);
168 ast_mutex_unlock(&qsdata->lock);
181 static enum ast_test_result_state query_set_test(
struct ast_test *
test,
int resolve,
int cancel)
183 int total = resolve +
cancel;
186 enum ast_test_result_state res = AST_TEST_PASS;
188 struct timespec timeout;
191 ast_test_status_update(test,
"Failed to register query set DNS resolver\n");
192 return AST_TEST_FAIL;
195 qsdata = query_set_data_alloc();
197 ast_test_status_update(test,
"Failed to allocate data necessary for query set test\n");
204 ast_test_status_update(test,
"Failed to create DNS query set\n");
212 for (idx = 0; idx < total; ++idx) {
214 ast_test_status_update(test,
"Failed to add query to DNS query set\n");
221 ast_test_status_update(test,
"DNS query set does not contain the correct number of queries\n");
228 if (cancel && (cancel == total)) {
230 ast_test_status_update(test,
"Failed to cancel DNS query set when it should be cancellable\n");
235 ast_test_status_update(test,
"Query set callback was invoked despite all queries being cancelled\n");
242 ast_test_status_update(test,
"Successfully cancelled DNS query set when it should not be possible\n");
249 timeout.tv_sec += 10;
251 ast_mutex_lock(&qsdata->lock);
253 if (ast_cond_timedwait(&qsdata->cond, &qsdata->lock, &timeout) == ETIMEDOUT) {
257 ast_mutex_unlock(&qsdata->lock);
260 ast_test_status_update(test,
"Query set did not complete when it should have\n");
269 ast_test_status_update(test,
"Query did not have expected name\n");
273 ast_test_status_update(test,
"Query did not have expected type\n");
277 ast_test_status_update(test,
"Query did not have expected class\n");
291 info->name =
"query_set";
292 info->category =
"/main/dns/query_set/";
293 info->summary =
"Test nominal asynchronous DNS query set";
295 "This tests nominal query set in the following ways:\n"
296 "\t* Multiple queries are added to a query set\n"
297 "\t* The mock resolver is configured to respond to all queries\n"
298 "\t* Asynchronous resolution of the query set is started\n"
299 "\t* The mock resolver responds to all queries\n"
300 "\t* We ensure that the query set callback is invoked upon completion";
301 return AST_TEST_NOT_RUN;
306 return query_set_test(test, 4, 0);
313 info->name =
"query_set_empty";
314 info->category =
"/main/dns/query_set/";
315 info->summary =
"Test nominal asynchronous empty DNS query set";
317 "This tests nominal query set in the following ways:\n"
318 "\t* No queries are added to a query set\n"
319 "\t* Asynchronous resolution of the query set is started\n"
320 "\t* We ensure that the query set callback is invoked upon completion";
321 return AST_TEST_NOT_RUN;
326 return query_set_test(test, 0, 0);
333 info->name =
"query_set_nominal_cancel";
334 info->category =
"/main/dns/query_set/";
335 info->summary =
"Test nominal asynchronous DNS query set cancellation";
337 "This tests nominal query set cancellation in the following ways:\n"
338 "\t* Multiple queries are added to a query set\n"
339 "\t* The mock resolver is configured to NOT respond to any queries\n"
340 "\t* Asynchronous resolution of the query set is started\n"
341 "\t* The query set is canceled and is confirmed to return with success";
342 return AST_TEST_NOT_RUN;
347 return query_set_test(test, 0, 4);
354 info->name =
"query_set_off_nominal_cancel";
355 info->category =
"/main/dns/query_set/";
356 info->summary =
"Test off-nominal asynchronous DNS query set cancellation";
358 "This tests nominal query set cancellation in the following ways:\n"
359 "\t* Multiple queries are added to a query set\n"
360 "\t* The mock resolver is configured to respond to half the queries\n"
361 "\t* Asynchronous resolution of the query set is started\n"
362 "\t* The query set is canceled and is confirmed to return failure\n"
363 "\t* The query set callback is confirmed to run, since it could not be fully canceled";
364 return AST_TEST_NOT_RUN;
369 return query_set_test(test, 2, 2);
372 static int unload_module(
void)
374 AST_TEST_UNREGISTER(query_set);
375 AST_TEST_UNREGISTER(query_set_empty);
376 AST_TEST_UNREGISTER(query_set_nominal_cancel);
377 AST_TEST_UNREGISTER(query_set_off_nominal_cancel);
382 static int load_module(
void)
384 AST_TEST_REGISTER(query_set);
385 AST_TEST_REGISTER(query_set_empty);
386 AST_TEST_REGISTER(query_set_nominal_cancel);
387 AST_TEST_REGISTER(query_set_off_nominal_cancel);
Asterisk main include file. File version handling, generic pbx functions.
const char * ast_dns_query_get_name(const struct ast_dns_query *query)
Get the name queried in a DNS query.
int ast_dns_query_get_rr_class(const struct ast_dns_query *query)
Get the record resource class of a DNS query.
void ast_dns_resolver_unregister(struct ast_dns_resolver *resolver)
Unregister a DNS resolver.
void * user_data
User-specific data.
struct ast_dns_query_set * ast_dns_query_set_create(void)
Create a query set to hold queries.
const char * name
The name of the resolver implementation.
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
static void cleanup(void)
Clean up any old apps that we don't need any more.
void * ast_dns_query_get_data(const struct ast_dns_query *query)
Get the user specific data of a DNS query.
struct ast_dns_query * ast_dns_query_set_get(const struct ast_dns_query_set *query_set, unsigned int index)
Retrieve a query from a query set.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
int ast_dns_resolver_register(struct ast_dns_resolver *resolver)
Register a DNS resolver.
void ast_dns_resolver_completed(struct ast_dns_query *query)
Mark a DNS query as having been completed.
DNS resolver implementation.
Internal DNS structure definitions.
int ast_dns_query_set_resolve_cancel(struct ast_dns_query_set *query_set)
Cancel an asynchronous DNS query set resolution.
Vector container support.
int ast_dns_query_get_rr_type(const struct ast_dns_query *query)
Get the record resource type of a DNS query.
int ast_dns_query_set_add(struct ast_dns_query_set *query_set, const char *name, int rr_type, int rr_class)
Add a query to a query set.
struct timespec ast_tsnow(void)
Returns current timespec. Meant to avoid calling ast_tvnow() just to create a timespec from the timev...
#define AST_TEST_DEFINE(hdr)
size_t ast_dns_query_set_num_queries(const struct ast_dns_query_set *query_set)
Retrieve the number of queries in a query set.
#define ASTERISK_GPL_KEY
The text the key() function should return.
int ast_dns_resolver_set_result(struct ast_dns_query *query, unsigned int secure, unsigned int bogus, unsigned int rcode, const char *canonical, const char *answer, size_t answer_size)
Set result information for a DNS query.
Asterisk module definitions.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
void ast_dns_query_set_resolve_async(struct ast_dns_query_set *query_set, ast_dns_query_set_callback callback, void *data)
Asynchronously resolve queries in a query set.
Structure for mutex and tracking information.
void * ast_dns_query_set_get_data(const struct ast_dns_query_set *query_set)
Retrieve user specific data from a query set.