Ignore:
Timestamp:
Apr 2, 2007 11:30:14 AM (17 years ago)
Author:
bennylp
Message:

ICE: work in progress

File:
1 edited

Legend:

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

    r1114 r1126  
    4141 
    4242/* String names for pj_ice_sess_check_state */ 
     43#if PJ_LOG_MAX_LEVEL >= 4 
    4344static const char *check_state_name[] =  
    4445{ 
     
    5657    "Completed" 
    5758}; 
     59#endif  /* PJ_LOG_MAX_LEVEL >= 4 */ 
    5860 
    5961static const char *role_names[] =  
     
    6163    "Controlled", 
    6264    "Controlling" 
     65}; 
     66 
     67/* Default ICE session preferences, according to draft-ice */ 
     68static pj_uint8_t cand_type_prefs[4] = 
     69{ 
     70    126,    /**< PJ_ICE_HOST_PREF       */ 
     71    100,    /**< PJ_ICE_SRFLX_PREF.     */ 
     72    110,    /**< PJ_ICE_PRFLX_PREF      */ 
     73    0       /**< PJ_ICE_RELAYED_PREF    */ 
    6374}; 
    6475 
     
    7283typedef struct stun_data 
    7384{ 
    74     pj_ice_sess *ice; 
    75     unsigned     lcand_id; 
     85    pj_ice_sess         *ice; 
    7686    pj_ice_sess_cand    *lcand; 
    7787} stun_data; 
     
    7989typedef struct timer_data 
    8090{ 
    81     pj_ice_sess         *ice; 
    82     pj_ice_sess_checklist       *clist; 
     91    pj_ice_sess             *ice; 
     92    pj_ice_sess_checklist   *clist; 
    8393} timer_data; 
    8494 
     
    132142                                          int *data_type, 
    133143                                          pj_str_t *data); 
    134 static pj_bool_t stun_auth_verify_nonce(const pj_stun_msg *msg, 
    135                                         void *user_data, 
    136                                         const pj_str_t *realm, 
    137                                         const pj_str_t *username, 
    138                                         const pj_str_t *nonce); 
    139144 
    140145 
     
    189194    pj_pool_t *pool; 
    190195    pj_ice_sess *ice; 
    191     char tmp[64]; 
    192     pj_str_t s; 
    193196    unsigned i; 
    194197    pj_status_t status; 
     
    205208    ice->tie_breaker.u32.hi = pj_rand(); 
    206209    ice->tie_breaker.u32.lo = pj_rand(); 
     210    ice->prefs = cand_type_prefs; 
    207211 
    208212    pj_ansi_snprintf(ice->obj_name, sizeof(ice->obj_name), 
     
    227231 
    228232    if (local_ufrag == NULL) { 
    229         pj_ansi_snprintf(tmp, sizeof(tmp), "%x%x", pj_rand(), pj_rand()); 
    230         s = pj_str(tmp); 
    231         local_ufrag = &s; 
    232     } 
    233     pj_strdup(ice->pool, &ice->rx_ufrag, local_ufrag); 
     233        ice->rx_ufrag.ptr = pj_pool_alloc(ice->pool, 16); 
     234        pj_create_random_string(ice->rx_ufrag.ptr, 16); 
     235    } else { 
     236        pj_strdup(ice->pool, &ice->rx_ufrag, local_ufrag); 
     237    } 
    234238 
    235239    if (local_passwd == NULL) { 
    236         pj_ansi_snprintf(tmp, sizeof(tmp), "%x%x", pj_rand(), pj_rand()); 
    237         s = pj_str(tmp); 
    238         local_passwd = &s; 
    239     } 
    240     pj_strdup(ice->pool, &ice->rx_pass, local_passwd); 
     240        ice->rx_pass.ptr = pj_pool_alloc(ice->pool, 16); 
     241        pj_create_random_string(ice->rx_pass.ptr, 16); 
     242    } else { 
     243        pj_strdup(ice->pool, &ice->rx_pass, local_passwd); 
     244    } 
    241245 
    242246 
     
    313317    } 
    314318 
     319    return PJ_SUCCESS; 
     320} 
     321 
     322 
     323/* 
     324 * Change type preference 
     325 */ 
     326PJ_DEF(pj_status_t) pj_ice_sess_set_prefs(pj_ice_sess *ice, 
     327                                          const pj_uint8_t prefs[4]) 
     328{ 
     329    PJ_ASSERT_RETURN(ice && prefs, PJ_EINVAL); 
     330    ice->prefs = pj_pool_calloc(ice->pool, PJ_ARRAY_SIZE(prefs),  
     331                                sizeof(pj_uint8_t)); 
     332    pj_memcpy(ice->prefs, prefs, sizeof(prefs)); 
    315333    return PJ_SUCCESS; 
    316334} 
     
    422440 
    423441 
    424 static pj_bool_t stun_auth_verify_nonce(const pj_stun_msg *msg, 
    425                                         void *user_data, 
    426                                         const pj_str_t *realm, 
    427                                         const pj_str_t *username, 
    428                                         const pj_str_t *nonce) 
    429 { 
    430     /* We don't use NONCE */ 
    431     PJ_UNUSED_ARG(msg); 
    432     PJ_UNUSED_ARG(user_data); 
    433     PJ_UNUSED_ARG(realm); 
    434     PJ_UNUSED_ARG(username); 
    435     PJ_UNUSED_ARG(nonce); 
    436     return PJ_TRUE; 
    437 } 
    438  
    439  
    440 static pj_uint32_t CALC_CAND_PRIO(pj_ice_cand_type type, 
     442static pj_uint32_t CALC_CAND_PRIO(pj_ice_sess *ice, 
     443                                  pj_ice_cand_type type, 
    441444                                  pj_uint32_t local_pref, 
    442445                                  pj_uint32_t comp_id) 
    443446{ 
    444     pj_uint32_t type_pref[] = 
    445     { 
    446         PJ_ICE_HOST_PREF, 
    447         PJ_ICE_SRFLX_PREF, 
    448         PJ_ICE_PRFLX_PREF, 
    449         PJ_ICE_RELAYED_PREF 
    450     }; 
    451  
    452     return ((type_pref[type] & 0xFF) << 24) +  
     447    return ((ice->prefs[type] & 0xFF) << 24) +  
    453448           ((local_pref & 0xFFFF)    << 8) + 
    454449           (((256 - comp_id) & 0xFF) << 0); 
     
    493488    lcand->type = type; 
    494489    pj_strdup(ice->pool, &lcand->foundation, foundation); 
    495     lcand->prio = CALC_CAND_PRIO(type, local_pref, lcand->comp_id); 
     490    lcand->prio = CALC_CAND_PRIO(ice, type, local_pref, lcand->comp_id); 
    496491    pj_memcpy(&lcand->addr, addr, addr_len); 
    497492    pj_memcpy(&lcand->base_addr, base_addr, addr_len); 
     
    521516    sd = PJ_POOL_ZALLOC_T(ice->pool, struct stun_data); 
    522517    sd->ice = ice; 
    523     sd->lcand_id = GET_LCAND_ID(lcand); 
    524518    sd->lcand = lcand; 
    525519    pj_stun_session_set_user_data(lcand->stun_sess, sd); 
     
    531525    auth_cred.data.dyn_cred.get_cred = &stun_auth_get_cred; 
    532526    auth_cred.data.dyn_cred.get_password = &stun_auth_get_password; 
    533     auth_cred.data.dyn_cred.verify_nonce = &stun_auth_verify_nonce; 
    534527    auth_cred.data.dyn_cred.user_data = lcand->stun_sess; 
    535528    pj_stun_session_set_credential(lcand->stun_sess, &auth_cred); 
     
    563556 
    564557/* Find default candidate ID for the component */ 
     558#if 0 
    565559PJ_DEF(pj_status_t) pj_ice_sess_find_default_cand(pj_ice_sess *ice, 
    566560                                                  unsigned comp_id, 
     
    630624    return PJ_EBUG; 
    631625} 
     626#endif  /* if 0 */ 
    632627 
    633628 
     
    640635#endif 
    641636 
    642 static pj_uint64_t CALC_CHECK_PRIO(const pj_ice_sess *ice,  
    643                                    const pj_ice_sess_cand *lcand, 
    644                                    const pj_ice_sess_cand *rcand) 
     637static pj_timestamp CALC_CHECK_PRIO(const pj_ice_sess *ice,  
     638                                    const pj_ice_sess_cand *lcand, 
     639                                    const pj_ice_sess_cand *rcand) 
    645640{ 
    646641    pj_uint32_t O, A; 
     642    pj_timestamp prio; 
     643 
     644    /* Original formula: 
     645     *   pair priority = 2^32*MIN(O,A) + 2*MAX(O,A) + (O>A?1:0) 
     646     */ 
    647647 
    648648    if (ice->role == PJ_ICE_SESS_ROLE_CONTROLLING) { 
     
    654654    } 
    655655 
     656    /* 
    656657    return ((pj_uint64_t)1 << 32) * MIN(O, A) + 
    657658           (pj_uint64_t)2 * MAX(O, A) + (O>A ? 1 : 0); 
    658 } 
    659  
     659    */ 
     660 
     661    prio.u32.hi = MIN(O,A); 
     662    prio.u32.lo = (MAX(O, A) << 1) + (O>A ? 1 : 0); 
     663 
     664    return prio; 
     665} 
     666 
     667 
     668PJ_INLINE(int) CMP_CHECK_PRIO(const pj_ice_sess_check *c1, 
     669                              const pj_ice_sess_check *c2) 
     670{ 
     671    return pj_cmp_timestamp(&c1->prio, &c2->prio); 
     672} 
     673 
     674 
     675#if PJ_LOG_MAX_LEVEL >= 4 
    660676static const char *dump_check(char *buffer, unsigned bufsize, 
    661677                              const pj_ice_sess_checklist *clist, 
     
    691707} 
    692708 
    693 #if PJ_LOG_MAX_LEVEL >= 4 
    694709static void dump_checklist(const char *title, const pj_ice_sess *ice,  
    695710                           const pj_ice_sess_checklist *clist) 
     
    747762        unsigned j, highest = i; 
    748763        for (j=i+1; j<clist->count; ++j) { 
    749             if (clist->checks[j].prio > clist->checks[highest].prio) { 
     764            if (CMP_CHECK_PRIO(&clist->checks[j], &clist->checks[highest]) > 0) { 
    750765                highest = j; 
    751766            } 
     
    828843                ljaddr = &ljcand->addr; 
    829844 
    830             if (sockaddr_cmp(liaddr, ljaddr) == SOCKADDR_EQUAL && 
    831                 sockaddr_cmp(&ricand->addr, &rjcand->addr) == SOCKADDR_EQUAL) 
     845            if (ricand == rjcand &&  
     846                sockaddr_cmp(liaddr, ljaddr) == SOCKADDR_EQUAL) 
    832847            { 
    833848                /* Found duplicate, remove it */ 
     
    835850 
    836851                LOG5((ice->obj_name, "Check %s pruned", 
    837                     dump_check(buf, sizeof(buf), &ice->clist,  
    838                                &clist->checks[j]))); 
     852                     dump_check(buf, sizeof(buf), &ice->clist,  
     853                                &clist->checks[j]))); 
    839854 
    840855                pj_array_erase(clist->checks, sizeof(clist->checks[0]), 
     
    929944            comp->valid_check = check; 
    930945        } else { 
    931             if (comp->valid_check->prio < check->prio) 
     946            if (CMP_CHECK_PRIO(comp->valid_check, check) < 0) 
    932947                comp->valid_check = check; 
    933948        } 
     
    11551170                                        PJ_STUN_BINDING_REQUEST,  
    11561171                                        &check->tdata); 
    1157     if (status != PJ_SUCCESS) 
     1172    if (status != PJ_SUCCESS) { 
     1173        pjnath_perror(ice->obj_name, "Error creating STUN request", status); 
    11581174        return status; 
     1175    } 
    11591176 
    11601177    /* Attach data to be retrieved later when STUN request transaction 
     
    11681185 
    11691186    /* Add PRIORITY */ 
    1170     prio = CALC_CAND_PRIO(PJ_ICE_CAND_TYPE_PRFLX, 65535,  
     1187    prio = CALC_CAND_PRIO(ice, PJ_ICE_CAND_TYPE_PRFLX, 65535,  
    11711188                          lcand->comp_id); 
    11721189    pj_stun_msg_add_uint_attr(check->tdata->pool, check->tdata->msg,  
     
    11901207    if (status != PJ_SUCCESS) { 
    11911208        check->tdata = NULL; 
     1209        pjnath_perror(ice->obj_name, "Error sending STUN request", status); 
    11921210        return status; 
    11931211    } 
     
    12901308} 
    12911309 
     1310 
     1311/* Utility: find string in string array */ 
     1312const pj_str_t *find_str(const pj_str_t *strlist[], unsigned count, 
     1313                         const pj_str_t *str) 
     1314{ 
     1315    unsigned i; 
     1316    for (i=0; i<count; ++i) { 
     1317        if (pj_strcmp(strlist[i], str)==0) 
     1318            return strlist[i]; 
     1319    } 
     1320    return NULL; 
     1321} 
     1322 
    12921323/* Start ICE check */ 
    12931324PJ_DEF(pj_status_t) pj_ice_sess_start_check(pj_ice_sess *ice) 
     
    12951326    pj_ice_sess_checklist *clist; 
    12961327    const pj_ice_sess_cand *cand0; 
    1297     unsigned i; 
     1328    const pj_str_t *flist[PJ_ICE_MAX_CAND]; 
     1329    unsigned i, flist_cnt = 0; 
    12981330 
    12991331    PJ_ASSERT_RETURN(ice, PJ_EINVAL); 
    1300     /* Checklist must be created */ 
     1332 
     1333    /* Checklist must have been created */ 
    13011334    PJ_ASSERT_RETURN(ice->clist.count > 0, PJ_EINVALIDOP); 
    13021335 
    13031336    LOG4((ice->obj_name, "Starting ICE check..")); 
    13041337 
     1338    /* The agent examines the check list for the first media stream (a 
     1339     * media stream is the first media stream when it is described by 
     1340     * the first m-line in the SDP offer and answer).  For that media 
     1341     * stream, it: 
     1342     *  
     1343     * -  Groups together all of the pairs with the same foundation, 
     1344     *  
     1345     * -  For each group, sets the state of the pair with the lowest 
     1346     *    component ID to Waiting.  If there is more than one such pair, 
     1347     *    the one with the highest priority is used. 
     1348     */ 
     1349 
    13051350    clist = &ice->clist; 
    13061351 
    1307     /* Pickup the first pair and set the state to Waiting */ 
    1308     clist->checks[0].state = PJ_ICE_SESS_CHECK_STATE_WAITING; 
    1309     cand0 = clist->checks[0].lcand; 
     1352    /* Pickup the first pair for component 1. */ 
     1353    for (i=0; i<clist->count; ++i) { 
     1354        if (clist->checks[0].lcand->comp_id == 1) 
     1355            break; 
     1356    } 
     1357    if (i == clist->count) { 
     1358        pj_assert(!"Unable to find checklist for component 1"); 
     1359        return PJNATH_EICEINCOMPID; 
     1360    } 
     1361 
     1362    /* Set this check to WAITING */ 
     1363    check_set_state(ice, &clist->checks[i],  
     1364                    PJ_ICE_SESS_CHECK_STATE_WAITING, PJ_SUCCESS); 
     1365    cand0 = clist->checks[i].lcand; 
     1366    flist[flist_cnt++] = &clist->checks[i].lcand->foundation; 
    13101367 
    13111368    /* Find all of the other pairs in that check list with the same 
     
    13131370     * states to Waiting as well. 
    13141371     */ 
    1315     for (i=1; i<clist->count; ++i) { 
     1372    for (++i; i<clist->count; ++i) { 
    13161373        const pj_ice_sess_cand *cand1; 
    13171374 
    13181375        cand1 = clist->checks[i].lcand; 
    13191376 
    1320         if (cand0->comp_id == cand1->comp_id && 
    1321             pj_strcmp(&cand0->foundation, &cand1->foundation)!=0) 
     1377        if (cand1->comp_id==cand0->comp_id && 
     1378            find_str(flist, flist_cnt, &cand1->foundation)==NULL) 
    13221379        { 
    1323             clist->checks[i].state = PJ_ICE_SESS_CHECK_STATE_WAITING; 
     1380            check_set_state(ice, &clist->checks[i],  
     1381                            PJ_ICE_SESS_CHECK_STATE_WAITING, PJ_SUCCESS); 
     1382            flist[flist_cnt++] = &cand1->foundation; 
    13241383        } 
    13251384    } 
     
    13421401{ 
    13431402    stun_data *sd = (stun_data*) pj_stun_session_get_user_data(sess); 
    1344     return (*sd->ice->cb.on_tx_pkt)(sd->ice, sd->lcand->comp_id, sd->lcand_id, 
     1403    pj_ice_sess *ice = sd->ice; 
     1404    return (*sd->ice->cb.on_tx_pkt)(sd->ice, sd->lcand->comp_id,  
     1405                                    GET_LCAND_ID(sd->lcand), 
    13451406                                    pkt, pkt_size,  
    13461407                                    dst_addr, addr_len); 
Note: See TracChangeset for help on using the changeset viewer.