Changeset 1101 for pjproject/trunk/pjnath/src/pjnath/ice.c
- Timestamp:
- Mar 24, 2007 1:00:30 PM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjnath/src/pjnath/ice.c
r1099 r1101 58 58 59 59 #define CHECK_NAME_LEN 128 60 #define LOG(expr) PJ_LOG(4,expr) 60 #define LOG4(expr) PJ_LOG(4,expr) 61 #define LOG5(expr) PJ_LOG(4,expr) 61 62 #define GET_LCAND_ID(cand) (cand - ice->lcand) 62 63 #define GET_CHECK_ID(chk) (chk - ice->clist.checks) … … 136 137 const char *name, 137 138 pj_ice_role role, 139 unsigned comp_cnt, 138 140 const pj_ice_cb *cb, 139 141 const pj_str_t *local_ufrag, … … 171 173 pj_memcpy(&ice->stun_cfg, stun_cfg, sizeof(*stun_cfg)); 172 174 173 for (i=0; i<PJ_ICE_MAX_COMP; ++i) { 174 ice->comp[i].nominated_check_id = -1; 175 ice->comp_cnt = comp_cnt; 176 for (i=0; i<comp_cnt; ++i) { 177 pj_ice_comp *comp; 178 comp = &ice->comp[i]; 179 comp->comp_id = i+1; 180 comp->nominated_check_id = -1; 175 181 } 176 182 … … 193 199 *p_ice = ice; 194 200 195 LOG ((ice->obj_name, "ICE stream session created, role is %s agent",196 (ice->role==PJ_ICE_ROLE_CONTROLLING ? "controlling" : "controlled")));201 LOG4((ice->obj_name, "ICE stream session created, role is %s agent", 202 (ice->role==PJ_ICE_ROLE_CONTROLLING ? "controlling" : "controlled"))); 197 203 198 204 return PJ_SUCCESS; … … 209 215 210 216 if (reason == PJ_SUCCESS) { 211 LOG((ice->obj_name, "Destroying ICE session")); 212 } 213 214 for (i=0; i<ice->comp_cnt; ++i) { 215 /* Nothing to do */ 217 LOG4((ice->obj_name, "Destroying ICE session")); 216 218 } 217 219 … … 251 253 static pj_ice_comp *find_comp(const pj_ice *ice, unsigned comp_id) 252 254 { 253 unsigned i; 254 for (i=0; i<ice->comp_cnt; ++i) { 255 if (ice->comp[i].comp_id == comp_id) 256 return (pj_ice_comp *) &ice->comp[i]; 257 } 258 259 return NULL; 260 } 261 262 263 /* Add a new component */ 264 PJ_DEF(pj_status_t) pj_ice_add_comp(pj_ice *ice, unsigned comp_id) 265 { 266 pj_ice_comp *comp; 267 268 PJ_ASSERT_RETURN(ice && comp_id, PJ_EINVAL); 269 PJ_ASSERT_RETURN(ice->comp_cnt < PJ_ARRAY_SIZE(ice->comp), PJ_ETOOMANY); 270 PJ_ASSERT_RETURN(comp_id==ice->comp_cnt+1, PJ_EICEINCOMPID); 271 PJ_ASSERT_RETURN(find_comp(ice, comp_id) == NULL, PJ_EEXISTS); 272 273 pj_mutex_lock(ice->mutex); 274 275 comp = &ice->comp[ice->comp_cnt]; 276 comp->comp_id = comp_id; 277 comp->nominated_check_id = -1; 278 279 /* Done */ 280 ice->comp_cnt++; 281 pj_mutex_unlock(ice->mutex); 282 283 return PJ_SUCCESS; 284 } 255 pj_assert(comp_id > 0 && comp_id <= ice->comp_cnt); 256 return (pj_ice_comp*) &ice->comp[comp_id-1]; 257 } 258 285 259 286 260 static pj_status_t stun_auth_get_auth(void *user_data, … … 357 331 /* Verify username */ 358 332 if (pj_strcmp(username, &ice->tx_uname) != 0) 359 return -1;333 return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_UNKNOWN_USERNAME); 360 334 *data_type = 0; 361 335 *data = ice->tx_pass; … … 408 382 }; 409 383 410 return (( 1 << 24) * type_pref[type]) +411 (( 1 << 8) * local_pref) +412 ( 256 - comp_id);384 return ((type_pref[type] & 0xFF) << 24) + 385 ((local_pref & 0xFFFF) << 8) + 386 (((256 - comp_id) & 0xFF) << 0); 413 387 } 414 388 … … 424 398 const pj_sockaddr_t *addr, 425 399 const pj_sockaddr_t *base_addr, 426 const pj_sockaddr_t * srv_addr,400 const pj_sockaddr_t *rel_addr, 427 401 int addr_len, 428 402 unsigned *p_cand_id) … … 453 427 pj_memcpy(&lcand->addr, addr, addr_len); 454 428 pj_memcpy(&lcand->base_addr, base_addr, addr_len); 455 if ( srv_addr)456 pj_memcpy(&lcand-> srv_addr, srv_addr, addr_len);429 if (rel_addr) 430 pj_memcpy(&lcand->rel_addr, rel_addr, addr_len); 457 431 else 458 pj_bzero(&lcand-> srv_addr, sizeof(lcand->srv_addr));432 pj_bzero(&lcand->rel_addr, sizeof(lcand->rel_addr)); 459 433 460 434 /* Init STUN callbacks */ … … 493 467 494 468 pj_ansi_strcpy(tmp, pj_inet_ntoa(lcand->addr.ipv4.sin_addr)); 495 LOG ((ice->obj_name,469 LOG4((ice->obj_name, 496 470 "Candidate %d added: comp_id=%d, type=%s, foundation=%.*s, " 497 471 "addr=%s:%d, base=%s:%d, prio=0x%x (%u)", … … 518 492 519 493 520 PJ_DEF(unsigned) pj_ice_get_cand_cnt(pj_ice *ice) 521 { 522 return ice->lcand_cnt; 523 } 524 525 526 PJ_DEF(pj_status_t) pj_ice_enum_cands(pj_ice *ice, 527 unsigned *p_count, 528 unsigned cand_ids[]) 529 { 530 unsigned i, count; 531 532 PJ_ASSERT_RETURN(ice && p_count && *p_count && cand_ids, PJ_EINVAL); 494 PJ_DEF(pj_status_t) pj_ice_find_default_cand(pj_ice *ice, 495 unsigned comp_id, 496 int *cand_id) 497 { 498 unsigned i; 499 500 PJ_ASSERT_RETURN(ice && comp_id && cand_id, PJ_EINVAL); 501 502 *cand_id = -1; 533 503 534 504 pj_mutex_lock(ice->mutex); 535 505 536 count = (*p_count < ice->lcand_cnt) ? *p_count : ice->lcand_cnt;537 for (i=0; i<count; ++i)538 cand_ids[i] = i;539 540 *p_count = count;541 pj_mutex_unlock(ice->mutex);542 543 return PJ_SUCCESS;544 }545 546 547 PJ_DEF(pj_status_t) pj_ice_get_default_cand(pj_ice *ice,548 unsigned comp_id,549 int *cand_id)550 {551 unsigned i;552 553 PJ_ASSERT_RETURN(ice && comp_id && cand_id, PJ_EINVAL);554 555 *cand_id = -1;556 557 pj_mutex_lock(ice->mutex);558 559 506 /* First find in valid list if we have nominated pair */ 560 for (i=0; i<ice->valid_ cnt; ++i) {561 pj_ice_c and *lcand;507 for (i=0; i<ice->valid_list.count; ++i) { 508 pj_ice_check *check = &ice->valid_list.checks[i]; 562 509 563 lcand = ice->clist.checks[ice->valid_list[i]].lcand; 564 if (lcand->comp_id==comp_id) { 565 *cand_id = GET_LCAND_ID(lcand); 510 if (check->lcand->comp_id == comp_id) { 511 *cand_id = GET_LCAND_ID(check->lcand); 566 512 pj_mutex_unlock(ice->mutex); 567 513 return PJ_SUCCESS; … … 609 555 610 556 pj_assert(!"Should have a candidate by now"); 611 return PJ_EICENOCAND; 612 } 613 614 615 PJ_DEF(pj_status_t) pj_ice_get_cand(pj_ice *ice, 616 unsigned cand_id, 617 pj_ice_cand **p_cand) 618 { 619 PJ_ASSERT_RETURN(ice && p_cand, PJ_EINVAL); 620 PJ_ASSERT_RETURN(cand_id <= ice->lcand_cnt, PJ_EINVAL); 621 622 *p_cand = &ice->lcand[cand_id]; 623 624 return PJ_SUCCESS; 625 } 557 return PJ_EBUG; 558 } 559 626 560 627 561 #ifndef MIN … … 690 624 char buffer[CHECK_NAME_LEN]; 691 625 692 LOG ((ice->obj_name, "%s", title));626 LOG4((ice->obj_name, "%s", title)); 693 627 for (i=0; i<clist->count; ++i) { 694 628 const pj_ice_check *c = &clist->checks[i]; 695 LOG ((ice->obj_name, " %s (%s, state=%s)",629 LOG4((ice->obj_name, " %s (%s, state=%s)", 696 630 dump_check(buffer, sizeof(buffer), ice, c), 697 631 (c->nominated ? "nominated" : "not nominated"), … … 700 634 } 701 635 702 static void dump_valid_list(const char *title, const pj_ice *ice)703 {704 unsigned i;705 char buffer[CHECK_NAME_LEN];706 707 LOG((ice->obj_name, "%s", title));708 for (i=0; i<ice->valid_cnt; ++i) {709 const pj_ice_check *c = &ice->clist.checks[ice->valid_list[i]];710 LOG((ice->obj_name, " %s (%s, state=%s)",711 dump_check(buffer, sizeof(buffer), ice, c),712 (c->nominated ? "nominated" : "not nominated"),713 check_state_name[c->state]));714 }715 }716 717 636 #else 718 637 #define dump_checklist(ice, clist) … … 727 646 pj_assert(check->state < PJ_ICE_CHECK_STATE_SUCCEEDED); 728 647 729 LOG ((ice->obj_name, "Check %s: state changed from %s to %s",648 LOG5((ice->obj_name, "Check %s: state changed from %s to %s", 730 649 dump_check(buf, sizeof(buf), ice, check), 731 650 check_state_name[check->state], … … 739 658 { 740 659 if (clist->state != st) { 741 LOG ((ice->obj_name, "Checklist: state changed from %s to %s",660 LOG5((ice->obj_name, "Checklist: state changed from %s to %s", 742 661 clist_state_name[clist->state], 743 662 clist_state_name[st])); … … 769 688 } 770 689 } 771 772 /* Sort valid list based on priority */773 static void sort_valid_list(pj_ice *ice)774 {775 unsigned i;776 777 for (i=0; i<ice->valid_cnt-1; ++i) {778 unsigned j, highest = i;779 pj_ice_check *ci = &ice->clist.checks[ice->valid_list[i]];780 781 for (j=i+1; j<ice->valid_cnt; ++j) {782 pj_ice_check *cj = &ice->clist.checks[ice->valid_list[j]];783 784 if (cj->prio > ci->prio) {785 highest = j;786 }787 }788 789 if (highest != i) {790 unsigned tmp = ice->valid_list[i];791 ice->valid_list[i] = ice->valid_list[j];792 ice->valid_list[j] = tmp;793 }794 }795 }796 797 690 798 691 enum … … 866 759 char buf[CHECK_NAME_LEN]; 867 760 868 LOG ((ice->obj_name, "Check %s pruned",761 LOG5((ice->obj_name, "Check %s pruned", 869 762 dump_check(buf, sizeof(buf), ice, &clist->checks[j]))); 870 763 … … 890 783 891 784 /* Log message */ 892 LOG ((ice->obj_name, "ICE process complete, status=%s",785 LOG4((ice->obj_name, "ICE process complete, status=%s", 893 786 pj_strerror(status, errmsg, sizeof(errmsg)).ptr)); 894 787 895 dump_checklist("Dumping checklist", ice, &ice->clist); 896 dump_valid_list("Dumping valid list", ice); 788 dump_checklist("Valid list", ice, &ice->valid_list); 897 789 898 790 /* Call callback */ … … 922 814 pj_ice_comp *comp; 923 815 924 LOG ((ice->obj_name, "Check %d is successful and nominated",816 LOG5((ice->obj_name, "Check %d is successful and nominated", 925 817 GET_CHECK_ID(check))); 926 818 … … 931 823 c->state==PJ_ICE_CHECK_STATE_WAITING)) 932 824 { 933 LOG ((ice->obj_name,825 LOG5((ice->obj_name, 934 826 "Check %d to be failed because state is %s", 935 827 i, check_state_name[c->state])); … … 982 874 983 875 984 #if 0985 /* For now, just see if we have a valid pair in component 1 and986 * just terminate ICE.987 */988 for (i=0; i<ice->valid_cnt; ++i) {989 pj_ice_check *c = &ice->clist.checks[ice->valid_list[i]];990 if (c->lcand->comp_id == 1)991 break;992 }993 994 if (i != ice->valid_cnt) {995 /* ICE succeeded */996 on_ice_complete(ice, PJ_SUCCESS);997 return PJ_TRUE;998 }999 #else1000 876 /* See if all components have nominated pair. If they do, then mark 1001 877 * ICE processing as success, otherwise wait. … … 1010 886 return PJ_TRUE; 1011 887 } 1012 #endif1013 888 1014 889 /* … … 1025 900 if (i == ice->clist.count) { 1026 901 /* All checks have completed */ 1027 on_ice_complete(ice, -1);902 on_ice_complete(ice, PJNATH_EICEFAILED); 1028 903 return PJ_TRUE; 1029 904 } … … 1167 1042 comp = find_comp(ice, lcand->comp_id); 1168 1043 1169 LOG ((ice->obj_name,1044 LOG5((ice->obj_name, 1170 1045 "Sending connectivity check for check %s", 1171 1046 dump_check(buffer, sizeof(buffer), ice, check))); … … 1239 1114 clist_set_state(ice, clist, PJ_ICE_CHECKLIST_ST_RUNNING); 1240 1115 1241 LOG ((ice->obj_name, "Starting checklist periodic check"));1116 LOG5((ice->obj_name, "Starting checklist periodic check")); 1242 1117 1243 1118 /* Send STUN Binding request for check with highest priority on … … 1307 1182 1308 1183 PJ_ASSERT_RETURN(ice, PJ_EINVAL); 1309 1310 LOG((ice->obj_name, "Starting ICE check..")); 1184 /* Checklist must be created */ 1185 PJ_ASSERT_RETURN(ice->clist.count > 0, PJ_EINVALIDOP); 1186 1187 LOG4((ice->obj_name, "Starting ICE check..")); 1311 1188 1312 1189 clist = &ice->clist; 1313 1314 if (clist->count == 0)1315 return PJ_EICENOCHECKLIST;1316 1190 1317 1191 /* Pickup the first pair and set the state to Waiting */ … … 1363 1237 struct req_data *rd = (struct req_data*) tdata->user_data; 1364 1238 pj_ice *ice; 1365 pj_ice_check *check; 1366 const pj_ice_cand *lcand; 1367 const pj_ice_cand *rcand; 1239 pj_ice_check *check, *new_check; 1240 pj_ice_cand *lcand; 1368 1241 pj_ice_checklist *clist; 1369 1242 pj_stun_xor_mapped_addr_attr *xaddr; … … 1379 1252 pj_mutex_lock(ice->mutex); 1380 1253 1381 lcand = check->lcand; 1382 rcand = check->rcand; 1383 1384 LOG((ice->obj_name, 1254 /* Init lcand to NULL. lcand will be found from the mapped address 1255 * found in the response. 1256 */ 1257 lcand = NULL; 1258 1259 LOG4((ice->obj_name, 1385 1260 "Check %s%s: connectivity check %s", 1386 1261 dump_check(buffer, sizeof(buffer), ice, check), … … 1403 1278 PJ_TODO(ICE_CHECK_RESPONSE_SOURCE_ADDRESS); 1404 1279 1405 /* Get the STUN MAPPED-ADDRESS attribute. */1280 /* Get the STUN XOR-MAPPED-ADDRESS attribute. */ 1406 1281 xaddr = (pj_stun_xor_mapped_addr_attr*) 1407 1282 pj_stun_msg_find_attr(response, PJ_STUN_ATTR_XOR_MAPPED_ADDR,0); 1408 1283 if (!xaddr) { 1409 1284 check_set_state(ice, check, PJ_ICE_CHECK_STATE_FAILED, 1410 PJNATH_ESTUNNO XORMAP);1285 PJNATH_ESTUNNOMAPPEDADDR); 1411 1286 on_check_complete(ice, check); 1412 1287 pj_mutex_unlock(ice->mutex); … … 1414 1289 } 1415 1290 1291 /* Find local candidate that matches the XOR-MAPPED-ADDRESS */ 1292 pj_assert(lcand == NULL); 1293 for (i=0; i<ice->lcand_cnt; ++i) { 1294 if (sockaddr_cmp(&xaddr->sockaddr, &ice->lcand[i].addr) == 0) { 1295 /* Match */ 1296 lcand = &ice->lcand[i]; 1297 break; 1298 } 1299 } 1300 1416 1301 /* If the transport address returned in XOR-MAPPED-ADDRESS does not match 1417 1302 * any of the local candidates that the agent knows about, the mapped 1418 1303 * address represents a new candidate - a peer reflexive candidate. 1419 1304 */ 1420 for (i=0; i<ice->lcand_cnt; ++i) { 1421 if (sockaddr_cmp(&xaddr->sockaddr, &ice->lcand[i].addr) == 0) { 1422 /* Match */ 1423 break; 1424 } 1425 } 1426 1427 if (i == ice->lcand_cnt) { 1305 if (lcand == NULL) { 1428 1306 unsigned cand_id; 1429 1307 char buf[32]; … … 1451 1329 } 1452 1330 1453 /* Sets the state of the pair that generated the check to succeeded. */ 1331 /* Add pair to valid list */ 1332 new_check = &ice->valid_list.checks[ice->valid_list.count++]; 1333 new_check->lcand = lcand; 1334 new_check->rcand = check->rcand; 1335 new_check->prio = CALC_CHECK_PRIO(ice, lcand, check->rcand); 1336 new_check->state = PJ_ICE_CHECK_STATE_SUCCEEDED; 1337 new_check->nominated = check->nominated; 1338 new_check->err_code = PJ_SUCCESS; 1339 1340 /* Sort valid_list */ 1341 sort_checklist(&ice->valid_list); 1342 1343 1344 /* Sets the state of the original pair that generated the check to 1345 * succeeded. 1346 */ 1454 1347 check_set_state(ice, check, PJ_ICE_CHECK_STATE_SUCCEEDED, PJ_SUCCESS); 1455 1456 /* This is a valid pair, so add this to the valid list */1457 ice->valid_list[ice->valid_cnt++] = rd->ckid;1458 1459 /* Sort valid_list */1460 sort_valid_list(ice);1461 1348 1462 1349 /* Inform about check completion. … … 1516 1403 } 1517 1404 1518 1405 /* This callback is called by the STUN session associated with a candidate 1406 * when it receives incoming request. 1407 */ 1519 1408 static pj_status_t on_stun_rx_request(pj_stun_session *sess, 1520 1409 const pj_uint8_t *pkt, … … 1541 1430 /* Reject any requests except Binding request */ 1542 1431 if (msg->hdr.type != PJ_STUN_BINDING_REQUEST) { 1543 pj_str_t err_msg = pj_str("Expecting Binding Request only");1544 1432 status = pj_stun_session_create_response(sess, msg, 1545 1433 PJ_STUN_SC_BAD_REQUEST, 1546 &err_msg, &tdata);1547 if (status != PJ_SUCCESS) {1434 NULL, &tdata); 1435 if (status != PJ_SUCCESS) 1548 1436 return status; 1549 } 1550 1551 status = pj_stun_session_send_msg(sess, PJ_TRUE, 1552 src_addr, src_addr_len, tdata); 1553 1554 return status; 1437 1438 return pj_stun_session_send_msg(sess, PJ_TRUE, 1439 src_addr, src_addr_len, tdata); 1555 1440 } 1556 1441 … … 1567 1452 pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_PRIORITY, 0); 1568 1453 if (ap == 0) { 1569 LOG ((ice->obj_name, "Received Binding request with no PRIORITY"));1454 LOG5((ice->obj_name, "Received Binding request with no PRIORITY")); 1570 1455 pj_mutex_unlock(ice->mutex); 1571 1456 return PJ_SUCCESS; … … 1627 1512 rcand->foundation.ptr); 1628 1513 1629 LOG ((ice->obj_name,1514 LOG4((ice->obj_name, 1630 1515 "Added new remote candidate from the request: %s:%d", 1631 1516 pj_inet_ntoa(rcand->addr.ipv4.sin_addr), … … 1679 1564 c->state == PJ_ICE_CHECK_STATE_WAITING) 1680 1565 { 1681 LOG ((ice->obj_name, "Performing triggered check for check %d",i));1566 LOG5((ice->obj_name, "Performing triggered check for check %d",i)); 1682 1567 perform_check(ice, &ice->clist, i); 1683 1568 … … 1686 1571 * TODO 1687 1572 */ 1688 LOG ((ice->obj_name, "Triggered check for check %d not performed "1573 LOG5((ice->obj_name, "Triggered check for check %d not performed " 1689 1574 "because it's in progress", i)); 1690 1575 } else if (c->state == PJ_ICE_CHECK_STATE_SUCCEEDED) { … … 1694 1579 pj_bool_t complete; 1695 1580 1696 LOG ((ice->obj_name, "Triggered check for check %d not performed "1581 LOG5((ice->obj_name, "Triggered check for check %d not performed " 1697 1582 "because it's completed", i)); 1698 1583 … … 1722 1607 c->err_code = PJ_SUCCESS; 1723 1608 1724 LOG ((ice->obj_name, "New triggered check added: %d",1609 LOG4((ice->obj_name, "New triggered check added: %d", 1725 1610 ice->clist.count)); 1726 1611 perform_check(ice, &ice->clist, ice->clist.count++); 1727 1612 1728 1613 } else { 1729 LOG ((ice->obj_name, "Error: unable to perform triggered check: "1614 LOG4((ice->obj_name, "Error: unable to perform triggered check: " 1730 1615 "TOO MANY CHECKS IN CHECKLIST!")); 1731 1616 } … … 1772 1657 comp = find_comp(ice, comp_id); 1773 1658 if (comp == NULL) { 1774 status = PJ _EICEINCOMPID;1659 status = PJNATH_EICEINCOMPID; 1775 1660 goto on_return; 1776 1661 } 1777 1662 1778 1663 if (comp->nominated_check_id == -1) { 1779 status = PJ _EICEINPROGRESS;1664 status = PJNATH_EICEINPROGRESS; 1780 1665 goto on_return; 1781 1666 } … … 1813 1698 comp = find_comp(ice, comp_id); 1814 1699 if (comp == NULL) { 1815 status = PJ _EICEINCOMPID;1700 status = PJNATH_EICEINCOMPID; 1816 1701 goto on_return; 1817 1702 }
Note: See TracChangeset
for help on using the changeset viewer.