Asterisk - The Open Source Telephony Project  GIT-master-4a4f1a5
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"

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)
Definition: astobj2.h:464
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
Definition: logger.h:286
#define NULL
Definition: resample.c:96
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:710
#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, and dns_query_set_query::query.

Referenced by ast_dns_resolve_ipv6_and_ipv4().

◆ 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 
64  query_set = ao2_alloc_options(sizeof(*query_set), dns_query_set_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK);
65  if (!query_set) {
66  return NULL;
67  }
68 
69  if (AST_VECTOR_INIT(&query_set->queries, DNS_QUERY_SET_EXPECTED_QUERY_COUNT)) {
70  ao2_ref(query_set, -1);
71  return NULL;
72  }
73 
74  return query_set;
75 }
@ AO2_ALLOC_OPT_LOCK_NOLOCK
Definition: astobj2.h:369
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:406
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, and NULL.

Referenced by ast_dns_resolve_ipv6_and_ipv4().

◆ 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:611
#define AST_VECTOR_GET_ADDR(vec, idx)
Get an address of element in a vector.
Definition: vector.h:670

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

Referenced by ast_dns_resolve_ipv6_and_ipv4().

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

Referenced by ast_dns_resolve_ipv6_and_ipv4().

◆ 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:1958
#define ao2_bump(obj)
Definition: astobj2.h:491
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, 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().

◆ 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_cancelled, dns_query_set_query::query, and ast_dns_query::resolver.

◆ 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:203
#define ast_cond_init(cond, attr)
Definition: lock.h:199
#define ast_mutex_init(pmutex)
Definition: lock.h:184
#define ast_mutex_unlock(a)
Definition: lock.h:188
#define ast_mutex_lock(a)
Definition: lock.h:187
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:755
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_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, 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:201

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

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

Referenced by ast_query_set_resolve().