Changeset 2705


Ignore:
Timestamp:
May 17, 2009 5:57:19 PM (15 years ago)
Author:
bennylp
Message:

Ticket #851: initial code to support regular nomination in ICE:

  • Added option to change nomination strategy in ICE strans and session. Default is still aggressive.
  • Added option to control nomination timer
  • Renamed no_host_cand to max_host_cands in ICE config
  • Updated icedemo
  • Also added timer for controlled agent to wait for nomination from controlling agent
Location:
pjproject/branches/projects/sipit24
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • pjproject/branches/projects/sipit24/pjnath/include/pjnath/config.h

    r2642 r2705  
    325325 
    326326/** 
     327 * For a controlled agent, specify how long it wants to wait (in milliseconds) 
     328 * for the controlling agent to complete sending connectivity check with 
     329 * nominated flag set to true for all components after the controlled agent 
     330 * has found that all connectivity checks in its checklist have been completed 
     331 * and there is at least one successful (but not nominated) check for every 
     332 * component. 
     333 * 
     334 * When selecting the value, bear in mind that the connectivity check from 
     335 * controlling agent may be delayed because of delay in receiving SDP answer 
     336 * from the controlled agent. 
     337 * 
     338 * Application may set this value to -1 to disable this timer. 
     339 * 
     340 * Default: 10000 (milliseconds) 
     341 */ 
     342#ifndef ICE_CONTROLLED_AGENT_WAIT_NOMINATION_TIMEOUT 
     343#   define ICE_CONTROLLED_AGENT_WAIT_NOMINATION_TIMEOUT 10000 
     344#endif 
     345 
     346 
     347/** 
     348 * For controlling agent if it uses regular nomination, specify the delay to 
     349 * perform nominated check (connectivity check with USE-CANDIDATE attribute) 
     350 * after all components have a valid pair. 
     351 * 
     352 * Default: 4*PJ_STUN_RTO_VALUE (milliseconds) 
     353 */ 
     354#ifndef PJ_ICE_NOMINATED_CHECK_DELAY 
     355#   define PJ_ICE_NOMINATED_CHECK_DELAY             (4*PJ_STUN_RTO_VALUE) 
     356#endif 
     357 
     358 
     359/** 
    327360 * Minimum interval value to be used for sending STUN keep-alive on the ICE 
    328361 * stream transport, in seconds. This minimum interval, plus a random value 
  • pjproject/branches/projects/sipit24/pjnath/include/pjnath/errno.h

    r2642 r2705  
    197197 */ 
    198198#define PJNATH_EICENOHOSTCAND       (PJNATH_ERRNO_START+92) /* 370092 */ 
    199  
     199/** 
     200 * @hideinitializer 
     201 * Controlled agent timed-out in waiting for the controlling agent to  
     202 * send nominated check after all connectivity checks have completed. 
     203 */ 
     204#define PJNATH_EICENOMTIMEOUT       (PJNATH_ERRNO_START+93) /* 370093 */ 
    200205 
    201206/************************************************************ 
  • pjproject/branches/projects/sipit24/pjnath/include/pjnath/ice_session.h

    r2642 r2705  
    177177{ 
    178178    /** 
    179      * The pointer to ICE check which was nominated for this component. 
    180      * The value will be NULL if a nominated check has not been found 
    181      * for this component. 
     179     * Pointer to ICE check with highest priority which connectivity check 
     180     * has been successful. The value will be NULL if a no successful check 
     181     * has not been found for this component. 
    182182     */ 
    183183    pj_ice_sess_check   *valid_check; 
     184 
     185    /** 
     186     * Pointer to ICE check with highest priority which connectivity check 
     187     * has been successful and it has been nominated. The value may be NULL 
     188     * if there is no such check yet. 
     189     */ 
     190    pj_ice_sess_check   *nominated_check; 
    184191 
    185192    /** 
     
    554561 
    555562/** 
     563 * This structure describes various ICE session options. Application 
     564 * configure the ICE session with these options by calling  
     565 * #pj_ice_sess_set_options(). 
     566 */ 
     567typedef struct pj_ice_sess_options 
     568{ 
     569    /** 
     570     * Specify whether to use aggressive nomination. 
     571     */ 
     572    pj_bool_t           aggressive; 
     573 
     574    /** 
     575     * For controlling agent if it uses regular nomination, specify the delay 
     576     * to perform nominated check (connectivity check with USE-CANDIDATE  
     577     * attribute) after all components have a valid pair. 
     578     * 
     579     * Default value is PJ_ICE_NOMINATED_CHECK_DELAY. 
     580     */ 
     581    unsigned            nominated_check_delay; 
     582 
     583    /** 
     584     * For a controlled agent, specify how long it wants to wait (in  
     585     * milliseconds) for the controlling agent to complete sending  
     586     * connectivity check with nominated flag set to true for all components 
     587     * after the controlled agent has found that all connectivity checks in 
     588     * its checklist have been completed and there is at least one successful 
     589     * (but not nominated) check for every component. 
     590     * 
     591     * Default value for this option is  
     592     * ICE_CONTROLLED_AGENT_WAIT_NOMINATION_TIMEOUT. Specify -1 to disable 
     593     * this timer. 
     594     */ 
     595    int                 controlled_agent_want_nom_timeout; 
     596 
     597} pj_ice_sess_options; 
     598 
     599 
     600/** 
    556601 * This structure describes the ICE session. For this version of PJNATH, 
    557602 * an ICE session corresponds to a single media stream (unlike the ICE 
     
    570615    pj_mutex_t          *mutex;                     /**< Mutex.             */ 
    571616    pj_ice_sess_role     role;                      /**< ICE role.          */ 
     617    pj_ice_sess_options  opt;                       /**< Options            */ 
    572618    pj_timestamp         tie_breaker;               /**< Tie breaker value  */ 
    573619    pj_uint8_t          *prefs;                     /**< Type preference.   */ 
     620    pj_bool_t            is_nominating;             /**< Nominating stage   */ 
    574621    pj_bool_t            is_complete;               /**< Complete?          */ 
    575622    pj_status_t          ice_status;                /**< Error status.      */ 
    576     pj_timer_entry       completion_timer;          /**< To call callback.  */ 
     623    pj_timer_entry       timer;                     /**< ICE timer.         */ 
    577624    pj_ice_sess_cb       cb;                        /**< Callback.          */ 
    578625 
     
    655702                                     const pj_sockaddr *base_addr); 
    656703 
     704/** 
     705 * Initialize ICE session options with library default values. 
     706 * 
     707 * @param opt           ICE session options. 
     708 */ 
     709PJ_DECL(void) pj_ice_sess_options_default(pj_ice_sess_options *opt); 
    657710 
    658711/** 
     
    690743 
    691744/** 
     745 * Get the value of various options of the ICE session. 
     746 * 
     747 * @param ice           The ICE session. 
     748 * @param opt           The options to be initialized with the values 
     749 *                      from the ICE session. 
     750 * 
     751 * @return              PJ_SUCCESS on success, or the appropriate error. 
     752 */ 
     753PJ_DECL(pj_status_t) pj_ice_sess_get_options(pj_ice_sess *ice, 
     754                                             pj_ice_sess_options *opt); 
     755 
     756/** 
     757 * Specify various options for this ICE session. Application MUST only 
     758 * call this function after the ICE session has been created but before 
     759 * any connectivity check is started. 
     760 * 
     761 * Application should call #pj_ice_sess_get_options() to initialize the 
     762 * options with their default values. 
     763 * 
     764 * @param ice           The ICE session. 
     765 * @param opt           Options to be applied to the ICE session. 
     766 * 
     767 * @return              PJ_SUCCESS on success, or the appropriate error. 
     768 */ 
     769PJ_DECL(pj_status_t) pj_ice_sess_set_options(pj_ice_sess *ice, 
     770                                             const pj_ice_sess_options *opt); 
     771 
     772/** 
    692773 * Destroy ICE session. This will cancel any connectivity checks currently 
    693774 * running, if any, and any other events scheduled by this session, as well 
  • pjproject/branches/projects/sipit24/pjnath/include/pjnath/ice_strans.h

    r2642 r2705  
    210210 
    211211        /** 
    212          * Disable host candidates. When this option is set, no 
    213          * host candidates will be added. 
    214          * 
    215          * Default: PJ_FALSE 
    216          */ 
    217         pj_bool_t            no_host_cands; 
     212         * Maximum number of host candidates to be added. If the 
     213         * value is zero, no host candidates will be added. 
     214         * 
     215         * Default: 64 
     216         */ 
     217        unsigned             max_host_cands; 
    218218 
    219219        /** 
     
    384384 */ 
    385385PJ_DECL(void*) pj_ice_strans_get_user_data(pj_ice_strans *ice_st); 
     386 
     387 
     388/** 
     389 * Get the value of various options of the ICE stream transport. 
     390 * 
     391 * @param ice_st        The ICE stream transport. 
     392 * @param opt           The options to be initialized with the values 
     393 *                      from the ICE stream transport. 
     394 * 
     395 * @return              PJ_SUCCESS on success, or the appropriate error. 
     396 */ 
     397PJ_DECL(pj_status_t) pj_ice_strans_get_options(pj_ice_strans *ice_st, 
     398                                               pj_ice_sess_options *opt); 
     399 
     400/** 
     401 * Specify various options for this ICE stream transport. Application  
     402 * should call #pj_ice_strans_get_options() to initialize the options  
     403 * with their default values. 
     404 * 
     405 * @param ice_st        The ICE stream transport. 
     406 * @param opt           Options to be applied to this ICE stream transport. 
     407 * 
     408 * @return              PJ_SUCCESS on success, or the appropriate error. 
     409 */ 
     410PJ_DECL(pj_status_t) pj_ice_strans_set_options(pj_ice_strans *ice_st, 
     411                                               const pj_ice_sess_options *opt); 
    386412 
    387413 
  • pjproject/branches/projects/sipit24/pjnath/src/pjnath-test/ice_test.c

    r2394 r2705  
    142142 
    143143    if (ept->cfg.enable_host == 0) { 
    144         ice_cfg.stun.no_host_cands = PJ_TRUE; 
     144        ice_cfg.stun.max_host_cands = 0; 
    145145    } else { 
    146         ice_cfg.stun.no_host_cands = PJ_FALSE; 
     146        //ice_cfg.stun.no_host_cands = PJ_FALSE; 
    147147        ice_cfg.stun.loop_addr = PJ_TRUE; 
    148148    } 
  • pjproject/branches/projects/sipit24/pjnath/src/pjnath/errno.c

    r2580 r2705  
    6868    PJ_BUILD_ERR( PJNATH_EICEINCANDSDP,     "Invalid SDP \"candidate\" attribute"), 
    6969    PJ_BUILD_ERR( PJNATH_EICENOHOSTCAND,    "No host candidate associated with srflx"), 
     70    PJ_BUILD_ERR( PJNATH_EICENOMTIMEOUT,    "Controlled agent timed out waiting for nomination"), 
    7071 
    7172    /* TURN related errors */ 
  • pjproject/branches/projects/sipit24/pjnath/src/pjnath/ice_session.c

    r2419 r2705  
    6767}; 
    6868 
     69typedef enum timer_type 
     70{ 
     71    TIMER_NONE,                 /**< Timer not active                   */ 
     72    TIMER_COMPLETION_CALLBACK,  /**< Call on_ice_complete() callback    */ 
     73    TIMER_CONTROLLED_WAIT_NOM,  /**< Controlled agent is waiting for  
     74                                     controlling agent to send connectivity 
     75                                     check with nominated flag after it has 
     76                                     valid check for every components.  */ 
     77    TIMER_START_NOMINATED_CHECK,/**< Controlling agent start connectivity 
     78                                     checks with USE-CANDIDATE flag.    */ 
     79                                         
     80 
     81}; 
     82 
    6983/* Candidate type preference */ 
    7084static pj_uint8_t cand_type_prefs[4] = 
     
    119133 
    120134/* Forward declarations */ 
     135static void on_timer(pj_timer_heap_t *th, pj_timer_entry *te); 
     136static void on_ice_complete(pj_ice_sess *ice, pj_status_t status); 
    121137static void destroy_ice(pj_ice_sess *ice, 
    122138                        pj_status_t reason); 
    123139static pj_status_t start_periodic_check(pj_timer_heap_t *th,  
    124140                                        pj_timer_entry *te); 
     141static void start_nominated_check(pj_ice_sess *ice); 
    125142static void periodic_timer(pj_timer_heap_t *th,  
    126143                          pj_timer_entry *te); 
     
    297314 
    298315 
     316/* Init options with default values */ 
     317PJ_DEF(void) pj_ice_sess_options_default(pj_ice_sess_options *opt) 
     318{ 
     319    opt->aggressive = PJ_TRUE; 
     320    opt->nominated_check_delay = PJ_ICE_NOMINATED_CHECK_DELAY; 
     321    opt->controlled_agent_want_nom_timeout =  
     322        ICE_CONTROLLED_AGENT_WAIT_NOMINATION_TIMEOUT; 
     323} 
     324 
    299325/* 
    300326 * Create ICE session. 
     
    327353    ice->tie_breaker.u32.lo = pj_rand(); 
    328354    ice->prefs = cand_type_prefs; 
     355    pj_ice_sess_options_default(&ice->opt); 
     356 
     357    pj_timer_entry_init(&ice->timer, TIMER_NONE, (void*)ice, &on_timer); 
    329358 
    330359    pj_ansi_snprintf(ice->obj_name, sizeof(ice->obj_name), 
     
    346375        comp = &ice->comp[i]; 
    347376        comp->valid_check = NULL; 
     377        comp->nominated_check = NULL; 
    348378 
    349379        status = init_comp(ice, i+1, comp); 
     
    390420 
    391421/* 
     422 * Get the value of various options of the ICE session. 
     423 */ 
     424PJ_DEF(pj_status_t) pj_ice_sess_get_options(pj_ice_sess *ice, 
     425                                            pj_ice_sess_options *opt) 
     426{ 
     427    PJ_ASSERT_RETURN(ice, PJ_EINVAL); 
     428    pj_memcpy(opt, &ice->opt, sizeof(*opt)); 
     429    return PJ_SUCCESS; 
     430} 
     431 
     432/* 
     433 * Specify various options for this ICE session. 
     434 */ 
     435PJ_DEF(pj_status_t) pj_ice_sess_set_options(pj_ice_sess *ice, 
     436                                            const pj_ice_sess_options *opt) 
     437{ 
     438    PJ_ASSERT_RETURN(ice && opt, PJ_EINVAL); 
     439    pj_memcpy(&ice->opt, opt, sizeof(*opt)); 
     440    return PJ_SUCCESS; 
     441} 
     442 
     443 
     444/* 
    392445 * Destroy 
    393446 */ 
     
    407460    } 
    408461 
    409     if (ice->completion_timer.id) { 
     462    if (ice->timer.id) { 
    410463        pj_timer_heap_cancel(ice->stun_cfg.timer_heap,  
    411                              &ice->completion_timer); 
    412         ice->completion_timer.id = PJ_FALSE; 
     464                             &ice->timer); 
     465        ice->timer.id = PJ_FALSE; 
    413466    } 
    414467 
     
    10401093} 
    10411094 
    1042 /* Timer callback to call on_ice_complete() callback */ 
    1043 static void on_completion_timer(pj_timer_heap_t *th,  
    1044                                 pj_timer_entry *te) 
     1095/* Timer callback */ 
     1096static void on_timer(pj_timer_heap_t *th, pj_timer_entry *te) 
    10451097{ 
    10461098    pj_ice_sess *ice = (pj_ice_sess*) te->user_data; 
     1099    enum timer_time type = (enum timer_type)te->id; 
    10471100 
    10481101    PJ_UNUSED_ARG(th); 
    10491102 
    1050     te->id = PJ_FALSE; 
    1051  
    1052     if (ice->cb.on_ice_complete) 
    1053         (*ice->cb.on_ice_complete)(ice, ice->ice_status); 
     1103    te->id = TIMER_NONE; 
     1104 
     1105    switch (type) { 
     1106    case TIMER_CONTROLLED_WAIT_NOM: 
     1107        LOG4((ice->obj_name,  
     1108              "Controlled agent timed-out in waiting for the controlling " 
     1109              "agent to send nominated check. Setting state to fail now..")); 
     1110        on_ice_complete(ice, PJNATH_EICENOMTIMEOUT); 
     1111        break; 
     1112    case TIMER_COMPLETION_CALLBACK: 
     1113        if (ice->cb.on_ice_complete) 
     1114            (*ice->cb.on_ice_complete)(ice, ice->ice_status); 
     1115        break; 
     1116    case TIMER_START_NOMINATED_CHECK: 
     1117        start_nominated_check(ice); 
     1118        break; 
     1119    } 
    10541120} 
    10551121 
     
    10611127        ice->ice_status = status; 
    10621128     
     1129        if (ice->timer.id != TIMER_NONE) { 
     1130            pj_timer_heap_cancel(ice->stun_cfg.timer_heap, &ice->timer); 
     1131            ice->timer.id = TIMER_NONE; 
     1132        } 
     1133 
    10631134        /* Log message */ 
    10641135        LOG4((ice->obj_name, "ICE process complete, status=%s",  
     
    10721143            pj_time_val delay = {0, 0}; 
    10731144 
    1074             ice->completion_timer.cb = &on_completion_timer; 
    1075             ice->completion_timer.user_data = (void*) ice; 
    1076             ice->completion_timer.id = PJ_TRUE; 
    1077  
     1145            ice->timer.id = TIMER_COMPLETION_CALLBACK; 
    10781146            pj_timer_heap_schedule(ice->stun_cfg.timer_heap,  
    1079                                    &ice->completion_timer, 
    1080                                    &delay); 
     1147                                   &ice->timer, &delay); 
    10811148        } 
    10821149    } 
     
    10881155                                   pj_ice_sess_check *check) 
    10891156{ 
     1157    pj_ice_sess_comp *comp; 
    10901158    unsigned i; 
    10911159 
    10921160    pj_assert(check->state >= PJ_ICE_SESS_CHECK_STATE_SUCCEEDED); 
     1161 
     1162    comp = find_comp(ice, check->lcand->comp_id); 
    10931163 
    10941164    /* 7.1.2.2.2.  Updating Pair States 
     
    11051175     */ 
    11061176    if (check->err_code==PJ_SUCCESS) { 
     1177 
    11071178        for (i=0; i<ice->clist.count; ++i) { 
    11081179            pj_ice_sess_check *c = &ice->clist.checks[i]; 
     
    11131184            } 
    11141185        } 
     1186 
     1187        /* Update valid check */ 
     1188        if (comp->valid_check == NULL) { 
     1189            comp->valid_check = check; 
     1190        } else { 
     1191            if (CMP_CHECK_PRIO(comp->valid_check, check) < 0) 
     1192                comp->valid_check = check; 
     1193        } 
     1194 
     1195        LOG5((ice->obj_name, "Check %d is successful%s", 
     1196             GET_CHECK_ID(&ice->clist, check), 
     1197             (check->nominated ? "  and nominated" : ""))); 
     1198 
    11151199    } 
    11161200 
     
    11371221     */ 
    11381222    if (check->err_code==PJ_SUCCESS && check->nominated) { 
    1139         pj_ice_sess_comp *comp; 
    1140  
    1141         LOG5((ice->obj_name, "Check %d is successful and nominated", 
    1142              GET_CHECK_ID(&ice->clist, check))); 
    1143  
    1144         comp = find_comp(ice, check->lcand->comp_id); 
    11451223 
    11461224        for (i=0; i<ice->clist.count; ++i) { 
     
    11821260 
    11831261        /* Update the nominated check for the component */ 
    1184         if (comp->valid_check == NULL) { 
    1185             comp->valid_check = check; 
     1262        if (comp->nominated_check == NULL) { 
     1263            comp->nominated_check = check; 
    11861264        } else { 
    1187             if (CMP_CHECK_PRIO(comp->valid_check, check) < 0) 
    1188                 comp->valid_check = check; 
     1265            if (CMP_CHECK_PRIO(comp->nominated_check, check) < 0) 
     1266                comp->nominated_check = check; 
    11891267        } 
    11901268    } 
     
    12121290     */ 
    12131291    for (i=0; i<ice->comp_cnt; ++i) { 
    1214         if (ice->comp[i].valid_check == NULL) 
     1292        if (ice->comp[i].nominated_check == NULL) 
    12151293            break; 
    12161294    } 
     
    12591337         * If agent's role is controlled, check if all components have 
    12601338         * valid pair. If it does, this means the controlled agent has 
    1261          * finished the check list early and it's waiting for controlling 
    1262          * agent to send a check with USE-CANDIDATE flag set. 
     1339         * finished the check list and it's waiting for controlling 
     1340         * agent to send checks with USE-CANDIDATE flag set. 
    12631341         */ 
    12641342        if (ice->role == PJ_ICE_SESS_ROLE_CONTROLLED) { 
    1265             unsigned comp_id; 
    1266             for (comp_id=1; comp_id <= ice->comp_cnt; ++comp_id) { 
    1267                 unsigned j; 
    1268                 for (j=0; j<ice->valid_list.count; ++j) { 
    1269                     pj_ice_sess_check *vc = &ice->valid_list.checks[j]; 
    1270                     if (vc->lcand->comp_id == comp_id) 
    1271                         break; 
    1272                 } 
    1273                 if (j == ice->valid_list.count) 
     1343            for (i=0; i < ice->comp_cnt; ++i) { 
     1344                if (ice->comp[i].valid_check == NULL) 
    12741345                    break; 
    12751346            } 
    12761347 
    1277             if (comp_id <= ice->comp_cnt) { 
     1348            if (i < ice->comp_cnt) { 
    12781349                /* This component ID doesn't have valid pair. 
    12791350                 * Mark ICE as failed.  
     
    12851356                 * We should wait until we receive nominated checks. 
    12861357                 */ 
     1358                if (ice->timer.id == TIMER_NONE && 
     1359                    ice->opt.controlled_agent_want_nom_timeout >= 0)  
     1360                { 
     1361                    pj_time_val delay; 
     1362 
     1363                    delay.sec = 0; 
     1364                    delay.msec = ice->opt.controlled_agent_want_nom_timeout; 
     1365                    pj_time_val_normalize(&delay); 
     1366 
     1367                    ice->timer.id = TIMER_CONTROLLED_WAIT_NOM; 
     1368                    pj_timer_heap_schedule(ice->stun_cfg.timer_heap,  
     1369                                           &ice->timer, 
     1370                                           &delay); 
     1371 
     1372                    LOG5((ice->obj_name,  
     1373                          "All checks have completed. Controlled agent now " 
     1374                          "waits for nomination from controlling agent " 
     1375                          "(timeout=%d msec)", 
     1376                          ice->opt.controlled_agent_want_nom_timeout)); 
     1377                } 
    12871378                return PJ_FALSE; 
    12881379            } 
    1289         } 
    1290  
    1291         on_ice_complete(ice, PJNATH_EICEFAILED); 
    1292         return PJ_TRUE; 
     1380 
     1381            /* Unreached */ 
     1382 
     1383        } else if (ice->is_nominating) { 
     1384            /* We are controlling agent and all checks have completed but 
     1385             * there's at least one component without nominated pair (or 
     1386             * more likely we don't have any nominated pairs at all). 
     1387             */ 
     1388            on_ice_complete(ice, PJNATH_EICEFAILED); 
     1389            return PJ_TRUE; 
     1390 
     1391        } else { 
     1392            /* We are controlling agent and all checks have completed. If 
     1393             * we have valid list for every component, then move on to 
     1394             * sending nominated check, otherwise we have failed. 
     1395             */ 
     1396            for (i=0; i<ice->comp_cnt; ++i) { 
     1397                if (ice->comp[i].valid_check == NULL) 
     1398                    break; 
     1399            } 
     1400 
     1401            if (i < ice->comp_cnt) { 
     1402                /* At least one component doesn't have a valid check. Mark 
     1403                 * ICE as failed. 
     1404                 */ 
     1405                on_ice_complete(ice, PJNATH_EICEFAILED); 
     1406                return PJ_TRUE; 
     1407            } 
     1408 
     1409            /* Now it's time to send connectivity check with nomination  
     1410             * flag set. 
     1411             */ 
     1412            LOG5((ice->obj_name,  
     1413                  "All checks have completed, starting nominated checks now")); 
     1414            start_nominated_check(ice); 
     1415            return PJ_FALSE; 
     1416        } 
     1417    } 
     1418 
     1419    /* If this connectivity check has been successful, scan all components 
     1420     * and see if they have a valid pair, if we are controlling and we haven't 
     1421     * started our nominated check yet. 
     1422     */ 
     1423    if (check->err_code == PJ_SUCCESS &&  
     1424        ice->role==PJ_ICE_SESS_ROLE_CONTROLLING && 
     1425        !ice->is_nominating && 
     1426        ice->timer.id == TIMER_NONE)  
     1427    { 
     1428        pj_time_val delay; 
     1429 
     1430        for (i=0; i<ice->comp_cnt; ++i) { 
     1431            if (ice->comp[i].valid_check == NULL) 
     1432                break; 
     1433        } 
     1434 
     1435        if (i < ice->comp_cnt) { 
     1436            /* Some components still don't have valid pair, continue 
     1437             * processing. 
     1438             */ 
     1439            return PJ_FALSE; 
     1440        } 
     1441 
     1442        LOG5((ice->obj_name,  
     1443              "Scheduling nominated check in %d ms", 
     1444              ice->opt.nominated_check_delay)); 
     1445 
     1446        /* All components have valid pair. Let connectivity checks run for 
     1447         * a little bit more time, then start our nominated check. 
     1448         */ 
     1449        delay.sec = 0; 
     1450        delay.msec = ice->opt.nominated_check_delay; 
     1451        pj_time_val_normalize(&delay); 
     1452 
     1453        ice->timer.id = TIMER_START_NOMINATED_CHECK; 
     1454        pj_timer_heap_schedule(ice->stun_cfg.timer_heap, &ice->timer, &delay); 
     1455        return PJ_FALSE; 
    12931456    } 
    12941457 
     
    12961459    return PJ_FALSE; 
    12971460} 
    1298  
    12991461 
    13001462 
     
    14311593} 
    14321594 
    1433 /* Perform check on the specified candidate pair */ 
     1595/* Perform check on the specified candidate pair. */ 
    14341596static pj_status_t perform_check(pj_ice_sess *ice,  
    14351597                                 pj_ice_sess_checklist *clist, 
    1436                                  unsigned check_id) 
     1598                                 unsigned check_id, 
     1599                                 pj_bool_t nominate) 
    14371600{ 
    14381601    pj_ice_sess_comp *comp; 
     
    14821645     */ 
    14831646    if (ice->role == PJ_ICE_SESS_ROLE_CONTROLLING) { 
    1484         pj_stun_msg_add_empty_attr(check->tdata->pool, check->tdata->msg,  
    1485                                    PJ_STUN_ATTR_USE_CANDIDATE); 
    1486         check->nominated = PJ_TRUE; 
     1647        if (nominate) { 
     1648            pj_stun_msg_add_empty_attr(check->tdata->pool, check->tdata->msg, 
     1649                                       PJ_STUN_ATTR_USE_CANDIDATE); 
     1650            check->nominated = PJ_TRUE; 
     1651        } 
    14871652 
    14881653        pj_stun_msg_add_uint64_attr(check->tdata->pool, check->tdata->msg,  
     
    15501715 
    15511716        if (check->state == PJ_ICE_SESS_CHECK_STATE_WAITING) { 
    1552             status = perform_check(ice, clist, i); 
     1717            status = perform_check(ice, clist, i, ice->is_nominating); 
    15531718            if (status != PJ_SUCCESS) { 
    15541719                pj_mutex_unlock(ice->mutex); 
     
    15691734 
    15701735            if (check->state == PJ_ICE_SESS_CHECK_STATE_FROZEN) { 
    1571                 status = perform_check(ice, clist, i); 
     1736                status = perform_check(ice, clist, i, ice->is_nominating); 
    15721737                if (status != PJ_SUCCESS) { 
    15731738                    pj_mutex_unlock(ice->mutex); 
     
    15961761} 
    15971762 
     1763 
     1764/* Start sending connectivity check with USE-CANDIDATE */ 
     1765static void start_nominated_check(pj_ice_sess *ice) 
     1766{ 
     1767    pj_time_val delay; 
     1768    unsigned i; 
     1769    pj_status_t status; 
     1770 
     1771    LOG4((ice->obj_name, "Starting nominated check..")); 
     1772 
     1773    pj_assert(ice->is_nominating == PJ_FALSE); 
     1774 
     1775    /* Stop our timer if it's active */ 
     1776    if (ice->timer.id == TIMER_START_NOMINATED_CHECK) { 
     1777        pj_timer_heap_cancel(ice->stun_cfg.timer_heap, &ice->timer); 
     1778        ice->timer.id = TIMER_NONE; 
     1779    } 
     1780 
     1781    /* For each component, set the check state of valid check with 
     1782     * highest priority to Waiting (it should have Success state now). 
     1783     */ 
     1784    for (i=0; i<ice->comp_cnt; ++i) { 
     1785        pj_assert(ice->comp[i].nominated_check == NULL); 
     1786        pj_assert(ice->comp[i].valid_check->err_code == PJ_SUCCESS); 
     1787 
     1788        ice->comp[i].valid_check->state = PJ_ICE_SESS_CHECK_STATE_FROZEN; 
     1789        check_set_state(ice, ice->comp[i].valid_check,  
     1790                        PJ_ICE_SESS_CHECK_STATE_WAITING, PJ_SUCCESS); 
     1791    } 
     1792 
     1793    /* And (re)start the periodic check */ 
     1794    if (!ice->clist.timer.id) { 
     1795        ice->clist.timer.id = PJ_TRUE; 
     1796        delay.sec = delay.msec = 0; 
     1797        status = pj_timer_heap_schedule(ice->stun_cfg.timer_heap,  
     1798                                        &ice->clist.timer, &delay); 
     1799        if (status != PJ_SUCCESS) { 
     1800            ice->clist.timer.id = PJ_FALSE; 
     1801        } 
     1802    } 
     1803 
     1804    ice->is_nominating = PJ_TRUE; 
     1805} 
    15981806 
    15991807/* Timer callback to perform periodic check */ 
     
    16421850 
    16431851    LOG4((ice->obj_name, "Starting ICE check..")); 
     1852 
     1853    /* If we are using aggressive nomination, set the is_nominating state */ 
     1854    if (ice->opt.aggressive) 
     1855        ice->is_nominating = PJ_TRUE; 
    16441856 
    16451857    /* The agent examines the check list for the first media stream (a 
     
    18272039            LOG4((ice->obj_name, "Resending check because of role conflict")); 
    18282040            check_set_state(ice, check, PJ_ICE_SESS_CHECK_STATE_WAITING, 0); 
    1829             perform_check(ice, clist, msg_data->data.req.ckid); 
     2041            perform_check(ice, clist, msg_data->data.req.ckid,  
     2042                          check->nominated); 
    18302043            pj_mutex_unlock(ice->mutex); 
    18312044            return; 
     
    23132526            c->state == PJ_ICE_SESS_CHECK_STATE_WAITING) 
    23142527        { 
     2528            /* See if we shall nominate this check */ 
     2529            pj_bool_t nominate = (c->nominated || ice->is_nominating); 
     2530 
    23152531            LOG5((ice->obj_name, "Performing triggered check for check %d",i)); 
    2316             perform_check(ice, &ice->clist, i); 
     2532            perform_check(ice, &ice->clist, i, nominate); 
    23172533 
    23182534        } else if (c->state == PJ_ICE_SESS_CHECK_STATE_IN_PROGRESS) { 
     
    23622578 
    23632579        pj_ice_sess_check *c = &ice->clist.checks[ice->clist.count]; 
     2580        pj_bool_t nominate; 
    23642581 
    23652582        c->lcand = lcand; 
     
    23702587        c->err_code = PJ_SUCCESS; 
    23712588 
     2589        nominate = (c->nominated || ice->is_nominating); 
     2590 
    23722591        LOG4((ice->obj_name, "New triggered check added: %d",  
    23732592             ice->clist.count)); 
    2374         perform_check(ice, &ice->clist, ice->clist.count++); 
     2593        perform_check(ice, &ice->clist, ice->clist.count++, nominate); 
    23752594 
    23762595    } else { 
  • pjproject/branches/projects/sipit24/pjnath/src/pjnath/ice_strans.c

    r2599 r2705  
    159159    pj_ice_strans_cb         cb;        /**< Application callback.      */ 
    160160    pj_lock_t               *init_lock; /**< Initialization mutex.      */ 
     161    pj_ice_sess_options      opt;       /**< ICE session options        */ 
    161162 
    162163    pj_ice_sess             *ice;       /**< ICE session.               */ 
     
    201202    cfg->stun.port = PJ_STUN_PORT; 
    202203    cfg->turn.conn_type = PJ_TURN_TP_UDP; 
     204 
     205    cfg->stun.max_host_cands = 64; 
    203206} 
    204207 
     
    246249 
    247250    /* Create STUN transport if configured */ 
    248     if (ice_st->cfg.stun.server.slen || !ice_st->cfg.stun.no_host_cands) { 
     251    if (ice_st->cfg.stun.server.slen || ice_st->cfg.stun.max_host_cands) { 
    249252        pj_stun_sock_cb stun_sock_cb; 
    250253        pj_ice_sess_cand *cand; 
     
    310313        } 
    311314 
    312         /* Add local addresses to host candidates, unless no_host_cands 
    313          * flag is set. 
     315        /* Add local addresses to host candidates, unless max_host_cands 
     316         * is set to zero. 
    314317         */ 
    315         if (ice_st->cfg.stun.no_host_cands == PJ_FALSE) { 
     318        if (ice_st->cfg.stun.max_host_cands) { 
    316319            pj_stun_sock_info stun_sock_info; 
    317320            unsigned i; 
     
    322325                return status; 
    323326 
    324             for (i=0; i<stun_sock_info.alias_cnt; ++i) { 
     327            for (i=0; i<stun_sock_info.alias_cnt &&  
     328                      i<ice_st->cfg.stun.max_host_cands; ++i)  
     329            { 
    325330                char addrinfo[PJ_INET6_ADDRSTRLEN+10]; 
    326331                const pj_sockaddr *addr = &stun_sock_info.aliases[i]; 
     
    444449    ice_st->obj_name = pool->obj_name; 
    445450    ice_st->user_data = user_data; 
     451 
     452    pj_ice_sess_options_default(&ice_st->opt); 
    446453 
    447454    PJ_LOG(4,(ice_st->obj_name,  
     
    648655 
    649656/* 
     657 * Get the value of various options of the ICE stream transport. 
     658 */ 
     659PJ_DEF(pj_status_t) pj_ice_strans_get_options( pj_ice_strans *ice_st, 
     660                                               pj_ice_sess_options *opt) 
     661{ 
     662    PJ_ASSERT_RETURN(ice_st && opt, PJ_EINVAL); 
     663    pj_memcpy(opt, &ice_st->opt, sizeof(*opt)); 
     664    return PJ_SUCCESS; 
     665} 
     666 
     667/* 
     668 * Specify various options for this ICE stream transport.  
     669 */ 
     670PJ_DEF(pj_status_t) pj_ice_strans_set_options(pj_ice_strans *ice_st, 
     671                                              const pj_ice_sess_options *opt) 
     672{ 
     673    PJ_ASSERT_RETURN(ice_st && opt, PJ_EINVAL); 
     674    pj_memcpy(&ice_st->opt, opt, sizeof(*opt)); 
     675    if (ice_st->ice) 
     676        pj_ice_sess_set_options(ice_st->ice, &ice_st->opt); 
     677    return PJ_SUCCESS; 
     678} 
     679 
     680/* 
    650681 * Create ICE! 
    651682 */ 
     
    682713    /* Associate user data */ 
    683714    ice_st->ice->user_data = (void*)ice_st; 
     715 
     716    /* Set options */ 
     717    pj_ice_sess_set_options(ice_st->ice, &ice_st->opt); 
    684718 
    685719    /* If default candidate for components are SRFLX one, upload a custom 
  • pjproject/branches/projects/sipit24/pjsip-apps/src/pjsua/pjsua_app.c

    r2704 r2705  
    47294729            status = pjmedia_transport_udp_create3(pjsua_get_pjmedia_endpt(),  
    47304730                                                   pj_AF_INET6(), 
    4731                                                    NULL,  
     4731                                                   app_config.rtp_cfg.public_addr.ptr,  
    47324732                                                   &app_config.rtp_cfg.bound_addr, 
    47334733                                                   port,  
  • pjproject/branches/projects/sipit24/pjsip-apps/src/samples/icedemo.c

    r2600 r2705  
    4040        unsigned    comp_cnt; 
    4141        pj_str_t    ns; 
    42         pj_bool_t   no_host; 
     42        int         max_host; 
     43        pj_bool_t   regular; 
    4344        pj_str_t    stun_srv; 
    4445        pj_str_t    turn_srv; 
     
    307308    /* -= Start initializing ICE stream transport config =- */ 
    308309 
    309     /* Disable host candidates? */ 
    310     icedemo.ice_cfg.stun.no_host_cands = icedemo.opt.no_host; 
     310    /* Maximum number of host candidates */ 
     311    if (icedemo.opt.max_host != -1) 
     312        icedemo.ice_cfg.stun.max_host_cands = icedemo.opt.max_host; 
    311313 
    312314    /* Configure STUN/srflx candidate resolution */ 
     
    375377{ 
    376378    pj_ice_strans_cb icecb; 
     379    pj_ice_sess_options opt; 
    377380    pj_status_t status; 
    378381 
     
    399402    else 
    400403        PJ_LOG(3,(THIS_FILE, "ICE instance successfully created")); 
     404 
     405    status = pj_ice_strans_get_options(icedemo.icest, &opt); 
     406    pj_assert(status == PJ_SUCCESS); 
     407 
     408    if (icedemo.opt.regular) 
     409        opt.aggressive = PJ_FALSE; 
     410    else 
     411        opt.aggressive = PJ_TRUE; 
     412 
     413    status = pj_ice_strans_set_options(icedemo.icest, &opt); 
     414    pj_assert(status == PJ_SUCCESS); 
    401415} 
    402416 
     
    961975    */ 
    962976 
    963     if (comp_id > pj_ice_strans_get_running_comp_cnt(icedemo.icest)) { 
     977    if (comp_id<1||comp_id>pj_ice_strans_get_running_comp_cnt(icedemo.icest)) { 
    964978        PJ_LOG(1,(THIS_FILE, "Error: invalid component ID")); 
    965979        return; 
     
    11381152    puts(" --nameserver, -n IP       Configure nameserver to activate DNS SRV"); 
    11391153    puts("                           resolution"); 
    1140     puts(" --no-host, -H             Disable host candidates"); 
     1154    puts(" --max-host, -H N          Set max number of host candidates to N"); 
     1155    puts(" --regular, -R             Use regular nomination (default aggressive)"); 
    11411156    puts(" --help, -h                Display this screen."); 
    11421157    puts(""); 
     
    11661181        { "comp-cnt",           1, 0, 'c'}, 
    11671182        { "nameserver",         1, 0, 'n'}, 
    1168         { "no-host",            0, 0, 'H'}, 
     1183        { "max-host",           1, 0, 'H'}, 
    11691184        { "help",               0, 0, 'h'}, 
    11701185        { "stun-srv",           1, 0, 's'}, 
     
    11731188        { "turn-username",      1, 0, 'u'}, 
    11741189        { "turn-password",      1, 0, 'p'}, 
    1175         { "turn-fingerprint",   0, 0, 'F'} 
     1190        { "turn-fingerprint",   0, 0, 'F'}, 
     1191        { "regular",            0, 0, 'R'} 
    11761192    }; 
    11771193    int c, opt_id; 
     
    11791195 
    11801196    icedemo.opt.comp_cnt = 1; 
    1181  
    1182     while((c=pj_getopt_long(argc,argv, "n:s:t:u:p:HhTF", long_options, &opt_id))!=-1) { 
     1197    icedemo.opt.max_host = -1; 
     1198 
     1199    while((c=pj_getopt_long(argc,argv, "c:n:s:t:u:p:H:hTFR", long_options, &opt_id))!=-1) { 
    11831200        switch (c) { 
    11841201        case 'c': 
     
    11931210            break; 
    11941211        case 'H': 
    1195             icedemo.opt.no_host = PJ_TRUE; 
     1212            icedemo.opt.max_host = atoi(pj_optarg); 
    11961213            break; 
    11971214        case 'h': 
     
    12161233            icedemo.opt.turn_fingerprint = PJ_TRUE; 
    12171234            break; 
     1235        case 'R': 
     1236            icedemo.opt.regular = PJ_TRUE; 
     1237            break; 
    12181238        default: 
    12191239            printf("Argument \"%s\" is not valid. Use -h to see help", 
  • pjproject/branches/projects/sipit24/pjsip/src/pjsua-lib/pjsua_media.c

    r2679 r2705  
    811811        ice_cfg.stun.port = pj_sockaddr_get_port(&pjsua_var.stun_srv); 
    812812    } 
    813     ice_cfg.stun.no_host_cands = pjsua_var.media_cfg.ice_no_host_cands; 
     813    if (pjsua_var.media_cfg.ice_no_host_cands) 
     814        ice_cfg.stun.max_host_cands = 0; 
    814815 
    815816    /* Configure TURN settings */ 
Note: See TracChangeset for help on using the changeset viewer.