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) { -- _____________________________________________________________________ -- Bandwidth and Colocation Provided by http://www.api-digital.com -- svn-commits mailing list To UNSUBSCRIBE or update options visit: http://lists.digium.com/mailman/listinfo/svn-commits