Author: file
Date: Sat Apr  4 14:46:19 2015
New Revision: 433993

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=433993
Log:
Simplify code, reduce memory usage, and restrict queries based on what 
transports are available.

Modified:
    team/group/dns_pjsip/include/asterisk/dns_core.h
    team/group/dns_pjsip/main/dns_core.c
    team/group/dns_pjsip/res/res_pjsip.c
    team/group/dns_pjsip/res/res_pjsip/pjsip_resolver.c

Modified: team/group/dns_pjsip/include/asterisk/dns_core.h
URL: 
http://svnview.digium.com/svn/asterisk/team/group/dns_pjsip/include/asterisk/dns_core.h?view=diff&rev=433993&r1=433992&r2=433993
==============================================================================
--- team/group/dns_pjsip/include/asterisk/dns_core.h (original)
+++ team/group/dns_pjsip/include/asterisk/dns_core.h Sat Apr  4 14:46:19 2015
@@ -205,6 +205,15 @@
 const char *ast_dns_record_get_data(const struct ast_dns_record *record);
 
 /*!
+ * \brief Retrieve the size of the raw DNS record
+ *
+ * \param record The DNS record
+ *
+ * \return the size of the raw DNS record
+ */
+size_t ast_dns_record_get_data_size(const struct ast_dns_record *record);
+
+/*!
  * \brief Get the next DNS record
  *
  * \param record The current DNS record

Modified: team/group/dns_pjsip/main/dns_core.c
URL: 
http://svnview.digium.com/svn/asterisk/team/group/dns_pjsip/main/dns_core.c?view=diff&rev=433993&r1=433992&r2=433993
==============================================================================
--- team/group/dns_pjsip/main/dns_core.c (original)
+++ team/group/dns_pjsip/main/dns_core.c Sat Apr  4 14:46:19 2015
@@ -163,6 +163,11 @@
        return record->data_ptr;
 }
 
+size_t ast_dns_record_get_data_size(const struct ast_dns_record *record)
+{
+       return record->data_len;
+}
+
 const struct ast_dns_record *ast_dns_record_get_next(const struct 
ast_dns_record *record)
 {
        return AST_LIST_NEXT(record, list);

Modified: team/group/dns_pjsip/res/res_pjsip.c
URL: 
http://svnview.digium.com/svn/asterisk/team/group/dns_pjsip/res/res_pjsip.c?view=diff&rev=433993&r1=433992&r2=433993
==============================================================================
--- team/group/dns_pjsip/res/res_pjsip.c (original)
+++ team/group/dns_pjsip/res/res_pjsip.c Sat Apr  4 14:46:19 2015
@@ -3441,8 +3441,6 @@
                return AST_MODULE_LOAD_DECLINE;
        }
 
-       ast_sip_initialize_resolver();
-
        pjsip_tsx_layer_init_module(ast_pjsip_endpoint);
        pjsip_ua_init_module(ast_pjsip_endpoint, NULL);
 
@@ -3474,6 +3472,9 @@
                pj_caching_pool_destroy(&caching_pool);
                return AST_MODULE_LOAD_DECLINE;
        }
+
+       ast_sip_initialize_resolver();
+       ast_sip_initialize_dns();
 
        if (ast_sip_initialize_distributor()) {
                ast_log(LOG_ERROR, "Failed to register distributor module. 
Aborting load\n");

Modified: team/group/dns_pjsip/res/res_pjsip/pjsip_resolver.c
URL: 
http://svnview.digium.com/svn/asterisk/team/group/dns_pjsip/res/res_pjsip/pjsip_resolver.c?view=diff&rev=433993&r1=433992&r2=433993
==============================================================================
--- team/group/dns_pjsip/res/res_pjsip/pjsip_resolver.c (original)
+++ team/group/dns_pjsip/res/res_pjsip/pjsip_resolver.c Sat Apr  4 14:46:19 2015
@@ -29,48 +29,57 @@
 #include "asterisk/res_pjsip.h"
 #include "include/res_pjsip_private.h"
 
-/*! \brief Structure which contains resolved target information */
-struct sip_resolved_target {
-       /*! \brief The record type that this target originated from */
+/*! \brief Structure which contains transport+port information for an active 
query */
+struct sip_target {
        /*! \brief The transport to be used */
        pjsip_transport_type_e transport;
        /*! \brief The port */
        int port;
-       /*! \brief Resulting addresses */
-       pjsip_server_addresses addresses;
 };
 
-/*! \brief The vector used for addresses */
-AST_VECTOR(addresses, struct sip_resolved_target);
+/*! \brief The vector used for current targets */
+AST_VECTOR(targets, struct sip_target);
 
 /*! \brief Structure which keeps track of resolution */
 struct sip_resolve {
        /*! \brief Addresses currently being resolved, indexed based on index 
of queries in query set */
-       struct addresses resolving;
-       /*! \brief Addresses that have been resolved, to ensure proper sorting 
go from back to front */
-       struct addresses resolved;
+       struct targets resolving;
        /*! \brief Active queries */
        struct ast_dns_query_set *queries;
+       /*! \brief Current viable server addresses */
+       pjsip_server_addresses addresses;
        /*! \brief Callback to invoke upon completion */
        pjsip_resolver_callback *callback;
        /*! \brief User provided data */
        void *token;
 };
 
+/*! \brief Available transports on the system */
+static int sip_available_transports[] = {
+       /* This is a list of transports understood by the resolver, with 
whether they are
+        * available as a valid transport stored
+        */
+       [PJSIP_TRANSPORT_UDP] = 0,
+       [PJSIP_TRANSPORT_TCP] = 0,
+       [PJSIP_TRANSPORT_TLS] = 0,
+       [PJSIP_TRANSPORT_UDP6] = 0,
+       [PJSIP_TRANSPORT_TCP6] = 0,
+       [PJSIP_TRANSPORT_TLS6] = 0,
+};
+
 /*! \brief Destructor for resolution data */
 static void sip_resolve_destroy(void *data)
 {
        struct sip_resolve *resolve = data;
 
        AST_VECTOR_FREE(&resolve->resolving);
-       AST_VECTOR_FREE(&resolve->resolved);
        ao2_cleanup(resolve->queries);
 }
 
 /*! \brief Perform resolution but keep transport and port information */
 static int sip_resolve_add(struct sip_resolve *resolve, const char *name, int 
rr_type, int rr_class, pjsip_transport_type_e transport, int port)
 {
-       struct sip_resolved_target target = {
+       struct sip_target target = {
                .transport = transport,
                .port = port,
        };
@@ -101,31 +110,18 @@
 static int sip_resolve_invoke_user_callback(void *data)
 {
        struct sip_resolve *resolve = data;
-       pjsip_server_addresses addresses = {
-               .count = 0,
-       };
        int idx;
 
-       /* We start from the end because the records with the highest 
preference are there */
-       for (idx = AST_VECTOR_SIZE(&resolve->resolved) - 1; idx >= 0; --idx) {
-               struct sip_resolved_target *target = 
AST_VECTOR_GET_ADDR(&resolve->resolved, idx);
-               int address_pos;
-               char addr[256];
-
-               for (address_pos = 0; address_pos < target->addresses.count; 
++address_pos) {
-                       ast_debug(2, "[%p] Address '%d' is '%s' port '%d' with 
transport '%s'\n",
-                               resolve, addresses.count, 
pj_sockaddr_print(&target->addresses.entry[address_pos].addr, addr, 
sizeof(addr), 0),
-                               
pj_sockaddr_get_port(&target->addresses.entry[address_pos].addr), 
pjsip_transport_get_type_name(target->addresses.entry[address_pos].type));
-                       addresses.entry[addresses.count++] = 
target->addresses.entry[address_pos];
-               }
-
-               if (addresses.count == PJSIP_MAX_RESOLVED_ADDRESSES) {
-                       break;
-               }
-       }
-
-       ast_debug(2, "[%p] Invoking user callback with '%d' addresses\n", 
resolve, addresses.count);
-       resolve->callback(PJ_SUCCESS, resolve->token, &addresses);
+       for (idx = 0; idx < resolve->addresses.count; ++idx) {
+               char addr[PJ_INET6_ADDRSTRLEN + 10];
+
+               ast_debug(2, "[%p] Address '%d' is %s with transport '%s'\n",
+                       resolve, idx, 
pj_sockaddr_print(&resolve->addresses.entry[idx].addr, addr, sizeof(addr), 3),
+                       
pjsip_transport_get_type_name(resolve->addresses.entry[idx].type));
+       }
+
+       ast_debug(2, "[%p] Invoking user callback with '%d' addresses\n", 
resolve, resolve->addresses.count);
+       resolve->callback(PJ_SUCCESS, resolve->token, &resolve->addresses);
 
        ao2_ref(resolve, -1);
 
@@ -137,8 +133,8 @@
 {
        struct sip_resolve *resolve = ast_dns_query_set_get_data(query_set);
        struct ast_dns_query_set *queries = resolve->queries;
-       struct addresses resolving;
-       int idx;
+       struct targets resolving;
+       int idx, address_count = 0;
 
        ast_debug(2, "[%p] All parallel queries completed\n", resolve);
 
@@ -148,13 +144,16 @@
         * to the old.
         */
        resolving = resolve->resolving;
-       AST_VECTOR_INIT(&resolve->resolving, 1);
-
-       /* Add any AAAA/A records to the resolved list */
+       AST_VECTOR_INIT(&resolve->resolving, 0);
+
+       /* The order of queries is what defines the preference order for the 
records within this invocation.
+        * The preference order overall is defined as a result of drilling down 
from other records. Each
+        * invocation starts placing records at the beginning, moving others 
that may have already been present.
+        */
        for (idx = 0; idx < ast_dns_query_set_num_queries(queries); ++idx) {
                struct ast_dns_query *query = ast_dns_query_set_get(queries, 
idx);
                struct ast_dns_result *result = ast_dns_query_get_result(query);
-               struct sip_resolved_target *target;
+               struct sip_target *target;
                const struct ast_dns_record *record;
 
                if (!result) {
@@ -165,31 +164,66 @@
 
                target = AST_VECTOR_GET_ADDR(&resolving, idx);
                for (record = ast_dns_result_get_records(result); record; 
record = ast_dns_record_get_next(record)) {
-                       if (ast_dns_record_get_rr_type(record) == ns_t_a) {
-                               ast_debug(2, "[%p] A record received on target 
'%s'\n", resolve, ast_dns_query_get_name(query));
-                               
target->addresses.entry[target->addresses.count].type = target->transport;
-                               
target->addresses.entry[target->addresses.count].addr_len = 
sizeof(pj_sockaddr_in);
-                               pj_sockaddr_init(pj_AF_INET(), 
&target->addresses.entry[target->addresses.count].addr, NULL, target->port);
-                               
target->addresses.entry[target->addresses.count++].addr.ipv4.sin_addr = 
*(struct pj_in_addr*)ast_dns_record_get_data(record);
-                       } else if (ast_dns_record_get_rr_type(record) == 
ns_t_aaaa) {
-                               ast_debug(2, "[%p] AAAA record received on 
target '%s'\n", resolve, ast_dns_query_get_name(query));
-                               
target->addresses.entry[target->addresses.count].type = target->transport;
-                               
target->addresses.entry[target->addresses.count].addr_len = 
sizeof(pj_sockaddr_in6);
-                               pj_sockaddr_init(pj_AF_INET6(), 
&target->addresses.entry[target->addresses.count].addr, NULL, target->port);
-                               
pj_memcpy(&target->addresses.entry[target->addresses.count++].addr.ipv6.sin6_addr,
 ast_dns_record_get_data(record),
-                                       sizeof(pj_sockaddr_in6));
+
+                       if (ast_dns_record_get_rr_type(record) == ns_t_a ||
+                               ast_dns_record_get_rr_type(record) == 
ns_t_aaaa) {
+
+                               /* If the maximum number of addresses has 
already been reached by this query set, skip subsequent
+                                * records as they have lower preference - any 
existing ones may get replaced/moved if another
+                                * invocation occurs after this one
+                                */
+                               if (address_count == 
PJSIP_MAX_RESOLVED_ADDRESSES) {
+                                       continue;
+                               }
+
+                               /* Move any existing addresses so we can make 
room for this record, this may hurt your head slightly but
+                                * essentially it figures out the maximum 
number of previous addresses that can exist and caps the
+                                * the memmove operation to that
+                                */
+                               memmove(&resolve->addresses.entry[address_count 
+ 1], &resolve->addresses.entry[address_count],
+                                       sizeof(resolve->addresses.entry[0]) *
+                                       MIN(resolve->addresses.count, 
PJSIP_MAX_RESOLVED_ADDRESSES - address_count - 1));
+
+                               resolve->addresses.entry[address_count].type = 
target->transport;
+
+                               /* Populate address information for the new 
address entry */
+                               if (ast_dns_record_get_rr_type(record) == 
ns_t_a) {
+                                       ast_debug(2, "[%p] A record received on 
target '%s'\n", resolve, ast_dns_query_get_name(query));
+                                       
resolve->addresses.entry[address_count].addr_len = sizeof(pj_sockaddr_in);
+                                       pj_sockaddr_init(pj_AF_INET(), 
&resolve->addresses.entry[address_count].addr, NULL,
+                                               target->port);
+                                       
resolve->addresses.entry[address_count].addr.ipv4.sin_addr = *(struct 
pj_in_addr*)ast_dns_record_get_data(record);
+                               } else {
+                                       ast_debug(2, "[%p] AAAA record received 
on target '%s'\n", resolve, ast_dns_query_get_name(query));
+                                       
resolve->addresses.entry[address_count].addr_len = sizeof(pj_sockaddr_in6);
+                                       pj_sockaddr_init(pj_AF_INET6(), 
&resolve->addresses.entry[address_count].addr, NULL,
+                                               target->port);
+                                       
pj_memcpy(&resolve->addresses.entry[address_count].addr.ipv6.sin6_addr, 
ast_dns_record_get_data(record),
+                                               
ast_dns_record_get_data_size(record));
+                               }
+
+                               address_count++;
                        } else if (ast_dns_record_get_rr_type(record) == 
ns_t_srv) {
+                               /* SRV records just create new queries for 
AAAA+A, nothing fancy */
                                ast_debug(2, "[%p] SRV record received on 
target '%s'\n", resolve, ast_dns_query_get_name(query));
-                               sip_resolve_add(resolve, 
ast_dns_srv_get_host(record), ns_t_a, ns_c_in, target->transport, 
ast_dns_srv_get_port(record));
-                               sip_resolve_add(resolve, 
ast_dns_srv_get_host(record), ns_t_aaaa, ns_c_in, target->transport, 
ast_dns_srv_get_port(record));
+
+                               if (sip_available_transports[target->transport 
+ PJSIP_TRANSPORT_IPV6]) {
+                                       sip_resolve_add(resolve, 
ast_dns_srv_get_host(record), ns_t_aaaa, ns_c_in, target->transport + 
PJSIP_TRANSPORT_IPV6,
+                                               ast_dns_srv_get_port(record));
+                               }
+
+                               if 
(sip_available_transports[target->transport]) {
+                                       sip_resolve_add(resolve, 
ast_dns_srv_get_host(record), ns_t_a, ns_c_in, target->transport,
+                                               ast_dns_srv_get_port(record));
+                               }
                        }
                }
-
-               /* Only add this finished result if there's actually addresses 
on it */
-               if (target->addresses.count) {
-                       AST_VECTOR_APPEND(&resolve->resolved, *target);
-               }
-       }
+       }
+
+       /* Update the server addresses to include any new entries, but since 
it's limited to the maximum resolved
+        * it must never exceed that
+        */
+       resolve->addresses.count = MIN(resolve->addresses.count + 
address_count, PJSIP_MAX_RESOLVED_ADDRESSES);
 
        /* Free the vector we stole as we are responsible for it */
        AST_VECTOR_FREE(&resolving);
@@ -202,8 +236,7 @@
                return;
        }
 
-       /* Invoke callback with target resolved addresses */
-       ast_debug(2, "[%p] Resolution completed - %zd viable targets\n", 
resolve, AST_VECTOR_SIZE(&resolve->resolved));
+       ast_debug(2, "[%p] Resolution completed - %d viable targets\n", 
resolve, resolve->addresses.count);
 
        /* Push a task to invoke the callback, we do this so it is guaranteed 
to run in a PJSIP thread */
        ao2_ref(resolve, +1);
@@ -237,7 +270,7 @@
        int ip_addr_ver;
        pjsip_transport_type_e type = target->type;
        struct sip_resolve *resolve;
-       char host[NI_MAXHOST], srv[NI_MAXHOST];
+       char host[NI_MAXHOST];
        int res = 0;
 
        ast_copy_pj_str(host, &target->addr.host, sizeof(host));
@@ -303,7 +336,7 @@
        resolve->callback = cb;
        resolve->token = token;
 
-       if (AST_VECTOR_INIT(&resolve->resolving, 2) || 
AST_VECTOR_INIT(&resolve->resolved, 2)) {
+       if (AST_VECTOR_INIT(&resolve->resolving, 2)) {
                ao2_ref(resolve, -1);
                cb(PJ_EINVAL, token, NULL);
                return;
@@ -311,23 +344,33 @@
 
        ast_debug(2, "[%p] Created resolution tracking for target '%s'\n", 
resolve, host);
 
-       res |= sip_resolve_add(resolve, host, ns_t_a, ns_c_in, (type == 
PJSIP_TRANSPORT_UNSPECIFIED ? PJSIP_TRANSPORT_UDP : type), target->addr.port);
-       res |= sip_resolve_add(resolve, host, ns_t_aaaa, ns_c_in, (type == 
PJSIP_TRANSPORT_UNSPECIFIED ? PJSIP_TRANSPORT_UDP : type), target->addr.port);
-
        /* If no port has been specified we can do NAPTR + SRV */
        if (!target->addr.port) {
-               if (type == PJSIP_TRANSPORT_UDP || type == 
PJSIP_TRANSPORT_UNSPECIFIED) {
+               char srv[NI_MAXHOST];
+
+               if ((type == PJSIP_TRANSPORT_TLS || type == 
PJSIP_TRANSPORT_UNSPECIFIED) &&
+                       (sip_available_transports[PJSIP_TRANSPORT_TLS] || 
sip_available_transports[PJSIP_TRANSPORT_TLS6])) {
+                       snprintf(srv, sizeof(srv), "_sips._tcp.%s", host);
+                       res |= sip_resolve_add(resolve, srv, ns_t_srv, ns_c_in, 
PJSIP_TRANSPORT_TLS, 0);
+               }
+               if ((type == PJSIP_TRANSPORT_TCP || type == 
PJSIP_TRANSPORT_UNSPECIFIED) &&
+                       (sip_available_transports[PJSIP_TRANSPORT_TCP] || 
sip_available_transports[PJSIP_TRANSPORT_TCP6])) {
+                       snprintf(srv, sizeof(srv), "_sip._tcp.%s", host);
+                       res |= sip_resolve_add(resolve, srv, ns_t_srv, ns_c_in, 
PJSIP_TRANSPORT_TCP, 0);
+               }
+               if ((type == PJSIP_TRANSPORT_UDP || type == 
PJSIP_TRANSPORT_UNSPECIFIED) &&
+                       (sip_available_transports[PJSIP_TRANSPORT_UDP] || 
sip_available_transports[PJSIP_TRANSPORT_UDP6])) {
                        snprintf(srv, sizeof(srv), "_sip._udp.%s", host);
                        res |= sip_resolve_add(resolve, srv, ns_t_srv, ns_c_in, 
PJSIP_TRANSPORT_UDP, 0);
                }
-               if (type == PJSIP_TRANSPORT_TCP || type == 
PJSIP_TRANSPORT_UNSPECIFIED) {
-                       snprintf(srv, sizeof(srv), "_sip._tcp.%s", host);
-                       res |= sip_resolve_add(resolve, srv, ns_t_srv, ns_c_in, 
PJSIP_TRANSPORT_TCP, 0);
-               }
-               if (type == PJSIP_TRANSPORT_TLS || type == 
PJSIP_TRANSPORT_UNSPECIFIED) {
-                       snprintf(srv, sizeof(srv), "_sips._tcp.%s", host);
-                       res |= sip_resolve_add(resolve, srv, ns_t_srv, ns_c_in, 
PJSIP_TRANSPORT_TLS, 0);
-               }
+       }
+
+       if (sip_available_transports[PJSIP_TRANSPORT_UDP6]) {
+               res |= sip_resolve_add(resolve, host, ns_t_aaaa, ns_c_in, (type 
== PJSIP_TRANSPORT_UNSPECIFIED ? PJSIP_TRANSPORT_UDP6 : type), 
target->addr.port);
+       }
+
+       if (sip_available_transports[PJSIP_TRANSPORT_UDP]) {
+               res |= sip_resolve_add(resolve, host, ns_t_a, ns_c_in, (type == 
PJSIP_TRANSPORT_UNSPECIFIED ? PJSIP_TRANSPORT_UDP : type), target->addr.port);
        }
 
        if (res) {
@@ -342,8 +385,45 @@
        ao2_ref(resolve, -1);
 }
 
+/*! \brief Internal function used to determine if a transport is available */
+static void sip_check_transport(pj_pool_t *pool, pjsip_transport_type_e type, 
const char *name)
+{
+       pjsip_tpmgr_fla2_param prm;
+
+       pjsip_tpmgr_fla2_param_default(&prm);
+       prm.tp_type = type;
+
+       if 
(pjsip_tpmgr_find_local_addr2(pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint()),
+               pool, &prm) == PJ_SUCCESS) {
+               ast_verb(2, "'%s' is an available SIP transport\n", name);
+               sip_available_transports[type] = 1;
+       } else {
+               ast_verb(2, "'%s' is not an available SIP transport, disabling 
resolver support for it\n",
+                       name);
+       }
+}
+
 static int sip_replace_resolver(void *data)
 {
+       pj_pool_t *pool;
+
+
+       pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "Transport 
Availability", 256, 256);
+       if (!pool) {
+               return -1;
+       }
+
+       /* Determine what transports are available on the system */
+       sip_check_transport(pool, PJSIP_TRANSPORT_UDP, "UDP+IPv4");
+       sip_check_transport(pool, PJSIP_TRANSPORT_TCP, "TCP+IPv4");
+       sip_check_transport(pool, PJSIP_TRANSPORT_TLS, "TLS+IPv4");
+       sip_check_transport(pool, PJSIP_TRANSPORT_UDP6, "UDP+IPv6");
+       sip_check_transport(pool, PJSIP_TRANSPORT_TCP6, "TCP+IPv6");
+       sip_check_transport(pool, PJSIP_TRANSPORT_TLS6, "TLS+IPv6");
+
+       pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
+
+       /* Replace the PJSIP resolver with our own implementation */
        pjsip_endpt_set_resolver_implementation(ast_sip_get_pjsip_endpoint(), 
sip_resolve);
        return 0;
 }


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