[asterisk-commits] file: branch group/dns_srv r433297 - in /team/group/dns_srv: include/asterisk...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Mar 23 07:23:21 CDT 2015


Author: file
Date: Mon Mar 23 07:23:20 2015
New Revision: 433297

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=433297
Log:
Add SRV recording parsing and sorting.

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

Modified: team/group/dns_srv/include/asterisk/dns_internal.h
URL: http://svnview.digium.com/svn/asterisk/team/group/dns_srv/include/asterisk/dns_internal.h?view=diff&rev=433297&r1=433296&r2=433297
==============================================================================
--- team/group/dns_srv/include/asterisk/dns_internal.h (original)
+++ team/group/dns_srv/include/asterisk/dns_internal.h Mon Mar 23 07:23:20 2015
@@ -44,14 +44,14 @@
 struct ast_dns_srv_record {
 	/*! \brief Generic DNS record information */
 	struct ast_dns_record generic;
-	/*! \brief The hostname in the SRV record */
-	const char *host;
 	/*! \brief The priority of the SRV record */
 	unsigned short priority;
 	/*! \brief The weight of the SRV record */
 	unsigned short weight;
 	/*! \brief The port in the SRV record */
 	unsigned short port;
+	/*! \brief The hostname in the SRV record */
+	char host[0];
 };
 
 /*! \brief A NAPTR record */
@@ -82,7 +82,7 @@
 	/*! \brief Optional rcode, set if an error occurred */
 	unsigned int rcode;
 	/*! \brief Records returned */
-	AST_LIST_HEAD_NOLOCK(, ast_dns_record) records;
+	AST_LIST_HEAD_NOLOCK(dns_records, ast_dns_record) records;
 	/*! \brief The canonical name */
 	const char *canonical;
 	/*! \brief The raw DNS answer */
@@ -147,3 +147,22 @@
  * \return scheduler context
  */
 struct ast_sched_context *ast_dns_get_sched(void);
+
+/*!
+ * \brief Allocate and parse a DNS SRV record
+ *
+ * \param query The DNS query
+ * \param data This specific SRV record
+ * \param size The size of the SRV record
+ *
+ * \retval non-NULL success
+ * \retval NULL failure
+ */
+struct ast_dns_record *ast_dns_srv_alloc(struct ast_dns_query *query, const char *data, const size_t size);
+
+/*!
+ * \brief Sort the SRV records on a result
+ *
+ * \param result The DNS result
+ */
+void ast_dns_srv_sort(struct ast_dns_result *result);

Modified: team/group/dns_srv/main/dns_core.c
URL: http://svnview.digium.com/svn/asterisk/team/group/dns_srv/main/dns_core.c?view=diff&rev=433297&r1=433296&r2=433297
==============================================================================
--- team/group/dns_srv/main/dns_core.c (original)
+++ team/group/dns_srv/main/dns_core.c Mon Mar 23 07:23:20 2015
@@ -583,6 +583,8 @@
 
 	if (rr_type == ns_t_naptr) {
 		record = naptr_record_alloc(query, data, size);
+	} else if (rr_type == ns_t_srv) {
+		record = ast_dns_srv_alloc(query, data, size);
 	} else {
 		record = generic_record_alloc(query, data, size);
 	}
@@ -604,6 +606,10 @@
 
 void ast_dns_resolver_completed(struct ast_dns_query *query)
 {
+	if (ast_dns_query_get_rr_type(query) == ns_t_srv) {
+		ast_dns_srv_sort(query->result);
+	}
+
 	query->callback(query);
 }
 

Modified: team/group/dns_srv/main/dns_srv.c
URL: http://svnview.digium.com/svn/asterisk/team/group/dns_srv/main/dns_srv.c?view=diff&rev=433297&r1=433296&r2=433297
==============================================================================
--- team/group/dns_srv/main/dns_srv.c (original)
+++ team/group/dns_srv/main/dns_srv.c Mon Mar 23 07:23:20 2015
@@ -31,25 +31,158 @@
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
 #include "asterisk/dns_core.h"
 #include "asterisk/dns_srv.h"
+#include "asterisk/linkedlists.h"
+#include "asterisk/dns_internal.h"
+#include "asterisk/utils.h"
+
+struct ast_dns_record *ast_dns_srv_alloc(struct ast_dns_query *query, const char *data, const size_t size)
+{
+	const char *ptr = data;
+	size_t remaining = size;
+	struct ast_dns_srv_record *srv;
+	unsigned short priority;
+	unsigned short weight;
+	unsigned short port;
+	int host_size;
+	char host[256] = "";
+
+	if (remaining < 2) {
+		return NULL;
+	}
+	priority = (ptr[1] << 0) | (ptr[0] << 8);
+	ptr += 2;
+	remaining -= 2;
+
+	if (remaining < 2) {
+		return NULL;
+	}
+	weight = (ptr[1] << 0) | (ptr[0] << 8);
+	ptr += 2;
+	remaining -= 2;
+
+	if (remaining < 2) {
+		return NULL;
+	}
+	port = (ptr[1] << 0) | (ptr[0] << 8);
+	ptr += 2;
+
+	/* This currently assumes that the DNS core will provide a record within the full answer, which I'm going to talk to
+	 * Mark about in a few hours
+	 */
+	host_size = dn_expand((unsigned char *)query->result->answer, (unsigned char *) data, (unsigned char *) ptr, host, sizeof(host) - 1);
+	if (host_size < 0) {
+		ast_log(LOG_ERROR, "Failed to expand domain name: %s\n", strerror(errno));
+		return NULL;
+	}
+
+	if (!strcmp(host, ".")) {
+		return NULL;
+	}
+
+	srv = ast_calloc(1, sizeof(*srv) + host_size + 1);
+	if (!srv) {
+		return NULL;
+	}
+
+	srv->priority = ntohs(priority);
+	srv->weight = ntohs(weight);
+	srv->port = ntohs(port);
+	strcpy(srv->host, host); /* SAFE */
+
+	return (struct ast_dns_record *)srv;
+}
+
+/* This implementation was taken from the existing srv.c which, after reading the RFC, implements it
+ * as it should.
+ */
+void ast_dns_srv_sort(struct ast_dns_result *result)
+{
+	struct ast_dns_record *current;
+	struct dns_records newlist = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
+
+	while (AST_LIST_FIRST(&result->records)) {
+		unsigned int random_weight;
+		unsigned int weight_sum;
+		unsigned short cur_priority = ((struct ast_dns_srv_record *)AST_LIST_FIRST(&result->records))->priority;
+		struct dns_records temp_list = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
+		weight_sum = 0;
+
+		AST_LIST_TRAVERSE_SAFE_BEGIN(&result->records, current, list) {
+			if (((struct ast_dns_srv_record *)current)->priority != cur_priority)
+				break;
+
+			AST_LIST_MOVE_CURRENT(&temp_list, list);
+		}
+		AST_LIST_TRAVERSE_SAFE_END;
+
+		while (AST_LIST_FIRST(&temp_list)) {
+			weight_sum = 0;
+
+			AST_LIST_TRAVERSE(&temp_list, current, list) {
+				weight_sum += ((struct ast_dns_srv_record *)current)->weight;
+			}
+
+			/* if all the remaining entries have weight == 0,
+			   then just append them to the result list and quit */
+			if (weight_sum == 0) {
+				AST_LIST_APPEND_LIST(&newlist, &temp_list, list);
+				break;
+			}
+
+			random_weight = 1 + (unsigned int) ((float) weight_sum * (ast_random() / ((float) RAND_MAX + 1.0)));
+
+			AST_LIST_TRAVERSE_SAFE_BEGIN(&temp_list, current, list) {
+				if (((struct ast_dns_srv_record *)current)->weight < random_weight)
+					continue;
+
+				AST_LIST_MOVE_CURRENT(&newlist, list);
+				break;
+			}
+			AST_LIST_TRAVERSE_SAFE_END;
+		}
+
+	}
+
+	/* now that the new list has been ordered,
+	   put it in place */
+
+	AST_LIST_APPEND_LIST(&result->records, &newlist, list);
+}
 
 const char *ast_dns_srv_get_host(const struct ast_dns_record *record)
 {
-	return NULL;
+	struct ast_dns_srv_record *srv = (struct ast_dns_srv_record *) record;
+
+	ast_assert(ast_dns_record_get_rr_type(record) == ns_t_srv);
+	return srv->host;
 }
 
 unsigned short ast_dns_srv_get_priority(const struct ast_dns_record *record)
 {
-	return 0;
+	struct ast_dns_srv_record *srv = (struct ast_dns_srv_record *) record;
+
+	ast_assert(ast_dns_record_get_rr_type(record) == ns_t_srv);
+	return srv->priority;
 }
 
 unsigned short ast_dns_srv_get_weight(const struct ast_dns_record *record)
 {
-	return 0;
+	struct ast_dns_srv_record *srv = (struct ast_dns_srv_record *) record;
+
+	ast_assert(ast_dns_record_get_rr_type(record) == ns_t_srv);
+	return srv->weight;
 }
 
 unsigned short ast_dns_srv_get_port(const struct ast_dns_record *record)
 {
-	return 0;
-}
+	struct ast_dns_srv_record *srv = (struct ast_dns_srv_record *) record;
+
+	ast_assert(ast_dns_record_get_rr_type(record) == ns_t_srv);
+	return srv->port;
+}




More information about the asterisk-commits mailing list