Author: mmichelson
Date: Mon Mar 23 12:30:55 2015
New Revision: 433314

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=433314
Log:
Add sorting to DNS NAPTR records.

I modeled this after the method being done in the SRV branch. That is,
I have an internal function that is defined in dns_naptr.c to sort the
records. I opted to sort records after they are collected in order to
make the code more uniform: SRV and NAPTR work the same way.

In order to test this, I added some more NAPTR records to the nominal
NAPTR resolution test and gave it a shot. This pointed to an error where
I needed to cast to unsigned char when getting the order and preference
from the NAPTR record.


Modified:
    team/group/dns_naptr/include/asterisk/dns_internal.h
    team/group/dns_naptr/main/dns_core.c
    team/group/dns_naptr/main/dns_naptr.c
    team/group/dns_naptr/res/res_resolver_unbound.c

Modified: team/group/dns_naptr/include/asterisk/dns_internal.h
URL: 
http://svnview.digium.com/svn/asterisk/team/group/dns_naptr/include/asterisk/dns_internal.h?view=diff&rev=433314&r1=433313&r2=433314
==============================================================================
--- team/group/dns_naptr/include/asterisk/dns_internal.h (original)
+++ team/group/dns_naptr/include/asterisk/dns_internal.h Mon Mar 23 12:30:55 
2015
@@ -147,3 +147,10 @@
  * \return scheduler context
  */
 struct ast_sched_context *ast_dns_get_sched(void);
+
+/*!
+ * \brief Sort the NAPTR records on a result
+ *
+ * \param result The DNS result
+ */
+void ast_dns_naptr_sort(struct ast_dns_result *result);

Modified: team/group/dns_naptr/main/dns_core.c
URL: 
http://svnview.digium.com/svn/asterisk/team/group/dns_naptr/main/dns_core.c?view=diff&rev=433314&r1=433313&r2=433314
==============================================================================
--- team/group/dns_naptr/main/dns_core.c (original)
+++ team/group/dns_naptr/main/dns_core.c Mon Mar 23 12:30:55 2015
@@ -485,7 +485,7 @@
        end_of_record = ptr + size;
 
        /* ORDER */
-       order = (ptr[1] << 0) | (ptr[0] << 8);
+       order = ((unsigned char)(ptr[1]) << 0) | ((unsigned char)(ptr[0]) << 8);
        ptr += 2;
 
        if (ptr >= end_of_record) {
@@ -493,7 +493,7 @@
        }
 
        /* PREFERENCE */
-       preference = (ptr[1] << 0) | (ptr[0] << 8);
+       preference = ((unsigned char) (ptr[1]) << 0) | ((unsigned char)(ptr[0]) 
<< 8);
        ptr += 2;
 
        if (ptr >= end_of_record) {
@@ -633,6 +633,9 @@
 
 void ast_dns_resolver_completed(struct ast_dns_query *query)
 {
+       if (ast_dns_query_get_rr_type(query) == ns_t_naptr) {
+               ast_dns_naptr_sort(query->result);
+       }
        query->callback(query);
 }
 

Modified: team/group/dns_naptr/main/dns_naptr.c
URL: 
http://svnview.digium.com/svn/asterisk/team/group/dns_naptr/main/dns_naptr.c?view=diff&rev=433314&r1=433313&r2=433314
==============================================================================
--- team/group/dns_naptr/main/dns_naptr.c (original)
+++ team/group/dns_naptr/main/dns_naptr.c Mon Mar 23 12:30:55 2015
@@ -38,6 +38,78 @@
 #include "asterisk/linkedlists.h"
 #include "asterisk/dns_internal.h"
 #include "asterisk/utils.h"
+
+static int compare_order(const void *record1, const void *record2)
+{
+       const struct ast_dns_naptr_record **left = (const struct 
ast_dns_naptr_record **)record1;
+       const struct ast_dns_naptr_record **right = (const struct 
ast_dns_naptr_record **)record2;
+
+       if ((*left)->order < (*right)->order) {
+               return -1;
+       } else if ((*left)->order > (*right)->order) {
+               return 1;
+       } else {
+               return 0;
+       }
+}
+
+static int compare_preference(const void *record1, const void *record2)
+{
+       const struct ast_dns_naptr_record **left = (const struct 
ast_dns_naptr_record **)record1;
+       const struct ast_dns_naptr_record **right = (const struct 
ast_dns_naptr_record **)record2;
+
+       if ((*left)->preference < (*right)->preference) {
+               return -1;
+       } else if ((*left)->preference > (*right)->preference) {
+               return 1;
+       } else {
+               return 0;
+       }
+}
+
+void ast_dns_naptr_sort(struct ast_dns_result *result)
+{
+       struct ast_dns_record *current;
+       size_t num_records = 0;
+       struct ast_dns_naptr_record **records;
+       int i = 0;
+       int j = 0;
+       int cur_order;
+
+       /* Determine the number of records */
+       AST_LIST_TRAVERSE(&result->records, current, list) {
+               ++num_records;
+       }
+
+       /* Allocate an array with that number of records */
+       records = ast_alloca(num_records * sizeof(*records));
+
+       /* Move records from the list to the array */
+       AST_LIST_TRAVERSE_SAFE_BEGIN(&result->records, current, list) {
+               records[i++] = (struct ast_dns_naptr_record *) current;
+               AST_LIST_REMOVE_CURRENT(list);
+       }
+       AST_LIST_TRAVERSE_SAFE_END;
+
+       /* Sort the array by order */
+       qsort(records, num_records, sizeof(*records), compare_order);
+
+       /* Sort subarrays by preference */
+       for (i = 0; i < num_records; i = j) {
+               cur_order = records[i]->order;
+               for (j = i + 1; j < num_records; ++j) {
+                       if (records[j]->order != cur_order) {
+                               break;
+                       }
+               }
+               qsort(&records[i], j - i, sizeof(*records), compare_preference);
+       }
+
+       /* Place sorted records back into the original list */
+       for (i = 0; i < num_records; ++i) {
+               AST_LIST_INSERT_TAIL(&result->records, (struct ast_dns_record 
*)(records[i]), list);
+       }
+}
 
 const char *ast_dns_naptr_get_flags(const struct ast_dns_record *record)
 {

Modified: team/group/dns_naptr/res/res_resolver_unbound.c
URL: 
http://svnview.digium.com/svn/asterisk/team/group/dns_naptr/res/res_resolver_unbound.c?view=diff&rev=433314&r1=433313&r2=433314
==============================================================================
--- team/group/dns_naptr/res/res_resolver_unbound.c (original)
+++ team/group/dns_naptr/res/res_resolver_unbound.c Mon Mar 23 12:30:55 2015
@@ -1210,7 +1210,10 @@
 
        ub_ctx_zone_add(resolver->context, DOMAIN1, "static");
 
-       ub_ctx_data_add(resolver->context, "goose.feathers 12345 IN NAPTR 100 
100 A \"Fake service\" \"\" goose.down");
+       ub_ctx_data_add(resolver->context, "goose.feathers 12345 IN NAPTR 200 
200 A \"Fake service\" \"\" goose.down");
+       ub_ctx_data_add(resolver->context, "goose.feathers 12345 IN NAPTR 200 
100 A \"Fake service\" \"\" duck.down");
+       ub_ctx_data_add(resolver->context, "goose.feathers 12345 IN NAPTR 100 
200 A \"Fake service\" \"\" pheasant.down");
+       ub_ctx_data_add(resolver->context, "goose.feathers 12345 IN NAPTR 100 
100 A \"Fake service\" \"\" platypus.fur");
 
        if (ast_dns_resolve(DOMAIN1, ns_t_naptr, ns_c_in, &result)) {
                ast_test_status_update(test, "Failed to resolve domain\n");
@@ -1228,16 +1231,18 @@
                return AST_TEST_FAIL;
        }
 
-       /* XXX This just prints data for my own inspection right now. It will 
need to actually
-        * perform a check in order to really pass. This will be done once more 
NAPTR records
-        * are added so I can check ordering as well as individual data
-        */
-       ast_log(LOG_NOTICE, "order is %hu\n", ast_dns_naptr_get_order(record));
-       ast_log(LOG_NOTICE, "preference is %hu\n", 
ast_dns_naptr_get_preference(record));
-       ast_log(LOG_NOTICE, "flags is %s\n", ast_dns_naptr_get_flags(record));
-       ast_log(LOG_NOTICE, "service is %s\n", 
ast_dns_naptr_get_service(record));
-       ast_log(LOG_NOTICE, "regexp is %s\n", ast_dns_naptr_get_regexp(record));
-       ast_log(LOG_NOTICE, "replacement is %s\n", 
ast_dns_naptr_get_replacement(record));
+       for (record = ast_dns_result_get_records(result); record; record = 
ast_dns_record_get_next(record)) {
+               /* XXX This just prints data for my own inspection right now. 
It will need to actually
+                * perform a check in order to really pass. This will be done 
once more NAPTR records
+                * are added so I can check ordering as well as individual data
+                */
+               ast_log(LOG_NOTICE, "order is %hu\n", 
ast_dns_naptr_get_order(record));
+               ast_log(LOG_NOTICE, "preference is %hu\n", 
ast_dns_naptr_get_preference(record));
+               ast_log(LOG_NOTICE, "flags is %s\n", 
ast_dns_naptr_get_flags(record));
+               ast_log(LOG_NOTICE, "service is %s\n", 
ast_dns_naptr_get_service(record));
+               ast_log(LOG_NOTICE, "regexp is %s\n", 
ast_dns_naptr_get_regexp(record));
+               ast_log(LOG_NOTICE, "replacement is %s\n", 
ast_dns_naptr_get_replacement(record));
+       }
 
        return AST_TEST_PASS;
 


-- 
_____________________________________________________________________
-- 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

Reply via email to