From 0a13964065c2e4592eff07ec0880cb2af0a86ff9 Mon Sep 17 00:00:00 2001
From: Nanang Izzuddin <nanang@teluu.com>
Date: Fri, 7 Aug 2020 16:03:43 +0700
Subject: [PATCH 1/3] - Assign unique local preferences for candidates with the
 same type. - Update component's valid pair condition, instead of just higher
 priority, also consider 'nominated' flag.

---
 pjnath/src/pjnath/ice_session.c | 18 +++++++++++++++++-
 pjnath/src/pjnath/ice_strans.c  |  9 +++++----
 2 files changed, 22 insertions(+), 5 deletions(-)

diff --git a/pjnath/src/pjnath/ice_session.c b/pjnath/src/pjnath/ice_session.c
index 2a4125bc5..4eb5adea9 100644
--- a/pjnath/src/pjnath/ice_session.c
+++ b/pjnath/src/pjnath/ice_session.c
@@ -1297,7 +1297,23 @@ static void update_comp_check(pj_ice_sess *ice, unsigned comp_id,
     if (comp->valid_check == NULL) {
 	comp->valid_check = check;
     } else {
-	if (CMP_CHECK_PRIO(comp->valid_check, check) < 0)
+	pj_bool_t update = PJ_FALSE;
+
+	/* Update component's valid check with conditions:
+	 * - it is the first nominated check, or
+	 * - it has higher prio, as long as nomination status is NOT degraded
+	 *   (existing is nominated -> new is not-nominated).
+	 */
+	if (!comp->nominated_check && check->nominated)
+	{
+	    update = PJ_TRUE;
+	} else if (CMP_CHECK_PRIO(comp->valid_check, check) < 0 &&
+		   (!comp->nominated_check || check->nominated))
+	{
+	    update = PJ_TRUE;
+	}
+
+	if (update)
 	    comp->valid_check = check;
     }
 
diff --git a/pjnath/src/pjnath/ice_strans.c b/pjnath/src/pjnath/ice_strans.c
index 5481c59e1..54ae9f769 100644
--- a/pjnath/src/pjnath/ice_strans.c
+++ b/pjnath/src/pjnath/ice_strans.c
@@ -418,7 +418,7 @@ static pj_status_t add_update_turn(pj_ice_strans *ice_st,
 	cand = &comp->cand_list[comp->cand_cnt];
 	cand->type = PJ_ICE_CAND_TYPE_RELAYED;
 	cand->status = PJ_EPENDING;
-	cand->local_pref = RELAY_PREF;
+	cand->local_pref = (pj_uint16_t)(RELAY_PREF - idx);
 	cand->transport_id = tp_id;
 	cand->comp_id = (pj_uint8_t) comp->comp_id;
 	new_cand = PJ_TRUE;
@@ -480,7 +480,8 @@ static pj_bool_t ice_cand_equals(pj_ice_sess_cand *lcand,
         || lcand->status != rcand->status
         || lcand->comp_id != rcand->comp_id
         || lcand->transport_id != rcand->transport_id
-        || lcand->local_pref != rcand->local_pref
+	// local pref is no longer a constant, so it may be different
+        //|| lcand->local_pref != rcand->local_pref
         || lcand->prio != rcand->prio
         || pj_sockaddr_cmp(&lcand->addr, &rcand->addr) != 0
         || pj_sockaddr_cmp(&lcand->base_addr, &rcand->base_addr) != 0)
@@ -539,7 +540,7 @@ static pj_status_t add_stun_and_host(pj_ice_strans *ice_st,
     cand = &comp->cand_list[comp->cand_cnt];
     cand->type = PJ_ICE_CAND_TYPE_SRFLX;
     cand->status = PJ_EPENDING;
-    cand->local_pref = SRFLX_PREF;
+    cand->local_pref = (pj_uint16_t)(SRFLX_PREF - idx);
     cand->transport_id = CREATE_TP_ID(TP_STUN, idx);
     cand->comp_id = (pj_uint8_t) comp->comp_id;
 
@@ -679,7 +680,7 @@ static pj_status_t add_stun_and_host(pj_ice_strans *ice_st,
 
 	    cand->type = PJ_ICE_CAND_TYPE_HOST;
 	    cand->status = PJ_SUCCESS;
-	    cand->local_pref = HOST_PREF;
+	    cand->local_pref = (pj_uint16_t)(HOST_PREF - *cand_cnt);
 	    cand->transport_id = CREATE_TP_ID(TP_STUN, idx);
 	    cand->comp_id = (pj_uint8_t) comp->comp_id;
 	    pj_sockaddr_cp(&cand->addr, addr);
-- 
2.25.1

