Asterisk - The Open Source Telephony Project  18.5.0
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_off_nominal)
 
 AST_TEST_DEFINE (recurring_query_cancel_between)
 
 AST_TEST_DEFINE (recurring_query_cancel_during)
 
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.

Referenced by resolution_thread().

◆ DNS_ANSWER_SIZE

#define DNS_ANSWER_SIZE   strlen(DNS_ANSWER)

Definition at line 81 of file test_dns_recurring.c.

Referenced by resolution_thread().

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.

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(), TEST_EXECUTE, TEST_INIT, and wait_for_resolution().

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 
342 cleanup:
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 }
static struct ast_dns_resolver recurring_resolver
void ast_dns_resolver_unregister(struct ast_dns_resolver *resolver)
Unregister a DNS resolver.
Definition: dns_core.c:680
static struct recurring_data * recurring_data_alloc(void)
#define NULL
Definition: resample.c:96
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_resolve_recurring_cancel(struct ast_dns_query_recurring *recurring)
Cancel an asynchronous recurring DNS resolution.
#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:911
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
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.
int ast_dns_resolver_register(struct ast_dns_resolver *resolver)
Register a DNS resolver.
Definition: dns_core.c:630
def info(msg)
static void async_callback(const struct ast_dns_query *query)
A recurring DNS query.
Definition: dns_internal.h:157
static void * cleanup(void *unused)
Definition: pbx_realtime.c:124
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
ast_test_result_state
Definition: test.h:200

◆ AST_TEST_DEFINE() [2/4]

AST_TEST_DEFINE ( recurring_query_off_nominal  )

Definition at line 368 of file test_dns_recurring.c.

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(), ast_dns_resolver::name, name, NULL, recurring_data::resolves, stub_callback(), stub_cancel(), TEST_EXECUTE, and TEST_INIT.

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;
383  ast_dns_resolve_callback callback;
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 ARRAY_LEN(a)
Definition: isdn_lib.c:42
static struct ast_dns_resolver recurring_resolver
void ast_dns_resolver_unregister(struct ast_dns_resolver *resolver)
Unregister a DNS resolver.
Definition: dns_core.c:680
void(* ast_dns_resolve_callback)(const struct ast_dns_query *query)
Callback invoked when a query completes.
Definition: dns_core.h:171
#define NULL
Definition: resample.c:96
const char * name
The name of the resolver implementation.
Definition: dns_resolver.h:34
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_resolve_recurring_cancel(struct ast_dns_query_recurring *recurring)
Cancel an asynchronous recurring DNS resolution.
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
int ast_dns_resolver_register(struct ast_dns_resolver *resolver)
Register a DNS resolver.
Definition: dns_core.c:630
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static int fail_resolve(struct ast_dns_query *query)
def info(msg)
static void stub_callback(const struct ast_dns_query *query)
DNS resolver implementation.
Definition: dns_resolver.h:32
static const char name[]
Definition: cdr_mysql.c:74
A recurring DNS query.
Definition: dns_internal.h:157
static int stub_cancel(struct ast_dns_query *query)
ast_test_result_state
Definition: test.h:200

◆ AST_TEST_DEFINE() [3/4]

AST_TEST_DEFINE ( recurring_query_cancel_between  )

Definition at line 449 of file test_dns_recurring.c.

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(), TEST_EXECUTE, TEST_INIT, and wait_for_resolution().

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 
524 cleanup:
526  return res;
527 }
static struct ast_dns_resolver recurring_resolver
void ast_dns_resolver_unregister(struct ast_dns_resolver *resolver)
Unregister a DNS resolver.
Definition: dns_core.c:680
static int timeout
Definition: cdr_mysql.c:86
static struct recurring_data * recurring_data_alloc(void)
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
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_resolve_recurring_cancel(struct ast_dns_query_recurring *recurring)
Cancel an asynchronous recurring DNS resolution.
#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:911
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
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.
int ast_dns_resolver_register(struct ast_dns_resolver *resolver)
Register a DNS resolver.
Definition: dns_core.c:630
def info(msg)
static void async_callback(const struct ast_dns_query *query)
A recurring DNS query.
Definition: dns_internal.h:157
static void * cleanup(void *unused)
Definition: pbx_realtime.c:124
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
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:177
#define ast_cond_timedwait(cond, mutex, time)
Definition: lock.h:204
ast_test_result_state
Definition: test.h:200
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ AST_TEST_DEFINE() [4/4]

AST_TEST_DEFINE ( recurring_query_cancel_during  )

Definition at line 529 of file test_dns_recurring.c.

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(), TEST_EXECUTE, TEST_INIT, and wait_for_resolution().

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 
622 cleanup:
624  return res;
625 }
static struct ast_dns_resolver recurring_resolver
void ast_dns_resolver_unregister(struct ast_dns_resolver *resolver)
Unregister a DNS resolver.
Definition: dns_core.c:680
static int timeout
Definition: cdr_mysql.c:86
static struct recurring_data * recurring_data_alloc(void)
#define ast_cond_wait(cond, mutex)
Definition: lock.h:203
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
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_resolve_recurring_cancel(struct ast_dns_query_recurring *recurring)
Cancel an asynchronous recurring DNS resolution.
#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:911
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
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.
int ast_dns_resolver_register(struct ast_dns_resolver *resolver)
Register a DNS resolver.
Definition: dns_core.c:630
def info(msg)
static void async_callback(const struct ast_dns_query *query)
A recurring DNS query.
Definition: dns_internal.h:157
static void * cleanup(void *unused)
Definition: pbx_realtime.c:124
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
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:177
#define ast_cond_timedwait(cond, mutex, time)
Definition: lock.h:204
ast_test_result_state
Definition: test.h:200
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ async_callback()

static void async_callback ( const struct ast_dns_query query)
static

Definition at line 257 of file test_dns_recurring.c.

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().

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 }
#define ast_assert(a)
Definition: utils.h:695
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
#define ast_cond_signal(cond)
Definition: lock.h:201
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_mutex_unlock(a)
Definition: lock.h:188

◆ fail_resolve()

static int fail_resolve ( struct ast_dns_query query)
static

Definition at line 353 of file test_dns_recurring.c.

Referenced by AST_TEST_DEFINE().

354 {
355  return -1;
356 }

◆ load_module()

static int load_module ( void  )
static

Definition at line 637 of file test_dns_recurring.c.

References AST_MODULE_LOAD_SUCCESS, and AST_TEST_REGISTER.

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 }
#define AST_TEST_REGISTER(cb)
Definition: test.h:127

◆ 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.

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.

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 }
#define ast_mutex_lock(a)
Definition: lock.h:187
#define ast_cond_signal(cond)
Definition: lock.h:201
void * user_data
User-specific data.
Definition: dns_internal.h:161
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
A recurring DNS query.
Definition: dns_internal.h:157
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ recurring_data_alloc()

static struct recurring_data* recurring_data_alloc ( void  )
static

Definition at line 65 of file test_dns_recurring.c.

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().

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 ast_cond_init(cond, attr)
Definition: lock.h:199
#define NULL
Definition: resample.c:96
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
static void recurring_data_destructor(void *obj)
#define ast_mutex_init(pmutex)
Definition: lock.h:184

◆ recurring_data_destructor()

static void recurring_data_destructor ( void *  obj)
static

Definition at line 57 of file test_dns_recurring.c.

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

Referenced by recurring_data_alloc().

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:200
#define ast_mutex_destroy(a)
Definition: lock.h:186

◆ 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.

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.

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 ast_pthread_create_detached(a, b, c, d)
Definition: utils.h:563
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96
#define ao2_bump(obj)
Definition: astobj2.h:491
void * user_data
User-specific data.
Definition: dns_internal.h:161
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
A recurring DNS query.
Definition: dns_internal.h:157
static void * resolution_thread(void *dns_query)
Thread that performs asynchronous resolution.

◆ 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.

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().

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_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
#define ast_cond_wait(cond, mutex)
Definition: lock.h:203
#define ast_assert(a)
Definition: utils.h:695
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
#define DNS_ANSWER_SIZE
#define ast_cond_signal(cond)
Definition: lock.h:201
void * user_data
User-specific data.
Definition: dns_internal.h:161
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 ao2_ref(o, delta)
Definition: astobj2.h:464
#define DNS_ANSWER
void ast_dns_resolver_completed(struct ast_dns_query *query)
Mark a DNS query as having been completed.
Definition: dns_core.c:599
A DNS query.
Definition: dns_internal.h:137
A recurring DNS query.
Definition: dns_internal.h:157
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
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ stub_callback()

static void stub_callback ( const struct ast_dns_query query)
static

Definition at line 363 of file test_dns_recurring.c.

Referenced by AST_TEST_DEFINE().

364 {
365  return;
366 }

◆ stub_cancel()

static int stub_cancel ( struct ast_dns_query query)
static

Definition at line 358 of file test_dns_recurring.c.

Referenced by AST_TEST_DEFINE().

359 {
360  return 0;
361 }

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 627 of file test_dns_recurring.c.

References AST_TEST_UNREGISTER.

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

◆ 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.

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, recurring_data::lock, recurring_data::query_complete, and recurring_data::resolves.

Referenced by AST_TEST_DEFINE().

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 }
static int timeout
Definition: cdr_mysql.c:86
#define ast_mutex_lock(a)
Definition: lock.h:187
char * end
Definition: eagi_proxy.c:73
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
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:177
#define ast_cond_timedwait(cond, mutex, time)
Definition: lock.h:204
#define ast_mutex_unlock(a)
Definition: lock.h:188

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.