Asterisk - The Open Source Telephony Project GIT-master-7e7a603
Data Structures | Macros | Functions | Variables
test_dns_recurring.c File Reference
#include "asterisk.h"
#include <arpa/nameser.h>
#include <arpa/inet.h>
#include "asterisk/test.h"
#include "asterisk/module.h"
#include "asterisk/dns_core.h"
#include "asterisk/dns_resolver.h"
#include "asterisk/dns_recurring.h"
#include "asterisk/dns_internal.h"
Include dependency graph for test_dns_recurring.c:

Go to the source code of this file.

Data Structures

struct  recurring_data
 

Macros

#define DNS_ANSWER   "Yes sirree"
 
#define DNS_ANSWER_SIZE   strlen(DNS_ANSWER)
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
 AST_TEST_DEFINE (recurring_query)
 
 AST_TEST_DEFINE (recurring_query_cancel_between)
 
 AST_TEST_DEFINE (recurring_query_cancel_during)
 
 AST_TEST_DEFINE (recurring_query_off_nominal)
 
static void async_callback (const struct ast_dns_query *query)
 
static int fail_resolve (struct ast_dns_query *query)
 
static int load_module (void)
 
static int recurring_cancel (struct ast_dns_query *query)
 Resolver's cancel() method. More...
 
static struct recurring_datarecurring_data_alloc (void)
 
static void recurring_data_destructor (void *obj)
 
static int recurring_resolve (struct ast_dns_query *query)
 Resolver's resolve() method. More...
 
static void * resolution_thread (void *dns_query)
 Thread that performs asynchronous resolution. More...
 
static void stub_callback (const struct ast_dns_query *query)
 
static int stub_cancel (struct ast_dns_query *query)
 
static int unload_module (void)
 
static int wait_for_resolution (struct ast_test *test, struct recurring_data *rdata, int expected_lapse, int num_resolves, int num_completed, int canceled)
 Wait for a successful resolution to complete. More...
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Recurring DNS query tests" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_dns_resolver recurring_resolver
 

Macro Definition Documentation

◆ DNS_ANSWER

#define DNS_ANSWER   "Yes sirree"

Definition at line 80 of file test_dns_recurring.c.

◆ DNS_ANSWER_SIZE

#define DNS_ANSWER_SIZE   strlen(DNS_ANSWER)

Definition at line 81 of file test_dns_recurring.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 647 of file test_dns_recurring.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 647 of file test_dns_recurring.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 647 of file test_dns_recurring.c.

◆ AST_TEST_DEFINE() [1/4]

AST_TEST_DEFINE ( recurring_query  )

Definition at line 269 of file test_dns_recurring.c.

270{
271 RAII_VAR(struct ast_dns_query_recurring *, recurring_query, NULL, ao2_cleanup);
272 RAII_VAR(struct recurring_data *, rdata, NULL, ao2_cleanup);
273
275 int expected_lapse;
276
277 switch (cmd) {
278 case TEST_INIT:
279 info->name = "recurring_query";
280 info->category = "/main/dns/recurring/";
281 info->summary = "Test nominal asynchronous recurring DNS queries";
282 info->description =
283 "This tests nominal recurring queries in the following ways:\n"
284 "\t* An asynchronous query is sent to a mock resolver\n"
285 "\t* The mock resolver returns two records with different TTLs\n"
286 "\t* We ensure that the query re-occurs according to the lower of the TTLs\n"
287 "\t* The mock resolver returns two records, this time with different TTLs\n"
288 "\t from the first time the query was resolved\n"
289 "\t* We ensure that the query re-occurs according to the new lower TTL";
290 return AST_TEST_NOT_RUN;
291 case TEST_EXECUTE:
292 break;
293 }
294
296 ast_test_status_update(test, "Failed to register recurring DNS resolver\n");
297 return AST_TEST_FAIL;
298 }
299
300 rdata = recurring_data_alloc();
301 if (!rdata) {
302 ast_test_status_update(test, "Failed to allocate data necessary for recurring test\n");
303 res = AST_TEST_FAIL;
304 goto cleanup;
305 }
306
307 expected_lapse = 0;
308 rdata->ttl1 = 5;
309 rdata->ttl2 = 20;
310
311 recurring_query = ast_dns_resolve_recurring("asterisk.org", T_A, C_IN, async_callback, rdata);
312 if (!recurring_query) {
313 ast_test_status_update(test, "Failed to create recurring DNS query\n");
314 res = AST_TEST_FAIL;
315 goto cleanup;
316 }
317
318 /* This should be near instantaneous */
319 if (wait_for_resolution(test, rdata, expected_lapse, 1, 1, 0)) {
320 res = AST_TEST_FAIL;
321 goto cleanup;
322 }
323
324 expected_lapse = rdata->ttl1;
325 rdata->ttl1 = 45;
326 rdata->ttl2 = 10;
327
328 /* This should take approximately 5 seconds */
329 if (wait_for_resolution(test, rdata, expected_lapse, 2, 2, 0)) {
330 res = AST_TEST_FAIL;
331 goto cleanup;
332 }
333
334 expected_lapse = rdata->ttl2;
335
336 /* This should take approximately 10 seconds */
337 if (wait_for_resolution(test, rdata, expected_lapse, 3, 3, 0)) {
338 res = AST_TEST_FAIL;
339 goto cleanup;
340 }
341
342cleanup:
343 if (recurring_query) {
344 /* XXX I don't like calling this here since I'm not testing
345 * canceling recurring queries, but I'm forced into it here
346 */
347 ast_dns_resolve_recurring_cancel(recurring_query);
348 }
350 return res;
351}
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
int ast_dns_resolve_recurring_cancel(struct ast_dns_query_recurring *recurring)
Cancel an asynchronous recurring DNS resolution.
struct ast_dns_query_recurring * ast_dns_resolve_recurring(const char *name, int rr_type, int rr_class, ast_dns_resolve_callback callback, void *data)
Asynchronously resolve a DNS query, and continue resolving it according to the lowest TTL available.
int ast_dns_resolver_register(struct ast_dns_resolver *resolver)
Register a DNS resolver.
Definition: dns_core.c:630
void ast_dns_resolver_unregister(struct ast_dns_resolver *resolver)
Unregister a DNS resolver.
Definition: dns_core.c:680
def info(msg)
static void * cleanup(void *unused)
Definition: pbx_realtime.c:124
#define NULL
Definition: resample.c:96
A recurring DNS query.
Definition: dns_internal.h:157
@ TEST_INIT
Definition: test.h:200
@ TEST_EXECUTE
Definition: test.h:201
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
ast_test_result_state
Definition: test.h:193
@ AST_TEST_PASS
Definition: test.h:195
@ AST_TEST_FAIL
Definition: test.h:196
@ AST_TEST_NOT_RUN
Definition: test.h:194
static struct ast_dns_resolver recurring_resolver
static int wait_for_resolution(struct ast_test *test, struct recurring_data *rdata, int expected_lapse, int num_resolves, int num_completed, int canceled)
Wait for a successful resolution to complete.
static struct recurring_data * recurring_data_alloc(void)
static void async_callback(const struct ast_dns_query *query)
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941

References ao2_cleanup, ast_dns_resolve_recurring(), ast_dns_resolve_recurring_cancel(), ast_dns_resolver_register(), ast_dns_resolver_unregister(), AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, async_callback(), cleanup(), sip_to_pjsip::info(), NULL, RAII_VAR, recurring_data_alloc(), recurring_resolver, TEST_EXECUTE, TEST_INIT, and wait_for_resolution().

◆ AST_TEST_DEFINE() [2/4]

AST_TEST_DEFINE ( recurring_query_cancel_between  )

Definition at line 449 of file test_dns_recurring.c.

450{
451 RAII_VAR(struct ast_dns_query_recurring *, recurring_query, NULL, ao2_cleanup);
452 RAII_VAR(struct recurring_data *, rdata, NULL, ao2_cleanup);
453
455 struct timespec timeout;
456
457 switch (cmd) {
458 case TEST_INIT:
459 info->name = "recurring_query_cancel_between";
460 info->category = "/main/dns/recurring/";
461 info->summary = "Test canceling a recurring DNS query during the downtime between queries";
462 info->description = "This test does the following:\n"
463 "\t* Issue a recurring DNS query.\n"
464 "\t* Once results have been returned, cancel the recurring query.\n"
465 "\t* Wait a while to ensure that no more queries are occurring.";
466 return AST_TEST_NOT_RUN;
467 case TEST_EXECUTE:
468 break;
469 }
470
472 ast_test_status_update(test, "Failed to register recurring DNS resolver\n");
473 return AST_TEST_FAIL;
474 }
475
476 rdata = recurring_data_alloc();
477 if (!rdata) {
478 ast_test_status_update(test, "Failed to allocate data necessary for recurring test\n");
479 res = AST_TEST_FAIL;
480 goto cleanup;
481 }
482
483 rdata->ttl1 = 5;
484 rdata->ttl2 = 20;
485
486 recurring_query = ast_dns_resolve_recurring("asterisk.org", T_A, C_IN, async_callback, rdata);
487 if (!recurring_query) {
488 ast_test_status_update(test, "Unable to make recurring query\n");
489 res = AST_TEST_FAIL;
490 goto cleanup;
491 }
492
493 if (wait_for_resolution(test, rdata, 0, 1, 1, 0)) {
494 res = AST_TEST_FAIL;
495 goto cleanup;
496 }
497
498 if (ast_dns_resolve_recurring_cancel(recurring_query)) {
499 ast_test_status_update(test, "Failed to cancel recurring query\n");
500 res = AST_TEST_FAIL;
501 goto cleanup;
502 }
503
504 /* Query has been canceled, so let's wait to make sure that we don't get
505 * told another query has occurred.
506 */
507 timeout = ast_tsnow();
508 timeout.tv_sec += 10;
509
510 ast_mutex_lock(&rdata->lock);
511 while (!rdata->query_complete) {
512 if (ast_cond_timedwait(&rdata->cond, &rdata->lock, &timeout) == ETIMEDOUT) {
513 break;
514 }
515 }
516 ast_mutex_unlock(&rdata->lock);
517
518 if (rdata->query_complete) {
519 ast_test_status_update(test, "Recurring query occurred after cancellation\n");
520 res = AST_TEST_FAIL;
521 goto cleanup;
522 }
523
524cleanup:
526 return res;
527}
#define ast_cond_timedwait(cond, mutex, time)
Definition: lock.h:206
#define ast_mutex_unlock(a)
Definition: lock.h:190
#define ast_mutex_lock(a)
Definition: lock.h:189
struct timespec ast_tsnow(void)
Returns current timespec. Meant to avoid calling ast_tvnow() just to create a timespec from the timev...
Definition: time.h:186

References ao2_cleanup, ast_cond_timedwait, ast_dns_resolve_recurring(), ast_dns_resolve_recurring_cancel(), ast_dns_resolver_register(), ast_dns_resolver_unregister(), ast_mutex_lock, ast_mutex_unlock, AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, ast_tsnow(), async_callback(), cleanup(), sip_to_pjsip::info(), NULL, RAII_VAR, recurring_data_alloc(), recurring_resolver, TEST_EXECUTE, TEST_INIT, and wait_for_resolution().

◆ AST_TEST_DEFINE() [3/4]

AST_TEST_DEFINE ( recurring_query_cancel_during  )

Definition at line 529 of file test_dns_recurring.c.

530{
531
532 RAII_VAR(struct ast_dns_query_recurring *, recurring_query, NULL, ao2_cleanup);
533 RAII_VAR(struct recurring_data *, rdata, NULL, ao2_cleanup);
534
536 struct timespec timeout;
537
538 switch (cmd) {
539 case TEST_INIT:
540 info->name = "recurring_query_cancel_during";
541 info->category = "/main/dns/recurring/";
542 info->summary = "Cancel a recurring DNS query while a query is actually happening";
543 info->description = "This test does the following:\n"
544 "\t* Initiate a recurring DNS query.\n"
545 "\t* Allow the initial query to complete, and a second query to start\n"
546 "\t* Cancel the recurring query while the second query is executing\n"
547 "\t* Ensure that the resolver's cancel() method was called\n"
548 "\t* Wait a while to make sure that recurring queries are no longer occurring";
549 return AST_TEST_NOT_RUN;
550 case TEST_EXECUTE:
551 break;
552 }
553
555 ast_test_status_update(test, "Failed to register recurring DNS resolver\n");
556 return AST_TEST_FAIL;
557 }
558
559 rdata = recurring_data_alloc();
560 if (!rdata) {
561 ast_test_status_update(test, "Failed to allocate data necessary for recurring test\n");
562 res = AST_TEST_FAIL;
563 goto cleanup;
564 }
565
566 rdata->ttl1 = 5;
567 rdata->ttl2 = 20;
568
569 recurring_query = ast_dns_resolve_recurring("asterisk.org", T_A, C_IN, async_callback, rdata);
570 if (!recurring_query) {
571 ast_test_status_update(test, "Failed to make recurring DNS query\n");
572 res = AST_TEST_FAIL;
573 goto cleanup;
574 }
575
576 if (wait_for_resolution(test, rdata, 0, 1, 1, 0)) {
577 res = AST_TEST_FAIL;
578 goto cleanup;
579 }
580
581 /* Initial query has completed. Now let's make the next query expect a cancelation */
582 rdata->cancel_expected = 1;
583
584 /* Wait to be told that the query should be canceled */
585 ast_mutex_lock(&rdata->lock);
586 while (!rdata->cancel_ready) {
587 ast_cond_wait(&rdata->cond, &rdata->lock);
588 }
589 rdata->cancel_expected = 0;
590 ast_mutex_unlock(&rdata->lock);
591
592 if (ast_dns_resolve_recurring_cancel(recurring_query)) {
593 ast_test_status_update(test, "Failed to cancel recurring DNS query\n");
594 res = AST_TEST_FAIL;
595 goto cleanup;
596 }
597
598 /* Query has been canceled. We'll be told that the query in flight has completed. */
599 if (wait_for_resolution(test, rdata, 0, 2, 1, 1)) {
600 res = AST_TEST_FAIL;
601 goto cleanup;
602 }
603
604 /* Now ensure that no more queries get completed after cancellation. */
605 timeout = ast_tsnow();
606 timeout.tv_sec += 10;
607
608 ast_mutex_lock(&rdata->lock);
609 while (!rdata->query_complete) {
610 if (ast_cond_timedwait(&rdata->cond, &rdata->lock, &timeout) == ETIMEDOUT) {
611 break;
612 }
613 }
614 ast_mutex_unlock(&rdata->lock);
615
616 if (rdata->query_complete) {
617 ast_test_status_update(test, "Recurring query occurred after cancellation\n");
618 res = AST_TEST_FAIL;
619 goto cleanup;
620 }
621
622cleanup:
624 return res;
625}
#define ast_cond_wait(cond, mutex)
Definition: lock.h:205

References ao2_cleanup, ast_cond_timedwait, ast_cond_wait, ast_dns_resolve_recurring(), ast_dns_resolve_recurring_cancel(), ast_dns_resolver_register(), ast_dns_resolver_unregister(), ast_mutex_lock, ast_mutex_unlock, AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, ast_tsnow(), async_callback(), cleanup(), sip_to_pjsip::info(), NULL, RAII_VAR, recurring_data_alloc(), recurring_resolver, TEST_EXECUTE, TEST_INIT, and wait_for_resolution().

◆ AST_TEST_DEFINE() [4/4]

AST_TEST_DEFINE ( recurring_query_off_nominal  )

Definition at line 368 of file test_dns_recurring.c.

369{
370 struct ast_dns_resolver terrible_resolver = {
371 .name = "Harold P. Warren's Filmography",
372 .priority = 0,
373 .resolve = fail_resolve,
374 .cancel = stub_cancel,
375 };
376
377 struct ast_dns_query_recurring *recurring;
378
379 struct dns_resolve_data {
380 const char *name;
381 int rr_type;
382 int rr_class;
384 } resolves [] = {
385 { NULL, T_A, C_IN, stub_callback },
386 { "asterisk.org", -1, C_IN, stub_callback },
387 { "asterisk.org", 65536 + 1, C_IN, stub_callback },
388 { "asterisk.org", T_A, -1, stub_callback },
389 { "asterisk.org", T_A, 65536 + 1, stub_callback },
390 { "asterisk.org", T_A, C_IN, NULL },
391 };
392 int i;
394
395 switch (cmd) {
396 case TEST_INIT:
397 info->name = "recurring_query_off_nominal";
398 info->category = "/main/dns/recurring/";
399 info->summary = "Test off-nominal recurring DNS resolution";
400 info->description =
401 "This test performs several off-nominal recurring DNS resolutions:\n"
402 "\t* Attempt resolution with NULL name\n"
403 "\t* Attempt resolution with invalid RR type\n"
404 "\t* Attempt resolution with invalid RR class\n"
405 "\t* Attempt resolution with NULL callback pointer\n"
406 "\t* Attempt resolution with resolver that returns an error";
407 return AST_TEST_NOT_RUN;
408 case TEST_EXECUTE:
409 break;
410 }
411
413 ast_test_status_update(test, "Failed to register test resolver\n");
414 return AST_TEST_FAIL;
415 }
416
417 for (i = 0; i < ARRAY_LEN(resolves); ++i) {
418 recurring = ast_dns_resolve_recurring(resolves[i].name, resolves[i].rr_type, resolves[i].rr_class,
419 resolves[i].callback, NULL);
420 if (recurring) {
421 ast_test_status_update(test, "Successfully performed recurring resolution with invalid data\n");
423 ao2_ref(recurring, -1);
424 res = AST_TEST_FAIL;
425 }
426 }
427
429
430 if (ast_dns_resolver_register(&terrible_resolver)) {
431 ast_test_status_update(test, "Failed to register the DNS resolver\n");
432 return AST_TEST_FAIL;
433 }
434
435 recurring = ast_dns_resolve_recurring("asterisk.org", T_A, C_IN, stub_callback, NULL);
436
437 ast_dns_resolver_unregister(&terrible_resolver);
438
439 if (recurring) {
440 ast_test_status_update(test, "Successfully performed recurring resolution with invalid data\n");
442 ao2_ref(recurring, -1);
443 return AST_TEST_FAIL;
444 }
445
446 return res;
447}
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
void(* ast_dns_resolve_callback)(const struct ast_dns_query *query)
Callback invoked when a query completes.
Definition: dns_core.h:171
static const char name[]
Definition: format_mp3.c:68
DNS resolver implementation.
Definition: dns_resolver.h:32
const char * name
The name of the resolver implementation.
Definition: dns_resolver.h:34
static int stub_cancel(struct ast_dns_query *query)
static void stub_callback(const struct ast_dns_query *query)
static int fail_resolve(struct ast_dns_query *query)
#define ARRAY_LEN(a)
Definition: utils.h:666

References ao2_ref, ARRAY_LEN, ast_dns_resolve_recurring(), ast_dns_resolve_recurring_cancel(), ast_dns_resolver_register(), ast_dns_resolver_unregister(), AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, fail_resolve(), sip_to_pjsip::info(), name, ast_dns_resolver::name, NULL, recurring_resolver, stub_callback(), stub_cancel(), TEST_EXECUTE, and TEST_INIT.

◆ async_callback()

static void async_callback ( const struct ast_dns_query query)
static

Definition at line 257 of file test_dns_recurring.c.

258{
259 struct recurring_data *rdata = ast_dns_query_get_data(query);
260
261 ast_assert(rdata != NULL);
262
263 ast_mutex_lock(&rdata->lock);
264 rdata->query_complete = 1;
265 ast_cond_signal(&rdata->cond);
266 ast_mutex_unlock(&rdata->lock);
267}
void * ast_dns_query_get_data(const struct ast_dns_query *query)
Get the user specific data of a DNS query.
Definition: dns_core.c:72
#define ast_cond_signal(cond)
Definition: lock.h:203
#define ast_assert(a)
Definition: utils.h:739

References ast_assert, ast_cond_signal, ast_dns_query_get_data(), ast_mutex_lock, ast_mutex_unlock, recurring_data::cond, recurring_data::lock, NULL, and recurring_data::query_complete.

Referenced by AST_TEST_DEFINE().

◆ fail_resolve()

static int fail_resolve ( struct ast_dns_query query)
static

Definition at line 353 of file test_dns_recurring.c.

354{
355 return -1;
356}

Referenced by AST_TEST_DEFINE().

◆ load_module()

static int load_module ( void  )
static

Definition at line 637 of file test_dns_recurring.c.

638{
639 AST_TEST_REGISTER(recurring_query);
640 AST_TEST_REGISTER(recurring_query_off_nominal);
641 AST_TEST_REGISTER(recurring_query_cancel_between);
642 AST_TEST_REGISTER(recurring_query_cancel_during);
643
645}
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
#define AST_TEST_REGISTER(cb)
Definition: test.h:127

References AST_MODULE_LOAD_SUCCESS, and AST_TEST_REGISTER.

◆ recurring_cancel()

static int recurring_cancel ( struct ast_dns_query query)
static

Resolver's cancel() method.

Parameters
queryThe query to cancel
Returns
0

Definition at line 172 of file test_dns_recurring.c.

173{
174 struct ast_dns_query_recurring *recurring = ast_dns_query_get_data(query);
175 struct recurring_data *rdata = recurring->user_data;
176
177 ast_mutex_lock(&rdata->lock);
178 rdata->canceled = 1;
179 ast_cond_signal(&rdata->cond);
180 ast_mutex_unlock(&rdata->lock);
181
182 return 0;
183}
void * user_data
User-specific data.
Definition: dns_internal.h:161

References ast_cond_signal, ast_dns_query_get_data(), ast_mutex_lock, ast_mutex_unlock, recurring_data::canceled, recurring_data::cond, recurring_data::lock, and ast_dns_query_recurring::user_data.

◆ recurring_data_alloc()

static struct recurring_data * recurring_data_alloc ( void  )
static

Definition at line 65 of file test_dns_recurring.c.

66{
67 struct recurring_data *rdata;
68
69 rdata = ao2_alloc(sizeof(*rdata), recurring_data_destructor);
70 if (!rdata) {
71 return NULL;
72 }
73
74 ast_mutex_init(&rdata->lock);
75 ast_cond_init(&rdata->cond, NULL);
76
77 return rdata;
78}
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
#define ast_cond_init(cond, attr)
Definition: lock.h:201
#define ast_mutex_init(pmutex)
Definition: lock.h:186
static void recurring_data_destructor(void *obj)

References ao2_alloc, ast_cond_init, ast_mutex_init, recurring_data::cond, recurring_data::lock, NULL, and recurring_data_destructor().

Referenced by AST_TEST_DEFINE().

◆ recurring_data_destructor()

static void recurring_data_destructor ( void *  obj)
static

Definition at line 57 of file test_dns_recurring.c.

58{
59 struct recurring_data *rdata = obj;
60
61 ast_mutex_destroy(&rdata->lock);
62 ast_cond_destroy(&rdata->cond);
63}
#define ast_cond_destroy(cond)
Definition: lock.h:202
#define ast_mutex_destroy(a)
Definition: lock.h:188

References ast_cond_destroy, ast_mutex_destroy, recurring_data::cond, and recurring_data::lock.

Referenced by recurring_data_alloc().

◆ recurring_resolve()

static int recurring_resolve ( struct ast_dns_query query)
static

Resolver's resolve() method.

Parameters
queryThe query that is to be resolved
Return values
0Successfully created thread to perform the resolution
non-zeroFailed to create resolution thread

Definition at line 155 of file test_dns_recurring.c.

156{
157 struct ast_dns_query_recurring *recurring = ast_dns_query_get_data(query);
158 struct recurring_data *rdata = recurring->user_data;
159 pthread_t resolver_thread;
160
161 ast_assert(rdata != NULL);
162 ++rdata->resolves;
163 return ast_pthread_create_detached(&resolver_thread, NULL, resolution_thread, ao2_bump(query));
164}
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
static void * resolution_thread(void *dns_query)
Thread that performs asynchronous resolution.
#define ast_pthread_create_detached(a, b, c, d)
Definition: utils.h:588

References ao2_bump, ast_assert, ast_dns_query_get_data(), ast_pthread_create_detached, NULL, resolution_thread(), recurring_data::resolves, and ast_dns_query_recurring::user_data.

◆ resolution_thread()

static void * resolution_thread ( void *  dns_query)
static

Thread that performs asynchronous resolution.

This thread uses the query's user data to determine how to perform the resolution. The query may either be canceled or it may be completed with records.

Parameters
dns_queryThe ast_dns_query that is being performed
Returns
NULL

Definition at line 93 of file test_dns_recurring.c.

94{
95 struct ast_dns_query *query = dns_query;
96
97 static const char *ADDR1 = "127.0.0.1";
98 static const size_t ADDR1_BUFSIZE = sizeof(struct in_addr);
99 char addr1_buf[ADDR1_BUFSIZE];
100
101 static const char *ADDR2 = "192.168.0.1";
102 static const size_t ADDR2_BUFSIZE = sizeof(struct in_addr);
103 char addr2_buf[ADDR2_BUFSIZE];
104
105 struct ast_dns_query_recurring *recurring = ast_dns_query_get_data(query);
106 struct recurring_data *rdata = recurring->user_data;
107
108 ast_assert(rdata != NULL);
109
110 /* Canceling is an interesting dance. This thread needs to signal that it is
111 * ready to be canceled. Then it needs to wait until the query is actually canceled.
112 */
113 if (rdata->cancel_expected) {
114 ast_mutex_lock(&rdata->lock);
115 rdata->cancel_ready = 1;
116 ast_cond_signal(&rdata->cond);
117
118 while (!rdata->canceled) {
119 ast_cond_wait(&rdata->cond, &rdata->lock);
120 }
121 ast_mutex_unlock(&rdata->lock);
122
124 ao2_ref(query, -1);
125
126 return NULL;
127 }
128
129 /* When the query isn't canceled, we set the TTL of the results based on what
130 * we've been told to set it to
131 */
132 ast_dns_resolver_set_result(query, 0, 0, NOERROR, "asterisk.org", DNS_ANSWER, DNS_ANSWER_SIZE);
133
134 inet_pton(AF_INET, ADDR1, addr1_buf);
135 ast_dns_resolver_add_record(query, T_A, C_IN, rdata->ttl1, addr1_buf, ADDR1_BUFSIZE);
136
137 inet_pton(AF_INET, ADDR2, addr2_buf);
138 ast_dns_resolver_add_record(query, T_A, C_IN, rdata->ttl2, addr2_buf, ADDR2_BUFSIZE);
139
140 ++rdata->complete_resolutions;
141
143
144 ao2_ref(query, -1);
145 return NULL;
146}
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.
Definition: dns_core.c:456
void ast_dns_resolver_completed(struct ast_dns_query *query)
Mark a DNS query as having been completed.
Definition: dns_core.c:599
int ast_dns_resolver_add_record(struct ast_dns_query *query, int rr_type, int rr_class, int ttl, const char *data, const size_t size)
Add a DNS record to the result of a DNS query.
Definition: dns_core.c:535
A DNS query.
Definition: dns_internal.h:137
#define DNS_ANSWER_SIZE
#define DNS_ANSWER

References ao2_ref, ast_assert, ast_cond_signal, ast_cond_wait, ast_dns_query_get_data(), ast_dns_resolver_add_record(), ast_dns_resolver_completed(), ast_dns_resolver_set_result(), ast_mutex_lock, ast_mutex_unlock, recurring_data::cancel_expected, recurring_data::cancel_ready, recurring_data::canceled, recurring_data::complete_resolutions, recurring_data::cond, DNS_ANSWER, DNS_ANSWER_SIZE, recurring_data::lock, NULL, recurring_data::ttl1, recurring_data::ttl2, and ast_dns_query_recurring::user_data.

Referenced by recurring_resolve().

◆ stub_callback()

static void stub_callback ( const struct ast_dns_query query)
static

Definition at line 363 of file test_dns_recurring.c.

364{
365 return;
366}

Referenced by AST_TEST_DEFINE().

◆ stub_cancel()

static int stub_cancel ( struct ast_dns_query query)
static

Definition at line 358 of file test_dns_recurring.c.

359{
360 return 0;
361}

Referenced by AST_TEST_DEFINE().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 627 of file test_dns_recurring.c.

628{
629 AST_TEST_UNREGISTER(recurring_query);
630 AST_TEST_UNREGISTER(recurring_query_off_nominal);
631 AST_TEST_UNREGISTER(recurring_query_cancel_between);
632 AST_TEST_UNREGISTER(recurring_query_cancel_during);
633
634 return 0;
635}
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128

References AST_TEST_UNREGISTER.

◆ wait_for_resolution()

static int wait_for_resolution ( struct ast_test *  test,
struct recurring_data rdata,
int  expected_lapse,
int  num_resolves,
int  num_completed,
int  canceled 
)
static

Wait for a successful resolution to complete.

This is called whenever a successful DNS resolution occurs. This function serves to ensure that parameters are as we expect them to be.

Parameters
testThe test being executed
rdataDNS query user data
expected_lapseThe amount of time we expect to wait for the query to complete
num_resolvesThe number of DNS resolutions that have been executed
num_completedThe number of DNS resolutions we expect to have completed successfully
canceledWhether the query is expected to have been canceled

Definition at line 205 of file test_dns_recurring.c.

207{
208 struct timespec begin;
209 struct timespec end;
210 struct timespec timeout;
211 int secdiff;
212
213 begin = ast_tsnow();
214
215 timeout.tv_sec = begin.tv_sec + 20;
216 timeout.tv_nsec = begin.tv_nsec;
217
218 ast_mutex_lock(&rdata->lock);
219 while (!rdata->query_complete) {
220 if (ast_cond_timedwait(&rdata->cond, &rdata->lock, &timeout) == ETIMEDOUT) {
221 break;
222 }
223 }
224 ast_mutex_unlock(&rdata->lock);
225
226 if (!rdata->query_complete) {
227 ast_test_status_update(test, "Query timed out\n");
228 return -1;
229 }
230
231 rdata->query_complete = 0;
232 end = ast_tsnow();
233
234 secdiff = end.tv_sec - begin.tv_sec;
235
236 /* Give ourselves some wiggle room */
237 if (secdiff < expected_lapse - 2 || secdiff > expected_lapse + 2) {
238 ast_test_status_update(test, "Query did not complete in expected time\n");
239 return -1;
240 }
241
242 if (rdata->resolves != num_resolves || rdata->complete_resolutions != num_completed) {
243 ast_test_status_update(test, "Query has not undergone expected number of resolutions\n");
244 return -1;
245 }
246
247 if (rdata->canceled != canceled) {
248 ast_test_status_update(test, "Query was canceled unexpectedly\n");
249 return -1;
250 }
251
252 ast_test_status_update(test, "Query completed in expected time frame\n");
253
254 return 0;
255}
char * end
Definition: eagi_proxy.c:73

References ast_cond_timedwait, ast_mutex_lock, ast_mutex_unlock, ast_test_status_update, ast_tsnow(), recurring_data::canceled, recurring_data::complete_resolutions, recurring_data::cond, end, recurring_data::lock, recurring_data::query_complete, and recurring_data::resolves.

Referenced by AST_TEST_DEFINE().

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Recurring DNS query tests" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
static

Definition at line 647 of file test_dns_recurring.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 647 of file test_dns_recurring.c.

◆ recurring_resolver

struct ast_dns_resolver recurring_resolver
static

Definition at line 185 of file test_dns_recurring.c.

Referenced by AST_TEST_DEFINE().