Asterisk - The Open Source Telephony Project GIT-master-4c84066
Loading...
Searching...
No Matches
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 <jcolp@digium.com>
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 <jcolp@digium.com>
24 */
25
26/*** MODULEINFO
27 <support_level>core</support_level>
28 ***/
29
30#include "asterisk.h"
31
32#include "asterisk/astobj2.h"
34#include "asterisk/sched.h"
35#include "asterisk/strings.h"
36#include "asterisk/dns_core.h"
39
40#include <arpa/nameser.h>
41
42/*! \brief Delay between TTL expiration and the next DNS query, to make sure the
43resolver cache really expired. */
44#define EXTRA_TTL 2
45#define MAX_TTL ((INT_MAX - EXTRA_TTL) / 1000)
46
47/*! \brief Destructor for a DNS query */
48static void dns_query_recurring_destroy(void *data)
49{
50 struct ast_dns_query_recurring *recurring = data;
51
52 ao2_cleanup(recurring->user_data);
53}
54
55static void dns_query_recurring_resolution_callback(const struct ast_dns_query *query);
56
57/*! \brief Scheduled recurring query callback */
58static int dns_query_recurring_scheduled_callback(const void *data)
59{
60 struct ast_dns_query_recurring *recurring = (struct ast_dns_query_recurring *)data;
61
62 ao2_lock(recurring);
63 recurring->timer = -1;
64 if (!recurring->cancelled) {
65 recurring->active = ast_dns_resolve_async(recurring->name, recurring->rr_type, recurring->rr_class, dns_query_recurring_resolution_callback,
66 recurring);
67 }
68 ao2_unlock(recurring);
69
70 ao2_ref(recurring, -1);
71
72 return 0;
73}
74
75/*! \brief Query resolution callback */
77{
78 struct ast_dns_query_recurring *recurring = ast_dns_query_get_data(query);
79 struct ast_dns_query *callback_query;
80
81 /* Create a separate query to invoke the user specific callback on as the
82 * recurring query user data may get used externally (by the unit test)
83 * and thus changing it is problematic
84 */
85 callback_query = dns_query_alloc(query->name, query->rr_type, query->rr_class,
86 recurring->callback, recurring->user_data);
87 if (callback_query) {
88 /* The result is immutable at this point and can be safely provided */
89 callback_query->result = query->result;
90 callback_query->callback(callback_query);
91 callback_query->result = NULL;
92 ao2_ref(callback_query, -1);
93 }
94
95 ao2_lock(recurring);
96 /* So.. if something has not externally cancelled this we can reschedule based on the TTL */
97 if (!recurring->cancelled) {
98 const struct ast_dns_result *result = ast_dns_query_get_result(query);
100
101 if (ttl) {
103 if (recurring->timer < 0) {
104 /* It is impossible for this to be the last reference as the query has a reference to it */
105 ao2_ref(recurring, -1);
106 }
107 ast_debug(2, "Rescheduled resolution for name: %s class: %d type: %d in %d seconds",
110 } else {
111 ast_debug(2, "TTL = 0 so not rescheduling resolution for name: %s class: %d type: %d",
113 }
114 } else {
115 ast_debug(2, "Recurring resolution cancelled for name: %s class: %d type: %d",
117 }
118
119 ao2_replace(recurring->active, NULL);
120 ao2_unlock(recurring);
121}
122
124{
125 struct ast_dns_query_recurring *recurring;
126
128 return NULL;
129 }
130
131 recurring = ao2_alloc(sizeof(*recurring) + strlen(name) + 1, dns_query_recurring_destroy);
132 if (!recurring) {
133 return NULL;
134 }
135
136 recurring->callback = callback;
137 recurring->user_data = ao2_bump(data);
138 recurring->timer = -1;
139 recurring->rr_type = rr_type;
140 recurring->rr_class = rr_class;
141 strcpy(recurring->name, name); /* SAFE */
142
144 if (!recurring->active) {
145 ao2_ref(recurring, -1);
146 return NULL;
147 }
148
149 return recurring;
150}
151
153{
154 int res = 0;
155
156 ao2_lock(recurring);
157
158 ast_debug(2, "Cancelling recurring resolution for name: %s class: %d type: %d",
159 recurring->name, recurring->rr_class, recurring->rr_type);
160
161 recurring->cancelled = 1;
162 AST_SCHED_DEL_UNREF(ast_dns_get_sched(), recurring->timer, ao2_ref(recurring, -1));
163
164 if (recurring->active) {
165 res = ast_dns_resolve_cancel(recurring->active);
166 ao2_replace(recurring->active, NULL);
167 }
168
169 ao2_unlock(recurring);
170
171 return res;
172}
Asterisk main include file. File version handling, generic pbx functions.
#define ao2_cleanup(obj)
Definition astobj2.h:1934
#define ao2_unlock(a)
Definition astobj2.h:729
#define ao2_replace(dst, src)
Replace one object reference with another cleaning up the original.
Definition astobj2.h:501
#define ao2_lock(a)
Definition astobj2.h:717
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition astobj2.h:459
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition astobj2.h:480
#define ao2_alloc(data_size, destructor_fn)
Definition astobj2.h:409
static PGresult * result
Definition cel_pgsql.c:84
static struct ast_channel * callback(struct ast_channelstorage_instance *driver, ao2_callback_data_fn *cb_fn, void *arg, void *data, int ao2_flags, int rdlock)
Core DNS API.
int ast_dns_query_get_rr_type(const struct ast_dns_query *query)
Get the record resource type of a DNS query.
Definition dns_core.c:62
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 ast_dns_resolve_cancel(struct ast_dns_query_active *active)
Cancel an asynchronous DNS resolution.
Definition dns_core.c:273
int ast_dns_query_get_rr_class(const struct ast_dns_query *query)
Get the record resource class of a DNS query.
Definition dns_core.c:67
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_resolve_callback)(const struct ast_dns_query *query)
Callback invoked when a query completes.
Definition dns_core.h:171
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
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
const char * ast_dns_query_get_name(const struct ast_dns_query *query)
Get the name queried in a DNS query.
Definition dns_core.c:57
Internal DNS structure definitions.
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
#define EXTRA_TTL
Delay between TTL expiration and the next DNS query, to make sure the resolver cache really expired.
int ast_dns_resolve_recurring_cancel(struct ast_dns_query_recurring *recurring)
Cancel an asynchronous recurring DNS resolution.
#define MAX_TTL
static void dns_query_recurring_destroy(void *data)
Destructor for a DNS query.
static void dns_query_recurring_resolution_callback(const struct ast_dns_query *query)
Query resolution callback.
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.
static int dns_query_recurring_scheduled_callback(const void *data)
Scheduled recurring query callback.
DNS Recurring Resolution API.
static const char name[]
Definition format_mp3.c:68
#define ast_debug(level,...)
Log a DEBUG message.
A set of macros to manage forward-linked lists.
#define NULL
Definition resample.c:96
Scheduler Routines (derived from cheops)
#define AST_SCHED_DEL_UNREF(sched, id, refcall)
schedule task to get deleted and call unref function
Definition sched.h:82
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:567
String manipulation functions.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition strings.h:65
A recurring DNS query.
void * user_data
User-specific data.
ast_dns_resolve_callback callback
Callback to invoke upon completion.
unsigned int cancelled
The recurring query has been cancelled.
struct ast_dns_query_active * active
Current active query.
int rr_class
Resource record class.
int rr_type
Resource record type.
int timer
Scheduled timer for next resolution.
char name[0]
The name of what is being resolved.
A DNS query.
ast_dns_resolve_callback callback
Callback to invoke upon completion.
struct ast_dns_result * result
Result of the DNS query.
int rr_class
Resource record class.
int rr_type
Resource record type.
char name[0]
The name of what is being resolved.
The result of a DNS query.
#define MIN(a, b)
Definition utils.h:252