[asterisk-commits] oej: branch oej/pgtips-srv-and-outbound-stuff-1.8 r386235 - in /team/oej/pgti...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Apr 22 10:01:39 CDT 2013


Author: oej
Date: Mon Apr 22 10:01:35 2013
New Revision: 386235

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=386235
Log:
Modifying APIs so that I can get the SRV lists with TTLs

Modified:
    team/oej/pgtips-srv-and-outbound-stuff-1.8/include/asterisk/srv.h
    team/oej/pgtips-srv-and-outbound-stuff-1.8/main/dns.c
    team/oej/pgtips-srv-and-outbound-stuff-1.8/main/srv.c

Modified: team/oej/pgtips-srv-and-outbound-stuff-1.8/include/asterisk/srv.h
URL: http://svnview.digium.com/svn/asterisk/team/oej/pgtips-srv-and-outbound-stuff-1.8/include/asterisk/srv.h?view=diff&rev=386235&r1=386234&r2=386235
==============================================================================
--- team/oej/pgtips-srv-and-outbound-stuff-1.8/include/asterisk/srv.h (original)
+++ team/oej/pgtips-srv-and-outbound-stuff-1.8/include/asterisk/srv.h Mon Apr 22 10:01:35 2013
@@ -50,16 +50,26 @@
  */
 void ast_srv_cleanup(struct srv_context **context);
 
+/*! \brief Free all entries in the context, but not the context itself */
+void ast_srv_context_free_list(struct srv_context *context);
+
 /*! Lookup entry in SRV records Returns 1 if found, 0 if not found, -1 on hangup 
 	Only do SRV record lookup if you get a domain without a port. If you get a port #, it's a DNS host name.
-*/
-/*!	\param	chan Ast channel
+	\param	chan Ast channel
 	\param	host host name (return value)
 	\param	hostlen Length of string "host"
 	\param	port Port number (return value)
 	\param service Service tag for SRV lookup (like "_sip._udp" or "_stun._udp"
 */
 extern int ast_get_srv(struct ast_channel *chan, char *host, int hostlen, int *port, const char *service);
+
+/*! Lookup entry in SRV records Returns 1 if found, 0 if not found, -1 on hangup 
+	Only do SRV record lookup if you get a domain without a port. If you get a port #, it's a DNS host name.
+	\param  context A context for SRV lookups that will contain the list. Client needs to free this list with ast_srv_cleanup
+	\param	chan Ast channel
+	\param service Service tag for SRV lookup (like "_sip._udp" or "_stun._udp"
+*/
+extern int ast_get_srv_list(struct srv_context *context, struct ast_channel *chan, const char *service);
 
 /*!
  * \brief Get the number of records for a given SRV context
@@ -96,4 +106,8 @@
  */
 int ast_srv_get_nth_record(struct srv_context *context, int record_num, const char **host,
 		unsigned short *port, unsigned short *priority, unsigned short *weight);
+/*!
+ * \brief Print out the complete data in the SRV list
+ */
+void ast_srv_debug_print(struct srv_context *context);
 #endif /* _ASTERISK_SRV_H */

Modified: team/oej/pgtips-srv-and-outbound-stuff-1.8/main/dns.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pgtips-srv-and-outbound-stuff-1.8/main/dns.c?view=diff&rev=386235&r1=386234&r2=386235
==============================================================================
--- team/oej/pgtips-srv-and-outbound-stuff-1.8/main/dns.c (original)
+++ team/oej/pgtips-srv-and-outbound-stuff-1.8/main/dns.c Mon Apr 22 10:01:35 2013
@@ -188,7 +188,7 @@
 /*! \brief Parse DNS lookup result, call callback */
 static int dns_parse_answer(void *context,
 	int class, int type, unsigned char *answer, int len,
-	int (*callback)(void *context, unsigned char *answer, int len, unsigned char *fullanswer))
+	int (*callback)(void *context, unsigned char *answer, int len, unsigned char *fullanswer, unsigned int ttl))
 {
 	unsigned char *fullanswer = answer;
 	struct dn_answer *ans;
@@ -196,6 +196,7 @@
 	int ret = 0;
 	int res;
 	int x;
+	ast_debug(3, "==> Parsing answer on DNS query \n");
 
 	h = (dns_HEADER *)answer;
 	answer += sizeof(dns_HEADER);
@@ -235,7 +236,8 @@
 
 		if (ntohs(ans->class) == class && ntohs(ans->rtype) == type) {
 			if (callback) {
-				if ((res = callback(context, answer, ntohs(ans->size), fullanswer)) < 0) {
+				ast_debug(3, "     ==> Using callback for DNS answer \n");
+				if ((res = callback(context, answer, ntohs(ans->size), fullanswer, ans->ttl)) < 0) {
 					ast_log(LOG_WARNING, "Failed to parse result\n");
 					return -1;
 				}
@@ -258,8 +260,9 @@
 */
 int ast_search_dns(void *context,
 	   const char *dname, int class, int type,
-	   int (*callback)(void *context, unsigned char *answer, int len, unsigned char *fullanswer))
+	   int (*callback)(void *context, unsigned char *answer, int len, unsigned char *fullanswer, unsigned int ttl))
 {
+	ast_debug(3, "==> Will send query for %s\n", dname);
 #ifdef HAVE_RES_NINIT
 	struct __res_state dnsstate;
 #endif
@@ -275,7 +278,9 @@
 	res_init();
 	res = res_search(dname, class, type, answer, sizeof(answer));
 #endif
+	ast_debug(3, "==> Got result on query for %s\n", dname);
 	if (res > 0) {
+		ast_debug(3, "==> Parsing answer for %s\n", dname);
 		if ((res = dns_parse_answer(context, class, type, answer, res, callback)) < 0) {
 			ast_log(LOG_WARNING, "DNS Parse error for %s\n", dname);
 			ret = -1;
@@ -285,7 +290,7 @@
 		} else
 			ret = 1;
 	} else {
-		ast_debug(1, "DNS lookup error %d for %s\n", dname, res);
+		ast_debug(1, "DNS lookup error %d for %s\n", res, dname);
 	}
 #ifdef HAVE_RES_NINIT
 #ifdef HAVE_RES_NDESTROY
@@ -299,6 +304,7 @@
 #endif
 	ast_mutex_unlock(&res_lock);
 #endif
+	ast_debug(3, "==> Finished query for %s result %d\n", dname, ret);
 
 	return ret;
 }

Modified: team/oej/pgtips-srv-and-outbound-stuff-1.8/main/srv.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pgtips-srv-and-outbound-stuff-1.8/main/srv.c?view=diff&rev=386235&r1=386234&r2=386235
==============================================================================
--- team/oej/pgtips-srv-and-outbound-stuff-1.8/main/srv.c (original)
+++ team/oej/pgtips-srv-and-outbound-stuff-1.8/main/srv.c Mon Apr 22 10:01:35 2013
@@ -64,6 +64,7 @@
 	unsigned short weight;
 	unsigned short port;
 	unsigned int weight_sum;
+	struct timeval ttl_expire;		/* Expiry time */
 	AST_LIST_ENTRY(srv_entry) list;
 	char host[1];
 };
@@ -72,10 +73,11 @@
 	unsigned int have_weights:1;
 	struct srv_entry *prev;
 	unsigned int num_records;
+	struct srv_entry *current;		/* Pointer into the list for failover */
 	AST_LIST_HEAD_NOLOCK(srv_entries, srv_entry) entries;
 };
 
-static int parse_srv(unsigned char *answer, int len, unsigned char *msg, struct srv_entry **result)
+static int parse_srv(unsigned char *answer, int len, unsigned char *msg, struct srv_entry **result, struct timeval *ttl_expire)
 {
 	struct srv {
 		unsigned short priority;
@@ -109,20 +111,33 @@
 	entry->priority = ntohs(srv->priority);
 	entry->weight = ntohs(srv->weight);
 	entry->port = ntohs(srv->port);
+	entry->ttl_expire = *ttl_expire;
 	strcpy(entry->host, repl);
+	if (option_debug > 3) {
+		char exptime[64];
+		struct ast_tm myt;
+		ast_strftime(exptime, sizeof(exptime), "%Y-%m-%d %H:%M:%S.%3q %Z", ast_localtime(ttl_expire, &myt, NULL));
+		ast_debug(3, "DNS SRV ==> Prio %-3.3d Weight %-3.3d Port %-5.5u TTL %s  Hostname %s\n", entry->priority, entry->weight, entry->port, exptime, entry->host);
+	}
 
 	*result = entry;
 	
 	return 0;
 }
 
-static int srv_callback(void *context, unsigned char *answer, int len, unsigned char *fullanswer)
+static int srv_callback(void *context, unsigned char *answer, int len, unsigned char *fullanswer, unsigned int ttl)
 {
 	struct srv_context *c = (struct srv_context *) context;
 	struct srv_entry *entry = NULL;
 	struct srv_entry *current;
-
-	if (parse_srv(answer, len, fullanswer, &entry))
+	struct timeval expiry  = {0,};
+
+	ast_debug(3, " ==> Callback received \n");
+
+	expiry.tv_sec =  (long) ttl;
+	expiry = ast_tvadd(expiry, ast_tvnow());
+
+	if (parse_srv(answer, len, fullanswer, &entry, &expiry))
 		return -1;
 
 	if (entry->weight)
@@ -262,20 +277,40 @@
 	}
 }
 
-int ast_get_srv(struct ast_channel *chan, char *host, int hostlen, int *port, const char *service)
-{
-	struct srv_context context = { .entries = AST_LIST_HEAD_NOLOCK_INIT_VALUE };
+/*! \brief Free all entries in the context, but not the context itself */
+void ast_srv_context_free_list(struct srv_context *context)
+{
 	struct srv_entry *current;
+
+	/* Remove list of SRV entries from memory */
+	while ((current = AST_LIST_REMOVE_HEAD(&context->entries, list))) {
+		ast_free(current);
+	}
+	context->have_weights = 0;
+	context->prev = NULL;
+	context->current = NULL;
+	context->num_records = 0;
+}
+
+int ast_get_srv_list(struct srv_context *context, struct ast_channel *chan, const char *service)
+{
 	int ret;
 
+	if (context == NULL) {
+		return -1;
+	}
+
+	ast_debug(3, "==> Searching for %s \n", service);
+
 	if (chan && ast_autoservice_start(chan) < 0) {
 		return -1;
 	}
 
-	ret = ast_search_dns(&context, service, C_IN, T_SRV, srv_callback);
-
-	if (context.have_weights) {
-		process_weights(&context);
+	ast_debug(3, "==> Searching in DNS for %s \n", service);
+	ret = ast_search_dns(context, service, C_IN, T_SRV, srv_callback);
+
+	if (ret > 0 && context->have_weights) {
+		process_weights(context);
 	}
 
 	if (chan) {
@@ -285,26 +320,47 @@
 	/* TODO: there could be a "." entry in the returned list of
 	   answers... if so, this requires special handling */
 
+
+
+	if (option_debug > 3) {
+		ast_srv_debug_print(context);
+	}
+
+
+	return ret;
+}
+
+int ast_get_srv(struct ast_channel *chan, char *host, int hostlen, int *port, const char *service)
+{
+	struct srv_context context_data = { .entries = AST_LIST_HEAD_NOLOCK_INIT_VALUE };
+	int res;
+	struct srv_entry *current;
+
+	/* Get the list and save one entry only */
+	res = ast_get_srv_list(&context_data, chan, service);
+
+
 	/* the list of entries will be sorted in the proper selection order
 	   already, so we just need the first one (if any) */
 
-	if ((ret > 0) && (current = AST_LIST_REMOVE_HEAD(&context.entries, list))) {
+	if ((res > 0) && (current = AST_LIST_REMOVE_HEAD(&context_data.entries, list))) {
 		ast_copy_string(host, current->host, hostlen);
 		*port = current->port;
 		ast_free(current);
-		ast_verb(4, "ast_get_srv: SRV lookup for '%s' mapped to host %s, port %d\n",
+		ast_verb(4, "ast_get_srv: SRV lookup for '%s' mapped to primary host %s, port %d\n",
 				    service, host, *port);
 	} else {
+		ast_verb(4, "ast_get_srv: Found no host, sorry\n");
 		host[0] = '\0';
 		*port = -1;
 	}
 
-	while ((current = AST_LIST_REMOVE_HEAD(&context.entries, list))) {
-		ast_free(current);
-	}
-
-	return ret;
-}
+	/* Remove list of SRV entries from memory */
+	ast_srv_context_free_list(&context_data);
+
+	return res;
+}
+
 
 unsigned int ast_srv_get_record_count(struct srv_context *context)
 {
@@ -319,6 +375,10 @@
 	struct srv_entry *entry;
 
 	if (record_num < 1 || record_num > context->num_records) {
+		return res;
+	}
+
+	if (context == NULL) {
 		return res;
 	}
 
@@ -336,3 +396,21 @@
 
 	return res;
 }
+
+void ast_srv_debug_print(struct srv_context *context)
+{
+	struct srv_entry *entry;
+	int i = 1;
+	char exptime[64];
+	struct ast_tm myt;
+
+	if (context == NULL) {
+		return;
+	}
+
+	AST_LIST_TRAVERSE(&context->entries, entry, list) {
+		ast_strftime(exptime, sizeof(exptime), "%Y-%m-%d %H:%M:%S.%3q %Z", ast_localtime(&entry->ttl_expire, &myt, NULL));
+		ast_debug(0, "DNS SRV Entry %-2.2d : P %-2.2d W %-4.4d Hostname %s Port %d Expire %s\n", i, entry->priority, entry->weight, entry->host, entry->port, exptime);
+		i++;
+	}
+}




More information about the asterisk-commits mailing list