[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