[asterisk-commits] file: branch group/dns_pjsip r433993 - in /team/group/dns_pjsip: include/aste...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Sat Apr 4 14:46:21 CDT 2015


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;
 }




More information about the asterisk-commits mailing list