Let ExtensionState resolve dynamic hints.
[asterisk/asterisk.git] / main / srv.c
index 262be80..c650650 100644 (file)
@@ -43,10 +43,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include <resolv.h>
 
 #include "asterisk/channel.h"
 #include <resolv.h>
 
 #include "asterisk/channel.h"
-#include "asterisk/logger.h"
 #include "asterisk/srv.h"
 #include "asterisk/dns.h"
 #include "asterisk/srv.h"
 #include "asterisk/dns.h"
-#include "asterisk/options.h"
 #include "asterisk/utils.h"
 #include "asterisk/linkedlists.h"
 
 #include "asterisk/utils.h"
 #include "asterisk/linkedlists.h"
 
@@ -66,6 +64,8 @@ struct srv_entry {
 
 struct srv_context {
        unsigned int have_weights:1;
 
 struct srv_context {
        unsigned int have_weights:1;
+       struct srv_entry *prev;
+       unsigned int num_records;
        AST_LIST_HEAD_NOLOCK(srv_entries, srv_entry) entries;
 };
 
        AST_LIST_HEAD_NOLOCK(srv_entries, srv_entry) entries;
 };
 
@@ -75,7 +75,7 @@ static int parse_srv(unsigned char *answer, int len, unsigned char *msg, struct
                unsigned short priority;
                unsigned short weight;
                unsigned short port;
                unsigned short priority;
                unsigned short weight;
                unsigned short port;
-       } __attribute__ ((__packed__)) *srv = (struct srv *) answer;
+       } __attribute__((__packed__)) *srv = (struct srv *) answer;
 
        int res = 0;
        char repl[256] = "";
 
        int res = 0;
        char repl[256] = "";
@@ -139,7 +139,7 @@ static int srv_callback(void *context, unsigned char *answer, int len, unsigned
        if (entry)
                AST_LIST_INSERT_TAIL(&c->entries, entry, list);
 
        if (entry)
                AST_LIST_INSERT_TAIL(&c->entries, entry, list);
 
-       return 1;
+       return 0;
 }
 
 /* Do the bizarre SRV record weight-handling algorithm
 }
 
 /* Do the bizarre SRV record weight-handling algorithm
@@ -199,6 +199,58 @@ static void process_weights(struct srv_context *context)
        AST_LIST_APPEND_LIST(&context->entries, &newlist, list);
 }
 
        AST_LIST_APPEND_LIST(&context->entries, &newlist, list);
 }
 
+int ast_srv_lookup(struct srv_context **context, const char *service, const char **host, unsigned short *port)
+{
+       struct srv_entry *cur;
+
+       if (*context == NULL) {
+               if (!(*context = ast_calloc(1, sizeof(struct srv_context)))) {
+                       return -1;
+               }
+               AST_LIST_HEAD_INIT_NOLOCK(&(*context)->entries);
+
+               if ((ast_search_dns(*context, service, C_IN, T_SRV, srv_callback)) < 0) {
+                       ast_free(*context);
+                       *context = NULL;
+                       return -1;
+               }
+
+               if ((*context)->have_weights) {
+                       process_weights(*context);
+               }
+
+               (*context)->prev = AST_LIST_FIRST(&(*context)->entries);
+               *host = (*context)->prev->host;
+               *port = (*context)->prev->port;
+               AST_LIST_TRAVERSE(&(*context)->entries, cur, list) {
+                       ++((*context)->num_records);
+               }
+               return 0;
+       }
+
+       if (((*context)->prev = AST_LIST_NEXT((*context)->prev, list))) {
+               /* Retrieve next item in result */
+               *host = (*context)->prev->host;
+               *port = (*context)->prev->port;
+               return 0;
+       } else {
+               /* No more results */
+               while ((cur = AST_LIST_REMOVE_HEAD(&(*context)->entries, list))) {
+                       ast_free(cur);
+               }
+               ast_free(*context);
+               *context = NULL;
+               return 1;
+       }
+}
+
+void ast_srv_cleanup(struct srv_context **context)
+{
+       const char *host;
+       unsigned short port;
+       while (!(ast_srv_lookup(context, NULL, &host, &port)));
+}
+
 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 };
 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 };
@@ -226,10 +278,8 @@ int ast_get_srv(struct ast_channel *chan, char *host, int hostlen, int *port, co
                ast_copy_string(host, current->host, hostlen);
                *port = current->port;
                ast_free(current);
                ast_copy_string(host, current->host, hostlen);
                *port = current->port;
                ast_free(current);
-               if (option_verbose > 3) {
-                       ast_verbose(VERBOSE_PREFIX_3 "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 host %s, port %d\n",
                                    service, host, *port);
                                    service, host, *port);
-               }
        } else {
                host[0] = '\0';
                *port = -1;
        } else {
                host[0] = '\0';
                *port = -1;
@@ -240,3 +290,34 @@ int ast_get_srv(struct ast_channel *chan, char *host, int hostlen, int *port, co
 
        return ret;
 }
 
        return ret;
 }
+
+unsigned int ast_srv_get_record_count(struct srv_context *context)
+{
+       return context->num_records;
+}
+
+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)
+{
+       int i = 1;
+       int res = -1;
+       struct srv_entry *entry;
+
+       if (record_num < 1 || record_num > context->num_records) {
+               return res;
+       }
+
+       AST_LIST_TRAVERSE(&context->entries, entry, list) {
+               if (i == record_num) {
+                       *host = entry->host;
+                       *port = entry->port;
+                       *priority = entry->priority;
+                       *weight = entry->weight;
+                       res = 0;
+                       break;
+               }
+               ++i;
+       }
+
+       return res;
+}