[Freeswitch-svn] [commit] r8893 - in freeswitch/trunk/src: . include mod/endpoints/mod_sofia

Freeswitch SVN mikej at freeswitch.org
Thu Jul 3 14:50:15 EDT 2008


Author: mikej
Date: Thu Jul  3 14:50:15 2008
New Revision: 8893

Modified:
   freeswitch/trunk/src/include/switch_utils.h
   freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c
   freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c
   freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c
   freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_presence.c
   freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_reg.c
   freeswitch/trunk/src/switch_apr.c
   freeswitch/trunk/src/switch_rtp.c
   freeswitch/trunk/src/switch_utils.c

Log:
update

Modified: freeswitch/trunk/src/include/switch_utils.h
==============================================================================
--- freeswitch/trunk/src/include/switch_utils.h	(original)
+++ freeswitch/trunk/src/include/switch_utils.h	Thu Jul  3 14:50:15 2008
@@ -118,10 +118,44 @@
   \brief find the char representation of an ip adress
   \param buf the buffer to write the ip adress found into
   \param len the length of the buf
-  \param in the struct in_addr * to get the adress from
+  \param sa the struct sockaddr * to get the adress from
+  \param salen the length of sa
   \return the ip adress string
 */
-SWITCH_DECLARE(char *) get_addr(char *buf, switch_size_t len, struct in_addr *in);
+SWITCH_DECLARE(char *) get_addr(char *buf, switch_size_t len, struct sockaddr *sa, socklen_t salen);
+
+/*!
+  \brief get the port number of an ip address
+  \param sa the struct sockaddr * to get the port from
+  \return the ip adress string
+*/
+SWITCH_DECLARE(unsigned short) get_port(struct sockaddr *sa);
+
+/*!
+  \brief flags to be used with switch_build_uri()
+ */
+enum switch_uri_flags {
+	SWITCH_URI_NUMERIC_HOST = 1,
+	SWITCH_URI_NUMERIC_PORT = 2,
+	SWITCH_URI_NO_SCOPE = 4,
+};
+
+/*!
+  \brief build a URI string from components
+  \param uri output string
+  \param size maximum size of output string (including trailing null)
+  \param scheme URI scheme
+  \param user user part or null if none
+  \param sa host address
+  \param flags logical OR-ed combination of flags from \ref switch_uri_flags
+  \return number of characters printed (not including the trailing null)
+ */
+SWITCH_DECLARE(int) switch_build_uri(char *uri,
+									 switch_size_t size,
+									 const char *scheme,
+									 const char *user,
+									 const switch_sockaddr_t *sa,
+									 int flags);
 
 #define SWITCH_STATUS_IS_BREAK(x) (x == SWITCH_STATUS_BREAK || x == 730035 || x == 35)
 

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.c	Thu Jul  3 14:50:15 2008
@@ -926,7 +926,8 @@
 			char ref_to[128] = "";
 
 			if (!strstr(msg->string_arg, "sip:")) {
-				switch_snprintf(ref_to, sizeof(ref_to), "sip:%s@%s", msg->string_arg, tech_pvt->profile->sipip);
+				const char *format = strchr(tech_pvt->profile->sipip, ':') ? "sip:%s@[%s]" : "sip:%s@%s";
+				switch_snprintf(ref_to, sizeof(ref_to), format, msg->string_arg, tech_pvt->profile->sipip);
 			} else {
 				switch_set_string(ref_to, msg->string_arg);
 			}

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c	Thu Jul  3 14:50:15 2008
@@ -215,7 +215,8 @@
 
 		if (authorization) {
 			char network_ip[80];
-			get_addr(network_ip, sizeof(network_ip), &((struct sockaddr_in *) msg_addrinfo(nua_current_request(nua))->ai_addr)->sin_addr);
+			su_addrinfo_t *addrinfo = msg_addrinfo(nua_current_request(nua));
+			get_addr(network_ip, sizeof(network_ip), addrinfo->ai_addr, addrinfo->ai_addrlen);
 			auth_res = sofia_reg_parse_auth(profile, authorization, sip,
 											(char *) sip->sip_request->rq_method_name, tech_pvt->key, strlen(tech_pvt->key), network_ip, NULL, 0,
 											REG_INVITE, NULL);
@@ -749,6 +750,7 @@
 		switch_mutex_unlock(mod_sofia_globals.hash_mutex);
 
 		if ((gateway = switch_core_alloc(profile->pool, sizeof(*gateway)))) {
+			const char *sipip, *format;
 			char *register_str = "true", *scheme = "Digest",
 				*realm = NULL,
 				*username = NULL,
@@ -893,8 +895,11 @@
 
 			gateway->register_url = switch_core_sprintf(gateway->pool, "sip:%s;transport=%s", register_proxy, register_transport);
 			gateway->register_from = switch_core_sprintf(gateway->pool, "<sip:%s@%s;transport=%s>", from_user, from_domain, register_transport);
-			gateway->register_contact = switch_core_sprintf(gateway->pool, "<sip:%s@%s:%d%s>", extension,
-															profile->extsipip ? profile->extsipip : profile->sipip,
+
+			sipip = profile->extsipip ?  profile->extsipip : profile->sipip;
+			format = strchr(sipip, ':') ? "<sip:%s@[%s]:%d%s>" : "<sip:%s@%s:%d%s>";
+			gateway->register_contact = switch_core_sprintf(gateway->pool, format, extension,
+															sipip,
 															sofia_glue_transport_has_tls(gateway->register_transport) ? profile->tls_sip_port : profile->
 															sip_port, params);
 
@@ -1389,10 +1394,22 @@
 					profile->sipdomain = switch_core_strdup(profile->pool, profile->sipip);
 				}
 				if (profile->extsipip) {
-					profile->url = switch_core_sprintf(profile->pool, "sip:mod_sofia@%s:%d", profile->extsipip, profile->sip_port);
+					char *ipv6 = strchr(profile->extsipip, ':');
+					profile->url = switch_core_sprintf(profile->pool,
+														"sip:mod_sofia@%s%s%s:%d",
+														ipv6 ? "[" : "",
+														profile->extsipip,
+														ipv6 ? "]" : "",
+														profile->sip_port);
 					profile->bindurl = switch_core_sprintf(profile->pool, "%s;maddr=%s", profile->url, profile->sipip);
 				} else {
-					profile->url = switch_core_sprintf(profile->pool, "sip:mod_sofia@%s:%d", profile->sipip, profile->sip_port);
+					char *ipv6 = strchr(profile->sipip, ':');
+					profile->url = switch_core_sprintf(profile->pool,
+														"sip:mod_sofia@%s%s%s:%d",
+														ipv6 ? "[" : "",
+														profile->sipip,
+														ipv6 ? "]" : "",
+														profile->sip_port);
 					profile->bindurl = profile->url;
 				}
 
@@ -1410,12 +1427,37 @@
 					}
 
 					if (profile->extsipip) {
-						profile->tls_url = switch_core_sprintf(profile->pool, "sip:mod_sofia@%s:%d", profile->extsipip, profile->tls_sip_port);
+						char *ipv6 = strchr(profile->extsipip, ':');
+						profile->tls_url = 
+							switch_core_sprintf(profile->pool,
+												"sip:mod_sofia@%s%s%s:%d",
+												ipv6 ? "[" : "",
+												profile->extsipip, ipv6 ? "]" : "",
+												profile->tls_sip_port);
 						profile->tls_bindurl =
-							switch_core_sprintf(profile->pool, "sips:mod_sofia@%s:%d;maddr=%s", profile->extsipip, profile->tls_sip_port, profile->sipip);
+							switch_core_sprintf(profile->pool,
+												"sips:mod_sofia@%s%s%s:%d;maddr=%s",
+												ipv6 ? "[" : "",
+												profile->extsipip,
+												ipv6 ? "]" : "",
+												profile->tls_sip_port,
+												profile->sipip);
 					} else {
-						profile->tls_url = switch_core_sprintf(profile->pool, "sip:mod_sofia@%s:%d", profile->sipip, profile->tls_sip_port);
-						profile->tls_bindurl = switch_core_sprintf(profile->pool, "sips:mod_sofia@%s:%d", profile->sipip, profile->tls_sip_port);
+						char *ipv6 = strchr(profile->sipip, ':');
+						profile->tls_url = 
+							switch_core_sprintf(profile->pool,
+												"sip:mod_sofia@%s%s%s:%d",
+												ipv6 ? "[" : "",
+												profile->sipip,
+												ipv6 ? "]" : "",
+												profile->tls_sip_port);
+						profile->tls_bindurl =
+							switch_core_sprintf(profile->pool,
+												"sips:mod_sofia@%s%s%s:%d",
+												ipv6 ? "[" : "",
+												profile->sipip,
+												ipv6 ? "]" : "",
+												profile->tls_sip_port);
 					}
 
 					if (profile->tls_bind_params) {
@@ -2637,7 +2679,7 @@
 		return;
 	}
 
-	get_addr(network_ip, sizeof(network_ip), &((struct sockaddr_in *) my_addrinfo->ai_addr)->sin_addr);
+	get_addr(network_ip, sizeof(network_ip), my_addrinfo->ai_addr, my_addrinfo->ai_addrlen);
 	network_port = ntohs(((struct sockaddr_in *) msg_addrinfo(nua_current_request(nua))->ai_addr)->sin_port);
 
 	if ((profile->pflags & PFLAG_AGGRESSIVE_NAT_DETECTION)) {
@@ -2754,9 +2796,17 @@
 		char tmp[35] = "";
 		sofia_transport_t transport = sofia_glue_url2transport(sip->sip_contact->m_url);
 
-		tech_pvt->record_route = switch_core_session_sprintf(session, "sip:%s@%s:%d;transport=%s",
-															 sip->sip_contact->m_url->url_user, tech_pvt->remote_ip, 
-															 tech_pvt->remote_port, sofia_glue_transport2str(transport));
+		const char *ipv6 = strchr(tech_pvt->remote_ip, ':');
+		tech_pvt->record_route =
+			switch_core_session_sprintf(session,
+			"sip:%s@%s%s%s:%d;transport=%s",
+			sip->sip_contact->m_url->url_user,
+			ipv6 ? "[" : "",
+			tech_pvt->remote_ip,
+			ipv6 ? "]" : "",
+			tech_pvt->remote_port,
+			sofia_glue_transport2str(transport));
+
 		switch_channel_set_variable(channel, "sip_received_ip", tech_pvt->remote_ip);
 		snprintf(tmp, sizeof(tmp), "%d", tech_pvt->remote_port);
 		switch_channel_set_variable(channel, "sip_received_port", tmp);
@@ -2871,6 +2921,7 @@
 
 		url_set_chanvars(session, sip->sip_to->a_url, sip_to);
 		if (switch_channel_get_variable(channel, "sip_to_uri")) {
+			const char *ipv6;
 
 			host = switch_channel_get_variable(channel, "sip_to_host");
 			user = switch_channel_get_variable(channel, "sip_to_user");
@@ -2887,7 +2938,14 @@
 				port = sofia_glue_transport_has_tls(transport) ? profile->tls_sip_port : profile->sip_port;
 			}
 
-			tech_pvt->to_uri = switch_core_session_sprintf(session, "sip:%s@%s:%d;transport=%s", user, host, port, sofia_glue_transport2str(transport));
+			ipv6 = strchr(host, ':');
+			tech_pvt->to_uri =
+				switch_core_session_sprintf(session,
+					"sip:%s@%s%s%s:%d;transport=%s",
+					user, ipv6 ? "[" : "",
+					host, ipv6 ? "]" : "",
+					port,
+					sofia_glue_transport2str(transport));
 
 			if (profile->ndlb & PFLAG_NDLB_TO_IN_200_CONTACT) {
 				if (strchr(tech_pvt->to_uri, '>')) {

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c	Thu Jul  3 14:50:15 2008
@@ -44,6 +44,7 @@
 	uint32_t v_port;
 	int use_cng = 1;
 	const char *val;
+	const char *family;
 	const char *pass_fmtp = switch_channel_get_variable(tech_pvt->channel, "sip_video_fmtp");
 	const char *ov_fmtp = switch_channel_get_variable(tech_pvt->channel, "sip_force_video_fmtp");
 
@@ -82,13 +83,14 @@
 
 	tech_pvt->session_id++;
 
+	family = strchr(ip, ':') ? "IP6" : "IP4";
 	switch_snprintf(buf, sizeof(buf),
 					"v=0\n"
-					"o=FreeSWITCH %010u %010u IN IP4 %s\n"
+					"o=FreeSWITCH %010u %010u IN %s %s\n"
 					"s=FreeSWITCH\n"
-					"c=IN IP4 %s\n" "t=0 0\n"
+					"c=IN %s %s\n" "t=0 0\n"
 					"a=%s\n"
-					"m=audio %d RTP/%sAVP", tech_pvt->owner_id, tech_pvt->session_id, ip, ip, sr, port,
+					"m=audio %d RTP/%sAVP", tech_pvt->owner_id, tech_pvt->session_id, family, ip, family, ip, sr, port,
 					(!switch_strlen_zero(tech_pvt->local_crypto_key) && switch_test_flag(tech_pvt, TFLAG_SECURE)) ? "S" : "");
 
 
@@ -730,7 +732,8 @@
 		return SWITCH_STATUS_FALSE;
 	}
 
-	if ((p = (char *) switch_stristr("c=IN IP4 ", tech_pvt->remote_sdp_str))) {
+	if ((p = (char *) switch_stristr("c=IN IP4 ", tech_pvt->remote_sdp_str)) ||
+		(p = (char *) switch_stristr("c=IN IP6 ", tech_pvt->remote_sdp_str))) {
 		ip_ptr = p + 9;
 	}
 
@@ -833,7 +836,8 @@
 
 	len = strlen(tech_pvt->local_sdp_str) + 384;
 
-	if ((p = (char *) switch_stristr("c=IN IP4 ", tech_pvt->local_sdp_str))) {
+	if ((p = (char *) switch_stristr("c=IN IP4 ", tech_pvt->local_sdp_str)) ||
+		(p = (char *) switch_stristr("c=IN IP6 ", tech_pvt->local_sdp_str))) {
 		ip_ptr = p + 9;
 	}
 
@@ -956,11 +960,15 @@
 	check_decode(cid_num, session);
 
 	if (!tech_pvt->from_str) {
-		tech_pvt->from_str = switch_core_session_sprintf(tech_pvt->session, "\"%s\" <sip:%s%s%s>",
-														 cid_name,
-														 cid_num,
-														 !switch_strlen_zero(cid_num) ? "@" : "",
-														 tech_pvt->profile->extsipip ? tech_pvt->profile->extsipip : tech_pvt->profile->sipip);
+		const char* sipip = tech_pvt->profile->extsipip ? tech_pvt->profile->extsipip : tech_pvt->profile->sipip;
+		const char* format = strchr(sipip, ':') ? "\"%s\" <sip:%s%s[%s]>" : "\"%s\" <sip:%s%s%s>";
+		tech_pvt->from_str = 
+			switch_core_session_sprintf(tech_pvt->session,
+										format,
+										cid_name,
+										cid_num,
+										!switch_strlen_zero(cid_num) ? "@" : "",
+										sipip);
 	}
 
 	if ((alertbuf = switch_channel_get_variable(channel, "alert_info"))) {
@@ -1223,15 +1231,17 @@
 	private_object_t *tech_pvt = switch_core_session_get_private(session);
 	switch_channel_t *channel = switch_core_session_get_channel(session);
 	switch_caller_profile_t *caller_profile;
+	const char *sipip, *format; 
 
 	switch_assert(tech_pvt != NULL);
 
 	caller_profile = switch_channel_get_caller_profile(channel);
 
-	if ((tech_pvt->from_str = switch_core_session_sprintf(session, "\"%s\" <sip:%s@%s>",
-														  caller_profile->caller_id_name,
-														  caller_profile->caller_id_number,
-														  tech_pvt->profile->extsipip ? tech_pvt->profile->extsipip : tech_pvt->profile->sipip))) {
+	sipip = tech_pvt->profile->extsipip ? tech_pvt->profile->extsipip : tech_pvt->profile->sipip;
+	format = strchr(sipip, ':') ? "\"%s\" <sip:%s@[%s]>" : "\"%s\" <sip:%s@%s>";
+	if ((tech_pvt->from_str = switch_core_session_sprintf(session, format,
+															caller_profile->caller_id_name,
+															caller_profile->caller_id_number, sipip))) {
 
 		const char *rep = switch_channel_get_variable(channel, SOFIA_REPLACES_HEADER);
 
@@ -1637,7 +1647,7 @@
 	}
 
 	if (!switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA)) {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "AUDIO RTP [%s] %s:%d->%s:%d codec: %u ms: %d\n",
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "AUDIO RTP [%s] %s port %d -> %s port %d codec: %u ms: %d\n",
 						  switch_channel_get_name(tech_pvt->channel),
 						  tech_pvt->local_sdp_audio_ip,
 						  tech_pvt->local_sdp_audio_port,

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_presence.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_presence.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_presence.c	Thu Jul  3 14:50:15 2008
@@ -1203,13 +1203,14 @@
 		char *port;
 		char new_port[25] = "";
 		char *is_nat = NULL;
+		const char *ipv6;
 
 		if (!(contact && sip->sip_contact->m_url)) {
 			nua_respond(nh, 481, "INVALID SUBSCRIPTION", TAG_END());
 			return;
 		}
 
-		get_addr(network_ip, sizeof(network_ip), &((struct sockaddr_in *) my_addrinfo->ai_addr)->sin_addr);
+		get_addr(network_ip, sizeof(network_ip), my_addrinfo->ai_addr, my_addrinfo->ai_addrlen);
 		network_port = ntohs(((struct sockaddr_in *) msg_addrinfo(nua_current_request(nua))->ai_addr)->sin_port);
 
 		tl_gets(tags, NUTAG_SUBSTATE_REF(sub_state), TAG_END());
@@ -1279,11 +1280,25 @@
 			switch_snprintf(new_port, sizeof(new_port), ":%s", port);
 		}
 
+		ipv6 = strchr(contact_host, ':');
 		if (contact->m_url->url_params) {
-			contact_str = switch_mprintf("%s <sip:%s@%s%s;%s>%s",
-										 display, contact->m_url->url_user, contact_host, new_port, contact->m_url->url_params, is_nat ? ";nat" : "");
+			contact_str = switch_mprintf("%s <sip:%s@%s%s%s%s;%s>%s",
+										display, contact->m_url->url_user,
+										ipv6 ? "[" : "",
+										contact_host,
+										ipv6 ? "]" : "",
+										new_port,
+										contact->m_url->url_params,
+										is_nat ? ";nat" : "");
 		} else {
-			contact_str = switch_mprintf("%s <sip:%s@%s%s>%s", display, contact->m_url->url_user, contact_host, new_port, is_nat ? ";nat" : "");
+			contact_str = switch_mprintf("%s <sip:%s@%s%s%s%s>%s",
+										display,
+										contact->m_url->url_user,
+										ipv6 ? "[" : "",
+										contact_host,
+										ipv6 ? "]" : "",
+										new_port,
+										is_nat ?  ";nat" : "");
 		}
 
 
@@ -1398,7 +1413,13 @@
 			char *sticky = NULL;
 
 			if (is_nat) {
-				sticky = switch_mprintf("sip:%s@%s:%d", contact_user, network_ip, network_port);
+				const char *ipv6 = strchr(network_ip, ':');
+				sticky = switch_mprintf("sip:%s@%s%s%s:%d",
+										contact_user,
+										ipv6 ? "[" : "",
+										network_ip,
+										ipv6 ? "]" : "",
+										network_port);
 			}
 
 			nua_respond(nh, SIP_202_ACCEPTED, NUTAG_WITH_THIS(nua), SIPTAG_SUBSCRIPTION_STATE_STR(sstr), TAG_IF(sticky, NUTAG_PROXY(sticky)),

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_reg.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_reg.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_reg.c	Thu Jul  3 14:50:15 2008
@@ -403,6 +403,7 @@
 	const char *rpid = "unknown";
 	const char *display = "\"user\"";
 	char network_ip[80];
+	char url_ip[80];
 	char *register_gateway = NULL;
 	int network_port;
 	const char *reg_desc = "Registered";
@@ -410,12 +411,15 @@
 	char *force_user;
 	char received_data[128] = "";
 	char *path_val = NULL;
-	
+	su_addrinfo_t *my_addrinfo = msg_addrinfo(nua_current_request(nua));
+
 	/* all callers must confirm that sip, sip->sip_request and sip->sip_contact are not NULL */
 	switch_assert(sip != NULL && sip->sip_contact != NULL && sip->sip_request != NULL);
 
-	get_addr(network_ip, sizeof(network_ip), &((struct sockaddr_in *) msg_addrinfo(nua_current_request(nua))->ai_addr)->sin_addr);
-	network_port = ntohs(((struct sockaddr_in *) msg_addrinfo(nua_current_request(nua))->ai_addr)->sin_port);
+	get_addr(network_ip, sizeof(network_ip), my_addrinfo->ai_addr,my_addrinfo->ai_addrlen);
+	network_port = get_port(my_addrinfo->ai_addr);
+
+	snprintf(url_ip, sizeof(url_ip), my_addrinfo->ai_addr->sa_family == AF_INET6 ? "[%s]" : "%s", network_ip);
 
 	expires = sip->sip_expires;
 	authorization = sip->sip_authorization;
@@ -466,7 +470,7 @@
 			} else {
 				reg_desc = "Registered(UDP-NAT)";
 			}
-			contact_host = network_ip;
+			contact_host = url_ip;
 			switch_snprintf(new_port, sizeof(new_port), ":%d", network_port);
 			port = NULL;
 		} else {
@@ -501,7 +505,7 @@
 		}
 
 		if (is_nat && (profile->pflags & PFLAG_RECIEVED_IN_NAT_REG_CONTACT)) {
-			switch_snprintf(received_data, sizeof(received_data), ";received=\"%s:%d\"", network_ip, network_port);
+			switch_snprintf(received_data, sizeof(received_data), ";received=\"%s:%d\"", url_ip, network_port);
 		}
 
 		if (contact->m_url->url_params) {
@@ -556,16 +560,16 @@
 			if ((v_contact_str = switch_event_get_header(*v_event, "sip-force-contact"))) {
 
 				if (*received_data && (profile->pflags & PFLAG_RECIEVED_IN_NAT_REG_CONTACT)) {
-					switch_snprintf(received_data, sizeof(received_data), ";received=\"%s:%d\"", network_ip, network_port);
+					switch_snprintf(received_data, sizeof(received_data), ";received=\"%s:%d\"", url_ip, network_port);
 				}
 
 				if (!strcasecmp(v_contact_str, "nat-connectile-dysfunction") ||
 					!strcasecmp(v_contact_str, "NDLB-connectile-dysfunction") || !strcasecmp(v_contact_str, "NDLB-tls-connectile-dysfunction")) {
 					if (contact->m_url->url_params) {
 						switch_snprintf(contact_str, sizeof(contact_str), "%s <sip:%s@%s:%d;%s%s;fs_nat=yes>",
-										display, contact->m_url->url_user, network_ip, network_port, contact->m_url->url_params, received_data);
+										display, contact->m_url->url_user, url_ip, network_port, contact->m_url->url_params, received_data);
 					} else {
-						switch_snprintf(contact_str, sizeof(contact_str), "%s <sip:%s@%s:%d%s;fs_nat=yes>", display, contact->m_url->url_user, network_ip,
+						switch_snprintf(contact_str, sizeof(contact_str), "%s <sip:%s@%s:%d%s;fs_nat=yes>", display, contact->m_url->url_user, url_ip,
 										network_port, received_data);
 					}
 					if (strstr(v_contact_str, "tls")) {
@@ -762,8 +766,8 @@
 	char *is_nat = NULL;
 
 
-	get_addr(network_ip, sizeof(network_ip), &((struct sockaddr_in *) my_addrinfo->ai_addr)->sin_addr);
-	network_port = ntohs(((struct sockaddr_in *) msg_addrinfo(nua_current_request(nua))->ai_addr)->sin_port);
+	get_addr(network_ip, sizeof(network_ip), my_addrinfo->ai_addr, my_addrinfo->ai_addrlen);
+	network_port = get_port(msg_addrinfo(nua_current_request(nua))->ai_addr);
 
 
 	if (!(sip->sip_contact && sip->sip_contact->m_url)) {

Modified: freeswitch/trunk/src/switch_apr.c
==============================================================================
--- freeswitch/trunk/src/switch_apr.c	(original)
+++ freeswitch/trunk/src/switch_apr.c	Thu Jul  3 14:50:15 2008
@@ -630,7 +630,7 @@
 	if (!in) {
 		return "";
 	}
-	return get_addr(buf, len, &in->sa.sin.sin_addr);
+	return get_addr(buf, len, (struct sockaddr*)&in->sa, in->salen);
 }
 
 SWITCH_DECLARE(uint16_t) switch_sockaddr_get_port(switch_sockaddr_t *sa)

Modified: freeswitch/trunk/src/switch_rtp.c
==============================================================================
--- freeswitch/trunk/src/switch_rtp.c	(original)
+++ freeswitch/trunk/src/switch_rtp.c	Thu Jul  3 14:50:15 2008
@@ -121,7 +121,13 @@
 };
 
 struct switch_rtp {
-	switch_socket_t *sock;
+	/* 
+	 * Two sockets are needed because we might be transcoding protocol families
+	 * (e.g. receive over IPv4 and send over IPv6). In case the protocol
+	 * families are equal, sock_input == sock_output and only one socket is
+	 * used.
+	 */
+	switch_socket_t *sock_input, *sock_output;
 
 	switch_sockaddr_t *local_addr;
 	rtp_msg_t send_msg;
@@ -220,7 +226,7 @@
 	packet = switch_stun_packet_build_header(SWITCH_STUN_BINDING_REQUEST, NULL, buf);
 	switch_stun_packet_attribute_add_username(packet, rtp_session->ice_user, 32);
 	bytes = switch_stun_packet_length(packet);
-	switch_socket_sendto(rtp_session->sock, rtp_session->remote_addr, 0, (void *) packet, &bytes);
+	switch_socket_sendto(rtp_session->sock_output, rtp_session->remote_addr, 0, (void *) packet, &bytes);
 	rtp_session->stuncount = 25;
 
   end:
@@ -296,7 +302,7 @@
 		remote_ip = switch_get_addr(ipbuf, sizeof(ipbuf), rtp_session->from_addr);
 		switch_stun_packet_attribute_add_binded_address(rpacket, (char *) remote_ip, switch_sockaddr_get_port(rtp_session->from_addr));
 		bytes = switch_stun_packet_length(rpacket);
-		switch_socket_sendto(rtp_session->sock, rtp_session->from_addr, 0, (void *) rpacket, &bytes);
+		switch_socket_sendto(rtp_session->sock_output, rtp_session->from_addr, 0, (void *) rpacket, &bytes);
 	}
 
   end:
@@ -440,11 +446,11 @@
 		goto done;
 	}
 
-	if (rtp_session->sock) {
+	if (rtp_session->sock_input) {
 		switch_rtp_kill_socket(rtp_session);
 	}
 
-	if (switch_socket_create(&new_sock, AF_INET, SOCK_DGRAM, 0, rtp_session->pool) != SWITCH_STATUS_SUCCESS) {
+	if (switch_socket_create(&new_sock, switch_sockaddr_get_family(rtp_session->local_addr), SOCK_DGRAM, 0, rtp_session->pool) != SWITCH_STATUS_SUCCESS) {
 		*err = "Socket Error!";
 		goto done;
 	}
@@ -483,12 +489,12 @@
 
 #endif
 
-	old_sock = rtp_session->sock;
-	rtp_session->sock = new_sock;
+	old_sock = rtp_session->sock_input;
+	rtp_session->sock_input = new_sock;
 	new_sock = NULL;
 
 	if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_USE_TIMER) || switch_test_flag(rtp_session, SWITCH_RTP_FLAG_NOBLOCK)) {
-		switch_socket_opt_set(rtp_session->sock, SWITCH_SO_NONBLOCK, TRUE);
+		switch_socket_opt_set(rtp_session->sock_input, SWITCH_SO_NONBLOCK, TRUE);
 		switch_set_flag_locked(rtp_session, SWITCH_RTP_FLAG_NOBLOCK);
 	}
 
@@ -522,6 +528,7 @@
 SWITCH_DECLARE(switch_status_t) switch_rtp_set_remote_address(switch_rtp_t *rtp_session, const char *host, switch_port_t port, const char **err)
 {
 	switch_sockaddr_t *remote_addr;
+	switch_status_t status = SWITCH_STATUS_SUCCESS;
 	*err = "Success";
 
 	if (switch_sockaddr_info_get(&remote_addr, host, SWITCH_UNSPEC, port, 0, rtp_session->pool) != SWITCH_STATUS_SUCCESS || !remote_addr) {
@@ -530,11 +537,32 @@
 	}
 
 	switch_mutex_lock(rtp_session->write_mutex);
+
 	rtp_session->remote_addr = remote_addr;
 	rtp_session->remote_port = port;
+
+	if (rtp_session->sock_input &&
+		switch_sockaddr_get_family(rtp_session->remote_addr) ==
+		switch_sockaddr_get_family(rtp_session->local_addr)) {
+			rtp_session->sock_output = rtp_session->sock_input;
+	}
+	else {
+		if (rtp_session->sock_output &&
+			rtp_session->sock_output != rtp_session->sock_input) {
+				switch_socket_close(rtp_session->sock_output);
+		}
+		if ((status = switch_socket_create(&rtp_session->sock_output,
+			switch_sockaddr_get_family(rtp_session->remote_addr),
+			SOCK_DGRAM, 0, rtp_session->pool)) !=
+			SWITCH_STATUS_SUCCESS)
+		{
+			*err = "Socket Error!";
+		}
+	}
+
 	switch_mutex_unlock(rtp_session->write_mutex);
 
-	return SWITCH_STATUS_SUCCESS;
+	return status;
 }
 
 SWITCH_DECLARE(switch_status_t) switch_rtp_add_crypto_key(switch_rtp_t *rtp_session,
@@ -829,9 +857,9 @@
 
 	switch_assert(rtp_session != NULL);
 	switch_mutex_lock(rtp_session->flag_mutex);
-	if (rtp_session->sock) {
+	if (rtp_session->sock_input) {
 		switch_set_flag_locked(rtp_session, SWITCH_RTP_FLAG_BREAK);
-		switch_socket_sendto(rtp_session->sock, rtp_session->local_addr, 0, (void *) &o, &len);
+		switch_socket_sendto(rtp_session->sock_input, rtp_session->local_addr, 0, (void *) &o, &len);
 	}
 	switch_mutex_unlock(rtp_session->flag_mutex);
 }
@@ -842,8 +870,11 @@
 	switch_mutex_lock(rtp_session->flag_mutex);
 	if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_IO)) {
 		switch_clear_flag(rtp_session, SWITCH_RTP_FLAG_IO);
-		if (rtp_session->sock) {
-			switch_socket_shutdown(rtp_session->sock, SWITCH_SHUTDOWN_READWRITE);
+		if (rtp_session->sock_input) {
+			switch_socket_shutdown(rtp_session->sock_input, SWITCH_SHUTDOWN_READWRITE);
+		}
+		if (rtp_session->sock_output && rtp_session->sock_output != rtp_session->sock_input) {
+			switch_socket_shutdown(rtp_session->sock_output, SWITCH_SHUTDOWN_READWRITE);
 		}
 	}
 	switch_mutex_unlock(rtp_session->flag_mutex);
@@ -858,7 +889,7 @@
 	}
 
 	switch_mutex_lock(rtp_session->flag_mutex);
-	ret = (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_IO) && rtp_session->sock && rtp_session->remote_addr && rtp_session->ready == 2) ? 1 : 0;
+	ret = (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_IO) && rtp_session->sock_input && rtp_session->sock_output && rtp_session->remote_addr && rtp_session->ready == 2) ? 1 : 0;
 	switch_mutex_unlock(rtp_session->flag_mutex);
 
 	return ret;
@@ -899,10 +930,15 @@
 		stfu_n_destroy(&(*rtp_session)->jb);
 	}
 
-	sock = (*rtp_session)->sock;
-	(*rtp_session)->sock = NULL;
+	sock = (*rtp_session)->sock_input;
+	(*rtp_session)->sock_input = NULL;
 	switch_socket_close(sock);
 
+	if ( (*rtp_session)->sock_output != sock ) {
+		sock = (*rtp_session)->sock_output;
+		(*rtp_session)->sock_output = NULL;
+		switch_socket_close(sock);
+	}
 
 	if (switch_test_flag((*rtp_session), SWITCH_RTP_FLAG_VAD)) {
 		switch_rtp_disable_vad(*rtp_session);
@@ -932,7 +968,7 @@
 
 SWITCH_DECLARE(switch_socket_t *) switch_rtp_get_rtp_socket(switch_rtp_t *rtp_session)
 {
-	return rtp_session->sock;
+	return rtp_session->sock_input;
 }
 
 SWITCH_DECLARE(void) switch_rtp_set_default_samples_per_interval(switch_rtp_t *rtp_session, uint16_t samples_per_interval)
@@ -1096,7 +1132,7 @@
 		int do_cng = 0;
 
 		bytes = sizeof(rtp_msg_t);
-		status = switch_socket_recvfrom(rtp_session->from_addr, rtp_session->sock, 0, (void *) &rtp_session->recv_msg, &bytes);
+		status = switch_socket_recvfrom(rtp_session->from_addr, rtp_session->sock_input, 0, (void *) &rtp_session->recv_msg, &bytes);
 
 		if (bytes < 0) {
 			ret = (int) bytes;
@@ -1184,7 +1220,7 @@
 			}
 
 			if (rtp_session->invalid_handler) {
-				rtp_session->invalid_handler(rtp_session, rtp_session->sock, (void *) &rtp_session->recv_msg, bytes, rtp_session->from_addr);
+				rtp_session->invalid_handler(rtp_session, rtp_session->sock_input, (void *) &rtp_session->recv_msg, bytes, rtp_session->from_addr);
 			}
 
 			memset(data, 0, 2);
@@ -1783,7 +1819,7 @@
 			bytes = sbytes;
 		}
 
-		if (switch_socket_sendto(rtp_session->sock, rtp_session->remote_addr, 0, (void *) send_msg, &bytes) != SWITCH_STATUS_SUCCESS) {
+		if (switch_socket_sendto(rtp_session->sock_output, rtp_session->remote_addr, 0, (void *) send_msg, &bytes) != SWITCH_STATUS_SUCCESS) {
 			rtp_session->seq--;
 			ret = -1;
 			goto end;
@@ -1889,7 +1925,7 @@
 			return 0;
 		}
 		bytes = frame->packetlen;
-		if (switch_socket_sendto(rtp_session->sock, rtp_session->remote_addr, 0, frame->packet, &bytes) != SWITCH_STATUS_SUCCESS) {
+		if (switch_socket_sendto(rtp_session->sock_output, rtp_session->remote_addr, 0, frame->packet, &bytes) != SWITCH_STATUS_SUCCESS) {
 			return -1;
 		}
 		return (int) bytes;
@@ -1971,7 +2007,7 @@
 		bytes = sbytes;
 	}
 
-	if (switch_socket_sendto(rtp_session->sock, rtp_session->remote_addr, 0, (void *) &rtp_session->write_msg, &bytes) != SWITCH_STATUS_SUCCESS) {
+	if (switch_socket_sendto(rtp_session->sock_output, rtp_session->remote_addr, 0, (void *) &rtp_session->write_msg, &bytes) != SWITCH_STATUS_SUCCESS) {
 		rtp_session->seq--;
 		ret = -1;
 		goto end;

Modified: freeswitch/trunk/src/switch_utils.c
==============================================================================
--- freeswitch/trunk/src/switch_utils.c	(original)
+++ freeswitch/trunk/src/switch_utils.c	Thu Jul  3 14:50:15 2008
@@ -757,7 +757,7 @@
 				goto doh;
 			}
 
-			switch_copy_string(buf, get_addr(abuf, sizeof(abuf), &iface_out.sin_addr), len);
+			switch_copy_string(buf, get_addr(abuf, sizeof(abuf), (struct sockaddr*)&iface_out, sizeof(iface_out)), len);
 			status = SWITCH_STATUS_SUCCESS;
 		}
 		break;
@@ -768,17 +768,13 @@
 			memset(&remote, 0, sizeof(struct sockaddr_in6));
 
 			remote.sin6_family = AF_INET6;
-			switch_inet_pton(AF_INET6, buf, &remote.sin6_addr);
+			switch_inet_pton(AF_INET6, base, &remote.sin6_addr);
 			remote.sin6_port = htons(4242);
 
 			memset(&iface_out, 0, sizeof(iface_out));
 			tmp_socket = socket(AF_INET6, SOCK_DGRAM, 0);
 
-			if (setsockopt(tmp_socket, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) == -1) {
-				goto doh;
-			}
-
-			if (connect(tmp_socket, (struct sockaddr *) &remote, sizeof(struct sockaddr_in)) == -1) {
+			if (connect(tmp_socket, (struct sockaddr *) &remote, sizeof(remote)) == -1) {
 				goto doh;
 			}
 
@@ -1054,16 +1050,66 @@
 
 #endif
 
-SWITCH_DECLARE(char *) get_addr(char *buf, switch_size_t len, struct in_addr *in)
+SWITCH_DECLARE(char *) get_addr(char *buf, switch_size_t len, struct sockaddr *sa, socklen_t salen)
 {
 	switch_assert(buf);
 	*buf = '\0';
-	if (in) {
-		switch_inet_ntop(AF_INET, in, buf, len);
+	if (sa) {
+		getnameinfo(sa, salen, buf, len, NULL, 0, NI_NUMERICHOST);
 	}
 	return buf;
 }
 
+SWITCH_DECLARE(unsigned short) get_port(struct sockaddr *sa)
+{
+	unsigned short port = 0;
+	if (sa) {
+		switch (sa->sa_family) {
+			case AF_INET:
+				port = ntohs(((struct sockaddr_in*)sa)->sin_port);
+				break;
+			case AF_INET6:
+				port = ntohs(((struct sockaddr_in6*)sa)->sin6_port);
+				break;
+		}
+	}
+	return port;
+}
+
+SWITCH_DECLARE(int) switch_build_uri(char *uri,
+									 switch_size_t size,
+									 const char *scheme,
+									 const char *user,
+									 const switch_sockaddr_t *sa,
+									 int flags)
+{
+	char host[NI_MAXHOST], serv[NI_MAXSERV];
+	struct sockaddr_storage ss;
+	const struct sockaddr *addr;
+	const char *colon;
+
+	if (flags & SWITCH_URI_NO_SCOPE && sa->family == AF_INET6) {
+		memcpy(&ss, &sa->sa, sa->salen);
+		((struct sockaddr_in6*) &ss)->sin6_scope_id = 0;
+		addr = (const struct sockaddr*) &ss;
+	} else {
+		addr = (const struct sockaddr*) &sa->sa;
+	}
+
+	if (getnameinfo(addr, sa->salen, host, sizeof(host), serv, sizeof(serv),
+		(flags & SWITCH_URI_NUMERIC_HOST) ? NI_NUMERICHOST : 0 |
+		(flags & SWITCH_URI_NUMERIC_PORT) ? NI_NUMERICSERV : 0) != 0) {
+			return 0;
+	}
+
+	colon = strchr(host, ':');
+
+	return switch_snprintf(uri, size, "%s:%s%s%s%s%s%s%s", scheme,
+		user ? user : "", user ? "@" : "",
+		colon ? "[" : "", host, colon ? "]" : "",
+		serv[0] ? ":" : "", serv[0] ? serv : "");
+}
+
 SWITCH_DECLARE(char) switch_rfc2833_to_char(int event)
 {
 	if (event > -1 && event < (int32_t) sizeof(RFC2833_CHARS)) {



More information about the Freeswitch-svn mailing list