Changeset 3212


Ignore:
Timestamp:
Jun 19, 2010 12:35:33 PM (9 years ago)
Author:
bennylp
Message:

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.
Location:
pjproject/trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjnath/include/pjnath/ice_strans.h

    r3028 r3212  
    124124 
    125125    /** Negotiation */ 
    126     PJ_ICE_STRANS_OP_NEGOTIATION 
     126    PJ_ICE_STRANS_OP_NEGOTIATION, 
     127 
     128    /** This operatino is used to report failure in keep-alive operation. 
     129     *  Currently it is only used to report TURN Refresh failure. 
     130     */ 
     131    PJ_ICE_STRANS_OP_KEEP_ALIVE 
    127132 
    128133} pj_ice_strans_op; 
     
    153158 
    154159    /** 
    155      * Callback to report status. 
     160     * Callback to report status of various ICE operations. 
    156161     *  
    157162     * @param ice_st        The ICE stream transport. 
    158      * @param op            The operation 
     163     * @param op            The operation which status is being reported. 
    159164     * @param status        Operation status. 
    160165     */ 
  • pjproject/trunk/pjnath/src/pjnath/ice_strans.c

    r3101 r3212  
    153153    pj_turn_sock        *turn_sock;     /**< TURN relay transport.      */ 
    154154    pj_bool_t            turn_log_off;  /**< TURN loggin off?           */ 
     155    unsigned             turn_err_cnt;  /**< TURN disconnected count.   */ 
    155156 
    156157    unsigned             cand_cnt;      /**< # of candidates/aliaes.    */ 
     
    240241                          &src->turn.auth_cred); 
    241242} 
     243 
     244 
     245/* 
     246 * Add or update TURN candidate. 
     247 */ 
     248static pj_status_t add_update_turn(pj_ice_strans *ice_st, 
     249                                   pj_ice_strans_comp *comp) 
     250{ 
     251    pj_turn_sock_cb turn_sock_cb; 
     252    pj_ice_sess_cand *cand = NULL; 
     253    unsigned i; 
     254    pj_status_t status; 
     255 
     256    /* Find relayed candidate in the component */ 
     257    for (i=0; i<comp->cand_cnt; ++i) { 
     258        if (comp->cand_list[i].type == PJ_ICE_CAND_TYPE_RELAYED) { 
     259            cand = &comp->cand_list[i]; 
     260            break; 
     261        } 
     262    } 
     263 
     264    /* If candidate is found, invalidate it first */ 
     265    if (cand) { 
     266        cand->status = PJ_EPENDING; 
     267 
     268        /* Also if this component's default candidate is set to relay, 
     269         * move it temporarily to something else. 
     270         */ 
     271        if (comp->default_cand == cand - comp->cand_list) { 
     272            /* Init to something */ 
     273            comp->default_cand = 0; 
     274            /* Use srflx candidate as the default, if any */ 
     275            for (i=0; i<comp->cand_cnt; ++i) { 
     276                if (comp->cand_list[i].type == PJ_ICE_CAND_TYPE_SRFLX) { 
     277                    comp->default_cand = i; 
     278                    break; 
     279                } 
     280            } 
     281        } 
     282    } 
     283 
     284    /* Init TURN socket */ 
     285    pj_bzero(&turn_sock_cb, sizeof(turn_sock_cb)); 
     286    turn_sock_cb.on_rx_data = &turn_on_rx_data; 
     287    turn_sock_cb.on_state = &turn_on_state; 
     288 
     289    /* Override with component specific QoS settings, if any */ 
     290    if (ice_st->cfg.comp[comp->comp_id-1].qos_type) { 
     291        ice_st->cfg.turn.cfg.qos_type = 
     292            ice_st->cfg.comp[comp->comp_id-1].qos_type; 
     293    } 
     294    if (ice_st->cfg.comp[comp->comp_id-1].qos_params.flags) { 
     295        pj_memcpy(&ice_st->cfg.turn.cfg.qos_params, 
     296                  &ice_st->cfg.comp[comp->comp_id-1].qos_params, 
     297                  sizeof(ice_st->cfg.turn.cfg.qos_params)); 
     298    } 
     299 
     300    /* Create the TURN transport */ 
     301    status = pj_turn_sock_create(&ice_st->cfg.stun_cfg, ice_st->cfg.af, 
     302                                 ice_st->cfg.turn.conn_type, 
     303                                 &turn_sock_cb, &ice_st->cfg.turn.cfg, 
     304                                 comp, &comp->turn_sock); 
     305    if (status != PJ_SUCCESS) { 
     306        return status; 
     307    } 
     308 
     309    /* Add pending job */ 
     310    ///sess_add_ref(ice_st); 
     311 
     312    /* Start allocation */ 
     313    status=pj_turn_sock_alloc(comp->turn_sock, 
     314                              &ice_st->cfg.turn.server, 
     315                              ice_st->cfg.turn.port, 
     316                              ice_st->cfg.resolver, 
     317                              &ice_st->cfg.turn.auth_cred, 
     318                              &ice_st->cfg.turn.alloc_param); 
     319    if (status != PJ_SUCCESS) { 
     320        ///sess_dec_ref(ice_st); 
     321        return status; 
     322    } 
     323 
     324    /* Add relayed candidate with pending status if there's no existing one */ 
     325    if (cand == NULL) { 
     326        cand = &comp->cand_list[comp->cand_cnt++]; 
     327        cand->type = PJ_ICE_CAND_TYPE_RELAYED; 
     328        cand->status = PJ_EPENDING; 
     329        cand->local_pref = RELAY_PREF; 
     330        cand->transport_id = TP_TURN; 
     331        cand->comp_id = (pj_uint8_t) comp->comp_id; 
     332    } 
     333 
     334    PJ_LOG(4,(ice_st->obj_name, 
     335                  "Comp %d: TURN relay candidate waiting for allocation", 
     336                  comp->comp_id)); 
     337 
     338    return PJ_SUCCESS; 
     339} 
     340 
    242341 
    243342/* 
     
    396495    /* Create TURN relay if configured. */ 
    397496    if (ice_st->cfg.turn.server.slen) { 
    398         pj_turn_sock_cb turn_sock_cb; 
    399         pj_ice_sess_cand *cand; 
    400  
    401         /* Init TURN socket */ 
    402         pj_bzero(&turn_sock_cb, sizeof(turn_sock_cb)); 
    403         turn_sock_cb.on_rx_data = &turn_on_rx_data; 
    404         turn_sock_cb.on_state = &turn_on_state; 
    405  
    406         /* Override with component specific QoS settings, if any */ 
    407         if (ice_st->cfg.comp[comp_id-1].qos_type) { 
    408             ice_st->cfg.turn.cfg.qos_type =  
    409                 ice_st->cfg.comp[comp_id-1].qos_type; 
    410         } 
    411         if (ice_st->cfg.comp[comp_id-1].qos_params.flags) { 
    412             pj_memcpy(&ice_st->cfg.turn.cfg.qos_params, 
    413                       &ice_st->cfg.comp[comp_id-1].qos_params, 
    414                       sizeof(ice_st->cfg.turn.cfg.qos_params)); 
    415         } 
    416  
    417         /* Create the TURN transport */ 
    418         status = pj_turn_sock_create(&ice_st->cfg.stun_cfg, ice_st->cfg.af, 
    419                                      ice_st->cfg.turn.conn_type, 
    420                                      &turn_sock_cb, &ice_st->cfg.turn.cfg,  
    421                                      comp, &comp->turn_sock); 
    422         if (status != PJ_SUCCESS) { 
    423             return status; 
    424         } 
    425  
    426         /* Add pending job */ 
    427         ///sess_add_ref(ice_st); 
    428  
    429         /* Start allocation */ 
    430         status=pj_turn_sock_alloc(comp->turn_sock,   
    431                                   &ice_st->cfg.turn.server, 
    432                                   ice_st->cfg.turn.port, 
    433                                   ice_st->cfg.resolver,  
    434                                   &ice_st->cfg.turn.auth_cred,  
    435                                   &ice_st->cfg.turn.alloc_param); 
    436         if (status != PJ_SUCCESS) { 
    437             ///sess_dec_ref(ice_st); 
    438             return status; 
    439         } 
    440  
    441         /* Add relayed candidate with pending status */ 
    442         cand = &comp->cand_list[comp->cand_cnt++]; 
    443         cand->type = PJ_ICE_CAND_TYPE_RELAYED; 
    444         cand->status = PJ_EPENDING; 
    445         cand->local_pref = RELAY_PREF; 
    446         cand->transport_id = TP_TURN; 
    447         cand->comp_id = (pj_uint8_t) comp_id; 
    448  
    449         PJ_LOG(4,(ice_st->obj_name,  
    450                       "Comp %d: TURN relay candidate waiting for allocation", 
    451                       comp_id)); 
    452  
    453         /* Set default candidate to relay */ 
    454         comp->default_cand = cand - comp->cand_list; 
     497        add_update_turn(ice_st, comp); 
    455498    } 
    456499 
     
    15821625        unsigned i; 
    15831626 
     1627        comp->turn_err_cnt = 0; 
     1628 
    15841629        /* Get allocation info */ 
    15851630        pj_turn_sock_get_info(turn_sock, &rel_info); 
     
    16081653        cand->status = PJ_SUCCESS; 
    16091654 
     1655        /* Set default candidate to relay */ 
     1656        comp->default_cand = cand - comp->cand_list; 
     1657 
    16101658        PJ_LOG(4,(comp->ice_st->obj_name,  
    16111659                  "Comp %d: TURN allocation complete, relay address is %s", 
     
    16191667        pj_turn_session_info info; 
    16201668 
     1669        ++comp->turn_err_cnt; 
     1670 
    16211671        pj_turn_sock_get_info(turn_sock, &info); 
    16221672 
     
    16261676 
    16271677        /* Set session to fail if we're still initializing */ 
    1628         if (old_state < PJ_TURN_STATE_READY) { 
     1678        if (comp->ice_st->state < PJ_ICE_STRANS_STATE_READY) { 
    16291679            sess_fail(comp->ice_st, PJ_ICE_STRANS_OP_INIT, 
    1630                       "TURN relay failed", info.last_status); 
     1680                      "TURN allocation failed", info.last_status); 
     1681        } else if (comp->turn_err_cnt > 1) { 
     1682            sess_fail(comp->ice_st, PJ_ICE_STRANS_OP_KEEP_ALIVE, 
     1683                      "TURN refresh failed", info.last_status); 
     1684        } else { 
     1685            PJ_PERROR(4,(comp->ice_st->obj_name, info.last_status, 
     1686                      "Comp %d: TURN allocation failed, retrying", 
     1687                      comp->comp_id)); 
     1688            add_update_turn(comp->ice_st, comp); 
    16311689        } 
    16321690    } 
  • pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c

    r3183 r3212  
    29102910 
    29112911/* 
     2912 * Notification on ICE error. 
     2913 */ 
     2914static void on_ice_transport_error(int index, pj_ice_strans_op op, 
     2915                                   pj_status_t status, void *param) 
     2916{ 
     2917    PJ_UNUSED_ARG(op); 
     2918    PJ_UNUSED_ARG(param); 
     2919    PJ_PERROR(1,(THIS_FILE, status, 
     2920                 "ICE keep alive failure for transport %d", index)); 
     2921} 
     2922 
     2923/* 
    29122924 * Print buddy list. 
    29132925 */ 
     
    45064518    app_config.cfg.cb.on_mwi_info = &on_mwi_info; 
    45074519    app_config.cfg.cb.on_transport_state = &on_transport_state; 
     4520    app_config.cfg.cb.on_ice_transport_error = &on_ice_transport_error; 
    45084521    app_config.log_cfg.cb = log_cb; 
    45094522 
  • pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h

    r3196 r3212  
    850850    pjsip_tp_state_callback on_transport_state; 
    851851 
     852    /** 
     853     * This callback is called to report error in ICE media transport. 
     854     * Currently it is used to report TURN Refresh error. 
     855     * 
     856     * @param index     Transport index. 
     857     * @param op        Operation which trigger the failure. 
     858     * @param status    Error status. 
     859     * @param param     Additional info about the event. Currently this will 
     860     *                  always be set to NULL. 
     861     */ 
     862    void (*on_ice_transport_error)(int index, pj_ice_strans_op op, 
     863                                   pj_status_t status, void *param); 
     864 
    852865} pjsua_callback; 
    853866 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c

    r3198 r3212  
    861861                pjsua_call_update(id, 0, NULL); 
    862862            } 
     863        } 
     864        break; 
     865    case PJ_ICE_STRANS_OP_KEEP_ALIVE: 
     866        if (result != PJ_SUCCESS) { 
     867            PJ_PERROR(4,(THIS_FILE, result, 
     868                         "ICE keep alive failure for transport %d", id)); 
     869        } 
     870        if (pjsua_var.ua_cfg.cb.on_ice_transport_error) { 
     871            (*pjsua_var.ua_cfg.cb.on_ice_transport_error)(id, op, result, 
     872                                                          NULL); 
    863873        } 
    864874        break; 
Note: See TracChangeset for help on using the changeset viewer.