Asterisk - The Open Source Telephony Project GIT-master-f36a736
Data Structures | Macros | Functions
dns_query_set.c File Reference

DNS Query Set API. More...

#include "asterisk.h"
#include "asterisk/vector.h"
#include "asterisk/astobj2.h"
#include "asterisk/utils.h"
#include "asterisk/linkedlists.h"
#include "asterisk/dns_core.h"
#include "asterisk/dns_query_set.h"
#include "asterisk/dns_internal.h"
#include "asterisk/dns_resolver.h"
Include dependency graph for dns_query_set.c:

Go to the source code of this file.

Data Structures

struct  dns_synchronous_resolve
 Structure used for signaling back for synchronous resolution completion. More...
 

Macros

#define DNS_QUERY_SET_EXPECTED_QUERY_COUNT   5
 The default number of expected queries to be added to the query set. More...
 

Functions

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. More...
 
struct ast_dns_query_setast_dns_query_set_create (void)
 Create a query set to hold queries. More...
 
struct ast_dns_queryast_dns_query_set_get (const struct ast_dns_query_set *query_set, unsigned int index)
 Retrieve a query from a query set. More...
 
void * ast_dns_query_set_get_data (const struct ast_dns_query_set *query_set)
 Retrieve user specific data from a query set. More...
 
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. More...
 
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. More...
 
int ast_dns_query_set_resolve_cancel (struct ast_dns_query_set *query_set)
 Cancel an asynchronous DNS query set resolution. More...
 
int ast_query_set_resolve (struct ast_dns_query_set *query_set)
 Synchronously resolve queries in a query set. More...
 
static void dns_query_set_callback (const struct ast_dns_query *query)
 Callback invoked upon completion of a DNS query. More...
 
static void dns_query_set_destroy (void *data)
 Destructor for DNS query set. More...
 
static void dns_synchronous_resolve_callback (const struct ast_dns_query_set *query_set)
 Callback used to implement synchronous resolution. More...
 
static void dns_synchronous_resolve_destroy (void *data)
 Destructor for synchronous resolution structure. More...
 

Detailed Description

DNS Query Set API.

Author
Joshua Colp jcolp.nosp@m.@dig.nosp@m.ium.c.nosp@m.om

Definition in file dns_query_set.c.

Macro Definition Documentation

◆ DNS_QUERY_SET_EXPECTED_QUERY_COUNT

#define DNS_QUERY_SET_EXPECTED_QUERY_COUNT   5

The default number of expected queries to be added to the query set.

Definition at line 42 of file dns_query_set.c.

Function Documentation

◆ ast_dns_query_set_add()

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.

Parameters
query_setA DNS query set
nameThe name of what to resolve
rr_typeResource record type
rr_classResource record class
Return values
0success
-1failure

Definition at line 105 of file dns_query_set.c.

106{
107 struct dns_query_set_query query = {
108 .started = 0,
109 };
110
111 ast_assert(!query_set->in_progress);
112 if (query_set->in_progress) {
113 ast_log(LOG_ERROR, "Attempted to add additional query to query set '%p' after resolution has started\n",
114 query_set);
115 return -1;
116 }
117
118 /*
119 * We are intentionally passing NULL for the user data even
120 * though dns_query_set_callback() is not NULL tolerant. Doing
121 * this avoids a circular reference chain until the queries are
122 * started. ast_dns_query_set_resolve_async() will set the
123 * query user_data for us later when we actually kick off the
124 * queries.
125 */
126 query.query = dns_query_alloc(name, rr_type, rr_class, dns_query_set_callback, NULL);
127 if (!query.query) {
128 return -1;
129 }
130
131 if (AST_VECTOR_APPEND(&query_set->queries, query)) {
132 ao2_ref(query.query, -1);
133 return -1;
134 }
135
136 return 0;
137}
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
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
static void dns_query_set_callback(const struct ast_dns_query *query)
Callback invoked upon completion of a DNS query.
Definition: dns_query_set.c:78
static const char name[]
Definition: format_mp3.c:68
#define LOG_ERROR
#define NULL
Definition: resample.c:96
struct ast_dns_query_set::@216 queries
DNS queries.
int in_progress
Whether the query set is in progress or not.
Definition: dns_internal.h:189
A DNS query set query, which includes its state.
Definition: dns_internal.h:177
struct ast_dns_query * query
The query itself.
Definition: dns_internal.h:181
#define ast_assert(a)
Definition: utils.h:739
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256

References ao2_ref, ast_assert, ast_log, AST_VECTOR_APPEND, dns_query_alloc(), dns_query_set_callback(), ast_dns_query_set::in_progress, LOG_ERROR, name, NULL, ast_dns_query_set::queries, and dns_query_set_query::query.

Referenced by ast_dns_resolve_ipv6_and_ipv4(), and query_set_test().

◆ ast_dns_query_set_create()

struct ast_dns_query_set * ast_dns_query_set_create ( void  )

Create a query set to hold queries.

Return values
non-NULLsuccess
NULLfailure
Note
The query set must be released upon cancellation or completion using ao2_ref

Definition at line 60 of file dns_query_set.c.

61{
62 struct ast_dns_query_set *query_set;
63
65 if (!query_set) {
66 return NULL;
67 }
68
70 ao2_ref(query_set, -1);
71 return NULL;
72 }
73
74 return query_set;
75}
@ AO2_ALLOC_OPT_LOCK_NOLOCK
Definition: astobj2.h:367
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:404
static void dns_query_set_destroy(void *data)
Destructor for DNS query set.
Definition: dns_query_set.c:45
#define DNS_QUERY_SET_EXPECTED_QUERY_COUNT
The default number of expected queries to be added to the query set.
Definition: dns_query_set.c:42
A set of DNS queries.
Definition: dns_internal.h:185
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_ref, AST_VECTOR_INIT, dns_query_set_destroy(), DNS_QUERY_SET_EXPECTED_QUERY_COUNT, NULL, and ast_dns_query_set::queries.

Referenced by ast_dns_resolve_ipv6_and_ipv4(), and query_set_test().

◆ ast_dns_query_set_get()

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.

Parameters
query_setA DNS query set
indexThe index of the query to retrieve
Return values
non-NULLsuccess
NULLfailure
Note
The returned query is only valid for the lifetime of the query set itself

Definition at line 144 of file dns_query_set.c.

145{
146 /* Only once all queries have been completed can results be retrieved */
147 if (query_set->queries_completed != AST_VECTOR_SIZE(&query_set->queries)) {
148 return NULL;
149 }
150
151 /* If the index exceeds the number of queries... no query for you */
152 if (index >= AST_VECTOR_SIZE(&query_set->queries)) {
153 return NULL;
154 }
155
156 return AST_VECTOR_GET_ADDR(&query_set->queries, index)->query;
157}
int queries_completed
The total number of completed queries.
Definition: dns_internal.h:191
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:609
#define AST_VECTOR_GET_ADDR(vec, idx)
Get an address of element in a vector.
Definition: vector.h:668

References AST_VECTOR_GET_ADDR, AST_VECTOR_SIZE, NULL, ast_dns_query_set::queries, and ast_dns_query_set::queries_completed.

Referenced by ast_dns_resolve_ipv6_and_ipv4(), and query_set_test().

◆ ast_dns_query_set_get_data()

void * ast_dns_query_set_get_data ( const struct ast_dns_query_set query_set)

Retrieve user specific data from a query set.

Parameters
query_setA DNS query set
Returns
user specific data

Definition at line 159 of file dns_query_set.c.

160{
161 return query_set->user_data;
162}
void * user_data
User-specific data.
Definition: dns_internal.h:197

References ast_dns_query_set::user_data.

Referenced by dns_synchronous_resolve_callback(), and query_set_callback().

◆ ast_dns_query_set_num_queries()

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.

Parameters
query_setA DNS query set
Returns
the number of queries

Definition at line 139 of file dns_query_set.c.

140{
141 return AST_VECTOR_SIZE(&query_set->queries);
142}

References AST_VECTOR_SIZE, and ast_dns_query_set::queries.

Referenced by ast_dns_resolve_ipv6_and_ipv4(), and query_set_test().

◆ ast_dns_query_set_resolve_async()

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.

Parameters
query_setThe query set
callbackThe callback to invoke upon completion
dataUser data to make available on the query set
Note
The callback will be invoked when all queries have completed
The user data passed in to this function must be ao2 allocated

Definition at line 164 of file dns_query_set.c.

165{
166 int idx;
167
168 ast_assert(!query_set->in_progress);
169 if (query_set->in_progress) {
170 ast_log(LOG_ERROR, "Attempted to start asynchronous resolution of query set '%p' when it has already started\n",
171 query_set);
172 return;
173 }
174
175 query_set->in_progress = 1;
176 query_set->callback = callback;
177 query_set->user_data = ao2_bump(data);
178
179 /*
180 * Bump the query_set ref in case all queries complete
181 * before we are done kicking them off.
182 */
183 ao2_ref(query_set, +1);
184 for (idx = 0; idx < AST_VECTOR_SIZE(&query_set->queries); ++idx) {
185 struct dns_query_set_query *query = AST_VECTOR_GET_ADDR(&query_set->queries, idx);
186
187 query->query->user_data = ao2_bump(query_set);
188
189 if (!query->query->resolver->resolve(query->query)) {
190 query->started = 1;
191 continue;
192 }
193
195 }
196 if (!idx) {
197 /*
198 * There were no queries in the set;
199 * therefore all queries are "completed".
200 * Invoke the final callback.
201 */
202 query_set->callback(query_set);
203 ao2_cleanup(query_set->user_data);
204 query_set->user_data = NULL;
205 }
206 ao2_ref(query_set, -1);
207}
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
ast_dns_query_set_callback callback
Callback to invoke upon completion.
Definition: dns_internal.h:195
void * user_data
User-specific data.
Definition: dns_internal.h:141
struct ast_dns_resolver * resolver
The resolver in use for this query.
Definition: dns_internal.h:143
int(* resolve)(struct ast_dns_query *query)
Perform resolution of a DNS query.
Definition: dns_resolver.h:45

References ao2_bump, ao2_cleanup, ao2_ref, ast_assert, ast_log, AST_VECTOR_GET_ADDR, AST_VECTOR_SIZE, ast_dns_query::callback, ast_dns_query_set::callback, dns_query_set_callback(), ast_dns_query_set::in_progress, LOG_ERROR, NULL, ast_dns_query_set::queries, dns_query_set_query::query, ast_dns_resolver::resolve, ast_dns_query::resolver, ast_dns_query::user_data, and ast_dns_query_set::user_data.

Referenced by ast_query_set_resolve(), and query_set_test().

◆ ast_dns_query_set_resolve_cancel()

int ast_dns_query_set_resolve_cancel ( struct ast_dns_query_set query_set)

Cancel an asynchronous DNS query set resolution.

Parameters
query_setThe DNS query set
Return values
0success (all queries have been cancelled)
-1failure (some queries could not be cancelled)
Note
If successfully cancelled the callback will not be invoked

Definition at line 265 of file dns_query_set.c.

266{
267 int idx;
268 size_t query_count = AST_VECTOR_SIZE(&query_set->queries);
269
270 for (idx = 0; idx < AST_VECTOR_SIZE(&query_set->queries); ++idx) {
271 struct dns_query_set_query *query = AST_VECTOR_GET_ADDR(&query_set->queries, idx);
272
273 if (query->started) {
274 if (!query->query->resolver->cancel(query->query)) {
275 query_set->queries_cancelled++;
277 }
278 } else {
279 query_set->queries_cancelled++;
280 }
281 }
282
283 return (query_set->queries_cancelled == query_count) ? 0 : -1;
284}
int queries_cancelled
The total number of cancelled queries.
Definition: dns_internal.h:193
int(* cancel)(struct ast_dns_query *query)
Cancel resolution of a DNS query.
Definition: dns_resolver.h:48

References AST_VECTOR_GET_ADDR, AST_VECTOR_SIZE, ast_dns_resolver::cancel, dns_query_set_callback(), ast_dns_query_set::queries, ast_dns_query_set::queries_cancelled, dns_query_set_query::query, and ast_dns_query::resolver.

Referenced by query_set_test().

◆ ast_query_set_resolve()

int ast_query_set_resolve ( struct ast_dns_query_set query_set)

Synchronously resolve queries in a query set.

Parameters
query_setThe query set
Return values
0success
-1failure
Note
This function will return when all queries have been completed

Definition at line 239 of file dns_query_set.c.

240{
241 struct dns_synchronous_resolve *synchronous;
242
244 if (!synchronous) {
245 return -1;
246 }
247
248 ast_mutex_init(&synchronous->lock);
249 ast_cond_init(&synchronous->cond, NULL);
250
252
253 /* Wait for resolution to complete */
254 ast_mutex_lock(&synchronous->lock);
255 while (!synchronous->completed) {
256 ast_cond_wait(&synchronous->cond, &synchronous->lock);
257 }
258 ast_mutex_unlock(&synchronous->lock);
259
260 ao2_ref(synchronous, -1);
261
262 return 0;
263}
static void dns_synchronous_resolve_callback(const struct ast_dns_query_set *query_set)
Callback used to implement synchronous resolution.
static void dns_synchronous_resolve_destroy(void *data)
Destructor for synchronous resolution structure.
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.
#define ast_cond_wait(cond, mutex)
Definition: lock.h:205
#define ast_cond_init(cond, attr)
Definition: lock.h:201
#define ast_mutex_init(pmutex)
Definition: lock.h:186
#define ast_mutex_unlock(a)
Definition: lock.h:190
#define ast_mutex_lock(a)
Definition: lock.h:189
Structure used for signaling back for synchronous resolution completion.
Definition: dns_core.c:278
ast_cond_t cond
Condition used for signaling.
Definition: dns_core.c:282
ast_mutex_t lock
Lock used for signaling.
Definition: dns_core.c:280
unsigned int completed
Whether the query has completed.
Definition: dns_core.c:284

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_ref, ast_cond_init, ast_cond_wait, ast_dns_query_set_resolve_async(), ast_mutex_init, ast_mutex_lock, ast_mutex_unlock, dns_synchronous_resolve::completed, dns_synchronous_resolve::cond, dns_synchronous_resolve_callback(), dns_synchronous_resolve_destroy(), dns_synchronous_resolve::lock, and NULL.

Referenced by ast_dns_resolve_ipv6_and_ipv4().

◆ dns_query_set_callback()

static void dns_query_set_callback ( const struct ast_dns_query query)
static

Callback invoked upon completion of a DNS query.

Definition at line 78 of file dns_query_set.c.

79{
80 struct ast_dns_query_set *query_set = ast_dns_query_get_data(query);
81
82 /* The reference count of the query set is bumped here in case this query holds the last reference */
83 ao2_ref(query_set, +1);
84
85 /* Drop the query set from the query so the query set can be destroyed if this is the last one */
86 ao2_cleanup(((struct ast_dns_query *)query)->user_data);
87 ((struct ast_dns_query *)query)->user_data = NULL;
88
89 if (ast_atomic_fetchadd_int(&query_set->queries_completed, +1) != (AST_VECTOR_SIZE(&query_set->queries) - 1)) {
90 ao2_ref(query_set, -1);
91 return;
92 }
93
94 /* All queries have been completed, invoke final callback */
95 if (query_set->queries_cancelled != AST_VECTOR_SIZE(&query_set->queries)) {
96 query_set->callback(query_set);
97 }
98
99 ao2_cleanup(query_set->user_data);
100 query_set->user_data = NULL;
101
102 ao2_ref(query_set, -1);
103}
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
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:757
A DNS query.
Definition: dns_internal.h:137

References ao2_cleanup, ao2_ref, ast_atomic_fetchadd_int(), ast_dns_query_get_data(), AST_VECTOR_SIZE, ast_dns_query_set::callback, NULL, ast_dns_query_set::queries, ast_dns_query_set::queries_cancelled, ast_dns_query_set::queries_completed, and ast_dns_query_set::user_data.

Referenced by ast_dns_query_set_add(), ast_dns_query_set_resolve_async(), and ast_dns_query_set_resolve_cancel().

◆ dns_query_set_destroy()

static void dns_query_set_destroy ( void *  data)
static

Destructor for DNS query set.

Definition at line 45 of file dns_query_set.c.

46{
47 struct ast_dns_query_set *query_set = data;
48 int idx;
49
50 for (idx = 0; idx < AST_VECTOR_SIZE(&query_set->queries); ++idx) {
51 struct dns_query_set_query *query = AST_VECTOR_GET_ADDR(&query_set->queries, idx);
52
53 ao2_ref(query->query, -1);
54 }
55 AST_VECTOR_FREE(&query_set->queries);
56
57 ao2_cleanup(query_set->user_data);
58}
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174

References ao2_cleanup, ao2_ref, AST_VECTOR_FREE, AST_VECTOR_GET_ADDR, AST_VECTOR_SIZE, ast_dns_query_set::queries, dns_query_set_query::query, and ast_dns_query_set::user_data.

Referenced by ast_dns_query_set_create().

◆ dns_synchronous_resolve_callback()

static void dns_synchronous_resolve_callback ( const struct ast_dns_query_set query_set)
static

Callback used to implement synchronous resolution.

Definition at line 229 of file dns_query_set.c.

230{
231 struct dns_synchronous_resolve *synchronous = ast_dns_query_set_get_data(query_set);
232
233 ast_mutex_lock(&synchronous->lock);
234 synchronous->completed = 1;
235 ast_cond_signal(&synchronous->cond);
236 ast_mutex_unlock(&synchronous->lock);
237}
void * ast_dns_query_set_get_data(const struct ast_dns_query_set *query_set)
Retrieve user specific data from a query set.
#define ast_cond_signal(cond)
Definition: lock.h:203

References ast_cond_signal, ast_dns_query_set_get_data(), ast_mutex_lock, ast_mutex_unlock, dns_synchronous_resolve::completed, dns_synchronous_resolve::cond, and dns_synchronous_resolve::lock.

Referenced by ast_query_set_resolve().

◆ dns_synchronous_resolve_destroy()

static void dns_synchronous_resolve_destroy ( void *  data)
static

Destructor for synchronous resolution structure.

Definition at line 220 of file dns_query_set.c.

221{
222 struct dns_synchronous_resolve *synchronous = data;
223
224 ast_mutex_destroy(&synchronous->lock);
225 ast_cond_destroy(&synchronous->cond);
226}
#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, dns_synchronous_resolve::cond, and dns_synchronous_resolve::lock.

Referenced by ast_query_set_resolve().