Changeset 1140 for pjproject/trunk
- Timestamp:
- Apr 3, 2007 6:01:27 PM (18 years ago)
- Location:
- pjproject/trunk
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/src/pjmedia/transport_ice.c
r1126 r1140 435 435 pj_bool_t remote_is_lite = PJ_FALSE; 436 436 pj_bool_t ice_mismatch = PJ_FALSE; 437 pjmedia_sdp_conn *conn = NULL; 438 pj_sockaddr conn_addr; 439 pj_bool_t conn_found_in_candidate = PJ_FALSE; 437 440 const pj_str_t STR_CANDIDATE = {"candidate", 9}; 438 441 const pj_str_t STR_ICE_LITE = {"ice-lite", 8}; … … 445 448 446 449 sdp_med = rem_sdp->media[media_index]; 450 451 /* Get the SDP connection for the media stream. 452 * We'll verify later if the SDP connection address is specified 453 * as one of the candidate. 454 */ 455 conn = sdp_med->conn; 456 if (conn == NULL) 457 conn = rem_sdp->conn; 458 459 if (conn == NULL) { 460 /* Unable to find SDP connection */ 461 return PJMEDIA_SDP_EMISSINGCONN; 462 } 463 464 pj_sockaddr_in_init(&conn_addr.ipv4, &conn->addr, 465 (pj_uint16_t)sdp_med->desc.port); 447 466 448 467 /* Find ice-ufrag attribute in session descriptor */ … … 481 500 attr = sdp_med->attr[i]; 482 501 502 /* Detect if remote is ICE lite */ 483 503 if (pj_strcmp(&attr->name, &STR_ICE_LITE)==0) { 484 504 remote_is_lite = PJ_TRUE; … … 486 506 } 487 507 508 /* Detect if remote has reported ICE mismatch */ 488 509 if (pj_strcmp(&attr->name, &STR_ICE_MISMATCH)==0) { 489 510 ice_mismatch = PJ_TRUE; … … 494 515 continue; 495 516 517 /* Parse candidate */ 496 518 status = parse_cand(pool, &attr->value, &cand[cand_cnt]); 497 519 if (status != PJ_SUCCESS) 498 520 return status; 499 521 522 /* Check if this candidate is equal to the connection line */ 523 if (!conn_found_in_candidate && 524 pj_memcmp(&conn_addr.ipv4, &cand[cand_cnt].addr.ipv4, 525 sizeof(pj_sockaddr_in))==0) 526 { 527 conn_found_in_candidate = PJ_TRUE; 528 } 529 500 530 cand_cnt++; 501 531 } … … 503 533 /* Handle ice-mismatch case */ 504 534 if (ice_mismatch) { 505 set_no_ice(tp_ice, "ice-mismatch detected"); 535 set_no_ice(tp_ice, "remote reported ice-mismatch"); 536 return PJ_SUCCESS; 537 } 538 539 /* Handle case where SDP connection address is not specified as 540 * one of the candidate. 541 */ 542 if (!conn_found_in_candidate) { 543 set_no_ice(tp_ice, "local reported ice-mismatch"); 506 544 return PJ_SUCCESS; 507 545 } … … 658 696 char dst_addr[32]; 659 697 698 pj_gettimeofday(&end_ice); 699 PJ_TIME_VAL_SUB(end_ice, tp_ice->start_ice); 700 660 701 if (status != PJ_SUCCESS) { 661 702 char errmsg[PJ_ERR_MSG_SIZE]; 662 703 pj_strerror(status, errmsg, sizeof(errmsg)); 663 PJ_LOG(1,(ice_st->obj_name, "ICE negotiation failed: %s", errmsg)); 704 PJ_LOG(1,(ice_st->obj_name, 705 "ICE negotiation failed after %d:%03ds: %s", 706 (int)end_ice.sec, (int)end_ice.msec, 707 errmsg)); 664 708 return; 665 709 } 666 667 pj_gettimeofday(&end_ice);668 PJ_TIME_VAL_SUB(end_ice, tp_ice->start_ice);669 710 670 711 check = &ice_st->ice->valid_list.checks[0]; -
pjproject/trunk/pjnath/include/pjnath/config.h
r1126 r1140 165 165 166 166 167 /** 168 * Minimum interval value to be used for sending STUN keep-alive on the ICE 169 * stream transport, in seconds. This minimum interval, plus a random value 170 * which maximum is PJ_ICE_ST_KEEP_ALIVE_MAX_RAND, specify the actual interval 171 * of the STUN keep-alive. 172 * 173 * Default: 20 seconds 174 * 175 * @see PJ_ICE_ST_KEEP_ALIVE_MAX_RAND 176 */ 177 #ifndef PJ_ICE_ST_KEEP_ALIVE_MIN 178 # define PJ_ICE_ST_KEEP_ALIVE_MIN 20 179 #endif 180 181 182 /** 183 * To prevent STUN keep-alives to be sent simultaneously, application should 184 * add random interval to minimum interval (PJ_ICE_ST_KEEP_ALIVE_MIN). This 185 * setting specifies the maximum random value to be added to the minimum 186 * interval, in seconds. 187 * 188 * Default: 5 seconds 189 * 190 * @see PJ_ICE_ST_KEEP_ALIVE_MIN 191 */ 192 #ifndef PJ_ICE_ST_KEEP_ALIVE_MAX_RAND 193 # define PJ_ICE_ST_KEEP_ALIVE_MAX_RAND 5 194 #endif 195 196 197 167 198 168 199 /** -
pjproject/trunk/pjnath/include/pjnath/ice_session.h
r1129 r1140 120 120 */ 121 121 pj_ice_sess_check *valid_check; 122 123 /** 124 * The STUN session to be used to send and receive STUN messages for this 125 * component. 126 */ 127 pj_stun_session *stun_sess; 122 128 123 129 } pj_ice_sess_comp; … … 188 194 pj_sockaddr rel_addr; 189 195 190 /**191 * The STUN session to be used to send and receive STUN messages for this192 * candidate.193 */194 pj_stun_session *stun_sess;195 196 196 } pj_ice_sess_cand; 197 197 … … 367 367 * @param ice The ICE session. 368 368 * @param comp_id ICE component ID. 369 * @param cand_id ICE candidate ID.370 369 * @param pkt The STUN packet. 371 370 * @param size The size of the packet. … … 374 373 */ 375 374 pj_status_t (*on_tx_pkt)(pj_ice_sess *ice, unsigned comp_id, 376 unsigned cand_id,377 375 const void *pkt, pj_size_t size, 378 376 const pj_sockaddr_t *dst_addr, … … 696 694 * @param ice The ICE session. 697 695 * @param comp_id Component ID. 698 * @param cand_id Candidate ID.699 696 * @param pkt Incoming packet. 700 697 * @param pkt_size Size of incoming packet. … … 706 703 PJ_DECL(pj_status_t) pj_ice_sess_on_rx_pkt(pj_ice_sess *ice, 707 704 unsigned comp_id, 708 unsigned cand_id,709 705 void *pkt, 710 706 pj_size_t pkt_size, -
pjproject/trunk/pjnath/include/pjnath/ice_strans.h
r1114 r1140 275 275 276 276 pj_stun_session *stun_sess; /**< STUN session. */ 277 pj_uint8_t ka_tsx_id[12]; /**< ID for keep STUN alives */ 277 278 278 279 pj_sockaddr local_addr; /**< Local/base address. */ -
pjproject/trunk/pjnath/include/pjnath/stun_session.h
r1110 r1140 246 246 * @param msg_type The STUN request message type, from pj_stun_method_e or 247 247 * from pj_stun_msg_type. 248 * @param tsx_id Optional transaction ID. 248 249 * @param p_tdata Pointer to receive STUN transmit data instance containing 249 250 * the request. … … 253 254 PJ_DECL(pj_status_t) pj_stun_session_create_req(pj_stun_session *sess, 254 255 int msg_type, 256 const pj_uint8_t tsx_id[12], 255 257 pj_stun_tx_data **p_tdata); 256 258 -
pjproject/trunk/pjnath/include/pjnath/stun_transaction.h
r1110 r1140 91 91 pj_size_t pkt_size); 92 92 93 /** 94 * This callback is called after the timer that was scheduled by 95 * #pj_stun_client_tsx_schedule_destroy() has elapsed. Application 96 * should call #pj_stun_client_tsx_destroy() upon receiving this 97 * callback. 98 * 99 * This callback is optional if application will not call 100 * #pj_stun_client_tsx_schedule_destroy(). 101 * 102 * @param tsx The STUN transaction instance. 103 */ 104 void (*on_destroy)(pj_stun_client_tsx *tsx); 105 93 106 } pj_stun_tsx_cb; 94 107 … … 117 130 118 131 /** 119 * Destroy a STUN client transaction. 132 * Schedule timer to destroy the transaction after the transaction is 133 * complete. Application normally calls this function in the on_complete() 134 * callback. When this timer elapsed, the on_destroy() callback will be 135 * called. 136 * 137 * This is convenient to let the STUN transaction absorbs any response 138 * for the previous request retransmissions. If application doesn't want 139 * this, it can destroy the transaction immediately by calling 140 * #pj_stun_client_tsx_destroy(). 141 * 142 * @param tsx The STUN transaction. 143 * @param delay The delay interval before on_destroy() callback 144 * is called. 145 * 146 * @return PJ_SUCCESS on success, or the appropriate error code. 147 */ 148 PJ_DECL(pj_status_t) 149 pj_stun_client_tsx_schedule_destroy(pj_stun_client_tsx *tsx, 150 const pj_time_val *delay); 151 152 153 /** 154 * Destroy a STUN client transaction immediately. This function can be 155 * called at any time to stop the transaction and destroy it. 120 156 * 121 157 * @param tsx The STUN transaction. -
pjproject/trunk/pjnath/src/pjnath/ice_session.c
r1129 r1140 84 84 { 85 85 pj_ice_sess *ice; 86 pj_ice_sess_cand *lcand; 86 unsigned comp_id; 87 pj_ice_sess_comp *comp; 87 88 } stun_data; 88 89 … … 180 181 181 182 183 /* Init component */ 184 static pj_status_t init_comp(pj_ice_sess *ice, 185 unsigned comp_id, 186 pj_ice_sess_comp *comp) 187 { 188 pj_stun_session_cb sess_cb; 189 pj_stun_auth_cred auth_cred; 190 stun_data *sd; 191 pj_status_t status; 192 193 /* Init STUN callbacks */ 194 pj_bzero(&sess_cb, sizeof(sess_cb)); 195 sess_cb.on_request_complete = &on_stun_request_complete; 196 sess_cb.on_rx_indication = &on_stun_rx_indication; 197 sess_cb.on_rx_request = &on_stun_rx_request; 198 sess_cb.on_send_msg = &on_stun_send_msg; 199 200 /* Create STUN session for this candidate */ 201 status = pj_stun_session_create(&ice->stun_cfg, NULL, 202 &sess_cb, PJ_FALSE, 203 &comp->stun_sess); 204 if (status != PJ_SUCCESS) 205 return status; 206 207 /* Associate data with this STUN session */ 208 sd = PJ_POOL_ZALLOC_T(ice->pool, struct stun_data); 209 sd->ice = ice; 210 sd->comp_id = comp_id; 211 sd->comp = comp; 212 pj_stun_session_set_user_data(comp->stun_sess, sd); 213 214 /* Init STUN authentication credential */ 215 pj_bzero(&auth_cred, sizeof(auth_cred)); 216 auth_cred.type = PJ_STUN_AUTH_CRED_DYNAMIC; 217 auth_cred.data.dyn_cred.get_auth = &stun_auth_get_auth; 218 auth_cred.data.dyn_cred.get_cred = &stun_auth_get_cred; 219 auth_cred.data.dyn_cred.get_password = &stun_auth_get_password; 220 auth_cred.data.dyn_cred.user_data = comp->stun_sess; 221 pj_stun_session_set_credential(comp->stun_sess, &auth_cred); 222 223 return PJ_SUCCESS; 224 } 225 226 182 227 /* 183 228 * Create ICE session. … … 228 273 comp = &ice->comp[i]; 229 274 comp->valid_check = NULL; 275 276 status = init_comp(ice, i+1, comp); 277 if (status != PJ_SUCCESS) { 278 destroy_ice(ice, status); 279 return status; 280 } 230 281 } 231 282 … … 233 284 ice->rx_ufrag.ptr = pj_pool_alloc(ice->pool, 16); 234 285 pj_create_random_string(ice->rx_ufrag.ptr, 16); 286 ice->rx_ufrag.slen = 16; 235 287 } else { 236 288 pj_strdup(ice->pool, &ice->rx_ufrag, local_ufrag); … … 240 292 ice->rx_pass.ptr = pj_pool_alloc(ice->pool, 16); 241 293 pj_create_random_string(ice->rx_pass.ptr, 16); 294 ice->rx_pass.slen = 16; 242 295 } else { 243 296 pj_strdup(ice->pool, &ice->rx_pass, local_passwd); … … 268 321 } 269 322 270 for (i=0; i<ice-> lcand_cnt; ++i) {271 if (ice-> lcand[i].stun_sess) {272 pj_stun_session_destroy(ice-> lcand[i].stun_sess);273 ice-> lcand[i].stun_sess = NULL;323 for (i=0; i<ice->comp_cnt; ++i) { 324 if (ice->comp[i].stun_sess) { 325 pj_stun_session_destroy(ice->comp[i].stun_sess); 326 ice->comp[i].stun_sess = NULL; 274 327 } 275 328 } … … 466 519 { 467 520 pj_ice_sess_cand *lcand; 468 pj_stun_session_cb sess_cb;469 pj_stun_auth_cred auth_cred;470 stun_data *sd;471 521 pj_status_t status = PJ_SUCCESS; 472 522 char tmp[128]; … … 495 545 else 496 546 pj_bzero(&lcand->rel_addr, sizeof(lcand->rel_addr)); 497 498 499 /* Init STUN callbacks */500 pj_bzero(&sess_cb, sizeof(sess_cb));501 sess_cb.on_request_complete = &on_stun_request_complete;502 sess_cb.on_rx_indication = &on_stun_rx_indication;503 sess_cb.on_rx_request = &on_stun_rx_request;504 sess_cb.on_send_msg = &on_stun_send_msg;505 506 /* Create STUN session for this candidate */507 status = pj_stun_session_create(&ice->stun_cfg, ice->obj_name,508 &sess_cb, PJ_FALSE,509 &lcand->stun_sess);510 if (status != PJ_SUCCESS) {511 pj_mutex_unlock(ice->mutex);512 return status;513 }514 515 /* Associate data with this STUN session */516 sd = PJ_POOL_ZALLOC_T(ice->pool, struct stun_data);517 sd->ice = ice;518 sd->lcand = lcand;519 pj_stun_session_set_user_data(lcand->stun_sess, sd);520 521 /* Init STUN authentication credential */522 pj_bzero(&auth_cred, sizeof(auth_cred));523 auth_cred.type = PJ_STUN_AUTH_CRED_DYNAMIC;524 auth_cred.data.dyn_cred.get_auth = &stun_auth_get_auth;525 auth_cred.data.dyn_cred.get_cred = &stun_auth_get_cred;526 auth_cred.data.dyn_cred.get_password = &stun_auth_get_password;527 auth_cred.data.dyn_cred.user_data = lcand->stun_sess;528 pj_stun_session_set_credential(lcand->stun_sess, &auth_cred);529 547 530 548 … … 909 927 GET_CHECK_ID(&ice->clist, check))); 910 928 929 comp = find_comp(ice, check->lcand->comp_id); 930 911 931 for (i=0; i<ice->clist.count; ++i) { 912 932 pj_ice_sess_check *c = &ice->clist.checks[i]; … … 927 947 "Cancelling check %s (In Progress)", 928 948 dump_check(buf, sizeof(buf), &ice->clist, c))); 929 pj_stun_session_cancel_req(c ->lcand->stun_sess,949 pj_stun_session_cancel_req(comp->stun_sess, 930 950 c->tdata, PJ_FALSE, 0); 931 951 c->tdata = NULL; … … 938 958 939 959 /* Update the nominated check for the component */ 940 comp = find_comp(ice, check->lcand->comp_id);941 960 if (comp->valid_check == NULL) { 942 961 comp->valid_check = check; … … 1165 1184 1166 1185 /* Create request */ 1167 status = pj_stun_session_create_req( lcand->stun_sess,1186 status = pj_stun_session_create_req(comp->stun_sess, 1168 1187 PJ_STUN_BINDING_REQUEST, 1169 &check->tdata);1188 NULL, &check->tdata); 1170 1189 if (status != PJ_SUCCESS) { 1171 1190 pjnath_perror(ice->obj_name, "Error creating STUN request", status); … … 1200 1219 1201 1220 /* Initiate STUN transaction to send the request */ 1202 status = pj_stun_session_send_msg( lcand->stun_sess, PJ_FALSE,1221 status = pj_stun_session_send_msg(comp->stun_sess, PJ_FALSE, 1203 1222 &rcand->addr, 1204 1223 sizeof(pj_sockaddr_in), check->tdata); … … 1400 1419 stun_data *sd = (stun_data*) pj_stun_session_get_user_data(sess); 1401 1420 pj_ice_sess *ice = sd->ice; 1402 return (*sd->ice->cb.on_tx_pkt)(sd->ice, sd->lcand->comp_id, 1403 GET_LCAND_ID(sd->lcand), 1404 pkt, pkt_size, 1405 dst_addr, addr_len); 1421 return (*ice->cb.on_tx_pkt)(ice, sd->comp_id, 1422 pkt, pkt_size, 1423 dst_addr, addr_len); 1406 1424 } 1407 1425 … … 1600 1618 pj_stun_use_candidate_attr *uc; 1601 1619 pj_ice_sess_comp *comp; 1602 pj_ice_sess_cand *lcand ;1620 pj_ice_sess_cand *lcand = NULL; 1603 1621 pj_ice_sess_cand *rcand; 1604 1622 unsigned i; … … 1625 1643 sd = (stun_data*) pj_stun_session_get_user_data(sess); 1626 1644 ice = sd->ice; 1627 lcand = sd->lcand; 1628 comp = find_comp(ice, lcand->comp_id); 1645 comp = sd->comp; 1629 1646 1630 1647 pj_mutex_lock(ice->mutex); … … 1683 1700 if (i == ice->rcand_cnt) { 1684 1701 rcand = &ice->rcand[ice->rcand_cnt++]; 1685 rcand->comp_id = lcand->comp_id;1702 rcand->comp_id = sd->comp_id; 1686 1703 rcand->type = PJ_ICE_CAND_TYPE_PRFLX; 1687 1704 rcand->prio = ap->value; … … 1703 1720 rcand = &ice->rcand[i]; 1704 1721 } 1722 1723 #if 0 1724 /* Find again the local candidate by matching the base address 1725 * with the local candidates in the checklist. Checks may have 1726 * been pruned before, so it's possible that if we use the lcand 1727 * as it is, we wouldn't be able to find the check in the checklist 1728 * and we will end up creating a new check unnecessarily. 1729 */ 1730 for (i=0; i<ice->clist.count; ++i) { 1731 pj_ice_sess_check *c = &ice->clist.checks[i]; 1732 if (/*c->lcand == lcand ||*/ 1733 sockaddr_cmp(&c->lcand->base_addr, &lcand->base_addr)==0) 1734 { 1735 lcand = c->lcand; 1736 break; 1737 } 1738 } 1739 #else 1740 /* Just get candidate with the highest priority for the specified 1741 * component ID in the checklist. 1742 */ 1743 for (i=0; i<ice->clist.count; ++i) { 1744 pj_ice_sess_check *c = &ice->clist.checks[i]; 1745 if (c->lcand->comp_id == sd->comp_id) { 1746 lcand = c->lcand; 1747 break; 1748 } 1749 } 1750 pj_assert(lcand != NULL); 1751 #endif 1705 1752 1706 1753 /* … … 1823 1870 1824 1871 1825 PJ_DEF(pj_status_t) pj_ice_sess_send_data( 1826 1827 1828 1872 PJ_DEF(pj_status_t) pj_ice_sess_send_data(pj_ice_sess *ice, 1873 unsigned comp_id, 1874 const void *data, 1875 pj_size_t data_len) 1829 1876 { 1830 1877 pj_status_t status = PJ_SUCCESS; 1831 1878 pj_ice_sess_comp *comp; 1832 unsigned cand_id;1833 1879 1834 1880 PJ_ASSERT_RETURN(ice && comp_id && comp_id <= ice->comp_cnt, PJ_EINVAL); … … 1847 1893 } 1848 1894 1849 cand_id = GET_LCAND_ID(comp->valid_check->lcand); 1850 status = (*ice->cb.on_tx_pkt)(ice, comp_id, cand_id, data, data_len, 1895 status = (*ice->cb.on_tx_pkt)(ice, comp_id, data, data_len, 1851 1896 &comp->valid_check->rcand->addr, 1852 1897 sizeof(pj_sockaddr_in)); … … 1858 1903 1859 1904 1860 PJ_DEF(pj_status_t) pj_ice_sess_on_rx_pkt( pj_ice_sess *ice, 1861 unsigned comp_id, 1862 unsigned cand_id, 1863 void *pkt, 1864 pj_size_t pkt_size, 1865 const pj_sockaddr_t *src_addr, 1866 int src_addr_len) 1905 PJ_DEF(pj_status_t) pj_ice_sess_on_rx_pkt(pj_ice_sess *ice, 1906 unsigned comp_id, 1907 void *pkt, 1908 pj_size_t pkt_size, 1909 const pj_sockaddr_t *src_addr, 1910 int src_addr_len) 1867 1911 { 1868 1912 pj_status_t status = PJ_SUCCESS; 1869 1913 pj_ice_sess_comp *comp; 1870 pj_ice_sess_cand *lcand;1871 1914 pj_status_t stun_status; 1872 1915 … … 1881 1924 } 1882 1925 1883 lcand = &ice->lcand[cand_id];1884 1885 1926 stun_status = pj_stun_msg_check(pkt, pkt_size, PJ_STUN_IS_DATAGRAM); 1886 1927 if (stun_status == PJ_SUCCESS) { 1887 status = pj_stun_session_on_rx_pkt( lcand->stun_sess, pkt, pkt_size,1928 status = pj_stun_session_on_rx_pkt(comp->stun_sess, pkt, pkt_size, 1888 1929 PJ_STUN_IS_DATAGRAM, 1889 1930 NULL, src_addr, src_addr_len); -
pjproject/trunk/pjnath/src/pjnath/ice_strans.c
r1126 r1140 24 24 #include <pj/log.h> 25 25 #include <pj/pool.h> 26 #include <pj/rand.h> 26 27 #include <pj/string.h> 28 29 30 #if 0 31 # define TRACE_PKT(expr) PJ_LOG(5,expr) 32 #else 33 # define TRACE_PKT(expr) 34 #endif 27 35 28 36 … … 31 39 static void on_ice_complete(pj_ice_sess *ice, pj_status_t status); 32 40 static pj_status_t ice_tx_pkt(pj_ice_sess *ice, 33 unsigned comp_id, unsigned cand_id,41 unsigned comp_id, 34 42 const void *pkt, pj_size_t size, 35 43 const pj_sockaddr_t *dst_addr, … … 85 93 86 94 if (name == NULL) 87 name = "ic est%p";95 name = "icstr%p"; 88 96 89 97 pool = pj_pool_create(stun_cfg->pf, name, 4000, 4000, NULL); … … 243 251 pj_ice_strans_comp *comp; 244 252 int retry, addr_len; 253 struct { 254 pj_uint32_t a1, a2, a3; 255 } tsx_id; 245 256 pj_status_t status; 246 257 … … 251 262 comp->sock = PJ_INVALID_SOCKET; 252 263 comp->last_status = PJ_SUCCESS; 264 265 /* Create transaction ID for STUN keep alives */ 266 tsx_id.a1 = 0; 267 tsx_id.a2 = comp_id; 268 tsx_id.a3 = (pj_uint32_t) ice_st; 269 pj_memcpy(comp->ka_tsx_id, &tsx_id, sizeof(comp->ka_tsx_id)); 253 270 254 271 /* Create socket */ … … 438 455 * The process below is just a workaround. 439 456 */ 440 if (ice_st->ice) { 441 PJ_TODO(DISTINGUISH_BETWEEN_LOCAL_AND_RELAY); 442 status = pj_ice_sess_on_rx_pkt(ice_st->ice, comp->comp_id, 443 comp->cand_list[0].ice_cand_id, 444 comp->pkt, bytes_read, 445 &comp->src_addr, comp->src_addr_len); 446 } else if (comp->stun_sess) { 447 status = pj_stun_msg_check(comp->pkt, bytes_read, 448 PJ_STUN_IS_DATAGRAM); 449 if (status == PJ_SUCCESS) { 457 status = pj_stun_msg_check(comp->pkt, bytes_read, 458 PJ_STUN_IS_DATAGRAM); 459 460 if (status == PJ_SUCCESS) { 461 if (ice_st->ice==NULL || 462 pj_memcmp(comp->pkt+8, comp->ka_tsx_id, 12) == 0) 463 { 450 464 status = pj_stun_session_on_rx_pkt(comp->stun_sess, comp->pkt, 451 465 bytes_read, … … 454 468 comp->src_addr_len); 455 469 } else { 456 (*ice_st->cb.on_rx_data)(ice_st, comp->comp_id, 457 comp->pkt, bytes_read, 458 &comp->src_addr, comp->src_addr_len); 459 470 PJ_TODO(DISTINGUISH_BETWEEN_LOCAL_AND_RELAY); 471 472 TRACE_PKT((comp->ice_st->obj_name, 473 "Component %d RX packet from %s:%d", 474 comp->comp_id, 475 pj_inet_ntoa(comp->src_addr.ipv4.sin_addr), 476 (int)pj_ntohs(comp->src_addr.ipv4.sin_port))); 477 478 status = pj_ice_sess_on_rx_pkt(ice_st->ice, comp->comp_id, 479 comp->pkt, bytes_read, 480 &comp->src_addr, 481 comp->src_addr_len); 460 482 } 461 483 } else { … … 528 550 /* Create STUN binding request */ 529 551 status = pj_stun_session_create_req(comp->stun_sess, 530 PJ_STUN_BINDING_REQUEST, &tdata); 552 PJ_STUN_BINDING_REQUEST, 553 comp->ka_tsx_id, &tdata); 531 554 if (status != PJ_SUCCESS) 532 555 continue; … … 555 578 return; 556 579 557 delay.sec = 20; 558 delay.msec = 0; 580 delay.sec = PJ_ICE_ST_KEEP_ALIVE_MIN; 581 delay.msec = pj_rand() % (PJ_ICE_ST_KEEP_ALIVE_MAX_RAND * 1000); 582 pj_time_val_normalize(&delay); 559 583 560 584 ice_st->ka_timer.cb = &ka_timer_cb; … … 617 641 /* Create STUN binding request */ 618 642 status = pj_stun_session_create_req(comp->stun_sess, 619 PJ_STUN_BINDING_REQUEST, &tdata); 643 PJ_STUN_BINDING_REQUEST, 644 comp->ka_tsx_id, 645 &tdata); 620 646 if (status != PJ_SUCCESS) 621 647 return status; … … 945 971 */ 946 972 static pj_status_t ice_tx_pkt(pj_ice_sess *ice, 947 unsigned comp_id, unsigned cand_id,973 unsigned comp_id, 948 974 const void *pkt, pj_size_t size, 949 975 const pj_sockaddr_t *dst_addr, … … 959 985 PJ_ASSERT_RETURN(comp_id && comp_id <= ice_st->comp_cnt, PJ_EINVAL); 960 986 comp = ice_st->comp[comp_id-1]; 987 988 TRACE_PKT((comp->ice_st->obj_name, 989 "Component %d TX packet to %s:%d", 990 comp_id, 991 pj_inet_ntoa(((pj_sockaddr_in*)dst_addr)->sin_addr), 992 (int)pj_ntohs(((pj_sockaddr_in*)dst_addr)->sin_port))); 961 993 962 994 pkt_size = size; … … 1027 1059 if (cand == NULL) { 1028 1060 /* This is keep-alive */ 1061 if (status != PJ_SUCCESS) { 1062 ice_st_perror(comp->ice_st, "STUN keep-alive request failed", 1063 status); 1064 } 1029 1065 return; 1030 1066 } -
pjproject/trunk/pjnath/src/pjnath/stun_session.c
r1126 r1140 50 50 51 51 52 static void tsx_on_complete(pj_stun_client_tsx *tsx, 53 pj_status_t status, 54 const pj_stun_msg *response); 55 static pj_status_t tsx_on_send_msg(pj_stun_client_tsx *tsx, 56 const void *stun_pkt, 57 pj_size_t pkt_size); 52 static void stun_tsx_on_complete(pj_stun_client_tsx *tsx, 53 pj_status_t status, 54 const pj_stun_msg *response); 55 static pj_status_t stun_tsx_on_send_msg(pj_stun_client_tsx *tsx, 56 const void *stun_pkt, 57 pj_size_t pkt_size); 58 static void stun_tsx_on_destroy(pj_stun_client_tsx *tsx); 58 59 59 60 static pj_stun_tsx_cb tsx_cb = 60 61 { 61 &tsx_on_complete, 62 &tsx_on_send_msg 62 &stun_tsx_on_complete, 63 &stun_tsx_on_send_msg, 64 &stun_tsx_on_destroy 63 65 }; 64 66 … … 121 123 static pj_status_t create_request_tdata(pj_stun_session *sess, 122 124 unsigned msg_type, 125 const pj_uint8_t tsx_id[12], 123 126 pj_stun_tx_data **p_tdata) 124 127 { … … 132 135 /* Create STUN message */ 133 136 status = pj_stun_msg_create(tdata->pool, msg_type, PJ_STUN_MAGIC, 134 NULL, &tdata->msg);137 tsx_id, &tdata->msg); 135 138 if (status != PJ_SUCCESS) { 136 139 pj_pool_release(tdata->pool); … … 149 152 } 150 153 154 155 static void stun_tsx_on_destroy(pj_stun_client_tsx *tsx) 156 { 157 pj_stun_tx_data *tdata; 158 159 tdata = (pj_stun_tx_data*) pj_stun_client_tsx_get_data(tsx); 160 pj_stun_client_tsx_destroy(tsx); 161 pj_pool_release(tdata->pool); 162 } 163 151 164 static void destroy_tdata(pj_stun_tx_data *tdata) 152 165 { 153 if (tdata->client_tsx) {154 tsx_erase(tdata->sess, tdata);155 pj_stun_client_tsx_destroy(tdata->client_tsx);156 tdata->client_tsx = NULL;157 }158 166 if (tdata->res_timer.id != PJ_FALSE) { 159 167 pj_timer_heap_cancel(tdata->sess->cfg->timer_heap, … … 162 170 pj_list_erase(tdata); 163 171 } 164 pj_pool_release(tdata->pool); 172 173 if (tdata->client_tsx) { 174 pj_time_val delay = {2, 0}; 175 tsx_erase(tdata->sess, tdata); 176 pj_stun_client_tsx_schedule_destroy(tdata->client_tsx, &delay); 177 tdata->client_tsx = NULL; 178 179 } else { 180 pj_pool_release(tdata->pool); 181 } 165 182 } 166 183 … … 307 324 308 325 309 static void tsx_on_complete(pj_stun_client_tsx *tsx,310 311 326 static void stun_tsx_on_complete(pj_stun_client_tsx *tsx, 327 pj_status_t status, 328 const pj_stun_msg *response) 312 329 { 313 330 pj_stun_tx_data *tdata; … … 321 338 } 322 339 323 static pj_status_t tsx_on_send_msg(pj_stun_client_tsx *tsx,324 325 340 static pj_status_t stun_tsx_on_send_msg(pj_stun_client_tsx *tsx, 341 const void *stun_pkt, 342 pj_size_t pkt_size) 326 343 { 327 344 pj_stun_tx_data *tdata; … … 442 459 PJ_DEF(pj_status_t) pj_stun_session_create_req(pj_stun_session *sess, 443 460 int method, 461 const pj_uint8_t tsx_id[12], 444 462 pj_stun_tx_data **p_tdata) 445 463 { … … 449 467 PJ_ASSERT_RETURN(sess && p_tdata, PJ_EINVAL); 450 468 451 status = create_request_tdata(sess, method, &tdata);469 status = create_request_tdata(sess, method, tsx_id, &tdata); 452 470 if (status != PJ_SUCCESS) 453 471 return status; … … 766 784 tdata = tsx_lookup(sess, msg); 767 785 if (tdata == NULL) { 768 PJ_LOG( 5,(SNAME(sess),786 PJ_LOG(4,(SNAME(sess), 769 787 "Transaction not found, response silently discarded")); 770 788 return PJ_SUCCESS; -
pjproject/trunk/pjnath/src/pjnath/stun_transaction.c
r1126 r1140 37 37 38 38 pj_bool_t complete; 39 \ 39 40 40 pj_bool_t require_retransmit; 41 pj_timer_entry timer;41 pj_timer_entry retransmit_timer; 42 42 unsigned transmit_count; 43 43 pj_time_val retransmit_time; 44 45 pj_timer_entry destroy_timer; 44 46 45 47 void *last_pkt; … … 50 52 static void retransmit_timer_callback(pj_timer_heap_t *timer_heap, 51 53 pj_timer_entry *timer); 54 static void destroy_timer_callback(pj_timer_heap_t *timer_heap, 55 pj_timer_entry *timer); 52 56 53 57 #define stun_perror(tsx,msg,rc) pjnath_perror(tsx->obj_name, msg, rc) … … 70 74 pj_memcpy(&tsx->cb, cb, sizeof(*cb)); 71 75 72 tsx->timer.cb = &retransmit_timer_callback; 73 tsx->timer.user_data = tsx; 76 tsx->retransmit_timer.cb = &retransmit_timer_callback; 77 tsx->retransmit_timer.user_data = tsx; 78 79 tsx->destroy_timer.cb = &destroy_timer_callback; 80 tsx->destroy_timer.user_data = tsx; 74 81 75 82 pj_ansi_snprintf(tsx->obj_name, sizeof(tsx->obj_name), "stuntsx%p", tsx); … … 82 89 83 90 84 /* 85 * . 91 PJ_DEF(pj_status_t) 92 pj_stun_client_tsx_schedule_destroy(pj_stun_client_tsx *tsx, 93 const pj_time_val *delay) 94 { 95 pj_status_t status; 96 97 PJ_ASSERT_RETURN(tsx && delay, PJ_EINVAL); 98 PJ_ASSERT_RETURN(tsx->cb.on_destroy, PJ_EINVAL); 99 100 /* Cancel previously registered timer */ 101 if (tsx->destroy_timer.id != 0) { 102 pj_timer_heap_cancel(tsx->cfg->timer_heap, &tsx->destroy_timer); 103 tsx->destroy_timer.id = 0; 104 } 105 106 /* Stop retransmission, just in case */ 107 if (tsx->retransmit_timer.id != 0) { 108 pj_timer_heap_cancel(tsx->cfg->timer_heap, &tsx->retransmit_timer); 109 tsx->retransmit_timer.id = 0; 110 } 111 112 status = pj_timer_heap_schedule(tsx->cfg->timer_heap, 113 &tsx->destroy_timer, delay); 114 if (status != PJ_SUCCESS) 115 return status; 116 117 tsx->destroy_timer.id = TIMER_ACTIVE; 118 119 return PJ_SUCCESS; 120 } 121 122 123 /* 124 * Destroy transaction immediately. 86 125 */ 87 126 PJ_DEF(pj_status_t) pj_stun_client_tsx_destroy(pj_stun_client_tsx *tsx) … … 89 128 PJ_ASSERT_RETURN(tsx, PJ_EINVAL); 90 129 91 if (tsx->timer.id != 0) { 92 pj_timer_heap_cancel(tsx->cfg->timer_heap, &tsx->timer); 93 tsx->timer.id = 0; 94 } 130 if (tsx->retransmit_timer.id != 0) { 131 pj_timer_heap_cancel(tsx->cfg->timer_heap, &tsx->retransmit_timer); 132 tsx->retransmit_timer.id = 0; 133 } 134 if (tsx->destroy_timer.id != 0) { 135 pj_timer_heap_cancel(tsx->cfg->timer_heap, &tsx->destroy_timer); 136 tsx->destroy_timer.id = 0; 137 } 138 139 PJ_LOG(5,(tsx->obj_name, "STUN client transaction destroyed")); 95 140 return PJ_SUCCESS; 96 141 } … … 136 181 pj_status_t status; 137 182 138 PJ_ASSERT_RETURN(tsx-> timer.id == 0, PJ_EBUSY);183 PJ_ASSERT_RETURN(tsx->retransmit_timer.id == 0, PJ_EBUSY); 139 184 140 185 if (tsx->require_retransmit) { … … 161 206 * cancel transmission). 162 207 */; 163 status = pj_timer_heap_schedule(tsx->cfg->timer_heap, &tsx->timer, 208 status = pj_timer_heap_schedule(tsx->cfg->timer_heap, 209 &tsx->retransmit_timer, 164 210 &tsx->retransmit_time); 165 211 if (status != PJ_SUCCESS) { 166 tsx-> timer.id = 0;212 tsx->retransmit_timer.id = 0; 167 213 return status; 168 214 } 169 tsx-> timer.id = TIMER_ACTIVE;215 tsx->retransmit_timer.id = TIMER_ACTIVE; 170 216 } 171 217 … … 174 220 status = tsx->cb.on_send_msg(tsx, tsx->last_pkt, tsx->last_pkt_size); 175 221 if (status != PJ_SUCCESS) { 176 if (tsx->timer.id != 0) { 177 pj_timer_heap_cancel(tsx->cfg->timer_heap, &tsx->timer); 178 tsx->timer.id = 0; 222 if (tsx->retransmit_timer.id != 0) { 223 pj_timer_heap_cancel(tsx->cfg->timer_heap, 224 &tsx->retransmit_timer); 225 tsx->retransmit_timer.id = 0; 179 226 } 180 227 stun_perror(tsx, "STUN error sending message", status); … … 199 246 { 200 247 PJ_ASSERT_RETURN(tsx && pkt && pkt_len, PJ_EINVAL); 201 PJ_ASSERT_RETURN(tsx-> timer.id == 0, PJ_EBUSY);248 PJ_ASSERT_RETURN(tsx->retransmit_timer.id == 0, PJ_EBUSY); 202 249 203 250 /* Encode message */ … … 224 271 if (tsx->transmit_count >= PJ_STUN_MAX_RETRANSMIT_COUNT) { 225 272 /* Retransmission count exceeded. Transaction has failed */ 226 tsx-> timer.id = 0;273 tsx->retransmit_timer.id = 0; 227 274 PJ_LOG(4,(tsx->obj_name, "STUN timeout waiting for response")); 228 tsx->complete = PJ_TRUE; 229 if (tsx->cb.on_complete) { 230 tsx->cb.on_complete(tsx, PJNATH_ESTUNTIMEDOUT, NULL); 275 if (!tsx->complete) { 276 tsx->complete = PJ_TRUE; 277 if (tsx->cb.on_complete) { 278 tsx->cb.on_complete(tsx, PJNATH_ESTUNTIMEDOUT, NULL); 279 } 231 280 } 232 281 return; 233 282 } 234 283 235 tsx-> timer.id = 0;284 tsx->retransmit_timer.id = 0; 236 285 status = tsx_transmit_msg(tsx); 237 286 if (status != PJ_SUCCESS) { 238 tsx->timer.id = 0; 239 tsx->complete = PJ_TRUE; 240 if (tsx->cb.on_complete) { 241 tsx->cb.on_complete(tsx, status, NULL); 242 } 243 } 244 } 245 287 tsx->retransmit_timer.id = 0; 288 if (!tsx->complete) { 289 tsx->complete = PJ_TRUE; 290 if (tsx->cb.on_complete) { 291 tsx->cb.on_complete(tsx, status, NULL); 292 } 293 } 294 } 295 } 296 297 298 /* Timer callback to destroy transaction */ 299 static void destroy_timer_callback(pj_timer_heap_t *timer_heap, 300 pj_timer_entry *timer) 301 { 302 pj_stun_client_tsx *tsx = (pj_stun_client_tsx *) timer->user_data; 303 304 PJ_UNUSED_ARG(timer_heap); 305 306 tsx->destroy_timer.id = PJ_FALSE; 307 tsx->cb.on_destroy(tsx); 308 /* Don't access transaction after this */ 309 } 246 310 247 311 … … 268 332 * We can cancel retransmit timer now. 269 333 */ 270 if (tsx-> timer.id) {271 pj_timer_heap_cancel(tsx->cfg->timer_heap, &tsx-> timer);272 tsx-> timer.id = 0;334 if (tsx->retransmit_timer.id) { 335 pj_timer_heap_cancel(tsx->cfg->timer_heap, &tsx->retransmit_timer); 336 tsx->retransmit_timer.id = 0; 273 337 } 274 338 … … 297 361 298 362 /* Call callback */ 299 tsx->complete = PJ_TRUE; 300 if (tsx->cb.on_complete) { 301 tsx->cb.on_complete(tsx, status, msg); 302 } 303 304 return PJ_SUCCESS; 305 306 } 307 363 if (!tsx->complete) { 364 tsx->complete = PJ_TRUE; 365 if (tsx->cb.on_complete) { 366 tsx->cb.on_complete(tsx, status, msg); 367 } 368 } 369 370 return PJ_SUCCESS; 371 372 } 373
Note: See TracChangeset
for help on using the changeset viewer.