[asterisk-commits] file: branch group/dns_pjsip r433943 - in /team/group/dns_pjsip: include/aste...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Apr 2 08:45:02 CDT 2015


Author: file
Date: Thu Apr  2 08:44:55 2015
New Revision: 433943

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=433943
Log:
Add a theoretical query set implementation.

Still some rough areas (like cancel) but usable enough for some PJSIP work.

Modified:
    team/group/dns_pjsip/include/asterisk/dns_internal.h
    team/group/dns_pjsip/include/asterisk/dns_query_set.h
    team/group/dns_pjsip/main/dns_core.c
    team/group/dns_pjsip/main/dns_query_set.c

Modified: team/group/dns_pjsip/include/asterisk/dns_internal.h
URL: http://svnview.digium.com/svn/asterisk/team/group/dns_pjsip/include/asterisk/dns_internal.h?view=diff&rev=433943&r1=433942&r2=433943
==============================================================================
--- team/group/dns_pjsip/include/asterisk/dns_internal.h (original)
+++ team/group/dns_pjsip/include/asterisk/dns_internal.h Thu Apr  2 08:44:55 2015
@@ -170,4 +170,24 @@
  */
 void ast_dns_srv_sort(struct ast_dns_result *result);
 
-
+/*!
+ * \brief Allocate a DNS query (but do not start resolution)
+ *
+ * \param name The name of what to resolve
+ * \param rr_type Resource record type
+ * \param rr_class Resource record class
+ * \param callback The callback to invoke upon completion
+ * \param data User data to make available on the query
+ *
+ * \retval non-NULL success
+ * \retval NULL failure
+ *
+ * \note The result passed to the callback does not need to be freed
+ *
+ * \note The user data MUST be an ao2 object
+ *
+ * \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 *dns_query_alloc(const char *name, int rr_type, int rr_class, ast_dns_resolve_callback callback, void *data);

Modified: team/group/dns_pjsip/include/asterisk/dns_query_set.h
URL: http://svnview.digium.com/svn/asterisk/team/group/dns_pjsip/include/asterisk/dns_query_set.h?view=diff&rev=433943&r1=433942&r2=433943
==============================================================================
--- team/group/dns_pjsip/include/asterisk/dns_query_set.h (original)
+++ team/group/dns_pjsip/include/asterisk/dns_query_set.h Thu Apr  2 08:44:55 2015
@@ -43,6 +43,8 @@
  *
  * \retval non-NULL success
  * \retval NULL failure
+ *
+ * \note The query set must be released upon cancellation or completion using ao2_ref
  */
 struct ast_dns_query_set *ast_dns_query_set_create(void);
 
@@ -106,28 +108,24 @@
  *
  * \param query_set The query set
  *
+ * \retval 0 success
+ * \retval -1 failure
+ *
  * \note This function will return when all queries have been completed
  */
-void ast_query_set_resolve(struct ast_dns_query_set *query_set);
+int ast_query_set_resolve(struct ast_dns_query_set *query_set);
 
 /*!
  * \brief Cancel an asynchronous DNS query set resolution
  *
  * \param query_set The DNS query set
  *
- * \retval 0 success
- * \retval -1 failure
+ * \retval 0 success (all queries have been cancelled)
+ * \retval -1 failure (some queries could not be cancelled)
  *
  * \note If successfully cancelled the callback will not be invoked
  */
 int ast_dns_query_set_resolve_cancel(struct ast_dns_query_set *query_set);
-
-/*!
- * \brief Free a query set
- *
- * \param query_set A DNS query set
- */
-void ast_dns_query_set_free(struct ast_dns_query_set *query_set);
 
 #if defined(__cplusplus) || defined(c_plusplus)
 }

Modified: team/group/dns_pjsip/main/dns_core.c
URL: http://svnview.digium.com/svn/asterisk/team/group/dns_pjsip/main/dns_core.c?view=diff&rev=433943&r1=433942&r2=433943
==============================================================================
--- team/group/dns_pjsip/main/dns_core.c (original)
+++ team/group/dns_pjsip/main/dns_core.c Thu Apr  2 08:44:55 2015
@@ -186,9 +186,9 @@
 	ast_dns_result_free(query->result);
 }
 
-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;
+struct ast_dns_query *dns_query_alloc(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)) {
 		ast_log(LOG_WARNING, "Could not perform asynchronous resolution, no name provided\n");
@@ -215,30 +215,42 @@
 		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 */
+
+	AST_RWLIST_RDLOCK(&resolvers);
+	query->resolver = AST_RWLIST_FIRST(&resolvers);
+	AST_RWLIST_UNLOCK(&resolvers);
+
+	if (!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;
+	}
+
+	return 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;
+
 	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);
+	active->query = dns_query_alloc(name, rr_type, rr_class, callback, data);
 	if (!active->query) {
-		ao2_ref(active, -1);
-		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);
-	active->query->resolver = AST_RWLIST_FIRST(&resolvers);
-	AST_RWLIST_UNLOCK(&resolvers);
-
-	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(active, -1);
 		return NULL;
 	}

Modified: team/group/dns_pjsip/main/dns_query_set.c
URL: http://svnview.digium.com/svn/asterisk/team/group/dns_pjsip/main/dns_query_set.c?view=diff&rev=433943&r1=433942&r2=433943
==============================================================================
--- team/group/dns_pjsip/main/dns_query_set.c (original)
+++ team/group/dns_pjsip/main/dns_query_set.c Thu Apr  2 08:44:55 2015
@@ -33,39 +33,104 @@
 
 #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"
 
 /*! \brief A set of DNS queries */
 struct ast_dns_query_set {
 	/*! \brief DNS queries */
 	AST_VECTOR(, struct ast_dns_query *) queries;
 	/*! \brief The total number of completed queries */
-	unsigned int queries_completed;
+	int queries_completed;
 	/*! \brief Callback to invoke upon completion */
 	ast_dns_query_set_callback callback;
 	/*! \brief User-specific data */
 	void *user_data;
 };
 
+/*! \brief Destructor for DNS query set */
+static void dns_query_set_destroy(void *data)
+{
+	struct ast_dns_query_set *query_set = data;
+	int idx;
+
+	for (idx = 0; idx < AST_VECTOR_SIZE(&query_set->queries); ++idx) {
+		struct ast_dns_query *query = AST_VECTOR_GET(&query_set->queries, idx);
+
+		ao2_ref(query, -1);
+	}
+	AST_VECTOR_FREE(&query_set->queries);
+
+	ao2_cleanup(query_set->user_data);
+}
+
 struct ast_dns_query_set *ast_dns_query_set_create(void)
 {
-	return NULL;
+	struct ast_dns_query_set *query_set;
+
+	query_set = ao2_alloc_options(sizeof(*query_set), dns_query_set_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK);
+	if (!query_set) {
+		return NULL;
+	}
+
+	/* It is likely that since they are creating a query set there will be at least 2 queries */
+	if (AST_VECTOR_INIT(&query_set->queries, 2)) {
+		ao2_ref(query_set, -1);
+		return NULL;
+	}
+
+	return query_set;
+}
+
+/*! \brief Callback invoked upon completion of a DNS query */
+static void dns_query_set_callback(const struct ast_dns_query *query)
+{
+	struct ast_dns_query_set *query_set = ast_dns_query_get_data(query);
+
+	if (ast_atomic_fetchadd_int(&query_set->queries_completed, +1) != (AST_VECTOR_SIZE(&query_set->queries) - 1)) {
+		return;
+	}
+
+	/* All queries have been completed, invoke final callback */
+	query_set->callback(query_set->user_data);
 }
 
 int ast_dns_query_set_add(struct ast_dns_query_set *query_set, const char *name, int rr_type, int rr_class)
 {
-	return -1;
+	struct ast_dns_query *query;
+
+	query = dns_query_alloc(name, rr_type, rr_class, dns_query_set_callback, query_set);
+	if (!query) {
+		return -1;
+	}
+
+	AST_VECTOR_APPEND(&query_set->queries, query);
+
+	return 0;
 }
 
 size_t ast_dns_query_set_num_queries(const struct ast_dns_query_set *query_set)
 {
-	return 0;
+	return AST_VECTOR_SIZE(&query_set->queries);
 }
 
 struct ast_dns_query *ast_dns_query_set_get(const struct ast_dns_query_set *query_set, unsigned int index)
 {
-	return NULL;
+	/* Only once all queries have been completed can results be retrieved */
+	if (query_set->queries_completed != AST_VECTOR_SIZE(&query_set->queries)) {
+		return NULL;
+	}
+
+	/* If the index exceeds the number of queries... no query for you */
+	if (index >= AST_VECTOR_SIZE(&query_set->queries)) {
+		return NULL;
+	}
+
+	return AST_VECTOR_GET(&query_set->queries, index);
 }
 
 void *ast_dns_query_set_get_data(const struct ast_dns_query_set *query_set)
@@ -75,19 +140,87 @@
 
 void ast_dns_query_set_resolve_async(struct ast_dns_query_set *query_set, ast_dns_query_set_callback callback, void *data)
 {
+	int idx;
+
 	query_set->callback = callback;
 	query_set->user_data = ao2_bump(data);
-}
-
-void ast_query_set_resolve(struct ast_dns_query_set *query_set)
-{
+
+	for (idx = 0; idx < AST_VECTOR_SIZE(&query_set->queries); ++idx) {
+		struct ast_dns_query *query = AST_VECTOR_GET(&query_set->queries, idx);
+
+		if (!query->resolver->resolve(query)) {
+			continue;
+		}
+
+		dns_query_set_callback(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 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);
+}
+
+/*! \brief Callback used to implement synchronous resolution */
+static void dns_synchronous_resolve_callback(const struct ast_dns_query_set *query_set)
+{
+	struct dns_synchronous_resolve *synchronous = ast_dns_query_set_get_data(query_set);
+
+	ast_mutex_lock(&synchronous->lock);
+	synchronous->completed = 1;
+	ast_cond_signal(&synchronous->cond);
+	ast_mutex_unlock(&synchronous->lock);
+}
+
+int ast_query_set_resolve(struct ast_dns_query_set *query_set)
+{
+	struct dns_synchronous_resolve *synchronous;
+
+	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);
+
+	ast_dns_query_set_resolve_async(query_set, dns_synchronous_resolve_callback, synchronous);
+
+	/* 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(synchronous, -1);
+
+	return 0;
 }
 
 int ast_dns_query_set_resolve_cancel(struct ast_dns_query_set *query_set)
 {
-	return -1;
-}
-
-void ast_dns_query_set_free(struct ast_dns_query_set *query_set)
-{
-}
+	int res = 0, idx;
+
+	for (idx = 0; idx < AST_VECTOR_SIZE(&query_set->queries); ++idx) {
+		struct ast_dns_query *query = AST_VECTOR_GET(&query_set->queries, idx);
+
+		res |= query->resolver->cancel(query);
+	}
+
+	return res;
+}




More information about the asterisk-commits mailing list