Asterisk - The Open Source Telephony Project  18.5.0
dns_recurring.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2015, Digium, Inc.
5  *
6  * Joshua Colp <[email protected]>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*! \file
20  *
21  * \brief DNS Recurring Query Support
22  *
23  * \author Joshua Colp <[email protected]>
24  */
25 
26 /*** MODULEINFO
27  <support_level>core</support_level>
28  ***/
29 
30 #include "asterisk.h"
31 
32 #include "asterisk/astobj2.h"
33 #include "asterisk/linkedlists.h"
34 #include "asterisk/sched.h"
35 #include "asterisk/strings.h"
36 #include "asterisk/dns_core.h"
37 #include "asterisk/dns_recurring.h"
38 #include "asterisk/dns_internal.h"
39 
40 #include <arpa/nameser.h>
41 
42 /*! \brief Destructor for a DNS query */
43 static void dns_query_recurring_destroy(void *data)
44 {
45  struct ast_dns_query_recurring *recurring = data;
46 
47  ao2_cleanup(recurring->user_data);
48 }
49 
50 static void dns_query_recurring_resolution_callback(const struct ast_dns_query *query);
51 
52 /*! \brief Scheduled recurring query callback */
53 static int dns_query_recurring_scheduled_callback(const void *data)
54 {
55  struct ast_dns_query_recurring *recurring = (struct ast_dns_query_recurring *)data;
56 
57  ao2_lock(recurring);
58  recurring->timer = -1;
59  if (!recurring->cancelled) {
60  recurring->active = ast_dns_resolve_async(recurring->name, recurring->rr_type, recurring->rr_class, dns_query_recurring_resolution_callback,
61  recurring);
62  }
63  ao2_unlock(recurring);
64 
65  ao2_ref(recurring, -1);
66 
67  return 0;
68 }
69 
70 /*! \brief Query resolution callback */
72 {
73  struct ast_dns_query_recurring *recurring = ast_dns_query_get_data(query);
74  struct ast_dns_query *callback_query;
75 
76  /* Create a separate query to invoke the user specific callback on as the
77  * recurring query user data may get used externally (by the unit test)
78  * and thus changing it is problematic
79  */
80  callback_query = dns_query_alloc(query->name, query->rr_type, query->rr_class,
81  recurring->callback, recurring->user_data);
82  if (callback_query) {
83  /* The result is immutable at this point and can be safely provided */
84  callback_query->result = query->result;
85  callback_query->callback(callback_query);
86  callback_query->result = NULL;
87  ao2_ref(callback_query, -1);
88  }
89 
90  ao2_lock(recurring);
91  /* So.. if something has not externally cancelled this we can reschedule based on the TTL */
92  if (!recurring->cancelled) {
93  const struct ast_dns_result *result = ast_dns_query_get_result(query);
94  int ttl = MIN(ast_dns_result_get_lowest_ttl(result), INT_MAX / 1000);
95 
96  if (ttl) {
98  if (recurring->timer < 0) {
99  /* It is impossible for this to be the last reference as the query has a reference to it */
100  ao2_ref(recurring, -1);
101  }
102  }
103  }
104 
105  ao2_replace(recurring->active, NULL);
106  ao2_unlock(recurring);
107 }
108 
110 {
111  struct ast_dns_query_recurring *recurring;
112 
113  if (ast_strlen_zero(name) || !callback || !ast_dns_get_sched()) {
114  return NULL;
115  }
116 
117  recurring = ao2_alloc(sizeof(*recurring) + strlen(name) + 1, dns_query_recurring_destroy);
118  if (!recurring) {
119  return NULL;
120  }
121 
122  recurring->callback = callback;
123  recurring->user_data = ao2_bump(data);
124  recurring->timer = -1;
125  recurring->rr_type = rr_type;
126  recurring->rr_class = rr_class;
127  strcpy(recurring->name, name); /* SAFE */
128 
129  recurring->active = ast_dns_resolve_async(name, rr_type, rr_class, dns_query_recurring_resolution_callback, recurring);
130  if (!recurring->active) {
131  ao2_ref(recurring, -1);
132  return NULL;
133  }
134 
135  return recurring;
136 }
137 
139 {
140  int res = 0;
141 
142  ao2_lock(recurring);
143 
144  recurring->cancelled = 1;
145  AST_SCHED_DEL_UNREF(ast_dns_get_sched(), recurring->timer, ao2_ref(recurring, -1));
146 
147  if (recurring->active) {
148  res = ast_dns_resolve_cancel(recurring->active);
149  ao2_replace(recurring->active, NULL);
150  }
151 
152  ao2_unlock(recurring);
153 
154  return res;
155 }
Asterisk main include file. File version handling, generic pbx functions.
ast_dns_resolve_callback callback
Callback to invoke upon completion.
Definition: dns_internal.h:159
char name[0]
The name of what is being resolved.
Definition: dns_internal.h:173
String manipulation functions.
void(* ast_dns_resolve_callback)(const struct ast_dns_query *query)
Callback invoked when a query completes.
Definition: dns_core.h:171
int rr_type
Resource record type.
Definition: dns_internal.h:149
struct ast_dns_query_active * ast_dns_resolve_async(const char *name, int rr_type, int rr_class, ast_dns_resolve_callback callback, void *data)
Asynchronously resolve a DNS query.
Definition: dns_core.c:247
int rr_class
Resource record class.
Definition: dns_internal.h:151
int rr_class
Resource record class.
Definition: dns_internal.h:171
#define AST_SCHED_DEL_UNREF(sched, id, refcall)
schedule task to get deleted and call unref function
Definition: sched.h:80
static int dns_query_recurring_scheduled_callback(const void *data)
Scheduled recurring query callback.
Definition: dns_recurring.c:53
#define ao2_unlock(a)
Definition: astobj2.h:730
char name[0]
The name of what is being resolved.
Definition: dns_internal.h:153
static void dns_query_recurring_destroy(void *data)
Destructor for a DNS query.
Definition: dns_recurring.c:43
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ao2_bump(obj)
Definition: astobj2.h:491
#define MIN(a, b)
Definition: utils.h:226
void * user_data
User-specific data.
Definition: dns_internal.h:161
struct ast_sched_context * ast_dns_get_sched(void)
Retrieve the DNS scheduler context.
Definition: dns_core.c:52
struct ast_dns_query * dns_query_alloc(const char *name, int rr_type, int rr_class, ast_dns_resolve_callback callback, void *data)
Allocate a DNS query (but do not start resolution)
Definition: dns_core.c:193
int ast_dns_result_get_lowest_ttl(const struct ast_dns_result *result)
Retrieve the lowest TTL from a result.
Definition: dns_core.c:112
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
Scheduler Routines (derived from cheops)
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct ast_dns_query_active * active
Current active query.
Definition: dns_internal.h:163
#define ao2_lock(a)
Definition: astobj2.h:718
A set of macros to manage forward-linked lists.
The result of a DNS query.
Definition: dns_internal.h:117
unsigned int cancelled
The recurring query has been cancelled.
Definition: dns_internal.h:165
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...
struct ast_dns_result * ast_dns_query_get_result(const struct ast_dns_query *query)
Get the result information for a DNS query.
Definition: dns_core.c:77
struct ast_dns_result * result
Result of the DNS query.
Definition: dns_internal.h:147
static void dns_query_recurring_resolution_callback(const struct ast_dns_query *query)
Query resolution callback.
Definition: dns_recurring.c:71
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
Internal DNS structure definitions.
ast_dns_resolve_callback callback
Callback to invoke upon completion.
Definition: dns_internal.h:139
static const char name[]
Definition: cdr_mysql.c:74
A DNS query.
Definition: dns_internal.h:137
A recurring DNS query.
Definition: dns_internal.h:157
int ast_sched_add(struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result
Adds a scheduled event.
Definition: sched.c:565
#define ao2_replace(dst, src)
Definition: astobj2.h:517
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
int ast_dns_resolve_recurring_cancel(struct ast_dns_query_recurring *recurring)
Cancel an asynchronous recurring DNS resolution.
int ast_dns_resolve_cancel(struct ast_dns_query_active *active)
Cancel an asynchronous DNS resolution.
Definition: dns_core.c:272
static PGresult * result
Definition: cel_pgsql.c:88
int rr_type
Resource record type.
Definition: dns_internal.h:169
Core DNS API.
DNS Recurring Resolution API.
int timer
Scheduled timer for next resolution.
Definition: dns_internal.h:167