Changeset 1988 for pjproject/trunk/pjnath/src/pjnath/ice_session.c
- Timestamp:
- Jun 6, 2008 2:47:10 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjnath/src/pjnath/ice_session.c
r1913 r1988 22 22 #include <pj/assert.h> 23 23 #include <pj/guid.h> 24 #include <pj/hash.h> 24 25 #include <pj/log.h> 25 26 #include <pj/os.h> … … 100 101 pj_ice_sess_checklist *clist; 101 102 } timer_data; 103 104 105 /* This is the data that will be attached as token to outgoing 106 * STUN messages. 107 */ 102 108 103 109 … … 170 176 171 177 178 PJ_DEF(const char*) pj_ice_sess_role_name(pj_ice_sess_role role) 179 { 180 switch (role) { 181 case PJ_ICE_SESS_ROLE_UNKNOWN: 182 return "Unknown"; 183 case PJ_ICE_SESS_ROLE_CONTROLLED: 184 return "Controlled"; 185 case PJ_ICE_SESS_ROLE_CONTROLLING: 186 return "Controlling"; 187 default: 188 return "??"; 189 } 190 } 191 192 172 193 /* Get the prefix for the foundation */ 173 194 static int get_type_prefix(pj_ice_cand_type type) … … 184 205 } 185 206 186 /* Calculate foundation */ 207 /* Calculate foundation: 208 * Two candidates have the same foundation when they are "similar" - of 209 * the same type and obtained from the same host candidate and STUN 210 * server using the same protocol. Otherwise, their foundation is 211 * different. 212 */ 187 213 PJ_DEF(void) pj_ice_calc_foundation(pj_pool_t *pool, 188 214 pj_str_t *foundation, … … 191 217 { 192 218 char buf[64]; 193 219 pj_uint32_t val; 220 221 if (base_addr->addr.sa_family == pj_AF_INET()) { 222 val = pj_ntohl(base_addr->ipv4.sin_addr.s_addr); 223 } else { 224 val = pj_hash_calc(0, pj_sockaddr_get_addr(base_addr), 225 pj_sockaddr_get_addr_len(base_addr)); 226 } 194 227 pj_ansi_snprintf(buf, sizeof(buf), "%c%x", 195 get_type_prefix(type), 196 (int)pj_ntohl(base_addr->ipv4.sin_addr.s_addr)); 228 get_type_prefix(type), val); 197 229 pj_strdup2(pool, foundation, buf); 198 230 } … … 264 296 265 297 if (name == NULL) 266 name = "ice %p";298 name = "icess%p"; 267 299 268 300 pool = pj_pool_create(stun_cfg->pf, name, PJNATH_POOL_LEN_ICE_SESS, … … 299 331 return status; 300 332 } 333 } 334 335 /* Initialize transport datas */ 336 for (i=0; i<PJ_ARRAY_SIZE(ice->tp_data); ++i) { 337 ice->tp_data[i].transport_id = i; 338 ice->tp_data[i].has_req_data = PJ_FALSE; 301 339 } 302 340 … … 552 590 PJ_DEF(pj_status_t) pj_ice_sess_add_cand(pj_ice_sess *ice, 553 591 unsigned comp_id, 592 unsigned transport_id, 554 593 pj_ice_cand_type type, 555 594 pj_uint16_t local_pref, … … 577 616 578 617 lcand = &ice->lcand[ice->lcand_cnt]; 579 lcand->comp_id = comp_id; 618 lcand->comp_id = (pj_uint8_t)comp_id; 619 lcand->transport_id = (pj_uint8_t)transport_id; 580 620 lcand->type = type; 581 621 pj_strdup(ice->pool, &lcand->foundation, foundation); … … 583 623 pj_memcpy(&lcand->addr, addr, addr_len); 584 624 pj_memcpy(&lcand->base_addr, base_addr, addr_len); 585 if (rel_addr) 586 pj_memcpy(&lcand->rel_addr, rel_addr, addr_len); 587 else 588 pj_bzero(&lcand->rel_addr, sizeof(lcand->rel_addr)); 589 625 pj_memcpy(&lcand->rel_addr, rel_addr, addr_len); 590 626 591 627 pj_ansi_strcpy(ice->tmp.txt, pj_inet_ntoa(lcand->addr.ipv4.sin_addr)); … … 1323 1359 1324 1360 /* Disable our components which don't have matching component */ 1325 if (ice->comp_cnt==2 && highest_comp==1) { 1326 ice->comp_cnt = 1; 1327 } 1361 for (i=highest_comp; i<ice->comp_cnt; ++i) { 1362 if (ice->comp[i].stun_sess) { 1363 pj_stun_session_destroy(ice->comp[i].stun_sess); 1364 pj_bzero(&ice->comp[i], sizeof(ice->comp[i])); 1365 } 1366 } 1367 ice->comp_cnt = highest_comp; 1328 1368 1329 1369 /* Init timer entry in the checklist. Initially the timer ID is FALSE … … 1346 1386 } 1347 1387 1348 1349 /* This is the data that will be attached as user data to outgoing1350 * STUN requests, and it will be given back when we receive completion1351 * status of the request.1352 */1353 struct req_data1354 {1355 pj_ice_sess *ice;1356 pj_ice_sess_checklist *clist;1357 unsigned ckid;1358 };1359 1360 1361 1388 /* Perform check on the specified candidate pair */ 1362 1389 static pj_status_t perform_check(pj_ice_sess *ice, … … 1365 1392 { 1366 1393 pj_ice_sess_comp *comp; 1367 struct req_data *rd;1394 pj_ice_msg_data *msg_data; 1368 1395 pj_ice_sess_check *check; 1369 1396 const pj_ice_sess_cand *lcand; … … 1393 1420 * completes and on_stun_request_complete() callback is called. 1394 1421 */ 1395 rd = PJ_POOL_ZALLOC_T(check->tdata->pool, struct req_data); 1396 rd->ice = ice; 1397 rd->clist = clist; 1398 rd->ckid = check_id; 1422 msg_data = PJ_POOL_ZALLOC_T(check->tdata->pool, pj_ice_msg_data); 1423 msg_data->transport_id = lcand->transport_id; 1424 msg_data->has_req_data = PJ_TRUE; 1425 msg_data->data.req.ice = ice; 1426 msg_data->data.req.clist = clist; 1427 msg_data->data.req.ckid = check_id; 1399 1428 1400 1429 /* Add PRIORITY */ … … 1428 1457 1429 1458 /* Initiate STUN transaction to send the request */ 1430 status = pj_stun_session_send_msg(comp->stun_sess, (void*)rd, PJ_FALSE,1459 status = pj_stun_session_send_msg(comp->stun_sess, msg_data, PJ_FALSE, 1431 1460 PJ_TRUE, &rcand->addr, 1432 1461 sizeof(pj_sockaddr_in), check->tdata); … … 1656 1685 stun_data *sd = (stun_data*) pj_stun_session_get_user_data(sess); 1657 1686 pj_ice_sess *ice = sd->ice; 1658 1659 PJ_UNUSED_ARG(token); 1660 1661 return (*ice->cb.on_tx_pkt)(ice, sd->comp_id, 1662 pkt, pkt_size, 1663 dst_addr, addr_len); 1687 pj_ice_msg_data *msg_data = (pj_ice_msg_data*) token; 1688 1689 return (*ice->cb.on_tx_pkt)(ice, sd->comp_id, msg_data->transport_id, 1690 pkt, pkt_size, dst_addr, addr_len); 1664 1691 } 1665 1692 … … 1674 1701 unsigned src_addr_len) 1675 1702 { 1676 struct req_data *rd = (struct req_data*) token;1703 pj_ice_msg_data *msg_data = (pj_ice_msg_data*) token; 1677 1704 pj_ice_sess *ice; 1678 1705 pj_ice_sess_check *check, *new_check; … … 1685 1712 PJ_UNUSED_ARG(src_addr_len); 1686 1713 1687 ice = rd->ice; 1688 check = &rd->clist->checks[rd->ckid]; 1689 clist = rd->clist; 1714 pj_assert(msg_data->has_req_data); 1715 1716 ice = msg_data->data.req.ice; 1717 clist = msg_data->data.req.clist; 1718 check = &clist->checks[msg_data->data.req.ckid]; 1719 1690 1720 1691 1721 /* Mark STUN transaction as complete */ … … 1740 1770 LOG4((ice->obj_name, "Resending check because of role conflict")); 1741 1771 check_set_state(ice, check, PJ_ICE_SESS_CHECK_STATE_WAITING, 0); 1742 perform_check(ice, clist, rd->ckid);1772 perform_check(ice, clist, msg_data->data.req.ckid); 1743 1773 pj_mutex_unlock(ice->mutex); 1744 1774 return; … … 1847 1877 /* Add new peer reflexive candidate */ 1848 1878 status = pj_ice_sess_add_cand(ice, check->lcand->comp_id, 1879 msg_data->transport_id, 1849 1880 PJ_ICE_CAND_TYPE_PRFLX, 1850 1881 65535, &foundation, … … 1920 1951 stun_data *sd; 1921 1952 const pj_stun_msg *msg = rdata->msg; 1953 pj_ice_msg_data *msg_data; 1922 1954 pj_ice_sess *ice; 1923 1955 pj_stun_priority_attr *prio_attr; … … 1930 1962 PJ_UNUSED_ARG(pkt); 1931 1963 PJ_UNUSED_ARG(pkt_len); 1932 PJ_UNUSED_ARG(token); 1933 1964 1934 1965 /* Reject any requests except Binding request */ 1935 1966 if (msg->hdr.type != PJ_STUN_BINDING_REQUEST) { 1936 1967 pj_stun_session_respond(sess, rdata, PJ_STUN_SC_BAD_REQUEST, 1937 NULL, NULL, PJ_TRUE,1968 NULL, token, PJ_TRUE, 1938 1969 src_addr, src_addr_len); 1939 1970 return PJ_SUCCESS; … … 2002 2033 /* Generate 487 response */ 2003 2034 pj_stun_session_respond(sess, rdata, PJ_STUN_SC_ROLE_CONFLICT, 2004 NULL, NULL, PJ_TRUE,2035 NULL, token, PJ_TRUE, 2005 2036 src_addr, src_addr_len); 2006 2037 pj_mutex_unlock(ice->mutex); … … 2014 2045 /* Generate 487 response */ 2015 2046 pj_stun_session_respond(sess, rdata, PJ_STUN_SC_ROLE_CONFLICT, 2016 NULL, NULL, PJ_TRUE,2047 NULL, token, PJ_TRUE, 2017 2048 src_addr, src_addr_len); 2018 2049 pj_mutex_unlock(ice->mutex); … … 2035 2066 } 2036 2067 2068 /* Add XOR-MAPPED-ADDRESS attribute */ 2037 2069 status = pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg, 2038 2070 PJ_STUN_ATTR_XOR_MAPPED_ADDR, 2039 2071 PJ_TRUE, src_addr, src_addr_len); 2040 2072 2041 status = pj_stun_session_send_msg(sess, NULL, PJ_TRUE, PJ_TRUE, 2073 /* Create a msg_data to be associated with this response */ 2074 msg_data = PJ_POOL_ZALLOC_T(tdata->pool, pj_ice_msg_data); 2075 msg_data->transport_id = ((pj_ice_msg_data*)token)->transport_id; 2076 msg_data->has_req_data = PJ_FALSE; 2077 2078 /* Send the response */ 2079 status = pj_stun_session_send_msg(sess, msg_data, PJ_TRUE, PJ_TRUE, 2042 2080 src_addr, src_addr_len, tdata); 2043 2081 … … 2059 2097 /* Init rcheck */ 2060 2098 rcheck->comp_id = sd->comp_id; 2099 rcheck->transport_id = ((pj_ice_msg_data*)token)->transport_id; 2061 2100 rcheck->src_addr_len = src_addr_len; 2062 2101 pj_memcpy(&rcheck->src_addr, src_addr, src_addr_len); … … 2091 2130 pj_ice_sess_cand *rcand; 2092 2131 unsigned i; 2093 pj_bool_t is_relayed;2094 2132 2095 2133 comp = find_comp(ice, rcheck->comp_id); … … 2110 2148 if (i == ice->rcand_cnt) { 2111 2149 rcand = &ice->rcand[ice->rcand_cnt++]; 2112 rcand->comp_id = rcheck->comp_id;2150 rcand->comp_id = (pj_uint8_t)rcheck->comp_id; 2113 2151 rcand->type = PJ_ICE_CAND_TYPE_PRFLX; 2114 2152 rcand->prio = rcheck->priority; … … 2148 2186 } 2149 2187 #else 2150 /* Just get candidate with the highest priority for the specified2151 * component ID in the checklist.2188 /* Just get candidate with the highest priority and same transport ID 2189 * for the specified component ID in the checklist. 2152 2190 */ 2153 2191 for (i=0; i<ice->clist.count; ++i) { 2154 2192 pj_ice_sess_check *c = &ice->clist.checks[i]; 2155 if (c->lcand->comp_id == rcheck->comp_id) { 2193 if (c->lcand->comp_id == rcheck->comp_id && 2194 c->lcand->transport_id == rcheck->transport_id) 2195 { 2156 2196 lcand = c->lcand; 2157 2197 break; … … 2171 2211 * Create candidate pair for this request. 2172 2212 */ 2173 /* First check if the source address is the source address of the2174 * STUN relay, to determine if local candidate is relayed candidate.2175 */2176 PJ_TODO(DETERMINE_IF_REQUEST_COMES_FROM_RELAYED_CANDIDATE);2177 is_relayed = PJ_FALSE;2178 2213 2179 2214 /* … … 2310 2345 pj_status_t status = PJ_SUCCESS; 2311 2346 pj_ice_sess_comp *comp; 2347 pj_ice_sess_cand *cand; 2312 2348 2313 2349 PJ_ASSERT_RETURN(ice && comp_id, PJ_EINVAL); … … 2333 2369 } 2334 2370 2335 status = (*ice->cb.on_tx_pkt)(ice, comp_id, data, data_len, 2371 cand = comp->valid_check->lcand; 2372 status = (*ice->cb.on_tx_pkt)(ice, comp_id, cand->transport_id, 2373 data, data_len, 2336 2374 &comp->valid_check->rcand->addr, 2337 2375 sizeof(pj_sockaddr_in)); … … 2345 2383 PJ_DEF(pj_status_t) pj_ice_sess_on_rx_pkt(pj_ice_sess *ice, 2346 2384 unsigned comp_id, 2385 unsigned transport_id, 2347 2386 void *pkt, 2348 2387 pj_size_t pkt_size, … … 2352 2391 pj_status_t status = PJ_SUCCESS; 2353 2392 pj_ice_sess_comp *comp; 2393 pj_ice_msg_data *msg_data = NULL; 2394 unsigned i; 2354 2395 pj_status_t stun_status; 2355 2396 … … 2364 2405 } 2365 2406 2407 /* Find transport */ 2408 for (i=0; i<PJ_ARRAY_SIZE(ice->tp_data); ++i) { 2409 if (ice->tp_data[i].transport_id == transport_id) { 2410 msg_data = &ice->tp_data[i]; 2411 break; 2412 } 2413 } 2414 if (msg_data == NULL) { 2415 pj_assert(!"Invalid transport ID"); 2416 status = PJ_EINVAL; 2417 goto on_return; 2418 } 2419 2366 2420 stun_status = pj_stun_msg_check((const pj_uint8_t*)pkt, pkt_size, 2367 2421 PJ_STUN_IS_DATAGRAM); 2368 2422 if (stun_status == PJ_SUCCESS) { 2369 2423 status = pj_stun_session_on_rx_pkt(comp->stun_sess, pkt, pkt_size, 2370 PJ_STUN_IS_DATAGRAM, NULL,2424 PJ_STUN_IS_DATAGRAM, msg_data, 2371 2425 NULL, src_addr, src_addr_len); 2372 2426 if (status != PJ_SUCCESS) { … … 2376 2430 } 2377 2431 } else { 2378 (*ice->cb.on_rx_data)(ice, comp_id, pkt, pkt_size,2432 (*ice->cb.on_rx_data)(ice, comp_id, transport_id, pkt, pkt_size, 2379 2433 src_addr, src_addr_len); 2380 2434 }
Note: See TracChangeset
for help on using the changeset viewer.