[asterisk-commits] file: branch group/dns r432451 - /team/group/dns/main/dns_core.c
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Wed Mar 4 12:33:38 CST 2015
Author: file
Date: Wed Mar 4 12:33:36 2015
New Revision: 432451
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=432451
Log:
Implement synchronous resolution using asynchronous resolution.
Modified:
team/group/dns/main/dns_core.c
Modified: team/group/dns/main/dns_core.c
URL: http://svnview.digium.com/svn/asterisk/team/group/dns/main/dns_core.c?view=diff&rev=432451&r1=432450&r2=432451
==============================================================================
--- team/group/dns/main/dns_core.c (original)
+++ team/group/dns/main/dns_core.c Wed Mar 4 12:33:36 2015
@@ -34,6 +34,7 @@
#include "asterisk/linkedlists.h"
#include "asterisk/vector.h"
#include "asterisk/astobj2.h"
+#include "asterisk/strings.h"
#include "asterisk/dns_core.h"
#include "asterisk/dns_naptr.h"
#include "asterisk/dns_srv.h"
@@ -210,17 +211,23 @@
return AST_LIST_NEXT(record, list);
}
-/*! \brief Destructor for a DNS query */
+/*! \brief \brief Destructor for a DNS query */
static void dns_query_destroy(void *data)
{
struct ast_dns_query *query = data;
ao2_cleanup(query->user_data);
+ ast_assert(query->resolver_data != NULL);
+ ast_dns_result_free(query->result);
}
struct ast_dns_query *ast_dns_resolve_async(const char *name, int rr_type, int rr_class, ast_dns_resolve_callback callback, void *data)
{
struct ast_dns_query *query;
+
+ if (ast_strlen_zero(name) || !callback) {
+ return NULL;
+ }
query = ao2_alloc_options(sizeof(*query) + strlen(name) + 1, dns_query_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK);
if (!query) {
@@ -263,9 +270,70 @@
return query->resolver->cancel(query);
}
+/*! \brief Structure used for signaling back for synchronous resolution completion */
+struct dns_synchronous_resolve {
+ /*! \brief Lock used for signaling */
+ ast_mutex_t lock;
+ /*! \brief Condition used for signaling */
+ ast_cond_t cond;
+ /*! \brief Whether the query has completed */
+ unsigned int completed;
+ /*! \brief The result from the query */
+ struct ast_dns_result *result;
+};
+
+/*! \brief Destructor for synchronous resolution structure */
+static void dns_synchronous_resolve_destroy(void *data)
+{
+ struct dns_synchronous_resolve *synchronous = data;
+
+ ast_mutex_destroy(&synchronous->lock);
+ ast_cond_destroy(&synchronous->cond);
+
+ /* This purposely does not unref result as it has been passed to the caller */
+}
+
+/*! \brief Callback used to implement synchronous resolution */
+static void dns_synchronous_resolve_callback(const struct ast_dns_query *query)
+{
+ struct dns_synchronous_resolve *synchronous = ast_dns_query_get_data(query);
+
+ synchronous->result = ao2_bump(ast_dns_query_get_result(query));
+
+ ast_mutex_lock(&synchronous->lock);
+ synchronous->completed = 1;
+ ast_cond_signal(&synchronous->cond);
+ ast_mutex_unlock(&synchronous->lock);
+}
+
int ast_dns_resolve(const char *name, int rr_type, int rr_class, struct ast_dns_result **result)
{
- return 0;
+ struct dns_synchronous_resolve *synchronous;
+ struct ast_dns_query *query;
+
+ synchronous = ao2_alloc_options(sizeof(*synchronous), dns_synchronous_resolve_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK);
+ if (!synchronous) {
+ return -1;
+ }
+
+ ast_mutex_init(&synchronous->lock);
+ ast_cond_init(&synchronous->cond, NULL);
+
+ query = ast_dns_resolve_async(name, rr_type, rr_class, dns_synchronous_resolve_callback, synchronous);
+ if (query) {
+ /* Wait for resolution to complete */
+ ast_mutex_lock(&synchronous->lock);
+ while (!synchronous->completed) {
+ ast_cond_wait(&synchronous->cond, &synchronous->lock);
+ }
+ ast_mutex_unlock(&synchronous->lock);
+ ao2_ref(query, -1);
+ }
+
+ *result = synchronous->result;
+ ao2_ref(synchronous, -1);
+
+ return *result ? 0 : -1;
}
const char *ast_dns_naptr_get_flags(const struct ast_dns_record *record)
@@ -351,21 +419,46 @@
void ast_dns_resolver_set_result(struct ast_dns_query *query, unsigned int nxdomain, unsigned int secure, unsigned int bogus,
const char *canonical)
{
+ if (query->result) {
+ ast_dns_result_free(query->result);
+ }
+
+ query->result = NULL;
}
int ast_dns_resolver_add_record(struct ast_dns_query *query, int rr_type, int rr_class, int ttl, char *data, size_t size)
{
+ if (!query->result) {
+ return -1;
+ }
+
return -1;
}
void ast_dns_resolver_completed(const struct ast_dns_query *query)
{
+ query->callback(query);
}
int ast_dns_resolver_register(struct ast_dns_resolver *resolver)
{
struct ast_dns_resolver *iter;
int inserted = 0;
+
+ if (!resolver) {
+ return -1;
+ } else if (ast_strlen_zero(resolver->name)) {
+ ast_log(LOG_ERROR, "Registration of DNS resolver failed as it does not have a name\n");
+ return -1;
+ } else if (!resolver->resolve) {
+ ast_log(LOG_ERROR, "DNS resolver '%s' does not implement the resolve callback which is required\n",
+ resolver->name);
+ return -1;
+ } else if (!resolver->cancel) {
+ ast_log(LOG_ERROR, "DNS resolver '%s' does not implement the cancel callback which is required\n",
+ resolver->name);
+ return -1;
+ }
AST_RWLIST_WRLOCK(&resolvers);
@@ -401,6 +494,10 @@
{
struct ast_dns_resolver *iter;
+ if (!resolver) {
+ return;
+ }
+
AST_RWLIST_WRLOCK(&resolvers);
AST_RWLIST_TRAVERSE_SAFE_BEGIN(&resolvers, iter, next) {
if (resolver == iter) {
More information about the asterisk-commits
mailing list