Trickle ICE (re #2588):

- Fix premature end-of-candidate indication.
- Fix premature ICE session destroy in sending INFO (update remote with local candidates).
- Fix assertion when foundation list is full.
- Fix assertion when pruned check is completed/timed-out.
- Minor, missing 'static' for internal functions.
This commit is contained in:
Nanang Izzuddin 2021-03-10 10:05:45 +07:00
parent eeef964ad7
commit 25c5eea417
3 changed files with 26 additions and 22 deletions

View File

@ -91,6 +91,7 @@ struct transport_ice
pj_ice_sess_trickle trickle_ice; /**< Trickle ICE mode. */
unsigned last_cand_cnt; /**< Last local candidate count. */
pj_bool_t end_of_cand; /**< Local cand gathering done? */
pj_str_t sdp_mid; /**< SDP "a=mid" attribute. */
void (*rtp_cb)(void*,
@ -693,8 +694,7 @@ PJ_DEF(pj_status_t) pjmedia_ice_trickle_send_local_cand(
return PJ_EINVALIDOP;
ice_state = pj_ice_strans_get_state(tp_ice->ice_st);
end_of_cand = (ice_state == PJ_ICE_STRANS_STATE_READY ||
ice_state == PJ_ICE_STRANS_STATE_SESS_READY);
end_of_cand = tp_ice->end_of_cand;
/* Get ufrag and pwd from current session */
pj_ice_strans_get_ufrag_pwd(tp_ice->ice_st, &ufrag, &pwd, NULL, NULL);
@ -1145,9 +1145,7 @@ static pj_status_t encode_session_in_sdp(struct transport_ice *tp_ice,
}
ice_state = pj_ice_strans_get_state(tp_ice->ice_st);
end_of_cand = (ice_state == PJ_ICE_STRANS_STATE_READY ||
ice_state == PJ_ICE_STRANS_STATE_SESS_READY);
end_of_cand = tp_ice->end_of_cand;
status = pjmedia_ice_trickle_encode_sdp(sdp_pool, sdp_local,
&tp_ice->sdp_mid, NULL, NULL,
0, NULL, end_of_cand);
@ -2599,6 +2597,10 @@ static void ice_on_ice_complete(pj_ice_strans *ice_st,
return;
}
/* Set the flag indicating that local candidate gathering is completed */
if (op == PJ_ICE_STRANS_OP_INIT && result == PJ_SUCCESS)
tp_ice->end_of_cand = PJ_TRUE;
pj_perror(5, tp_ice->base.name, result, "ICE operation complete"
" (op=%d%s)", op,
(op==PJ_ICE_STRANS_OP_INIT? "/initialization" :

View File

@ -474,7 +474,7 @@ struct pj_ice_sess_checklist
/**
* Array of foundations, check foundation index refers to this array.
*/
pj_str_t foundation[PJ_ICE_MAX_CHECKS];
pj_str_t foundation[PJ_ICE_MAX_CHECKS * 2];
/**
* A timer used to perform periodic check for this checklist.

View File

@ -454,7 +454,7 @@ PJ_DEF(pj_status_t) pj_ice_sess_set_options(pj_ice_sess *ice,
ice->is_trickling = (ice->opt.trickle != PJ_ICE_SESS_TRICKLE_DISABLED);
if (ice->is_trickling) {
LOG5((ice->obj_name, "Trickle ICE is active (%s mode)",
(ice->opt.trickle!=PJ_ICE_SESS_TRICKLE_HALF? "half":"full")));
(ice->opt.trickle==PJ_ICE_SESS_TRICKLE_HALF? "half":"full")));
if (ice->opt.aggressive) {
/* Disable aggressive when ICE trickle is active */
@ -1072,9 +1072,9 @@ static void sort_checklist(pj_ice_sess *ice, pj_ice_sess_checklist *clist)
}
/* Remove a check pair from checklist */
void remove_check(pj_ice_sess *ice, pj_ice_sess_checklist *clist,
unsigned check_idx,
const char *reason)
static void remove_check(pj_ice_sess *ice, pj_ice_sess_checklist *clist,
unsigned check_idx,
const char *reason)
{
LOG5((ice->obj_name, "Check %s pruned (%s)",
dump_check(ice->tmp.txt, sizeof(ice->tmp.txt),
@ -1707,10 +1707,10 @@ static pj_bool_t on_check_complete(pj_ice_sess *ice,
* adding a new foundation (combination of local & remote cands foundations)
* to checklist.
*/
int get_check_foundation_idx(pj_ice_sess *ice,
const pj_ice_sess_cand *lcand,
const pj_ice_sess_cand *rcand,
pj_bool_t add_if_not_found)
static int get_check_foundation_idx(pj_ice_sess *ice,
const pj_ice_sess_cand *lcand,
const pj_ice_sess_cand *rcand,
pj_bool_t add_if_not_found)
{
pj_ice_sess_checklist *clist = &ice->clist;
char fnd_str[65];
@ -1736,8 +1736,8 @@ int get_check_foundation_idx(pj_ice_sess *ice,
/* Discard a pair check with Failed state or lowest prio (as long as lower
* than prio_lower_than.
*/
int discard_check(pj_ice_sess *ice, pj_ice_sess_checklist *clist,
const pj_timestamp *prio_lower_than)
static int discard_check(pj_ice_sess *ice, pj_ice_sess_checklist *clist,
const pj_timestamp *prio_lower_than)
{
/* Discard any Failed check */
unsigned k;
@ -1867,7 +1867,10 @@ static pj_status_t add_rcand_and_update_checklist(
chk->state = PJ_ICE_SESS_CHECK_STATE_FROZEN;
chk->foundation_idx = get_check_foundation_idx(ice, lcand, rcand,
PJ_TRUE);
pj_assert(chk->foundation_idx >= 0);
/* Check if foundation cannot be added (e.g: list is full) */
if (chk->foundation_idx < 0)
continue;
/* Check if the check can be unfrozen */
if (ice->is_trickling) {
@ -2079,16 +2082,16 @@ PJ_DEF(pj_status_t) pj_ice_sess_update_check_list(
PJ_ASSERT_RETURN(ice->tx_ufrag.slen, PJ_EINVALIDOP);
/* Ignore if trickle has been stopped (e.g: received end-of-candidate) */
if (!ice->is_trickling) {
if (!ice->is_trickling && rem_cand_cnt) {
LOG5((ice->obj_name,
"Cannot update checklist when ICE trickling is disabled or"
" has been ended"));
return PJ_EINVALIDOP;
return PJ_SUCCESS;
}
pj_grp_lock_acquire(ice->grp_lock);
if (trickle_done) {
if (trickle_done && ice->is_trickling) {
LOG5((ice->obj_name, "Trickling done."));
ice->is_trickling = PJ_FALSE;
}
@ -2573,8 +2576,7 @@ static void on_stun_request_complete(pj_stun_session *stun_sess,
}
}
if (i == clist->count) {
/* Should not happen */
pj_assert(!"Check not found");
/* The check may have been pruned */
check->tdata = NULL;
pj_grp_lock_release(ice->grp_lock);
return;