Author: file Date: Mon Mar 16 10:55:38 2015 New Revision: 432997 URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=432997 Log: Hide an asynchronous query behind an opaque structure so results can not be retrieved until the callback is invoked.
Modified: team/group/dns/include/asterisk/dns_core.h team/group/dns/include/asterisk/dns_internal.h team/group/dns/main/dns_core.c team/group/dns/main/dns_recurring.c team/group/dns/res/res_resolver_unbound.c team/group/dns/tests/test_dns.c Modified: team/group/dns/include/asterisk/dns_core.h URL: http://svnview.digium.com/svn/asterisk/team/group/dns/include/asterisk/dns_core.h?view=diff&rev=432997&r1=432996&r2=432997 ============================================================================== --- team/group/dns/include/asterisk/dns_core.h (original) +++ team/group/dns/include/asterisk/dns_core.h Mon Mar 16 10:55:38 2015 @@ -28,6 +28,9 @@ extern "C" { #endif +/*! \brief Opaque structure for an active DNS query */ +struct ast_dns_query_active; + /*! \brief Opaque structure for a DNS query */ struct ast_dns_query; @@ -220,21 +223,21 @@ * * \note This function increments the reference count of the user data, it does NOT steal * - * \note The query must be released upon completion or cancellation using ao2_ref - */ -struct ast_dns_query *ast_dns_resolve_async(const char *name, int rr_type, int rr_class, ast_dns_resolve_callback callback, void *data); + * \note The active query must be released upon completion or cancellation using ao2_ref + */ +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); /*! * \brief Cancel an asynchronous DNS resolution * - * \param query The DNS query returned from ast_dns_resolve_async + * \param active The active DNS query returned from ast_dns_resolve_async * * \retval 0 success * \retval -1 failure * * \note If successfully cancelled the callback will not be invoked */ -int ast_dns_resolve_cancel(struct ast_dns_query *query); +int ast_dns_resolve_cancel(struct ast_dns_query_active *active); /*! * \brief Synchronously resolve a DNS query Modified: team/group/dns/include/asterisk/dns_internal.h URL: http://svnview.digium.com/svn/asterisk/team/group/dns/include/asterisk/dns_internal.h?view=diff&rev=432997&r1=432996&r2=432997 ============================================================================== --- team/group/dns/include/asterisk/dns_internal.h (original) +++ team/group/dns/include/asterisk/dns_internal.h Mon Mar 16 10:55:38 2015 @@ -106,14 +106,13 @@ }; /*! \brief A recurring DNS query */ -struct ast_dns_query_recurring -{ +struct ast_dns_query_recurring { /*! \brief Callback to invoke upon completion */ ast_dns_resolve_callback callback; /*! \brief User-specific data */ void *user_data; /*! \brief Current active query */ - struct ast_dns_query *query; + struct ast_dns_query_active *active; /*! \brief The recurring query has been cancelled */ unsigned int cancelled; /*! \brief Scheduled timer for next resolution */ @@ -126,6 +125,12 @@ char name[0]; }; +/*! \brief An active DNS query */ +struct ast_dns_query_active { + /*! \brief The underlying DNS query */ + struct ast_dns_query *query; +}; + struct ast_sched_context; /*! 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=432997&r1=432996&r2=432997 ============================================================================== --- team/group/dns/main/dns_core.c (original) +++ team/group/dns/main/dns_core.c Mon Mar 16 10:55:38 2015 @@ -162,6 +162,14 @@ return AST_LIST_NEXT(record, list); } +/*! \brief Destructor for an active DNS query */ +static void dns_query_active_destroy(void *data) +{ + struct ast_dns_query_active *active = data; + + ao2_cleanup(active->query); +} + /*! \brief \brief Destructor for a DNS query */ static void dns_query_destroy(void *data) { @@ -172,9 +180,9 @@ 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; +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) +{ + struct ast_dns_query_active *active; if (ast_strlen_zero(name)) { ast_log(LOG_WARNING, "Could not perform asynchronous resolution, no name provided\n"); @@ -201,41 +209,46 @@ return NULL; } - query = ao2_alloc_options(sizeof(*query) + strlen(name) + 1, dns_query_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK); - if (!query) { - return NULL; - } - - query->callback = callback; - query->user_data = ao2_bump(data); - query->rr_type = rr_type; - query->rr_class = rr_class; - strcpy(query->name, name); /* SAFE */ + active = ao2_alloc_options(sizeof(*active), dns_query_active_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK); + if (!active) { + return NULL; + } + + active->query = ao2_alloc_options(sizeof(*active->query) + strlen(name) + 1, dns_query_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK); + if (!active->query) { + return NULL; + } + + active->query->callback = callback; + active->query->user_data = ao2_bump(data); + active->query->rr_type = rr_type; + active->query->rr_class = rr_class; + strcpy(active->query->name, name); /* SAFE */ AST_RWLIST_RDLOCK(&resolvers); - query->resolver = AST_RWLIST_FIRST(&resolvers); + active->query->resolver = AST_RWLIST_FIRST(&resolvers); AST_RWLIST_UNLOCK(&resolvers); - if (!query->resolver) { + if (!active->query->resolver) { ast_log(LOG_ERROR, "Attempted to do a DNS query for '%s' of class '%d' and type '%d' but no resolver is available\n", name, rr_class, rr_type); - ao2_ref(query, -1); - return NULL; - } - - if (query->resolver->resolve(query)) { + ao2_ref(active, -1); + return NULL; + } + + if (active->query->resolver->resolve(active->query)) { ast_log(LOG_ERROR, "Resolver '%s' returned an error when resolving '%s' of class '%d' and type '%d'\n", - query->resolver->name, name, rr_class, rr_type); - ao2_ref(query, -1); - return NULL; - } - - return query; -} - -int ast_dns_resolve_cancel(struct ast_dns_query *query) -{ - return query->resolver->cancel(query); + active->query->resolver->name, name, rr_class, rr_type); + ao2_ref(active, -1); + return NULL; + } + + return active; +} + +int ast_dns_resolve_cancel(struct ast_dns_query_active *active) +{ + return active->query->resolver->cancel(active->query); } /*! \brief Structure used for signaling back for synchronous resolution completion */ @@ -278,7 +291,7 @@ int ast_dns_resolve(const char *name, int rr_type, int rr_class, struct ast_dns_result **result) { struct dns_synchronous_resolve *synchronous; - struct ast_dns_query *query; + struct ast_dns_query_active *active; if (ast_strlen_zero(name)) { ast_log(LOG_WARNING, "Could not perform synchronous resolution, no name provided\n"); @@ -313,15 +326,15 @@ 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) { + active = ast_dns_resolve_async(name, rr_type, rr_class, dns_synchronous_resolve_callback, synchronous); + if (active) { /* 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); + ao2_ref(active, -1); } *result = synchronous->result; Modified: team/group/dns/main/dns_recurring.c URL: http://svnview.digium.com/svn/asterisk/team/group/dns/main/dns_recurring.c?view=diff&rev=432997&r1=432996&r2=432997 ============================================================================== --- team/group/dns/main/dns_recurring.c (original) +++ team/group/dns/main/dns_recurring.c Mon Mar 16 10:55:38 2015 @@ -59,7 +59,7 @@ ao2_lock(recurring); recurring->timer = -1; if (!recurring->cancelled) { - recurring->query = ast_dns_resolve_async(recurring->name, recurring->rr_type, recurring->rr_class, dns_query_recurring_resolution_callback, + recurring->active = ast_dns_resolve_async(recurring->name, recurring->rr_type, recurring->rr_class, dns_query_recurring_resolution_callback, recurring); } ao2_unlock(recurring); @@ -93,7 +93,7 @@ } } - ao2_replace(recurring->query, NULL); + ao2_replace(recurring->active, NULL); ao2_unlock(recurring); /* Since we stole the reference from the query we need to drop it ourselves */ @@ -120,8 +120,8 @@ recurring->rr_class = rr_class; strcpy(recurring->name, name); /* SAFE */ - recurring->query = ast_dns_resolve_async(name, rr_type, rr_class, dns_query_recurring_resolution_callback, recurring); - if (!recurring->query) { + recurring->active = ast_dns_resolve_async(name, rr_type, rr_class, dns_query_recurring_resolution_callback, recurring); + if (!recurring->active) { ao2_ref(recurring, -1); return NULL; } @@ -138,9 +138,9 @@ recurring->cancelled = 1; AST_SCHED_DEL_UNREF(ast_dns_get_sched(), recurring->timer, ao2_ref(recurring, -1)); - if (recurring->query) { - res = ast_dns_resolve_cancel(recurring->query); - ao2_replace(recurring->query, NULL); + if (recurring->active) { + res = ast_dns_resolve_cancel(recurring->active); + ao2_replace(recurring->active, NULL); } ao2_unlock(recurring); Modified: team/group/dns/res/res_resolver_unbound.c URL: http://svnview.digium.com/svn/asterisk/team/group/dns/res/res_resolver_unbound.c?view=diff&rev=432997&r1=432996&r2=432997 ============================================================================== --- team/group/dns/res/res_resolver_unbound.c (original) +++ team/group/dns/res/res_resolver_unbound.c Mon Mar 16 10:55:38 2015 @@ -681,7 +681,7 @@ static int async_run(struct ast_test *test, const char *domain, int rr_type, int rr_class, struct dns_record *records, size_t num_records) { - RAII_VAR(struct ast_dns_query *, query, NULL, ao2_cleanup); + RAII_VAR(struct ast_dns_query_active *, active, NULL, ao2_cleanup); RAII_VAR(struct async_data *, adata, NULL, ao2_cleanup); int i; @@ -698,8 +698,8 @@ ast_test_status_update(test, "Performing DNS query '%s', type %d\n", domain, rr_type); - query = ast_dns_resolve_async(domain, rr_type, rr_class, async_callback, adata); - if (!query) { + active = ast_dns_resolve_async(domain, rr_type, rr_class, async_callback, adata); + if (!active) { ast_test_status_update(test, "Failed to perform asynchronous resolution of domain %s\n", domain); return -1; } Modified: team/group/dns/tests/test_dns.c URL: http://svnview.digium.com/svn/asterisk/team/group/dns/tests/test_dns.c?view=diff&rev=432997&r1=432996&r2=432997 ============================================================================== --- team/group/dns/tests/test_dns.c (original) +++ team/group/dns/tests/test_dns.c Mon Mar 16 10:55:38 2015 @@ -1005,7 +1005,7 @@ AST_TEST_DEFINE(resolver_resolve_async) { RAII_VAR(struct async_resolution_data *, async_data, NULL, ao2_cleanup); - RAII_VAR(struct ast_dns_query *, query, NULL, ao2_cleanup); + RAII_VAR(struct ast_dns_query_active *, active, NULL, ao2_cleanup); struct ast_dns_result *result; enum ast_test_result_state res = AST_TEST_PASS; struct timespec timeout; @@ -1039,8 +1039,8 @@ goto cleanup; } - query = ast_dns_resolve_async("asterisk.org", ns_t_a, ns_c_in, async_callback, async_data); - if (!query) { + active = ast_dns_resolve_async("asterisk.org", ns_t_a, ns_c_in, async_callback, async_data); + if (!active) { ast_test_status_update(test, "Asynchronous resolution of address failed\n"); res = AST_TEST_FAIL; goto cleanup; @@ -1080,7 +1080,7 @@ goto cleanup; } - result = ast_dns_query_get_result(query); + result = ast_dns_query_get_result(active->query); if (!result) { ast_test_status_update(test, "Asynchronous resolution yielded no result\n"); res = AST_TEST_FAIL; @@ -1128,7 +1128,7 @@ { "asterisk.org", ns_t_a, ns_c_in, NULL }, }; - struct ast_dns_query *query; + struct ast_dns_query_active *active; enum ast_test_result_state res = AST_TEST_PASS; int i; @@ -1155,11 +1155,11 @@ } for (i = 0; i < ARRAY_LEN(resolves); ++i) { - query = ast_dns_resolve_async(resolves[i].name, resolves[i].rr_type, resolves[i].rr_class, + active = ast_dns_resolve_async(resolves[i].name, resolves[i].rr_type, resolves[i].rr_class, resolves[i].callback, NULL); - if (query) { + if (active) { ast_test_status_update(test, "Successfully performed asynchronous resolution with invalid data\n"); - ao2_ref(query, -1); + ao2_ref(active, -1); res = AST_TEST_FAIL; } } @@ -1171,13 +1171,13 @@ return AST_TEST_FAIL; } - query = ast_dns_resolve_async("asterisk.org", ns_t_a, ns_c_in, stub_callback, NULL); + active = ast_dns_resolve_async("asterisk.org", ns_t_a, ns_c_in, stub_callback, NULL); ast_dns_resolver_unregister(&terrible_resolver); - if (query) { + if (active) { ast_test_status_update(test, "Successfully performed asynchronous resolution with invalid data\n"); - ao2_ref(query, -1); + ao2_ref(active, -1); return AST_TEST_FAIL; } @@ -1187,7 +1187,7 @@ AST_TEST_DEFINE(resolver_resolve_async_cancel) { RAII_VAR(struct async_resolution_data *, async_data, NULL, ao2_cleanup); - RAII_VAR(struct ast_dns_query *, query, NULL, ao2_cleanup); + RAII_VAR(struct ast_dns_query_active *, active, NULL, ao2_cleanup); struct ast_dns_result *result; enum ast_test_result_state res = AST_TEST_PASS; struct timespec timeout; @@ -1221,8 +1221,8 @@ goto cleanup; } - query = ast_dns_resolve_async("asterisk.org", ns_t_a, ns_c_in, async_callback, async_data); - if (!query) { + active = ast_dns_resolve_async("asterisk.org", ns_t_a, ns_c_in, async_callback, async_data); + if (!active) { ast_test_status_update(test, "Asynchronous resolution of address failed\n"); res = AST_TEST_FAIL; goto cleanup; @@ -1240,7 +1240,7 @@ goto cleanup; } - ast_dns_resolve_cancel(query); + ast_dns_resolve_cancel(active); if (!test_resolver_data.canceled) { ast_test_status_update(test, "Resolver's cancel() method was not called\n"); @@ -1270,7 +1270,7 @@ goto cleanup; } - result = ast_dns_query_get_result(query); + result = ast_dns_query_get_result(active->query); if (result) { ast_test_status_update(test, "Canceled resolution had a result\n"); res = AST_TEST_FAIL; -- _____________________________________________________________________ -- 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