Changeset 1126 for pjproject/trunk/pjnath/src/pjnath/ice_session.c
- Timestamp:
- Apr 2, 2007 11:30:14 AM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjnath/src/pjnath/ice_session.c
r1114 r1126 41 41 42 42 /* String names for pj_ice_sess_check_state */ 43 #if PJ_LOG_MAX_LEVEL >= 4 43 44 static const char *check_state_name[] = 44 45 { … … 56 57 "Completed" 57 58 }; 59 #endif /* PJ_LOG_MAX_LEVEL >= 4 */ 58 60 59 61 static const char *role_names[] = … … 61 63 "Controlled", 62 64 "Controlling" 65 }; 66 67 /* Default ICE session preferences, according to draft-ice */ 68 static 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 */ 63 74 }; 64 75 … … 72 83 typedef struct stun_data 73 84 { 74 pj_ice_sess *ice; 75 unsigned lcand_id; 85 pj_ice_sess *ice; 76 86 pj_ice_sess_cand *lcand; 77 87 } stun_data; … … 79 89 typedef struct timer_data 80 90 { 81 pj_ice_sess *ice;82 pj_ice_sess_checklist 91 pj_ice_sess *ice; 92 pj_ice_sess_checklist *clist; 83 93 } timer_data; 84 94 … … 132 142 int *data_type, 133 143 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);139 144 140 145 … … 189 194 pj_pool_t *pool; 190 195 pj_ice_sess *ice; 191 char tmp[64];192 pj_str_t s;193 196 unsigned i; 194 197 pj_status_t status; … … 205 208 ice->tie_breaker.u32.hi = pj_rand(); 206 209 ice->tie_breaker.u32.lo = pj_rand(); 210 ice->prefs = cand_type_prefs; 207 211 208 212 pj_ansi_snprintf(ice->obj_name, sizeof(ice->obj_name), … … 227 231 228 232 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 } 234 238 235 239 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 } 241 245 242 246 … … 313 317 } 314 318 319 return PJ_SUCCESS; 320 } 321 322 323 /* 324 * Change type preference 325 */ 326 PJ_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)); 315 333 return PJ_SUCCESS; 316 334 } … … 422 440 423 441 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, 442 static pj_uint32_t CALC_CAND_PRIO(pj_ice_sess *ice, 443 pj_ice_cand_type type, 441 444 pj_uint32_t local_pref, 442 445 pj_uint32_t comp_id) 443 446 { 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) + 453 448 ((local_pref & 0xFFFF) << 8) + 454 449 (((256 - comp_id) & 0xFF) << 0); … … 493 488 lcand->type = type; 494 489 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); 496 491 pj_memcpy(&lcand->addr, addr, addr_len); 497 492 pj_memcpy(&lcand->base_addr, base_addr, addr_len); … … 521 516 sd = PJ_POOL_ZALLOC_T(ice->pool, struct stun_data); 522 517 sd->ice = ice; 523 sd->lcand_id = GET_LCAND_ID(lcand);524 518 sd->lcand = lcand; 525 519 pj_stun_session_set_user_data(lcand->stun_sess, sd); … … 531 525 auth_cred.data.dyn_cred.get_cred = &stun_auth_get_cred; 532 526 auth_cred.data.dyn_cred.get_password = &stun_auth_get_password; 533 auth_cred.data.dyn_cred.verify_nonce = &stun_auth_verify_nonce;534 527 auth_cred.data.dyn_cred.user_data = lcand->stun_sess; 535 528 pj_stun_session_set_credential(lcand->stun_sess, &auth_cred); … … 563 556 564 557 /* Find default candidate ID for the component */ 558 #if 0 565 559 PJ_DEF(pj_status_t) pj_ice_sess_find_default_cand(pj_ice_sess *ice, 566 560 unsigned comp_id, … … 630 624 return PJ_EBUG; 631 625 } 626 #endif /* if 0 */ 632 627 633 628 … … 640 635 #endif 641 636 642 static pj_ uint64_tCALC_CHECK_PRIO(const pj_ice_sess *ice,643 const pj_ice_sess_cand *lcand,644 const pj_ice_sess_cand *rcand)637 static pj_timestamp CALC_CHECK_PRIO(const pj_ice_sess *ice, 638 const pj_ice_sess_cand *lcand, 639 const pj_ice_sess_cand *rcand) 645 640 { 646 641 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 */ 647 647 648 648 if (ice->role == PJ_ICE_SESS_ROLE_CONTROLLING) { … … 654 654 } 655 655 656 /* 656 657 return ((pj_uint64_t)1 << 32) * MIN(O, A) + 657 658 (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 668 PJ_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 660 676 static const char *dump_check(char *buffer, unsigned bufsize, 661 677 const pj_ice_sess_checklist *clist, … … 691 707 } 692 708 693 #if PJ_LOG_MAX_LEVEL >= 4694 709 static void dump_checklist(const char *title, const pj_ice_sess *ice, 695 710 const pj_ice_sess_checklist *clist) … … 747 762 unsigned j, highest = i; 748 763 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) { 750 765 highest = j; 751 766 } … … 828 843 ljaddr = &ljcand->addr; 829 844 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) 832 847 { 833 848 /* Found duplicate, remove it */ … … 835 850 836 851 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]))); 839 854 840 855 pj_array_erase(clist->checks, sizeof(clist->checks[0]), … … 929 944 comp->valid_check = check; 930 945 } else { 931 if ( comp->valid_check->prio < check->prio)946 if (CMP_CHECK_PRIO(comp->valid_check, check) < 0) 932 947 comp->valid_check = check; 933 948 } … … 1155 1170 PJ_STUN_BINDING_REQUEST, 1156 1171 &check->tdata); 1157 if (status != PJ_SUCCESS) 1172 if (status != PJ_SUCCESS) { 1173 pjnath_perror(ice->obj_name, "Error creating STUN request", status); 1158 1174 return status; 1175 } 1159 1176 1160 1177 /* Attach data to be retrieved later when STUN request transaction … … 1168 1185 1169 1186 /* 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, 1171 1188 lcand->comp_id); 1172 1189 pj_stun_msg_add_uint_attr(check->tdata->pool, check->tdata->msg, … … 1190 1207 if (status != PJ_SUCCESS) { 1191 1208 check->tdata = NULL; 1209 pjnath_perror(ice->obj_name, "Error sending STUN request", status); 1192 1210 return status; 1193 1211 } … … 1290 1308 } 1291 1309 1310 1311 /* Utility: find string in string array */ 1312 const 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 1292 1323 /* Start ICE check */ 1293 1324 PJ_DEF(pj_status_t) pj_ice_sess_start_check(pj_ice_sess *ice) … … 1295 1326 pj_ice_sess_checklist *clist; 1296 1327 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; 1298 1330 1299 1331 PJ_ASSERT_RETURN(ice, PJ_EINVAL); 1300 /* Checklist must be created */ 1332 1333 /* Checklist must have been created */ 1301 1334 PJ_ASSERT_RETURN(ice->clist.count > 0, PJ_EINVALIDOP); 1302 1335 1303 1336 LOG4((ice->obj_name, "Starting ICE check..")); 1304 1337 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 1305 1350 clist = &ice->clist; 1306 1351 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; 1310 1367 1311 1368 /* Find all of the other pairs in that check list with the same … … 1313 1370 * states to Waiting as well. 1314 1371 */ 1315 for ( i=1; i<clist->count; ++i) {1372 for (++i; i<clist->count; ++i) { 1316 1373 const pj_ice_sess_cand *cand1; 1317 1374 1318 1375 cand1 = clist->checks[i].lcand; 1319 1376 1320 if (cand 0->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) 1322 1379 { 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; 1324 1383 } 1325 1384 } … … 1342 1401 { 1343 1402 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), 1345 1406 pkt, pkt_size, 1346 1407 dst_addr, addr_len);
Note: See TracChangeset
for help on using the changeset viewer.