From 62469d7d94fc19619d7fef8b07d284624c8e997e Mon Sep 17 00:00:00 2001 From: Liong Sauw Ming Date: Fri, 28 Oct 2016 03:57:55 +0000 Subject: Re #1972: ICE initialization issues when creating a component/candidate fails. Fixed ICE stuck if TURN creation fails in resolved state, assertions when trying to access other components/candidates, and crash when trying to access destroyed TURN socket. git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@5474 74dad513-b988-da41-8d7b-12977e46ad98 --- pjnath/src/pjnath/ice_strans.c | 26 +++++++++++++++++++++----- pjnath/src/pjnath/turn_sock.c | 4 ++++ 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/pjnath/src/pjnath/ice_strans.c b/pjnath/src/pjnath/ice_strans.c index 7ef22a99..19e3bb12 100644 --- a/pjnath/src/pjnath/ice_strans.c +++ b/pjnath/src/pjnath/ice_strans.c @@ -164,6 +164,7 @@ typedef struct pj_ice_strans_comp unsigned err_cnt; /**< TURN disconnected count. */ } turn[PJ_ICE_MAX_TURN]; + pj_bool_t creating; /**< Is creating the candidates?*/ unsigned cand_cnt; /**< # of candidates/aliaes. */ pj_ice_sess_cand cand_list[PJ_ICE_ST_MAX_CAND]; /**< Cand array */ @@ -665,6 +666,7 @@ static pj_status_t create_comp(pj_ice_strans *ice_st, unsigned comp_id) comp = PJ_POOL_ZALLOC_T(ice_st->pool, pj_ice_strans_comp); comp->ice_st = ice_st; comp->comp_id = comp_id; + comp->creating = PJ_TRUE; ice_st->comp[comp_id-1] = comp; @@ -693,6 +695,9 @@ static pj_status_t create_comp(pj_ice_strans *ice_st, unsigned comp_id) } } + /* Done creating all the candidates */ + comp->creating = PJ_FALSE; + /* It's possible that we end up without any candidates */ if (comp->cand_cnt == 0) { PJ_LOG(4,(ice_st->obj_name, @@ -932,6 +937,11 @@ static void sess_init_update(pj_ice_strans *ice_st) unsigned j; pj_ice_strans_comp *comp = ice_st->comp[i]; + /* This function can be called when all components or candidates + * have not been created. + */ + if (!comp || comp->creating) return; + for (j=0; jcand_cnt; ++j) { pj_ice_sess_cand *cand = &comp->cand_list[j]; @@ -1307,7 +1317,7 @@ PJ_DEF(pj_status_t) pj_ice_strans_start_ice( pj_ice_strans *ice_st, } } - if (count) { + if (count && !comp->turn[n].err_cnt && comp->turn[n].sock) { status = pj_turn_sock_set_perm(comp->turn[n].sock, count, addrs, 0); if (status != PJ_SUCCESS) { @@ -1989,13 +1999,16 @@ static void turn_on_state(pj_turn_sock *turn_sock, pj_turn_state_t old_state, sess_init_update(comp->ice_st); - } else if (old_state == PJ_TURN_STATE_RESOLVING && + } else if ((old_state == PJ_TURN_STATE_RESOLVING || + old_state == PJ_TURN_STATE_RESOLVED) && new_state == PJ_TURN_STATE_DESTROYING) { pj_ice_sess_cand *cand = NULL; unsigned i; - /* DNS resolution has failed! */ + /* DNS resolution or TURN transport creation/allocation + * has failed. + */ ++comp->turn[tp_idx].err_cnt; /* Unregister ourself from the TURN relay */ @@ -2014,11 +2027,14 @@ static void turn_on_state(pj_turn_sock *turn_sock, pj_turn_state_t old_state, break; } } - pj_assert(cand != NULL); pj_grp_lock_release(comp->ice_st->grp_lock); - cand->status = PJ_ERESOLVE; + /* If the error happens during pj_turn_sock_create() or + * pj_turn_sock_alloc(), the candidate hasn't been added + * to the list. + */ + if (cand) cand->status = PJ_ERESOLVE; sess_init_update(comp->ice_st); diff --git a/pjnath/src/pjnath/turn_sock.c b/pjnath/src/pjnath/turn_sock.c index 541175c6..f1f5bb6d 100644 --- a/pjnath/src/pjnath/turn_sock.c +++ b/pjnath/src/pjnath/turn_sock.c @@ -890,6 +890,10 @@ static void turn_on_state(pj_turn_session *sess, if (status == PJ_SUCCESS) { on_connect_complete(turn_sock->active_sock, PJ_SUCCESS); } else if (status != PJ_EPENDING) { + pj_perror(3, turn_sock->pool->obj_name, status, + "Failed to connect to %s", + pj_sockaddr_print(&info.server, addrtxt, + sizeof(addrtxt), 3)); pj_turn_sock_destroy(turn_sock); return; } -- cgit v1.2.3