From 45bd5952b11a38d73ab0e2a7ce9596cb674aaf62 Mon Sep 17 00:00:00 2001
From: Anthony Minessale <anthm@freeswitch.org>
Date: Tue, 19 Feb 2013 20:18:12 -0600
Subject: [PATCH] fix some regressions and improve candidate selection

---
 src/mod/endpoints/mod_sofia/mod_sofia.c   | 12 +++---
 src/mod/endpoints/mod_sofia/sofia_media.c |  8 ++--
 src/switch_core_media.c                   | 52 +++++++++++++++++++++++
 src/switch_rtp.c                          |  8 ++--
 4 files changed, 66 insertions(+), 14 deletions(-)

diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c
index f483a0c8c6..c088e7a940 100644
--- a/src/mod/endpoints/mod_sofia/mod_sofia.c
+++ b/src/mod/endpoints/mod_sofia/mod_sofia.c
@@ -689,7 +689,7 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
 	}
 
 	if (sofia_test_flag(tech_pvt, TFLAG_ANS) || switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
-		printf("BALLZ %d\n", __LINE__);return SWITCH_STATUS_SUCCESS;
+		return SWITCH_STATUS_SUCCESS;
 	}
 
 
@@ -703,7 +703,7 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
 		if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
 			switch_core_media_patch_sdp(tech_pvt->session);
 			if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) {
-				printf("BALLZ %d\n", __LINE__);return SWITCH_STATUS_FALSE;
+				return SWITCH_STATUS_FALSE;
 			}
 		}
 	} else {
@@ -722,7 +722,7 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
 				if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
 					switch_core_media_patch_sdp(tech_pvt->session);
 					if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) {
-						printf("BALLZ %d\n", __LINE__);return SWITCH_STATUS_FALSE;
+						return SWITCH_STATUS_FALSE;
 					}
 				}
 			}
@@ -777,7 +777,7 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
 			}
 
 			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "3PCC-PROXY, Done waiting for ACK\n");
-			printf("BALLZ %d\n", __LINE__);return SWITCH_STATUS_SUCCESS;
+			return SWITCH_STATUS_SUCCESS;
 		}
 
 		if ((is_proxy && !b_sdp) || sofia_test_flag(tech_pvt, TFLAG_LATE_NEGOTIATION) ||
@@ -800,14 +800,14 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
 					//switch_mutex_lock(tech_pvt->sofia_mutex);
 					//nua_respond(tech_pvt->nh, SIP_488_NOT_ACCEPTABLE, TAG_END());
 					//switch_mutex_unlock(tech_pvt->sofia_mutex);
-					printf("BALLZ %d\n", __LINE__);return SWITCH_STATUS_FALSE;
+					return SWITCH_STATUS_FALSE;
 				}
 			}
 		}
 
 		if ((status = switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0)) != SWITCH_STATUS_SUCCESS) {
 			switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
-			printf("BALLZ %d\n", __LINE__);return status;
+			return status;
 		}
 
 		switch_core_media_gen_local_sdp(session, NULL, 0, NULL, 0);
diff --git a/src/mod/endpoints/mod_sofia/sofia_media.c b/src/mod/endpoints/mod_sofia/sofia_media.c
index ff6f3ae1c7..2d8cc97e25 100644
--- a/src/mod/endpoints/mod_sofia/sofia_media.c
+++ b/src/mod/endpoints/mod_sofia/sofia_media.c
@@ -77,20 +77,20 @@ switch_status_t sofia_media_tech_media(private_object_t *tech_pvt, const char *r
 	switch_assert(r_sdp != NULL);
 
 	if (zstr(r_sdp)) {
-		printf("BALLZ %d\n", __LINE__);return SWITCH_STATUS_FALSE;
+		return SWITCH_STATUS_FALSE;
 	}
 
 	if ((match = sofia_media_negotiate_sdp(tech_pvt->session, r_sdp))) {
 		if (switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0) != SWITCH_STATUS_SUCCESS) {
-			printf("BALLZ %d\n", __LINE__);return SWITCH_STATUS_FALSE;
+			return SWITCH_STATUS_FALSE;
 		}
 		if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) {
-			printf("BALLZ %d\n", __LINE__);return SWITCH_STATUS_FALSE;
+			return SWITCH_STATUS_FALSE;
 		}
 		switch_channel_set_variable(tech_pvt->channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "EARLY MEDIA");
 		sofia_set_flag_locked(tech_pvt, TFLAG_EARLY_MEDIA);
 		switch_channel_mark_pre_answered(tech_pvt->channel);
-		printf("BALLZ %d\n", __LINE__);return SWITCH_STATUS_SUCCESS;
+		return SWITCH_STATUS_SUCCESS;
 	}
 
 
diff --git a/src/switch_core_media.c b/src/switch_core_media.c
index 10f8d1aed8..1586928240 100644
--- a/src/switch_core_media.c
+++ b/src/switch_core_media.c
@@ -1946,6 +1946,58 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
 		}
 		
 	}
+	
+	/* still no candidates, so start searching for some based on sane deduction */
+
+	/* look for candidates on the same network */
+	if (!engine->ice_in.chosen[0] || !engine->ice_in.chosen[1]) {
+		for (i = 0; i <= engine->ice_in.cand_idx && (!engine->ice_in.chosen[0] || !engine->ice_in.chosen[1]); i++) {
+			if (!engine->ice_in.chosen[0] && engine->ice_in.cands[i][0].component_id == 1 && 
+				!engine->ice_in.cands[i][0].rport && switch_check_network_list_ip(engine->ice_in.cands[i][0].con_addr, "localnet.auto")) {
+				engine->ice_in.chosen[0] = i;
+				engine->ice_in.cands[engine->ice_in.chosen[0]][0].ready++;
+				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, "No RTP candidate found; defaulting to the first local one.\n");
+			}
+			if (!engine->ice_in.chosen[1] && engine->ice_in.cands[i][1].component_id == 2 && 
+				!engine->ice_in.cands[i][1].rport && switch_check_network_list_ip(engine->ice_in.cands[i][1].con_addr, "localnet.auto")) {
+				engine->ice_in.chosen[1] = i;
+				engine->ice_in.cands[engine->ice_in.chosen[1]][1].ready++;
+				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session),SWITCH_LOG_NOTICE, "No RTCP candidate found; defaulting to the first local one.\n");
+			}
+		}
+	}
+
+	/* look for candidates with srflx */
+	if (!engine->ice_in.chosen[0] || !engine->ice_in.chosen[1]) {
+		for (i = 0; i <= engine->ice_in.cand_idx && (!engine->ice_in.chosen[0] || !engine->ice_in.chosen[1]); i++) {
+			if (!engine->ice_in.chosen[0] && engine->ice_in.cands[i][0].component_id == 1 && engine->ice_in.cands[i][0].rport) {
+				engine->ice_in.chosen[0] = i;
+				engine->ice_in.cands[engine->ice_in.chosen[0]][0].ready++;
+				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, "No RTP candidate found; defaulting to the first srflx one.\n");
+			}
+			if (!engine->ice_in.chosen[1] && engine->ice_in.cands[i][1].component_id == 2 && engine->ice_in.cands[i][1].rport) {
+				engine->ice_in.chosen[1] = i;
+				engine->ice_in.cands[engine->ice_in.chosen[1]][1].ready++;
+				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session),SWITCH_LOG_NOTICE, "No RTCP candidate found; defaulting to the first srflx one.\n");
+			}
+		}
+	}
+
+	/* look for any candidates and hope for auto-adjust */
+	if (!engine->ice_in.chosen[0] || !engine->ice_in.chosen[1]) {
+		for (i = 0; i <= engine->ice_in.cand_idx && (!engine->ice_in.chosen[0] || !engine->ice_in.chosen[1]); i++) {
+			if (!engine->ice_in.chosen[0] && engine->ice_in.cands[i][0].component_id == 1) {
+				engine->ice_in.chosen[0] = i;
+				engine->ice_in.cands[engine->ice_in.chosen[0]][0].ready++;
+				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, "No RTP candidate found; defaulting to the first one.\n");
+			}
+			if (!engine->ice_in.chosen[1] && engine->ice_in.cands[i][1].component_id == 2) {
+				engine->ice_in.chosen[1] = i;
+				engine->ice_in.cands[engine->ice_in.chosen[1]][1].ready++;
+				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, "No RTCP candidate found; defaulting to the first one.\n");
+			}
+		}
+	}
 
 	for (i = 0; i < 2; i++) {
 		if (engine->ice_in.cands[engine->ice_in.chosen[i]][i].ready) {
diff --git a/src/switch_rtp.c b/src/switch_rtp.c
index 1026b2b7f5..8968a3a141 100644
--- a/src/switch_rtp.c
+++ b/src/switch_rtp.c
@@ -845,7 +845,7 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d
 	}
 
 	if ((ice->type & ICE_VANILLA)) {
-		if (!ok && ice == &rtp_session->ice && pri && 
+		if (!ok && ice == &rtp_session->ice && rtp_session->rtcp_ice.ice_params && pri && 
 			*pri == rtp_session->rtcp_ice.ice_params->cands[rtp_session->rtcp_ice.ice_params->chosen[1]][1].priority) {
 			ice = &rtp_session->rtcp_ice;
 			ok = 1;
@@ -937,7 +937,7 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d
 
 	}
 
-	if (ok || ice->missed_count > 1) {
+	if (ok || (ice->missed_count > 3 && !ice->rready)) {
 		if ((packet->header.type == SWITCH_STUN_BINDING_RESPONSE)) {
 			if (rtp_session->flags[SWITCH_RTP_FLAG_RTCP_MUX]) {
 				rtp_session->ice.rready = 1;
@@ -996,13 +996,13 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d
 
 				switch_sockaddr_info_get(&ice->addr, host, SWITCH_UNSPEC, port, 0, rtp_session->pool);
 
-				if (!is_rtcp) {
+				if (!is_rtcp || rtp_session->flags[SWITCH_RTP_FLAG_RTCP_MUX]) {
 					switch_rtp_set_remote_address(rtp_session, host, port, 0, SWITCH_FALSE, &err);
 				}
 
 				if (rtp_session->dtls) {
 
-					if (!is_rtcp) {
+					if (!is_rtcp || rtp_session->flags[SWITCH_RTP_FLAG_RTCP_MUX]) {
 						switch_sockaddr_info_get(&rtp_session->dtls->remote_addr, host, SWITCH_UNSPEC, port, 0, rtp_session->pool);
 					}