- Timestamp:
- Apr 5, 2007 11:32:47 AM (18 years ago)
- Location:
- pjproject/trunk
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/src/pjmedia/transport_ice.c
r1140 r1152 465 465 (pj_uint16_t)sdp_med->desc.port); 466 466 467 /* Find ice-ufrag attribute in sessiondescriptor */468 attr = pjmedia_sdp_attr_find2( rem_sdp->attr_count, rem_sdp->attr,467 /* Find ice-ufrag attribute in media descriptor */ 468 attr = pjmedia_sdp_attr_find2(sdp_med->attr_count, sdp_med->attr, 469 469 "ice-ufrag", NULL); 470 470 if (attr == NULL) { 471 /* Find i n mediadescriptor */472 attr = pjmedia_sdp_attr_find2( sdp_med->attr_count, sdp_med->attr,471 /* Find ice-ufrag attribute in session descriptor */ 472 attr = pjmedia_sdp_attr_find2(rem_sdp->attr_count, rem_sdp->attr, 473 473 "ice-ufrag", NULL); 474 474 if (attr == NULL) { … … 479 479 uname = attr->value; 480 480 481 /* Find ice-pwd attribute in sessiondescriptor */482 attr = pjmedia_sdp_attr_find2( rem_sdp->attr_count, rem_sdp->attr,481 /* Find ice-pwd attribute in media descriptor */ 482 attr = pjmedia_sdp_attr_find2(sdp_med->attr_count, sdp_med->attr, 483 483 "ice-pwd", NULL); 484 484 if (attr == NULL) { 485 /* Not found, find in mediadescriptor */486 attr = pjmedia_sdp_attr_find2( sdp_med->attr_count, sdp_med->attr,485 /* Find ice-pwd attribute in session descriptor */ 486 attr = pjmedia_sdp_attr_find2(rem_sdp->attr_count, rem_sdp->attr, 487 487 "ice-pwd", NULL); 488 488 if (attr == NULL) { -
pjproject/trunk/pjnath/include/pjnath/config.h
r1140 r1152 166 166 167 167 /** 168 * According to ICE Section 8.2. Updating States, if an In-Progress pair in 169 * the check list is for the same component as a nominated pair, the agent 170 * SHOULD cease retransmissions for its check if its pair priority is lower 171 * than the lowest priority nominated pair for that component. 172 * 173 * If a higher priority check is In Progress, this rule would cause that 174 * check to be performed even when it most likely will fail. 175 * 176 * The macro here controls if ICE session should cancel all In Progress 177 * checks for the same component regardless of its priority. 178 * 179 * Default: 1 (yes, cancel all) 180 */ 181 #ifndef PJ_ICE_CANCEL_ALL 182 # define PJ_ICE_CANCEL_ALL 1 183 #endif 184 185 186 /** 168 187 * Minimum interval value to be used for sending STUN keep-alive on the ICE 169 188 * stream transport, in seconds. This minimum interval, plus a random value … … 196 215 197 216 198 199 217 /** 200 218 * @} -
pjproject/trunk/pjnath/include/pjnath/ice_session.h
r1141 r1152 420 420 421 421 /** 422 * This structure represents an incoming check (an incoming Binding 423 * request message), and is mainly used to keep early checks in the 424 * list in the ICE session. An early check is a request received 425 * from remote when we haven't received SDP answer yet, therefore we 426 * can't perform triggered check. For such cases, keep the incoming 427 * request in a list, and we'll do triggered checks (simultaneously) 428 * as soon as we receive answer. 429 */ 430 typedef struct pj_ice_rx_check 431 { 432 PJ_DECL_LIST_MEMBER(struct pj_ice_rx_check); 433 434 unsigned comp_id; /**< Component ID. */ 435 436 pj_sockaddr src_addr; /**< Source address of request */ 437 unsigned src_addr_len; /**< Length of src address. */ 438 439 pj_bool_t use_candidate; /**< USE-CANDIDATE is present? */ 440 pj_uint32_t priority; /**< PRIORITY value in the req. */ 441 pj_stun_uint64_attr *role_attr; /**< ICE-CONTROLLING/CONTROLLED */ 442 443 } pj_ice_rx_check; 444 445 446 /** 422 447 * This structure describes the ICE session. For this version of PJNATH, 423 448 * an ICE session corresponds to a single media stream (unlike the ICE … … 463 488 unsigned rcand_cnt; /**< # of remote cand. */ 464 489 pj_ice_sess_cand rcand[PJ_ICE_MAX_CAND]; /**< Array of cand. */ 490 491 /* List of eearly checks */ 492 pj_ice_rx_check early_check; /**< Early checks. */ 465 493 466 494 /* Checklist */ -
pjproject/trunk/pjnath/include/pjnath/stun_session.h
r1141 r1152 359 359 360 360 /** 361 * Explicitly request retransmission of the request. Normally application 362 * doesn't need to do this, but this functionality is needed by ICE to 363 * speed up connectivity check completion. 364 * 365 * @param sess The STUN session instance. 366 * @param tdata The request message previously sent. 367 * 368 * @return PJ_SUCCESS on success, or the appropriate error. 369 */ 370 PJ_DECL(pj_status_t) pj_stun_session_retransmit_req(pj_stun_session *sess, 371 pj_stun_tx_data *tdata); 372 373 374 /** 361 375 * Application must call this function to notify the STUN session about 362 376 * the arrival of STUN packet. The STUN packet MUST have been checked -
pjproject/trunk/pjnath/include/pjnath/stun_transaction.h
r1141 r1152 222 222 unsigned pkt_len); 223 223 224 /** 225 * Request to retransmit the request. Normally application should not need 226 * to call this function since retransmission would be handled internally, 227 * but this functionality is needed by ICE. 228 * 229 * @param tsx The STUN client transaction instance. 230 * 231 * @return PJ_SUCCESS on success or the appropriate error code. 232 */ 233 PJ_DECL(pj_status_t) pj_stun_client_tsx_retransmit(pj_stun_client_tsx *tsx); 224 234 225 235 -
pjproject/trunk/pjnath/src/pjnath/ice_session.c
r1144 r1152 81 81 82 82 83 /* The data that will be attached to the STUN session on each 84 * component. 85 */ 83 86 typedef struct stun_data 84 87 { … … 88 91 } stun_data; 89 92 93 94 /* The data that will be attached to the timer to perform 95 * periodic check. 96 */ 90 97 typedef struct timer_data 91 98 { … … 95 102 96 103 97 104 /* Forward declarations */ 98 105 static void destroy_ice(pj_ice_sess *ice, 99 106 pj_status_t reason); … … 101 108 pj_timer_entry *te); 102 109 static void periodic_timer(pj_timer_heap_t *th, 103 pj_timer_entry *te); 110 pj_timer_entry *te); 111 static void handle_incoming_check(pj_ice_sess *ice, 112 const pj_ice_rx_check *rcheck); 113 114 /* These are the callbacks registered to the STUN sessions */ 104 115 static pj_status_t on_stun_send_msg(pj_stun_session *sess, 105 116 const void *pkt, … … 126 137 unsigned src_addr_len); 127 138 139 /* These are the callbacks for performing STUN authentication */ 128 140 static pj_status_t stun_auth_get_auth(void *user_data, 129 141 pj_pool_t *pool, … … 299 311 } 300 312 313 pj_list_init(&ice->early_check); 301 314 302 315 /* Done */ … … 483 496 * or answer for a session in-progress, and the MESSAGE-INTEGRITY 484 497 * is the output of a hash of the password and the STUN packet's 485 * contents. 498 * contents. 486 499 */ 487 PJ_TODO(CHECK_USERNAME_FOR_INCOMING_STUN_REQUEST); 500 const char *pos; 501 pj_str_t ufrag; 502 503 pos = (const char*)pj_memchr(username->ptr, ':', username->slen); 504 if (pos == NULL) 505 return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_UNKNOWN_USERNAME); 506 507 ufrag.ptr = (char*)username->ptr; 508 ufrag.slen = (pos - username->ptr); 509 510 if (pj_strcmp(&ufrag, &ice->rx_ufrag) != 0) 511 return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_UNKNOWN_USERNAME); 512 488 513 *data_type = 0; 489 514 *data = ice->rx_pass; … … 921 946 * 922 947 * 1. The agent changes the states for all other Frozen pairs for the 923 * same media stream and same foundation to Waiting. Typically 924 * these other pairs will have different component IDs but not 925 * always. 926 */ 927 928 929 /* If there is at least one nominated pair in the valid list: 930 * - The agent MUST remove all Waiting and Frozen pairs in the check 931 * list for the same component as the nominated pairs for that 932 * media stream 933 * - If an In-Progress pair in the check list is for the same 934 * component as a nominated pair, the agent SHOULD cease 935 * retransmissions for its check if its pair priority is lower 936 * than the lowest priority nominated pair for that component 948 * same media stream and same foundation to Waiting. Typically 949 * these other pairs will have different component IDs but not 950 * always. 951 */ 952 if (check->err_code==PJ_SUCCESS) { 953 for (i=0; i<ice->clist.count; ++i) { 954 pj_ice_sess_check *c = &ice->clist.checks[i]; 955 if (pj_strcmp(&c->lcand->foundation, &check->lcand->foundation)==0 956 && c->state == PJ_ICE_SESS_CHECK_STATE_FROZEN) 957 { 958 check_set_state(ice, c, PJ_ICE_SESS_CHECK_STATE_WAITING, 0); 959 } 960 } 961 } 962 963 /* 8.2. Updating States 964 * 965 * For both controlling and controlled agents, the state of ICE 966 * processing depends on the presence of nominated candidate pairs in 967 * the valid list and on the state of the check list: 968 * 969 * o If there are no nominated pairs in the valid list for a media 970 * stream and the state of the check list is Running, ICE processing 971 * continues. 972 * 973 * o If there is at least one nominated pair in the valid list: 974 * 975 * - The agent MUST remove all Waiting and Frozen pairs in the check 976 * list for the same component as the nominated pairs for that 977 * media stream 978 * 979 * - If an In-Progress pair in the check list is for the same 980 * component as a nominated pair, the agent SHOULD cease 981 * retransmissions for its check if its pair priority is lower 982 * than the lowest priority nominated pair for that component 937 983 */ 938 984 if (check->err_code==PJ_SUCCESS && check->nominated) { … … 946 992 947 993 for (i=0; i<ice->clist.count; ++i) { 994 948 995 pj_ice_sess_check *c = &ice->clist.checks[i]; 996 949 997 if (c->lcand->comp_id == check->lcand->comp_id) { 998 950 999 if (c->state < PJ_ICE_SESS_CHECK_STATE_IN_PROGRESS) { 1000 951 1001 /* Just fail Frozen/Waiting check */ 952 1002 LOG5((ice->obj_name, … … 957 1007 PJ_ECANCELLED); 958 1008 959 } else if (c->state == PJ_ICE_SESS_CHECK_STATE_IN_PROGRESS) { 1009 } else if (c->state == PJ_ICE_SESS_CHECK_STATE_IN_PROGRESS 1010 && (PJ_ICE_CANCEL_ALL || 1011 CMP_CHECK_PRIO(c, check) < 0)) { 1012 960 1013 /* State is IN_PROGRESS, cancel transaction */ 961 1014 if (c->tdata) { … … 982 1035 } 983 1036 984 /* Once there is at least one nominated pair in the valid list for 985 * every component of at least one media stream: 986 * - The agent MUST change the state of processing for its check 987 * list for that media stream to Completed. 988 * - The agent MUST continue to respond to any checks it may still 989 * receive for that media stream, and MUST perform triggered 990 * checks if required by the processing of Section 7.2. 991 * - The agent MAY begin transmitting media for this media stream as 992 * described in Section 11.1 993 */ 994 /* TODO */ 995 996 /* Once there is at least one nominated pair in the valid list for 997 * each component of each media stream: 998 * - The agent sets the state of ICE processing overall to 999 * Completed. 1000 * - If an agent is controlling, it examines the highest priority 1001 * nominated candidate pair for each component of each media 1002 * stream. If any of those candidate pairs differ from the 1003 * default candidate pairs in the most recent offer/answer 1004 * exchange, the controlling agent MUST generate an updated offer 1005 * as described in Section 9. If the controlling agent is using 1006 * an aggressive nomination algorithm, this may result in several 1007 * updated offers as the pairs selected for media change. An 1008 * agent MAY delay sending the offer for a brief interval (one 1009 * second is RECOMMENDED) in order to allow the selected pairs to 1010 * stabilize. 1011 */ 1012 /* TODO */ 1013 1037 1038 /* Still in 8.2. Updating States 1039 * 1040 * o Once there is at least one nominated pair in the valid list for 1041 * every component of at least one media stream and the state of the 1042 * check list is Running: 1043 * 1044 * * The agent MUST change the state of processing for its check 1045 * list for that media stream to Completed. 1046 * 1047 * * The agent MUST continue to respond to any checks it may still 1048 * receive for that media stream, and MUST perform triggered 1049 * checks if required by the processing of Section 7.2. 1050 * 1051 * * The agent MAY begin transmitting media for this media stream as 1052 * described in Section 11.1 1053 */ 1014 1054 1015 1055 /* See if all components have nominated pair. If they do, then mark … … 1025 1065 return PJ_TRUE; 1026 1066 } 1067 1068 /* Note: this is the stuffs that we don't do in 7.1.2.2.2, since our 1069 * ICE session only supports one media stream for now: 1070 * 1071 * 7.1.2.2.2. Updating Pair States 1072 * 1073 * 2. If there is a pair in the valid list for every component of this 1074 * media stream (where this is the actual number of components being 1075 * used, in cases where the number of components signaled in the SDP 1076 * differs from offerer to answerer), the success of this check may 1077 * unfreeze checks for other media streams. 1078 */ 1079 1080 /* 7.1.2.3. Check List and Timer State Updates 1081 * Regardless of whether the check was successful or failed, the 1082 * completion of the transaction may require updating of check list and 1083 * timer states. 1084 * 1085 * If all of the pairs in the check list are now either in the Failed or 1086 * Succeeded state, and there is not a pair in the valid list for each 1087 * component of the media stream, the state of the check list is set to 1088 * Failed. 1089 */ 1027 1090 1028 1091 /* … … 1366 1429 } 1367 1430 1368 /* Start ICE check */ 1431 1432 /* 1433 * Start ICE periodic check. This function will return immediately, and 1434 * application will be notified about the connectivity check status in 1435 * #pj_ice_sess_cb callback. 1436 */ 1369 1437 PJ_DEF(pj_status_t) pj_ice_sess_start_check(pj_ice_sess *ice) 1370 1438 { … … 1372 1440 const pj_ice_sess_cand *cand0; 1373 1441 const pj_str_t *flist[PJ_ICE_MAX_CAND]; 1442 pj_ice_rx_check *rcheck; 1374 1443 unsigned i, flist_cnt = 0; 1375 1444 … … 1429 1498 } 1430 1499 1500 /* First, perform all pending triggered checks, simultaneously. */ 1501 rcheck = ice->early_check.next; 1502 while (rcheck != &ice->early_check) { 1503 LOG4((ice->obj_name, 1504 "Performing delayed triggerred check for component %d", 1505 rcheck->comp_id)); 1506 handle_incoming_check(ice, rcheck); 1507 rcheck = rcheck->next; 1508 } 1509 pj_list_init(&ice->early_check); 1510 1431 1511 /* Start periodic check */ 1432 1512 return start_periodic_check(ice->stun_cfg.timer_heap, &clist->timer); … … 1492 1572 1493 1573 if (status==PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_ROLE_CONFLICT)) { 1574 1494 1575 /* Role conclict response. 1576 * 1495 1577 * 7.1.2.1. Failure Cases: 1578 * 1496 1579 * If the request had contained the ICE-CONTROLLED attribute, 1497 1580 * the agent MUST switch to the controlling role if it has not … … 1518 1601 if (new_role != ice->role) { 1519 1602 LOG4((ice->obj_name, 1520 "Changing role because of role conflict "));1603 "Changing role because of role conflict response")); 1521 1604 pj_ice_sess_change_role(ice, new_role); 1522 1605 } … … 1544 1627 1545 1628 1546 /* The agent MUST check that the source IP address and port of the 1629 /* 7.1.2.1. Failure Cases 1630 * 1631 * The agent MUST check that the source IP address and port of the 1547 1632 * response equals the destination IP address and port that the Binding 1548 1633 * Request was sent to, and that the destination IP address and port of … … 1562 1647 } 1563 1648 1649 /* 7.1.2.2. Success Cases 1650 * 1651 * A check is considered to be a success if all of the following are 1652 * true: 1653 * 1654 * o the STUN transaction generated a success response 1655 * 1656 * o the source IP address and port of the response equals the 1657 * destination IP address and port that the Binding Request was sent 1658 * to 1659 * 1660 * o the destination IP address and port of the response match the 1661 * source IP address and port that the Binding Request was sent from 1662 */ 1663 1664 1564 1665 LOG4((ice->obj_name, 1565 1666 "Check %s%s: connectivity check SUCCESS", … … 1588 1689 } 1589 1690 1590 /* If the transport address returned in XOR-MAPPED-ADDRESS does not match 1691 /* 7.1.2.2.1. Discovering Peer Reflexive Candidates 1692 * If the transport address returned in XOR-MAPPED-ADDRESS does not match 1591 1693 * any of the local candidates that the agent knows about, the mapped 1592 1694 * address represents a new candidate - a peer reflexive candidate. … … 1599 1701 &check->lcand->base_addr); 1600 1702 1601 /* According to: 7.1.2.2.1. Discovering Peer Reflexive Candidates:1703 /* Still in 7.1.2.2.1. Discovering Peer Reflexive Candidates 1602 1704 * Its priority is set equal to the value of the PRIORITY attribute 1603 1705 * in the Binding Request. … … 1628 1730 } 1629 1731 1732 /* 7.1.2.2.3. Constructing a Valid Pair 1733 * Next, the agent constructs a candidate pair whose local candidate 1734 * equals the mapped address of the response, and whose remote candidate 1735 * equals the destination address to which the request was sent. 1736 */ 1737 1630 1738 /* Add pair to valid list */ 1739 pj_assert(ice->valid_list.count < PJ_ICE_MAX_CHECKS); 1631 1740 new_check = &ice->valid_list.checks[ice->valid_list.count++]; 1632 1741 new_check->lcand = lcand; … … 1641 1750 1642 1751 1643 /* Sets the state of the original pair that generated the check to 1644 * succeeded. 1752 /* 7.1.2.2.2. Updating Pair States 1753 * 1754 * The agent sets the state of the pair that generated the check to 1755 * Succeeded. The success of this check might also cause the state of 1756 * other checks to change as well. 1645 1757 */ 1646 1758 check_set_state(ice, check, PJ_ICE_SESS_CHECK_STATE_SUCCEEDED, 1647 1759 PJ_SUCCESS); 1648 1760 1649 /* Inform about check completion.1761 /* Perform 7.1.2.2.2. Updating Pair States. 1650 1762 * This may terminate ICE processing. 1651 1763 */ … … 1656 1768 } 1657 1769 1658 /* If the pair had a component ID of 1, the agent MUST change the1659 * states for all other Frozen pairs for the same media stream and1660 * same foundation, but different component IDs, to Waiting.1661 */1662 if (lcand->comp_id == 1) {1663 unsigned i;1664 pj_bool_t unfrozen = PJ_FALSE;1665 1666 for (i=0; i<clist->count; ++i) {1667 pj_ice_sess_check *c = &clist->checks[i];1668 1669 if (c->state == PJ_ICE_SESS_CHECK_STATE_FROZEN &&1670 c->lcand->comp_id != lcand->comp_id &&1671 pj_strcmp(&c->lcand->foundation, &lcand->foundation)==0)1672 {1673 /* Unfreeze and start check */1674 check_set_state(ice, c, PJ_ICE_SESS_CHECK_STATE_WAITING,1675 PJ_SUCCESS);1676 unfrozen = PJ_TRUE;1677 }1678 }1679 1680 if (unfrozen && clist->timer.id == PJ_FALSE)1681 start_periodic_check(ice->stun_cfg.timer_heap, &clist->timer);1682 }1683 1684 /* If the pair had a component ID equal to the number of components1685 * for the media stream (where this is the actual number of1686 * components being used, in cases where the number of components1687 * signaled in the SDP differs from offerer to answerer), the agent1688 * MUST change the state for all other Frozen pairs for the first1689 * component of different media streams (and thus in different check1690 * lists) but the same foundation, to Waiting.1691 */1692 else if (0) {1693 PJ_TODO(UNFREEZE_OTHER_COMPONENT_ID);1694 }1695 /* If the pair has any other component ID, no other pairs can be1696 * unfrozen.1697 */1698 else {1699 PJ_TODO(UNFREEZE_OTHER_COMPONENT_ID1);1700 }1701 1702 1770 pj_mutex_unlock(ice->mutex); 1703 1771 } 1772 1704 1773 1705 1774 /* This callback is called by the STUN session associated with a candidate … … 1715 1784 stun_data *sd; 1716 1785 pj_ice_sess *ice; 1717 pj_stun_priority_attr *ap; 1718 pj_stun_use_candidate_attr *uc; 1719 pj_ice_sess_comp *comp; 1720 pj_ice_sess_cand *lcand = NULL; 1721 pj_ice_sess_cand *rcand; 1722 unsigned i; 1786 pj_stun_priority_attr *prio_attr; 1787 pj_stun_use_candidate_attr *uc_attr; 1788 pj_stun_uint64_attr *role_attr; 1723 1789 pj_stun_tx_data *tdata; 1724 pj_ bool_t is_relayed;1790 pj_ice_rx_check *rcheck, tmp_rcheck; 1725 1791 pj_status_t status; 1726 1792 … … 1743 1809 sd = (stun_data*) pj_stun_session_get_user_data(sess); 1744 1810 ice = sd->ice; 1745 comp = sd->comp;1746 1811 1747 1812 pj_mutex_lock(ice->mutex); 1748 1813 1814 /* 1815 * Note: 1816 * Be aware that when STUN request is received, we might not get 1817 * SDP answer yet, so we might not have remote candidates and 1818 * checklist yet. This case will be handled after we send 1819 * a response. 1820 */ 1821 1749 1822 /* Get PRIORITY attribute */ 1750 ap= (pj_stun_priority_attr*)1751 pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_PRIORITY, 0);1752 if ( ap == 0) {1823 prio_attr = (pj_stun_priority_attr*) 1824 pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_PRIORITY, 0); 1825 if (prio_attr == NULL) { 1753 1826 LOG5((ice->obj_name, "Received Binding request with no PRIORITY")); 1754 1827 pj_mutex_unlock(ice->mutex); … … 1757 1830 1758 1831 /* Get USE-CANDIDATE attribute */ 1759 uc = (pj_stun_use_candidate_attr*) 1760 pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_USE_CANDIDATE, 0); 1761 1762 /* For simplicity, ignore incoming requests when we don't have remote 1763 * candidates yet. The peer agent should retransmit the STUN request 1764 * and we'll receive it again later. 1765 */ 1766 if (ice->rcand_cnt == 0) { 1767 pj_mutex_unlock(ice->mutex); 1768 return PJ_SUCCESS; 1769 } 1832 uc_attr = (pj_stun_use_candidate_attr*) 1833 pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_USE_CANDIDATE, 0); 1834 1835 1836 /* Get ICE-CONTROLLING or ICE-CONTROLLED */ 1837 role_attr = (pj_stun_uint64_attr*) 1838 pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_ICE_CONTROLLING, 0); 1839 if (role_attr == NULL) { 1840 role_attr = (pj_stun_uint64_attr*) 1841 pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_ICE_CONTROLLED, 0); 1842 } 1843 1844 /* 7.2.1.1. Detecting and Repairing Role Conflicts 1845 */ 1846 if (ice->role == PJ_ICE_SESS_ROLE_CONTROLLING && 1847 role_attr && role_attr->hdr.type == PJ_STUN_ATTR_ICE_CONTROLLING) 1848 { 1849 if (pj_cmp_timestamp(&ice->tie_breaker, &role_attr->value) < 0) { 1850 /* Switch role to controlled */ 1851 LOG4((ice->obj_name, 1852 "Changing role because of ICE-CONTROLLING attribute")); 1853 pj_ice_sess_change_role(ice, PJ_ICE_SESS_ROLE_CONTROLLED); 1854 } else { 1855 /* Generate 487 response */ 1856 status = pj_stun_session_create_response(sess, msg, 1857 PJ_STUN_SC_ROLE_CONFLICT, 1858 NULL, &tdata); 1859 if (status == PJ_SUCCESS) { 1860 pj_stun_session_send_msg(sess, PJ_TRUE, 1861 src_addr, src_addr_len, tdata); 1862 } 1863 pj_mutex_unlock(ice->mutex); 1864 return PJ_SUCCESS; 1865 } 1866 1867 } else if (ice->role == PJ_ICE_SESS_ROLE_CONTROLLED && 1868 role_attr && role_attr->hdr.type == PJ_STUN_ATTR_ICE_CONTROLLED) 1869 { 1870 if (pj_cmp_timestamp(&ice->tie_breaker, &role_attr->value) < 0) { 1871 /* Generate 487 response */ 1872 status = pj_stun_session_create_response(sess, msg, 1873 PJ_STUN_SC_ROLE_CONFLICT, 1874 NULL, &tdata); 1875 if (status == PJ_SUCCESS) { 1876 pj_stun_session_send_msg(sess, PJ_TRUE, 1877 src_addr, src_addr_len, tdata); 1878 } 1879 pj_mutex_unlock(ice->mutex); 1880 return PJ_SUCCESS; 1881 } else { 1882 /* Switch role to controlled */ 1883 LOG4((ice->obj_name, 1884 "Changing role because of ICE-CONTROLLED attribute")); 1885 pj_ice_sess_change_role(ice, PJ_ICE_SESS_ROLE_CONTROLLING); 1886 } 1887 } 1888 1770 1889 1771 1890 /* … … 1786 1905 1787 1906 1907 /* 1908 * Handling early check. 1909 * 1910 * It's possible that we receive this request before we receive SDP 1911 * answer. In this case, we can't perform trigger check since we 1912 * don't have checklist yet, so just save this check in a pending 1913 * triggered check array to be acted upon later. 1914 */ 1915 if (ice->rcand_cnt == 0) { 1916 rcheck = PJ_POOL_ZALLOC_T(ice->pool, pj_ice_rx_check); 1917 } else { 1918 rcheck = &tmp_rcheck; 1919 } 1920 1921 /* Init rcheck */ 1922 rcheck->comp_id = sd->comp_id; 1923 rcheck->src_addr_len = src_addr_len; 1924 pj_memcpy(&rcheck->src_addr, src_addr, src_addr_len); 1925 rcheck->use_candidate = (uc_attr != NULL); 1926 rcheck->priority = prio_attr->value; 1927 rcheck->role_attr = role_attr; 1928 1929 if (ice->rcand_cnt == 0) { 1930 /* We don't have answer yet, so keep this request for later */ 1931 LOG4((ice->obj_name, "Received an early check for comp %d", 1932 rcheck->comp_id)); 1933 pj_list_push_back(&ice->early_check, rcheck); 1934 } else { 1935 /* Handle this check */ 1936 handle_incoming_check(ice, rcheck); 1937 } 1938 1939 pj_mutex_unlock(ice->mutex); 1940 return PJ_SUCCESS; 1941 } 1942 1943 1944 /* Handle incoming Binding request and perform triggered check. 1945 * This function may be called by on_stun_rx_request(), or when 1946 * SDP answer is received and we have received early checks. 1947 */ 1948 static void handle_incoming_check(pj_ice_sess *ice, 1949 const pj_ice_rx_check *rcheck) 1950 { 1951 pj_ice_sess_comp *comp; 1952 pj_ice_sess_cand *lcand = NULL; 1953 pj_ice_sess_cand *rcand; 1954 unsigned i; 1955 pj_bool_t is_relayed; 1956 1957 comp = find_comp(ice, rcheck->comp_id); 1958 1788 1959 /* Find remote candidate based on the source transport address of 1789 1960 * the request. 1790 1961 */ 1791 1962 for (i=0; i<ice->rcand_cnt; ++i) { 1792 if (sockaddr_cmp( (const pj_sockaddr*)src_addr, &ice->rcand[i].addr)==0)1963 if (sockaddr_cmp(&rcheck->src_addr, &ice->rcand[i].addr)==0) 1793 1964 break; 1794 1965 } 1795 1966 1796 /* If the source transport address of the request does not match any 1967 /* 7.2.1.3. Learning Peer Reflexive Candidates 1968 * If the source transport address of the request does not match any 1797 1969 * existing remote candidates, it represents a new peer reflexive remote 1798 1970 * candidate. … … 1800 1972 if (i == ice->rcand_cnt) { 1801 1973 rcand = &ice->rcand[ice->rcand_cnt++]; 1802 rcand->comp_id = sd->comp_id;1974 rcand->comp_id = rcheck->comp_id; 1803 1975 rcand->type = PJ_ICE_CAND_TYPE_PRFLX; 1804 rcand->prio = ap->value;1805 pj_memcpy(&rcand->addr, src_addr,src_addr_len);1976 rcand->prio = rcheck->priority; 1977 pj_memcpy(&rcand->addr, &rcheck->src_addr, rcheck->src_addr_len); 1806 1978 1807 1979 /* Foundation is random, unique from other foundation */ 1808 rcand->foundation.ptr = pj_pool_alloc(ice->pool, 3 2);1809 rcand->foundation.slen = pj_ansi_snprintf(rcand->foundation.ptr, 3 2,1980 rcand->foundation.ptr = pj_pool_alloc(ice->pool, 36); 1981 rcand->foundation.slen = pj_ansi_snprintf(rcand->foundation.ptr, 36, 1810 1982 "f%p", 1811 1983 rcand->foundation.ptr); … … 1843 2015 for (i=0; i<ice->clist.count; ++i) { 1844 2016 pj_ice_sess_check *c = &ice->clist.checks[i]; 1845 if (c->lcand->comp_id == sd->comp_id) {2017 if (c->lcand->comp_id == rcheck->comp_id) { 1846 2018 lcand = c->lcand; 1847 2019 break; 1848 2020 } 1849 2021 } 1850 pj_assert(lcand != NULL); 2022 if (lcand == NULL) { 2023 /* Should not happen, but just in case remote is sending a 2024 * Binding request for a component which it doesn't have. 2025 */ 2026 LOG4((ice->obj_name, 2027 "Received Binding request but no local candidate is found!")); 2028 return; 2029 } 1851 2030 #endif 1852 2031 … … 1860 2039 is_relayed = PJ_FALSE; 1861 2040 1862 /* Now that we have local and remote candidate, check if we already 2041 /* 2042 * 7.2.1.4. Triggered Checks 2043 * 2044 * Now that we have local and remote candidate, check if we already 1863 2045 * have this pair in our checklist. 1864 2046 */ … … 1888 2070 * Note: DO NOT overwrite nominated flag if one is already set. 1889 2071 */ 1890 c->nominated = (( uc != NULL) || c->nominated);2072 c->nominated = ((rcheck->use_candidate) || c->nominated); 1891 2073 1892 2074 if (c->state == PJ_ICE_SESS_CHECK_STATE_FROZEN || … … 1897 2079 1898 2080 } else if (c->state == PJ_ICE_SESS_CHECK_STATE_IN_PROGRESS) { 1899 /* Should retransmit here, but how?? 1900 * TODO 2081 /* Should retransmit immediately 1901 2082 */ 1902 2083 LOG5((ice->obj_name, "Triggered check for check %d not performed " 1903 "because it's in progress", i)); 2084 "because it's in progress. Retransmitting", i)); 2085 pj_stun_session_retransmit_req(comp->stun_sess, c->tdata); 2086 1904 2087 } else if (c->state == PJ_ICE_SESS_CHECK_STATE_SUCCEEDED) { 1905 2088 /* Check complete for this component. … … 1913 2096 complete = on_check_complete(ice, c); 1914 2097 if (complete) { 1915 pj_mutex_unlock(ice->mutex); 1916 return PJ_SUCCESS; 2098 return; 1917 2099 } 1918 2100 } … … 1933 2115 c->prio = CALC_CHECK_PRIO(ice, lcand, rcand); 1934 2116 c->state = PJ_ICE_SESS_CHECK_STATE_WAITING; 1935 c->nominated = (uc != NULL);2117 c->nominated = rcheck->use_candidate; 1936 2118 c->err_code = PJ_SUCCESS; 1937 2119 … … 1944 2126 "TOO MANY CHECKS IN CHECKLIST!")); 1945 2127 } 1946 1947 pj_mutex_unlock(ice->mutex);1948 return status;1949 2128 } 1950 2129 -
pjproject/trunk/pjnath/src/pjnath/stun_msg_dump.c
r1126 r1152 228 228 229 229 len = pj_ansi_snprintf(p, end-p, 230 " Hdr: length=%d, magic=%08x, tsx_id=%08x %08x%08x\n"230 " Hdr: length=%d, magic=%08x, tsx_id=%08x%08x%08x\n" 231 231 " Attributes:\n", 232 232 msg->hdr.length, -
pjproject/trunk/pjnath/src/pjnath/stun_session.c
r1151 r1152 711 711 pj_mutex_unlock(sess->mutex); 712 712 return PJ_SUCCESS; 713 714 } 713 } 714 715 /* 716 * Explicitly request retransmission of the request. 717 */ 718 PJ_DEF(pj_status_t) pj_stun_session_retransmit_req(pj_stun_session *sess, 719 pj_stun_tx_data *tdata) 720 { 721 pj_status_t status; 722 723 PJ_ASSERT_RETURN(sess && tdata, PJ_EINVAL); 724 PJ_ASSERT_RETURN(PJ_STUN_IS_REQUEST(tdata->msg->hdr.type), PJ_EINVAL); 725 726 pj_mutex_lock(sess->mutex); 727 728 status = pj_stun_client_tsx_retransmit(tdata->client_tsx); 729 730 pj_mutex_unlock(sess->mutex); 731 732 return status; 733 } 734 715 735 716 736 /* Send response */ -
pjproject/trunk/pjnath/src/pjnath/stun_transaction.c
r1141 r1152 295 295 } 296 296 297 /* 298 * Request to retransmit the request. 299 */ 300 PJ_DEF(pj_status_t) pj_stun_client_tsx_retransmit(pj_stun_client_tsx *tsx) 301 { 302 if (tsx->destroy_timer.id != 0) { 303 return PJ_SUCCESS; 304 } 305 306 if (tsx->retransmit_timer.id != 0) { 307 pj_timer_heap_cancel(tsx->cfg->timer_heap, &tsx->retransmit_timer); 308 tsx->retransmit_timer.id = 0; 309 } 310 311 return tsx_transmit_msg(tsx); 312 } 297 313 298 314 /* Timer callback to destroy transaction */ -
pjproject/trunk/pjnath/src/pjstun-client/client_main.c
r1151 r1152 30 30 #define REQ_IP NULL /* IP address string */ 31 31 32 #define OPTIONS PJ_STUN_NO_AUTHENTICATE 32 //#define OPTIONS PJ_STUN_NO_AUTHENTICATE 33 #define OPTIONS 0 34 33 35 34 36 static struct global
Note: See TracChangeset
for help on using the changeset viewer.