diff options
author | Benny Prijono <bennylp@teluu.com> | 2010-06-19 12:35:33 +0000 |
---|---|---|
committer | Benny Prijono <bennylp@teluu.com> | 2010-06-19 12:35:33 +0000 |
commit | 8d35b8f739dbad39422332ecb8376cc18a858f2e (patch) | |
tree | 622f42846ed18a5eb31b861693a922f51dd4e008 /pjnath/src | |
parent | f762fd7b4817c6668da0859b188d9d21a21e38bf (diff) |
Fixed #1077: In ICE stream transport (ice_strans.c), automaticaly retry allocation once if TURN allocation fails. If this allocation retry also fails, notify the TURN user via on_ice_complete() callback. Details:
- added new PJ_ICE_STRANS_OP_KEEP_ALIVE operation
- also added new on_ice_transport_error() pjsua callback to allow application to react to the failure.
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@3212 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjnath/src')
-rw-r--r-- | pjnath/src/pjnath/ice_strans.c | 176 |
1 files changed, 117 insertions, 59 deletions
diff --git a/pjnath/src/pjnath/ice_strans.c b/pjnath/src/pjnath/ice_strans.c index d53e5bf3..1f7ca1e8 100644 --- a/pjnath/src/pjnath/ice_strans.c +++ b/pjnath/src/pjnath/ice_strans.c @@ -152,6 +152,7 @@ typedef struct pj_ice_strans_comp pj_stun_sock *stun_sock; /**< STUN transport. */ pj_turn_sock *turn_sock; /**< TURN relay transport. */ pj_bool_t turn_log_off; /**< TURN loggin off? */ + unsigned turn_err_cnt; /**< TURN disconnected count. */ unsigned cand_cnt; /**< # of candidates/aliaes. */ pj_ice_sess_cand cand_list[PJ_ICE_ST_MAX_CAND]; /**< Cand array */ @@ -240,6 +241,104 @@ PJ_DEF(void) pj_ice_strans_cfg_copy( pj_pool_t *pool, &src->turn.auth_cred); } + +/* + * Add or update TURN candidate. + */ +static pj_status_t add_update_turn(pj_ice_strans *ice_st, + pj_ice_strans_comp *comp) +{ + pj_turn_sock_cb turn_sock_cb; + pj_ice_sess_cand *cand = NULL; + unsigned i; + pj_status_t status; + + /* Find relayed candidate in the component */ + for (i=0; i<comp->cand_cnt; ++i) { + if (comp->cand_list[i].type == PJ_ICE_CAND_TYPE_RELAYED) { + cand = &comp->cand_list[i]; + break; + } + } + + /* If candidate is found, invalidate it first */ + if (cand) { + cand->status = PJ_EPENDING; + + /* Also if this component's default candidate is set to relay, + * move it temporarily to something else. + */ + if (comp->default_cand == cand - comp->cand_list) { + /* Init to something */ + comp->default_cand = 0; + /* Use srflx candidate as the default, if any */ + for (i=0; i<comp->cand_cnt; ++i) { + if (comp->cand_list[i].type == PJ_ICE_CAND_TYPE_SRFLX) { + comp->default_cand = i; + break; + } + } + } + } + + /* Init TURN socket */ + pj_bzero(&turn_sock_cb, sizeof(turn_sock_cb)); + turn_sock_cb.on_rx_data = &turn_on_rx_data; + turn_sock_cb.on_state = &turn_on_state; + + /* Override with component specific QoS settings, if any */ + if (ice_st->cfg.comp[comp->comp_id-1].qos_type) { + ice_st->cfg.turn.cfg.qos_type = + ice_st->cfg.comp[comp->comp_id-1].qos_type; + } + if (ice_st->cfg.comp[comp->comp_id-1].qos_params.flags) { + pj_memcpy(&ice_st->cfg.turn.cfg.qos_params, + &ice_st->cfg.comp[comp->comp_id-1].qos_params, + sizeof(ice_st->cfg.turn.cfg.qos_params)); + } + + /* Create the TURN transport */ + status = pj_turn_sock_create(&ice_st->cfg.stun_cfg, ice_st->cfg.af, + ice_st->cfg.turn.conn_type, + &turn_sock_cb, &ice_st->cfg.turn.cfg, + comp, &comp->turn_sock); + if (status != PJ_SUCCESS) { + return status; + } + + /* Add pending job */ + ///sess_add_ref(ice_st); + + /* Start allocation */ + status=pj_turn_sock_alloc(comp->turn_sock, + &ice_st->cfg.turn.server, + ice_st->cfg.turn.port, + ice_st->cfg.resolver, + &ice_st->cfg.turn.auth_cred, + &ice_st->cfg.turn.alloc_param); + if (status != PJ_SUCCESS) { + ///sess_dec_ref(ice_st); + return status; + } + + /* Add relayed candidate with pending status if there's no existing one */ + if (cand == NULL) { + cand = &comp->cand_list[comp->cand_cnt++]; + cand->type = PJ_ICE_CAND_TYPE_RELAYED; + cand->status = PJ_EPENDING; + cand->local_pref = RELAY_PREF; + cand->transport_id = TP_TURN; + cand->comp_id = (pj_uint8_t) comp->comp_id; + } + + PJ_LOG(4,(ice_st->obj_name, + "Comp %d: TURN relay candidate waiting for allocation", + comp->comp_id)); + + return PJ_SUCCESS; +} + + /* * Create the component. */ @@ -395,63 +494,7 @@ static pj_status_t create_comp(pj_ice_strans *ice_st, unsigned comp_id) /* Create TURN relay if configured. */ if (ice_st->cfg.turn.server.slen) { - pj_turn_sock_cb turn_sock_cb; - pj_ice_sess_cand *cand; - - /* Init TURN socket */ - pj_bzero(&turn_sock_cb, sizeof(turn_sock_cb)); - turn_sock_cb.on_rx_data = &turn_on_rx_data; - turn_sock_cb.on_state = &turn_on_state; - - /* Override with component specific QoS settings, if any */ - if (ice_st->cfg.comp[comp_id-1].qos_type) { - ice_st->cfg.turn.cfg.qos_type = - ice_st->cfg.comp[comp_id-1].qos_type; - } - if (ice_st->cfg.comp[comp_id-1].qos_params.flags) { - pj_memcpy(&ice_st->cfg.turn.cfg.qos_params, - &ice_st->cfg.comp[comp_id-1].qos_params, - sizeof(ice_st->cfg.turn.cfg.qos_params)); - } - - /* Create the TURN transport */ - status = pj_turn_sock_create(&ice_st->cfg.stun_cfg, ice_st->cfg.af, - ice_st->cfg.turn.conn_type, - &turn_sock_cb, &ice_st->cfg.turn.cfg, - comp, &comp->turn_sock); - if (status != PJ_SUCCESS) { - return status; - } - - /* Add pending job */ - ///sess_add_ref(ice_st); - - /* Start allocation */ - status=pj_turn_sock_alloc(comp->turn_sock, - &ice_st->cfg.turn.server, - ice_st->cfg.turn.port, - ice_st->cfg.resolver, - &ice_st->cfg.turn.auth_cred, - &ice_st->cfg.turn.alloc_param); - if (status != PJ_SUCCESS) { - ///sess_dec_ref(ice_st); - return status; - } - - /* Add relayed candidate with pending status */ - cand = &comp->cand_list[comp->cand_cnt++]; - cand->type = PJ_ICE_CAND_TYPE_RELAYED; - cand->status = PJ_EPENDING; - cand->local_pref = RELAY_PREF; - cand->transport_id = TP_TURN; - cand->comp_id = (pj_uint8_t) comp_id; - - PJ_LOG(4,(ice_st->obj_name, - "Comp %d: TURN relay candidate waiting for allocation", - comp_id)); - - /* Set default candidate to relay */ - comp->default_cand = cand - comp->cand_list; + add_update_turn(ice_st, comp); } return PJ_SUCCESS; @@ -1581,6 +1624,8 @@ static void turn_on_state(pj_turn_sock *turn_sock, pj_turn_state_t old_state, pj_ice_sess_cand *cand = NULL; unsigned i; + comp->turn_err_cnt = 0; + /* Get allocation info */ pj_turn_sock_get_info(turn_sock, &rel_info); @@ -1607,6 +1652,9 @@ static void turn_on_state(pj_turn_sock *turn_sock, pj_turn_state_t old_state, &rel_info.relay_addr); cand->status = PJ_SUCCESS; + /* Set default candidate to relay */ + comp->default_cand = cand - comp->cand_list; + PJ_LOG(4,(comp->ice_st->obj_name, "Comp %d: TURN allocation complete, relay address is %s", comp->comp_id, @@ -1618,6 +1666,8 @@ static void turn_on_state(pj_turn_sock *turn_sock, pj_turn_state_t old_state, } else if (new_state >= PJ_TURN_STATE_DEALLOCATING) { pj_turn_session_info info; + ++comp->turn_err_cnt; + pj_turn_sock_get_info(turn_sock, &info); /* Unregister ourself from the TURN relay */ @@ -1625,9 +1675,17 @@ static void turn_on_state(pj_turn_sock *turn_sock, pj_turn_state_t old_state, comp->turn_sock = NULL; /* Set session to fail if we're still initializing */ - if (old_state < PJ_TURN_STATE_READY) { + if (comp->ice_st->state < PJ_ICE_STRANS_STATE_READY) { sess_fail(comp->ice_st, PJ_ICE_STRANS_OP_INIT, - "TURN relay failed", info.last_status); + "TURN allocation failed", info.last_status); + } else if (comp->turn_err_cnt > 1) { + sess_fail(comp->ice_st, PJ_ICE_STRANS_OP_KEEP_ALIVE, + "TURN refresh failed", info.last_status); + } else { + PJ_PERROR(4,(comp->ice_st->obj_name, info.last_status, + "Comp %d: TURN allocation failed, retrying", + comp->comp_id)); + add_update_turn(comp->ice_st, comp); } } |