DNS: Fix some corner cases.
authorRichard Mudgett <rmudgett@digium.com>
Fri, 5 Jun 2015 17:16:22 +0000 (12:16 -0500)
committerRichard Mudgett <rmudgett@digium.com>
Wed, 10 Jun 2015 23:06:15 +0000 (18:06 -0500)
* Fix query_set destruction before we are done kicking the queries off.

* Fixed no queries requested handling.

* Add empty queries request unit test.

* Added missing allocation check in ast_dns_query_set_add().

* Made initial pjsip resolving query vector slightly larger.

ASTERISK-25115
Reported by: John Bigelow

Change-Id: Ie8be8347d0992e93946d72b6e7b1299727b038f2

main/dns_query_set.c
res/res_pjsip/pjsip_resolver.c
tests/test_dns_query_set.c

index 147c737..40a89e1 100644 (file)
@@ -130,7 +130,10 @@ int ast_dns_query_set_add(struct ast_dns_query_set *query_set, const char *name,
                return -1;
        }
 
-       AST_VECTOR_APPEND(&query_set->queries, query);
+       if (AST_VECTOR_APPEND(&query_set->queries, query)) {
+               ao2_ref(query.query, -1);
+               return -1;
+       }
 
        return 0;
 }
@@ -175,6 +178,11 @@ void ast_dns_query_set_resolve_async(struct ast_dns_query_set *query_set, ast_dn
        query_set->callback = callback;
        query_set->user_data = ao2_bump(data);
 
+       /*
+        * Bump the query_set ref in case all queries complete
+        * before we are done kicking them off.
+        */
+       ao2_ref(query_set, +1);
        for (idx = 0; idx < AST_VECTOR_SIZE(&query_set->queries); ++idx) {
                struct dns_query_set_query *query = AST_VECTOR_GET_ADDR(&query_set->queries, idx);
 
@@ -187,6 +195,17 @@ void ast_dns_query_set_resolve_async(struct ast_dns_query_set *query_set, ast_dn
 
                dns_query_set_callback(query->query);
        }
+       if (!idx) {
+               /*
+                * There were no queries in the set;
+                * therefore all queries are "completed".
+                * Invoke the final callback.
+                */
+               query_set->callback(query_set);
+               ao2_cleanup(query_set->user_data);
+               query_set->user_data = NULL;
+       }
+       ao2_ref(query_set, -1);
 }
 
 /*! \brief Structure used for signaling back for synchronous resolution completion */
index 4573e4c..915d1d9 100644 (file)
@@ -516,7 +516,7 @@ static void sip_resolve(pjsip_resolver_t *resolver, pj_pool_t *pool, const pjsip
        resolve->callback = cb;
        resolve->token = token;
 
-       if (AST_VECTOR_INIT(&resolve->resolving, 2)) {
+       if (AST_VECTOR_INIT(&resolve->resolving, 4)) {
                ao2_ref(resolve, -1);
                cb(PJ_ENOMEM, token, NULL);
                return;
@@ -565,6 +565,12 @@ static void sip_resolve(pjsip_resolver_t *resolver, pj_pool_t *pool, const pjsip
                cb(PJ_ENOMEM, token, NULL);
                return;
        }
+       if (!resolve->queries) {
+               ast_debug(2, "[%p] No resolution queries for target '%s'\n", resolve, host);
+               ao2_ref(resolve, -1);
+               cb(PJLIB_UTIL_EDNSNOANSWERREC, token, NULL);
+               return;
+       }
 
        ast_debug(2, "[%p] Starting initial resolution using parallel queries for target '%s'\n", resolve, host);
        ast_dns_query_set_resolve_async(resolve->queries, sip_resolve_callback, resolve);
index 2efc881..98a6051 100644 (file)
@@ -306,6 +306,26 @@ AST_TEST_DEFINE(query_set)
        return query_set_test(test, 4, 0);
 }
 
+AST_TEST_DEFINE(query_set_empty)
+{
+       switch (cmd) {
+       case TEST_INIT:
+               info->name = "query_set_empty";
+               info->category = "/main/dns/query_set/";
+               info->summary = "Test nominal asynchronous empty DNS query set";
+               info->description =
+                       "This tests nominal query set in the following ways:\n"
+                       "\t* No queries are added to a query set\n"
+                       "\t* Asynchronous resolution of the query set is started\n"
+                       "\t* We ensure that the query set callback is invoked upon completion";
+               return AST_TEST_NOT_RUN;
+       case TEST_EXECUTE:
+               break;
+       }
+
+       return query_set_test(test, 0, 0);
+}
+
 AST_TEST_DEFINE(query_set_nominal_cancel)
 {
        switch (cmd) {
@@ -352,6 +372,7 @@ AST_TEST_DEFINE(query_set_off_nominal_cancel)
 static int unload_module(void)
 {
        AST_TEST_UNREGISTER(query_set);
+       AST_TEST_UNREGISTER(query_set_empty);
        AST_TEST_UNREGISTER(query_set_nominal_cancel);
        AST_TEST_UNREGISTER(query_set_off_nominal_cancel);
 
@@ -361,6 +382,7 @@ static int unload_module(void)
 static int load_module(void)
 {
        AST_TEST_REGISTER(query_set);
+       AST_TEST_REGISTER(query_set_empty);
        AST_TEST_REGISTER(query_set_nominal_cancel);
        AST_TEST_REGISTER(query_set_off_nominal_cancel);