Ignore:
Timestamp:
May 29, 2009 1:04:03 PM (12 years ago)
Author:
bennylp
Message:

Integration of Sipit24 branch, many tickets involved:

  • #793: AMR encoder should regard 'mode-set' param specified by remote decoder.
  • #831: Automatically switch to TCP transport when sending large request
  • #832: Support for outbound proxy setting without using Route header
  • #849: Modify conference audio switch behavior in connecting ports.
  • #850: Remove 'Require=replaces' param in 'Refer-To' header (in call transfer with replaces).
  • #851: Support for regular nomination in ICE
  • #852: --ip-addr support for IPv6 for media transport in pjsua
  • #854: Adding SOFTWARE attribute in all outgoing requests may cause compatibility problem with older STUN server (thanks Alexei Kuznetsov for the report)
  • #855: Bug in digit map frequencies for DTMF digits (thanks FCCH for the report)
  • #856: Put back the ICE candidate priority values according to the default values in the draft-mmusic-ice
  • #857: Support for ICE keep-alive with Binding indication
  • #858: Do not authenticate STUN 438 response
  • #859: AMR-WB format param in the SDP is not negotiated correctly.
  • #867: Return error instead of asserting when PJSUA-LIB fails to open log file
File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjnath/src/pjnath/ice_session.c

    r2419 r2724  
    3030#include <pj/string.h> 
    3131 
    32  
    3332/* String names for candidate types */ 
    3433static const char *cand_type_names[] = 
     
    6564    "Controlled", 
    6665    "Controlling" 
     66}; 
     67 
     68enum timer_type 
     69{ 
     70    TIMER_NONE,                 /**< Timer not active                   */ 
     71    TIMER_COMPLETION_CALLBACK,  /**< Call on_ice_complete() callback    */ 
     72    TIMER_CONTROLLED_WAIT_NOM,  /**< Controlled agent is waiting for  
     73                                     controlling agent to send connectivity 
     74                                     check with nominated flag after it has 
     75                                     valid check for every components.  */ 
     76    TIMER_START_NOMINATED_CHECK,/**< Controlling agent start connectivity 
     77                                     checks with USE-CANDIDATE flag.    */ 
     78    TIMER_KEEP_ALIVE            /**< ICE keep-alive timer.              */ 
     79 
    6780}; 
    6881 
     
    119132 
    120133/* Forward declarations */ 
     134static void on_timer(pj_timer_heap_t *th, pj_timer_entry *te); 
     135static void on_ice_complete(pj_ice_sess *ice, pj_status_t status); 
     136static void ice_keep_alive(pj_ice_sess *ice, pj_bool_t send_now); 
    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); 
     
    226243                                    const pj_sockaddr *base_addr) 
    227244{ 
    228 #if 0 
     245#if PJNATH_ICE_PRIO_STD 
    229246    char buf[64]; 
    230247    pj_uint32_t val; 
     
    296313} 
    297314 
     315 
     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} 
    298324 
    299325/* 
     
    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    LOG5((ice->obj_name, "ICE nomination type set to %s", 
     441          (ice->opt.aggressive ? "aggressive" : "regular"))); 
     442    return PJ_SUCCESS; 
     443} 
     444 
     445 
     446/* 
    392447 * Destroy 
    393448 */ 
     
    407462    } 
    408463 
    409     if (ice->completion_timer.id) { 
     464    if (ice->timer.id) { 
    410465        pj_timer_heap_cancel(ice->stun_cfg.timer_heap,  
    411                              &ice->completion_timer); 
    412         ice->completion_timer.id = PJ_FALSE; 
     466                             &ice->timer); 
     467        ice->timer.id = PJ_FALSE; 
    413468    } 
    414469 
     
    604659                                  pj_uint32_t comp_id) 
    605660{ 
    606 #if 0 
     661#if PJNATH_ICE_PRIO_STD 
    607662    return ((ice->prefs[type] & 0xFF) << 24) +  
    608663           ((local_pref & 0xFFFF)    << 8) + 
     
    10401095} 
    10411096 
    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) 
     1097/* Timer callback */ 
     1098static void on_timer(pj_timer_heap_t *th, pj_timer_entry *te) 
    10451099{ 
    10461100    pj_ice_sess *ice = (pj_ice_sess*) te->user_data; 
     1101    enum timer_type type = (enum timer_type)te->id; 
    10471102 
    10481103    PJ_UNUSED_ARG(th); 
    10491104 
    1050     te->id = PJ_FALSE; 
    1051  
    1052     if (ice->cb.on_ice_complete) 
    1053         (*ice->cb.on_ice_complete)(ice, ice->ice_status); 
     1105    pj_mutex_lock(ice->mutex); 
     1106 
     1107    te->id = TIMER_NONE; 
     1108 
     1109    switch (type) { 
     1110    case TIMER_CONTROLLED_WAIT_NOM: 
     1111        LOG4((ice->obj_name,  
     1112              "Controlled agent timed-out in waiting for the controlling " 
     1113              "agent to send nominated check. Setting state to fail now..")); 
     1114        on_ice_complete(ice, PJNATH_EICENOMTIMEOUT); 
     1115        break; 
     1116    case TIMER_COMPLETION_CALLBACK: 
     1117        /* Start keep-alive timer but don't send any packets yet. 
     1118         * Need to do it here just in case app destroy the session 
     1119         * in the callback. 
     1120         */ 
     1121        if (ice->ice_status == PJ_SUCCESS) 
     1122            ice_keep_alive(ice, PJ_FALSE); 
     1123 
     1124        /* Notify app about ICE completion*/ 
     1125        if (ice->cb.on_ice_complete) 
     1126            (*ice->cb.on_ice_complete)(ice, ice->ice_status); 
     1127        break; 
     1128    case TIMER_START_NOMINATED_CHECK: 
     1129        start_nominated_check(ice); 
     1130        break; 
     1131    case TIMER_KEEP_ALIVE: 
     1132        ice_keep_alive(ice, PJ_TRUE); 
     1133        break; 
     1134    case TIMER_NONE: 
     1135        /* Nothing to do, just to get rid of gcc warning */ 
     1136        break; 
     1137    } 
     1138 
     1139    pj_mutex_unlock(ice->mutex); 
     1140} 
     1141 
     1142/* Send keep-alive */ 
     1143static void ice_keep_alive(pj_ice_sess *ice, pj_bool_t send_now) 
     1144{ 
     1145    if (send_now) { 
     1146        /* Send Binding Indication for the component */ 
     1147        pj_ice_sess_comp *comp = &ice->comp[ice->comp_ka]; 
     1148        pj_stun_tx_data *tdata; 
     1149        pj_ice_sess_check *the_check; 
     1150        pj_ice_msg_data *msg_data; 
     1151        int addr_len; 
     1152        pj_bool_t saved; 
     1153        pj_status_t status; 
     1154 
     1155        /* Must have nominated check by now */ 
     1156        pj_assert(comp->nominated_check != NULL); 
     1157        the_check = comp->nominated_check; 
     1158 
     1159        /* Create the Binding Indication */ 
     1160        status = pj_stun_session_create_ind(comp->stun_sess,  
     1161                                            PJ_STUN_BINDING_INDICATION, 
     1162                                            &tdata); 
     1163        if (status != PJ_SUCCESS) 
     1164            goto done; 
     1165 
     1166        /* Need the transport_id */ 
     1167        msg_data = PJ_POOL_ZALLOC_T(tdata->pool, pj_ice_msg_data); 
     1168        msg_data->transport_id = the_check->lcand->transport_id; 
     1169 
     1170        /* Temporarily disable FINGERPRINT. The Binding Indication  
     1171         * SHOULD NOT contain any attributes. 
     1172         */ 
     1173        saved = pj_stun_session_use_fingerprint(comp->stun_sess, PJ_FALSE); 
     1174 
     1175        /* Send to session */ 
     1176        addr_len = pj_sockaddr_get_len(&the_check->rcand->addr); 
     1177        status = pj_stun_session_send_msg(comp->stun_sess, msg_data, 
     1178                                          PJ_FALSE, PJ_FALSE,  
     1179                                          &the_check->rcand->addr,  
     1180                                          addr_len, tdata); 
     1181 
     1182        /* Restore FINGERPRINT usage */ 
     1183        pj_stun_session_use_fingerprint(comp->stun_sess, saved); 
     1184 
     1185done: 
     1186        ice->comp_ka = (ice->comp_ka + 1) % ice->comp_cnt; 
     1187    } 
     1188 
     1189    if (ice->timer.id == TIMER_NONE) { 
     1190        pj_time_val delay = { 0, 0 }; 
     1191 
     1192        delay.msec = (PJ_ICE_SESS_KEEP_ALIVE_MIN +  
     1193                      (pj_rand() % PJ_ICE_SESS_KEEP_ALIVE_MAX_RAND)) * 1000 /  
     1194                     ice->comp_cnt; 
     1195        pj_time_val_normalize(&delay); 
     1196 
     1197        ice->timer.id = TIMER_KEEP_ALIVE; 
     1198        pj_timer_heap_schedule(ice->stun_cfg.timer_heap, &ice->timer, &delay); 
     1199 
     1200    } else { 
     1201        pj_assert(!"Not expected any timer active"); 
     1202    } 
    10541203} 
    10551204 
     
    10611210        ice->ice_status = status; 
    10621211     
     1212        if (ice->timer.id != TIMER_NONE) { 
     1213            pj_timer_heap_cancel(ice->stun_cfg.timer_heap, &ice->timer); 
     1214            ice->timer.id = TIMER_NONE; 
     1215        } 
     1216 
    10631217        /* Log message */ 
    10641218        LOG4((ice->obj_name, "ICE process complete, status=%s",  
     
    10721226            pj_time_val delay = {0, 0}; 
    10731227 
    1074             ice->completion_timer.cb = &on_completion_timer; 
    1075             ice->completion_timer.user_data = (void*) ice; 
    1076             ice->completion_timer.id = PJ_TRUE; 
    1077  
     1228            ice->timer.id = TIMER_COMPLETION_CALLBACK; 
    10781229            pj_timer_heap_schedule(ice->stun_cfg.timer_heap,  
    1079                                    &ice->completion_timer, 
    1080                                    &delay); 
    1081         } 
    1082     } 
    1083 } 
    1084  
     1230                                   &ice->timer, &delay); 
     1231        } 
     1232    } 
     1233} 
     1234 
     1235/* Update valid check and nominated check for the candidate */ 
     1236static void update_comp_check(pj_ice_sess *ice, unsigned comp_id,  
     1237                              pj_ice_sess_check *check) 
     1238{ 
     1239    pj_ice_sess_comp *comp; 
     1240 
     1241    comp = find_comp(ice, comp_id); 
     1242    if (comp->valid_check == NULL) { 
     1243        comp->valid_check = check; 
     1244    } else { 
     1245        if (CMP_CHECK_PRIO(comp->valid_check, check) < 0) 
     1246            comp->valid_check = check; 
     1247    } 
     1248 
     1249    if (check->nominated) { 
     1250        /* Update the nominated check for the component */ 
     1251        if (comp->nominated_check == NULL) { 
     1252            comp->nominated_check = check; 
     1253        } else { 
     1254            if (CMP_CHECK_PRIO(comp->nominated_check, check) < 0) 
     1255                comp->nominated_check = check; 
     1256        } 
     1257    } 
     1258} 
    10851259 
    10861260/* This function is called when one check completes */ 
     
    10881262                                   pj_ice_sess_check *check) 
    10891263{ 
     1264    pj_ice_sess_comp *comp; 
    10901265    unsigned i; 
    10911266 
    10921267    pj_assert(check->state >= PJ_ICE_SESS_CHECK_STATE_SUCCEEDED); 
     1268 
     1269    comp = find_comp(ice, check->lcand->comp_id); 
    10931270 
    10941271    /* 7.1.2.2.2.  Updating Pair States 
     
    11051282     */ 
    11061283    if (check->err_code==PJ_SUCCESS) { 
     1284 
    11071285        for (i=0; i<ice->clist.count; ++i) { 
    11081286            pj_ice_sess_check *c = &ice->clist.checks[i]; 
     
    11131291            } 
    11141292        } 
     1293 
     1294        LOG5((ice->obj_name, "Check %d is successful%s", 
     1295             GET_CHECK_ID(&ice->clist, check), 
     1296             (check->nominated ? "  and nominated" : ""))); 
     1297 
    11151298    } 
    11161299 
     
    11371320     */ 
    11381321    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); 
    11451322 
    11461323        for (i=0; i<ice->clist.count; ++i) { 
     
    11791356                } 
    11801357            } 
    1181         } 
    1182  
    1183         /* Update the nominated check for the component */ 
    1184         if (comp->valid_check == NULL) { 
    1185             comp->valid_check = check; 
    1186         } else { 
    1187             if (CMP_CHECK_PRIO(comp->valid_check, check) < 0) 
    1188                 comp->valid_check = check; 
    11891358        } 
    11901359    } 
     
    12121381     */ 
    12131382    for (i=0; i<ice->comp_cnt; ++i) { 
    1214         if (ice->comp[i].valid_check == NULL) 
     1383        if (ice->comp[i].nominated_check == NULL) 
    12151384            break; 
    12161385    } 
     
    12591428         * If agent's role is controlled, check if all components have 
    12601429         * 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. 
     1430         * finished the check list and it's waiting for controlling 
     1431         * agent to send checks with USE-CANDIDATE flag set. 
    12631432         */ 
    12641433        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) 
     1434            for (i=0; i < ice->comp_cnt; ++i) { 
     1435                if (ice->comp[i].valid_check == NULL) 
    12741436                    break; 
    12751437            } 
    12761438 
    1277             if (comp_id <= ice->comp_cnt) { 
     1439            if (i < ice->comp_cnt) { 
    12781440                /* This component ID doesn't have valid pair. 
    12791441                 * Mark ICE as failed.  
     
    12851447                 * We should wait until we receive nominated checks. 
    12861448                 */ 
     1449                if (ice->timer.id == TIMER_NONE && 
     1450                    ice->opt.controlled_agent_want_nom_timeout >= 0)  
     1451                { 
     1452                    pj_time_val delay; 
     1453 
     1454                    delay.sec = 0; 
     1455                    delay.msec = ice->opt.controlled_agent_want_nom_timeout; 
     1456                    pj_time_val_normalize(&delay); 
     1457 
     1458                    ice->timer.id = TIMER_CONTROLLED_WAIT_NOM; 
     1459                    pj_timer_heap_schedule(ice->stun_cfg.timer_heap,  
     1460                                           &ice->timer, 
     1461                                           &delay); 
     1462 
     1463                    LOG5((ice->obj_name,  
     1464                          "All checks have completed. Controlled agent now " 
     1465                          "waits for nomination from controlling agent " 
     1466                          "(timeout=%d msec)", 
     1467                          ice->opt.controlled_agent_want_nom_timeout)); 
     1468                } 
    12871469                return PJ_FALSE; 
    12881470            } 
    1289         } 
    1290  
    1291         on_ice_complete(ice, PJNATH_EICEFAILED); 
    1292         return PJ_TRUE; 
     1471 
     1472            /* Unreached */ 
     1473 
     1474        } else if (ice->is_nominating) { 
     1475            /* We are controlling agent and all checks have completed but 
     1476             * there's at least one component without nominated pair (or 
     1477             * more likely we don't have any nominated pairs at all). 
     1478             */ 
     1479            on_ice_complete(ice, PJNATH_EICEFAILED); 
     1480            return PJ_TRUE; 
     1481 
     1482        } else { 
     1483            /* We are controlling agent and all checks have completed. If 
     1484             * we have valid list for every component, then move on to 
     1485             * sending nominated check, otherwise we have failed. 
     1486             */ 
     1487            for (i=0; i<ice->comp_cnt; ++i) { 
     1488                if (ice->comp[i].valid_check == NULL) 
     1489                    break; 
     1490            } 
     1491 
     1492            if (i < ice->comp_cnt) { 
     1493                /* At least one component doesn't have a valid check. Mark 
     1494                 * ICE as failed. 
     1495                 */ 
     1496                on_ice_complete(ice, PJNATH_EICEFAILED); 
     1497                return PJ_TRUE; 
     1498            } 
     1499 
     1500            /* Now it's time to send connectivity check with nomination  
     1501             * flag set. 
     1502             */ 
     1503            LOG4((ice->obj_name,  
     1504                  "All checks have completed, starting nominated checks now")); 
     1505            start_nominated_check(ice); 
     1506            return PJ_FALSE; 
     1507        } 
     1508    } 
     1509 
     1510    /* If this connectivity check has been successful, scan all components 
     1511     * and see if they have a valid pair, if we are controlling and we haven't 
     1512     * started our nominated check yet. 
     1513     */ 
     1514    if (check->err_code == PJ_SUCCESS &&  
     1515        ice->role==PJ_ICE_SESS_ROLE_CONTROLLING && 
     1516        !ice->is_nominating && 
     1517        ice->timer.id == TIMER_NONE)  
     1518    { 
     1519        pj_time_val delay; 
     1520 
     1521        for (i=0; i<ice->comp_cnt; ++i) { 
     1522            if (ice->comp[i].valid_check == NULL) 
     1523                break; 
     1524        } 
     1525 
     1526        if (i < ice->comp_cnt) { 
     1527            /* Some components still don't have valid pair, continue 
     1528             * processing. 
     1529             */ 
     1530            return PJ_FALSE; 
     1531        } 
     1532 
     1533        LOG4((ice->obj_name,  
     1534              "Scheduling nominated check in %d ms", 
     1535              ice->opt.nominated_check_delay)); 
     1536 
     1537        if (ice->timer.id != TIMER_NONE) { 
     1538            pj_timer_heap_cancel(ice->stun_cfg.timer_heap, &ice->timer); 
     1539            ice->timer.id = TIMER_NONE; 
     1540        } 
     1541 
     1542        /* All components have valid pair. Let connectivity checks run for 
     1543         * a little bit more time, then start our nominated check. 
     1544         */ 
     1545        delay.sec = 0; 
     1546        delay.msec = ice->opt.nominated_check_delay; 
     1547        pj_time_val_normalize(&delay); 
     1548 
     1549        ice->timer.id = TIMER_START_NOMINATED_CHECK; 
     1550        pj_timer_heap_schedule(ice->stun_cfg.timer_heap, &ice->timer, &delay); 
     1551        return PJ_FALSE; 
    12931552    } 
    12941553 
     
    12961555    return PJ_FALSE; 
    12971556} 
    1298  
    12991557 
    13001558 
     
    14311689} 
    14321690 
    1433 /* Perform check on the specified candidate pair */ 
     1691/* Perform check on the specified candidate pair. */ 
    14341692static pj_status_t perform_check(pj_ice_sess *ice,  
    14351693                                 pj_ice_sess_checklist *clist, 
    1436                                  unsigned check_id) 
     1694                                 unsigned check_id, 
     1695                                 pj_bool_t nominate) 
    14371696{ 
    14381697    pj_ice_sess_comp *comp; 
     
    14731732 
    14741733    /* Add PRIORITY */ 
     1734#if PJNATH_ICE_PRIO_STD 
     1735    prio = CALC_CAND_PRIO(ice, PJ_ICE_CAND_TYPE_PRFLX, 65535,  
     1736                          lcand->comp_id); 
     1737#else 
    14751738    prio = CALC_CAND_PRIO(ice, PJ_ICE_CAND_TYPE_PRFLX, 0,  
    14761739                          lcand->comp_id); 
     1740#endif 
    14771741    pj_stun_msg_add_uint_attr(check->tdata->pool, check->tdata->msg,  
    14781742                              PJ_STUN_ATTR_PRIORITY, prio); 
     
    14821746     */ 
    14831747    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; 
     1748        if (nominate) { 
     1749            pj_stun_msg_add_empty_attr(check->tdata->pool, check->tdata->msg, 
     1750                                       PJ_STUN_ATTR_USE_CANDIDATE); 
     1751            check->nominated = PJ_TRUE; 
     1752        } 
    14871753 
    14881754        pj_stun_msg_add_uint64_attr(check->tdata->pool, check->tdata->msg,  
     
    15501816 
    15511817        if (check->state == PJ_ICE_SESS_CHECK_STATE_WAITING) { 
    1552             status = perform_check(ice, clist, i); 
     1818            status = perform_check(ice, clist, i, ice->is_nominating); 
    15531819            if (status != PJ_SUCCESS) { 
    15541820                pj_mutex_unlock(ice->mutex); 
     
    15691835 
    15701836            if (check->state == PJ_ICE_SESS_CHECK_STATE_FROZEN) { 
    1571                 status = perform_check(ice, clist, i); 
     1837                status = perform_check(ice, clist, i, ice->is_nominating); 
    15721838                if (status != PJ_SUCCESS) { 
    15731839                    pj_mutex_unlock(ice->mutex); 
     
    15961862} 
    15971863 
     1864 
     1865/* Start sending connectivity check with USE-CANDIDATE */ 
     1866static void start_nominated_check(pj_ice_sess *ice) 
     1867{ 
     1868    pj_time_val delay; 
     1869    unsigned i; 
     1870    pj_status_t status; 
     1871 
     1872    LOG4((ice->obj_name, "Starting nominated check..")); 
     1873 
     1874    pj_assert(ice->is_nominating == PJ_FALSE); 
     1875 
     1876    /* Stop our timer if it's active */ 
     1877    if (ice->timer.id == TIMER_START_NOMINATED_CHECK) { 
     1878        pj_timer_heap_cancel(ice->stun_cfg.timer_heap, &ice->timer); 
     1879        ice->timer.id = TIMER_NONE; 
     1880    } 
     1881 
     1882    /* For each component, set the check state of valid check with 
     1883     * highest priority to Waiting (it should have Success state now). 
     1884     */ 
     1885    for (i=0; i<ice->comp_cnt; ++i) { 
     1886        unsigned j; 
     1887        const pj_ice_sess_check *vc = ice->comp[i].valid_check; 
     1888 
     1889        pj_assert(ice->comp[i].nominated_check == NULL); 
     1890        pj_assert(vc->err_code == PJ_SUCCESS); 
     1891 
     1892        for (j=0; j<ice->clist.count; ++j) { 
     1893            pj_ice_sess_check *c = &ice->clist.checks[j]; 
     1894            if (c->lcand->transport_id == vc->lcand->transport_id && 
     1895                c->rcand == vc->rcand) 
     1896            { 
     1897                pj_assert(c->err_code == PJ_SUCCESS); 
     1898                c->state = PJ_ICE_SESS_CHECK_STATE_FROZEN; 
     1899                check_set_state(ice, c, PJ_ICE_SESS_CHECK_STATE_WAITING,  
     1900                                PJ_SUCCESS); 
     1901                break; 
     1902            } 
     1903        } 
     1904    } 
     1905 
     1906    /* And (re)start the periodic check */ 
     1907    if (!ice->clist.timer.id) { 
     1908        pj_timer_heap_cancel(ice->stun_cfg.timer_heap, &ice->clist.timer); 
     1909        ice->clist.timer.id = PJ_FALSE; 
     1910    } 
     1911 
     1912    ice->clist.timer.id = PJ_TRUE; 
     1913    delay.sec = delay.msec = 0; 
     1914    status = pj_timer_heap_schedule(ice->stun_cfg.timer_heap,  
     1915                                    &ice->clist.timer, &delay); 
     1916    if (status != PJ_SUCCESS) { 
     1917        ice->clist.timer.id = PJ_FALSE; 
     1918    } else { 
     1919        LOG5((ice->obj_name, "Periodic timer rescheduled..")); 
     1920    } 
     1921 
     1922    ice->is_nominating = PJ_TRUE; 
     1923} 
    15981924 
    15991925/* Timer callback to perform periodic check */ 
     
    16421968 
    16431969    LOG4((ice->obj_name, "Starting ICE check..")); 
     1970 
     1971    /* If we are using aggressive nomination, set the is_nominating state */ 
     1972    if (ice->opt.aggressive) 
     1973        ice->is_nominating = PJ_TRUE; 
    16441974 
    16451975    /* The agent examines the check list for the first media stream (a 
     
    18272157            LOG4((ice->obj_name, "Resending check because of role conflict")); 
    18282158            check_set_state(ice, check, PJ_ICE_SESS_CHECK_STATE_WAITING, 0); 
    1829             perform_check(ice, clist, msg_data->data.req.ckid); 
     2159            perform_check(ice, clist, msg_data->data.req.ckid,  
     2160                          check->nominated || ice->is_nominating); 
    18302161            pj_mutex_unlock(ice->mutex); 
    18312162            return; 
     
    19602291     */ 
    19612292 
    1962     /* Add pair to valid list */ 
    1963     pj_assert(ice->valid_list.count < PJ_ICE_MAX_CHECKS); 
    1964     new_check = &ice->valid_list.checks[ice->valid_list.count++]; 
    1965     new_check->lcand = lcand; 
    1966     new_check->rcand = check->rcand; 
    1967     new_check->prio = CALC_CHECK_PRIO(ice, lcand, check->rcand); 
    1968     new_check->state = PJ_ICE_SESS_CHECK_STATE_SUCCEEDED; 
    1969     new_check->nominated = check->nominated; 
    1970     new_check->err_code = PJ_SUCCESS; 
     2293    /* Add pair to valid list, if it's not there, otherwise just update 
     2294     * nominated flag 
     2295     */ 
     2296    for (i=0; i<ice->valid_list.count; ++i) { 
     2297        if (ice->valid_list.checks[i].lcand == lcand && 
     2298            ice->valid_list.checks[i].rcand == check->rcand) 
     2299            break; 
     2300    } 
     2301 
     2302    if (i==ice->valid_list.count) { 
     2303        pj_assert(ice->valid_list.count < PJ_ICE_MAX_CHECKS); 
     2304        new_check = &ice->valid_list.checks[ice->valid_list.count++]; 
     2305        new_check->lcand = lcand; 
     2306        new_check->rcand = check->rcand; 
     2307        new_check->prio = CALC_CHECK_PRIO(ice, lcand, check->rcand); 
     2308        new_check->state = PJ_ICE_SESS_CHECK_STATE_SUCCEEDED; 
     2309        new_check->nominated = check->nominated; 
     2310        new_check->err_code = PJ_SUCCESS; 
     2311    } else { 
     2312        new_check = &ice->valid_list.checks[i]; 
     2313        ice->valid_list.checks[i].nominated = check->nominated; 
     2314    } 
    19712315 
    19722316    /* Sort valid_list */ 
    19732317    sort_checklist(&ice->valid_list); 
    19742318 
     2319    /* Update valid check and nominated check for the component */ 
     2320    update_comp_check(ice, new_check->lcand->comp_id, new_check); 
    19752321 
    19762322    /* 7.1.2.2.2.  Updating Pair States 
     
    23132659            c->state == PJ_ICE_SESS_CHECK_STATE_WAITING) 
    23142660        { 
     2661            /* See if we shall nominate this check */ 
     2662            pj_bool_t nominate = (c->nominated || ice->is_nominating); 
     2663 
    23152664            LOG5((ice->obj_name, "Performing triggered check for check %d",i)); 
    2316             perform_check(ice, &ice->clist, i); 
     2665            perform_check(ice, &ice->clist, i, nominate); 
    23172666 
    23182667        } else if (c->state == PJ_ICE_SESS_CHECK_STATE_IN_PROGRESS) { 
     
    23372686                for (j=0; j<ice->valid_list.count; ++j) { 
    23382687                    pj_ice_sess_check *vc = &ice->valid_list.checks[j]; 
    2339                     if (vc->lcand == c->lcand && vc->rcand == c->rcand) { 
     2688                    if (vc->lcand->transport_id == c->lcand->transport_id &&  
     2689                        vc->rcand == c->rcand)  
     2690                    { 
     2691                        /* Set nominated flag */ 
    23402692                        vc->nominated = PJ_TRUE; 
     2693 
     2694                        /* Update valid check and nominated check for the component */ 
     2695                        update_comp_check(ice, vc->lcand->comp_id, vc); 
     2696 
     2697                        dump_check(ice->tmp.txt, sizeof(ice->tmp.txt), &ice->valid_list, vc); 
     2698                        LOG5((ice->obj_name, "Valid check %s is nominated", ice->tmp.txt)); 
    23412699                    } 
    23422700                } 
     
    23622720 
    23632721        pj_ice_sess_check *c = &ice->clist.checks[ice->clist.count]; 
     2722        pj_bool_t nominate; 
    23642723 
    23652724        c->lcand = lcand; 
     
    23702729        c->err_code = PJ_SUCCESS; 
    23712730 
     2731        nominate = (c->nominated || ice->is_nominating); 
     2732 
    23722733        LOG4((ice->obj_name, "New triggered check added: %d",  
    23732734             ice->clist.count)); 
    2374         perform_check(ice, &ice->clist, ice->clist.count++); 
     2735        perform_check(ice, &ice->clist, ice->clist.count++, nominate); 
    23752736 
    23762737    } else { 
     
    23892750                                         unsigned src_addr_len) 
    23902751{ 
     2752    struct stun_data *sd; 
     2753 
    23912754    PJ_UNUSED_ARG(sess); 
    23922755    PJ_UNUSED_ARG(pkt); 
     
    23972760    PJ_UNUSED_ARG(src_addr_len); 
    23982761 
    2399     PJ_TODO(SUPPORT_RX_BIND_REQUEST_AS_INDICATION); 
    2400  
    2401     return PJ_ENOTSUP; 
     2762    sd = (struct stun_data*) pj_stun_session_get_user_data(sess); 
     2763 
     2764    if (msg->hdr.type == PJ_STUN_BINDING_INDICATION) { 
     2765        LOG5((sd->ice->obj_name, "Received Binding Indication keep-alive " 
     2766              "for component %d", sd->comp_id)); 
     2767    } else { 
     2768        LOG4((sd->ice->obj_name, "Received unexpected %s indication " 
     2769              "for component %d", pj_stun_get_method_name(msg->hdr.type),  
     2770              sd->comp_id)); 
     2771    } 
     2772 
     2773    return PJ_SUCCESS; 
    24022774} 
    24032775 
Note: See TracChangeset for help on using the changeset viewer.