- Timestamp:
- Mar 20, 2007 8:44:26 AM (18 years ago)
- Location:
- pjproject/trunk/pjnath
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjnath/build/pjnath.dsp
r1080 r1085 42 42 # PROP Target_Dir "" 43 43 # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c 44 # ADD CPP /nologo /MD /W4 /GX /Zi /O2 /Ob2 /I "../include" /I "../../pjlib/include" / D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /FD /c44 # ADD CPP /nologo /MD /W4 /GX /Zi /O2 /Ob2 /I "../include" /I "../../pjlib/include" /I "../../pjlib-util/include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /FD /c 45 45 # SUBTRACT CPP /YX 46 46 # ADD BASE RSC /l 0x409 /d "NDEBUG" … … 66 66 # PROP Target_Dir "" 67 67 # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c 68 # ADD CPP /nologo /MTd /W4 /Gm /GX /ZI /Od /I "../include" /I "../../pjlib/include" / D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /FD /GZ /c68 # ADD CPP /nologo /MTd /W4 /Gm /GX /ZI /Od /I "../include" /I "../../pjlib/include" /I "../../pjlib-util/include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /FD /GZ /c 69 69 # SUBTRACT CPP /YX 70 70 # ADD BASE RSC /l 0x409 /d "_DEBUG" -
pjproject/trunk/pjnath/include/pjnath/ice.h
r1080 r1085 25 25 */ 26 26 #include <pjnath/types.h> 27 #include <pjnath/stun_ endpoint.h>27 #include <pjnath/stun_session.h> 28 28 #include <pjlib-util/resolver.h> 29 29 #include <pj/sock.h> … … 65 65 66 66 67 #define PJ_ICE_MAX_CAND 3267 #define PJ_ICE_MAX_CAND 16 68 68 #define PJ_ICE_MAX_COMP 8 69 69 #define PJ_ICE_MAX_CHECKS 32 70 70 71 71 /** … … 105 105 typedef struct pj_ice_check 106 106 { 107 unsigned local_cand_id; 107 unsigned cand_id; 108 pj_uint32_t comp_id; 109 pj_str_t foundation; 110 108 111 pj_uint64_t check_prio; 109 112 pj_ice_check_state check_state; … … 128 131 pj_ice_checklist_state state; 129 132 unsigned count; 130 pj_ice_check *checks;133 pj_ice_check checks[PJ_ICE_MAX_CHECKS]; 131 134 } pj_ice_checklist; 132 135 … … 137 140 typedef struct pj_ice_cb 138 141 { 139 pj_ bool_t (*on_found_cand)(pj_ice *sock,140 pj_ice_cand_type type,141 const pj_sockaddr_t * addr,142 intaddr_len);142 pj_status_t (*on_send_pkt)(pj_ice *ice, 143 const void *pkt, pj_size_t size, 144 const pj_sockaddr_t *dst_addr, 145 unsigned addr_len); 143 146 } pj_ice_cb; 144 147 … … 154 157 } pj_ice_state; 155 158 159 typedef enum pj_ice_role 160 { 161 PJ_ICE_ROLE_CONTROLLED, 162 PJ_ICE_ROLE_CONTROLLING 163 } pj_ice_role; 164 156 165 /** 157 166 * ICE structure. … … 165 174 int af; 166 175 int sock_type; 167 176 pj_ice_role role; 168 177 pj_ice_state state; 178 179 pj_ice_cb cb; 180 181 /* STUN credentials */ 182 pj_str_t tx_uname; 183 pj_str_t tx_pass; 184 pj_str_t rx_uname; 185 pj_str_t rx_pass; 169 186 170 187 /* Components */ … … 173 190 174 191 /* Local candidates */ 175 unsigned cand_cnt; 176 pj_ice_cand cand[PJ_ICE_MAX_CAND]; 177 178 /* Checklist */ 192 unsigned lcand_cnt; 193 pj_ice_cand lcand[PJ_ICE_MAX_CAND]; 194 195 /* Remote candidates */ 196 unsigned rcand_cnt; 197 pj_ice_cand rcand[PJ_ICE_MAX_CAND]; 198 199 /* Checklists */ 179 200 pj_ice_checklist cklist; 201 pj_ice_checklist valid_list; 180 202 181 203 /* STUN servers */ … … 184 206 pj_bool_t relay_enabled; 185 207 pj_sockaddr stun_srv; 208 209 /* STUN sessions */ 210 pj_stun_session *tx_sess; 211 pj_stun_session *rx_sess; 186 212 }; 187 213 … … 189 215 PJ_DECL(pj_status_t) pj_ice_create(pj_stun_config *cfg, 190 216 const char *name, 217 pj_ice_role role, 218 const pj_ice_cb *cb, 191 219 int af, 192 220 int sock_type, … … 208 236 unsigned comp_id, 209 237 pj_sock_t sock); 210 238 PJ_DECL(pj_status_t) pj_ice_set_credentials(pj_ice *ice, 239 const pj_str_t *local_ufrag, 240 const pj_str_t *local_pass, 241 const pj_str_t *remote_ufrag, 242 const pj_str_t *remote_pass); 211 243 PJ_DECL(pj_status_t) pj_ice_start_gather(pj_ice *ice, 212 244 unsigned flags); -
pjproject/trunk/pjnath/include/pjnath/stun_msg.h
r1080 r1085 1513 1513 * @param length Length of data, or zero if no data is to be 1514 1514 * copied now. 1515 * @param p_attr Pointer to receive the attribute.1516 1515 * 1517 1516 * @return PJ_SUCCESS on success or the appropriate error code. … … 1523 1522 unsigned length); 1524 1523 1524 /** 1525 * Create STUN empty attribute. 1526 * 1527 * @param pool The pool to allocate memory from. 1528 * @param attr_type The attribute type, from #pj_stun_attr_type. 1529 * @param p_attr Pointer to receive the attribute. 1530 * 1531 * @return PJ_SUCCESS on success or the appropriate error code. 1532 */ 1533 PJ_DECL(pj_status_t) pj_stun_empty_attr_create(pj_pool_t *pool, 1534 int attr_type, 1535 pj_stun_empty_attr **p_attr); 1536 1537 /** 1538 * Create STUN empty attribute and add the attribute to the message. 1539 * 1540 * @param pool The pool to allocate memory from. 1541 * @param msg The STUN message. 1542 * @param attr_type The attribute type, from #pj_stun_attr_type. 1543 * 1544 * @return PJ_SUCCESS on success or the appropriate error code. 1545 */ 1546 PJ_DECL(pj_status_t) pj_stun_msg_add_empty_attr(pj_pool_t *pool, 1547 pj_stun_msg *msg, 1548 int attr_type); 1525 1549 1526 1550 /** -
pjproject/trunk/pjnath/include/pjnath/stun_session.h
r1080 r1085 139 139 pj_stun_msg *msg; /**< The STUN message. */ 140 140 141 void *user_data; /**< Arbitrary application data. */ 142 141 143 pj_stun_client_tsx *client_tsx; /**< Client STUN transaction. */ 142 144 pj_uint32_t msg_magic; /**< Message magic. */ -
pjproject/trunk/pjnath/src/pjnath/ice.c
r1080 r1085 19 19 #include <pjnath/ice.h> 20 20 #include <pjnath/errno.h> 21 #include <pj/addr_resolv.h> 21 22 #include <pj/assert.h> 23 #include <pj/log.h> 22 24 #include <pj/os.h> 23 25 #include <pj/pool.h> 24 26 #include <pj/string.h> 25 27 28 29 static const char *check_state_name[] = 30 { 31 "Frozen", 32 "Waiting", 33 "In Progress", 34 "Succeeded", 35 "Failed" 36 }; 26 37 27 38 static void destroy_ice(pj_ice *ice, … … 30 41 pj_ice_state new_state); 31 42 43 static pj_status_t on_stun_send_msg(pj_stun_session *sess, 44 const void *pkt, 45 pj_size_t pkt_size, 46 const pj_sockaddr_t *dst_addr, 47 unsigned addr_len); 48 static pj_status_t on_stun_rx_request(pj_stun_session *sess, 49 const pj_uint8_t *pkt, 50 unsigned pkt_len, 51 const pj_stun_msg *msg, 52 const pj_sockaddr_t *src_addr, 53 unsigned src_addr_len); 54 static void on_stun_request_complete(pj_stun_session *sess, 55 pj_status_t status, 56 pj_stun_tx_data *tdata, 57 const pj_stun_msg *response); 58 static pj_status_t on_stun_rx_indication(pj_stun_session *sess, 59 const pj_uint8_t *pkt, 60 unsigned pkt_len, 61 const pj_stun_msg *msg, 62 const pj_sockaddr_t *src_addr, 63 unsigned src_addr_len); 64 65 static pj_status_t stun_auth_get_auth(void *user_data, 66 pj_pool_t *pool, 67 pj_str_t *realm, 68 pj_str_t *nonce); 69 static pj_status_t stun_auth_get_password(void *user_data, 70 const pj_str_t *realm, 71 const pj_str_t *username, 72 pj_pool_t *pool, 73 int *data_type, 74 pj_str_t *data); 75 static pj_bool_t stun_auth_verify_nonce(void *user_data, 76 const pj_str_t *realm, 77 const pj_str_t *username, 78 const pj_str_t *nonce); 79 32 80 33 81 PJ_DEF(pj_status_t) pj_ice_create(pj_stun_config *cfg, 34 82 const char *name, 83 pj_ice_role role, 84 const pj_ice_cb *cb, 35 85 int af, 36 86 int sock_type, … … 39 89 pj_pool_t *pool; 40 90 pj_ice *ice; 91 pj_stun_session_cb sess_cb; 92 pj_stun_auth_cred auth_cred; 41 93 pj_status_t status; 42 94 43 PJ_ASSERT_RETURN(cfg && p_ice, PJ_EINVAL);95 PJ_ASSERT_RETURN(cfg && cb && p_ice, PJ_EINVAL); 44 96 PJ_ASSERT_RETURN(sock_type==PJ_SOCK_DGRAM || sock_type==PJ_SOCK_STREAM, 45 97 PJ_EINVAL); … … 53 105 ice->af = af; 54 106 ice->sock_type = sock_type; 107 ice->role = role; 55 108 56 109 pj_ansi_snprintf(ice->obj_name, sizeof(ice->obj_name), … … 64 117 } 65 118 119 pj_memcpy(&ice->cb, cb, sizeof(*cb)); 120 121 /* Init STUN callbacks */ 122 pj_bzero(&sess_cb, sizeof(sess_cb)); 123 sess_cb.on_request_complete = &on_stun_request_complete; 124 sess_cb.on_rx_indication = &on_stun_rx_indication; 125 sess_cb.on_rx_request = &on_stun_rx_request; 126 sess_cb.on_send_msg = &on_stun_send_msg; 127 128 /* Init STUN authentication credential */ 129 pj_bzero(&auth_cred, sizeof(auth_cred)); 130 auth_cred.type = PJ_STUN_AUTH_CRED_DYNAMIC; 131 auth_cred.data.dyn_cred.get_auth = &stun_auth_get_auth; 132 auth_cred.data.dyn_cred.get_password = &stun_auth_get_password; 133 auth_cred.data.dyn_cred.verify_nonce = &stun_auth_verify_nonce; 134 135 /* Create STUN session for outgoing requests */ 136 status = pj_stun_session_create(cfg, ice->obj_name, &sess_cb, PJ_FALSE, 137 &ice->tx_sess); 138 if (status != PJ_SUCCESS) { 139 destroy_ice(ice, status); 140 return status; 141 } 142 143 pj_stun_session_set_user_data(ice->tx_sess, ice); 144 auth_cred.data.dyn_cred.user_data = ice->tx_sess; 145 pj_stun_session_set_credential(ice->tx_sess, &auth_cred); 146 147 /* Create STUN session for incoming requests */ 148 status = pj_stun_session_create(cfg, ice->obj_name, &sess_cb, PJ_FALSE, 149 &ice->rx_sess); 150 if (status != PJ_SUCCESS) { 151 destroy_ice(ice, status); 152 return status; 153 } 154 155 pj_stun_session_set_user_data(ice->rx_sess, ice); 156 auth_cred.data.dyn_cred.user_data = ice->rx_sess; 157 pj_stun_session_set_credential(ice->rx_sess, &auth_cred); 158 159 /* Done */ 66 160 *p_ice = ice; 161 162 PJ_LOG(4,(ice->obj_name, "ICE session created")); 67 163 68 164 return PJ_SUCCESS; … … 73 169 pj_status_t reason) 74 170 { 171 if (reason == PJ_SUCCESS) { 172 PJ_LOG(4,(ice->obj_name, "Destroying ICE session")); 173 } 174 75 175 if (ice->resv_q) { 76 176 pj_dns_resolver_cancel_query(ice->resv_q, PJ_FALSE); … … 109 209 { 110 210 pj_assert(!"Not implemented yet!"); 211 PJ_UNUSED_ARG(user_data); 212 PJ_UNUSED_ARG(status); 213 PJ_UNUSED_ARG(response); 111 214 } 112 215 … … 260 363 261 364 365 static pj_status_t stun_auth_get_auth(void *user_data, 366 pj_pool_t *pool, 367 pj_str_t *realm, 368 pj_str_t *nonce) 369 { 370 PJ_UNUSED_ARG(user_data); 371 PJ_UNUSED_ARG(pool); 372 373 realm->slen = 0; 374 nonce->slen = 0; 375 376 return PJ_SUCCESS; 377 } 378 379 380 static pj_status_t stun_auth_get_password(void *user_data, 381 const pj_str_t *realm, 382 const pj_str_t *username, 383 pj_pool_t *pool, 384 int *data_type, 385 pj_str_t *data) 386 { 387 pj_stun_session *sess = (pj_stun_session *)user_data; 388 pj_ice *ice = (pj_ice*) pj_stun_session_get_user_data(sess); 389 390 PJ_UNUSED_ARG(realm); 391 PJ_UNUSED_ARG(pool); 392 393 if (sess == ice->tx_sess) { 394 /* Verify username */ 395 if (pj_strcmp(username, &ice->tx_uname) != 0) 396 return -1; 397 *data_type = 0; 398 *data = ice->tx_pass; 399 } else { 400 /* The agent MUST accept a credential if the username consists 401 * of two values separated by a colon, where the first value is 402 * equal to the username fragment generated by the agent in an offer 403 * or answer for a session in-progress, and the MESSAGE-INTEGRITY 404 * is the output of a hash of the password and the STUN packet's 405 * contents. 406 */ 407 PJ_TODO(CHECK_USERNAME_FOR_INCOMING_STUN_REQUEST); 408 *data_type = 0; 409 *data = ice->rx_pass; 410 } 411 412 return PJ_SUCCESS; 413 } 414 415 416 static pj_bool_t stun_auth_verify_nonce(void *user_data, 417 const pj_str_t *realm, 418 const pj_str_t *username, 419 const pj_str_t *nonce) 420 { 421 /* We don't use NONCE */ 422 PJ_UNUSED_ARG(user_data); 423 PJ_UNUSED_ARG(realm); 424 PJ_UNUSED_ARG(username); 425 PJ_UNUSED_ARG(nonce); 426 return PJ_TRUE; 427 } 428 429 430 PJ_DEF(pj_status_t) pj_ice_set_credentials(pj_ice *ice, 431 const pj_str_t *local_ufrag, 432 const pj_str_t *local_pass, 433 const pj_str_t *remote_ufrag, 434 const pj_str_t *remote_pass) 435 { 436 char buf[128]; 437 pj_str_t username; 438 439 username.ptr = buf; 440 441 PJ_ASSERT_RETURN(ice && local_ufrag && local_pass && 442 remote_ufrag && remote_pass, PJ_EINVAL); 443 PJ_ASSERT_RETURN(local_ufrag->slen + remote_ufrag->slen < 444 sizeof(buf), PJ_ENAMETOOLONG); 445 446 pj_strcpy(&username, remote_ufrag); 447 pj_strcat2(&username, ":"); 448 pj_strcat(&username, local_ufrag); 449 450 pj_strdup(ice->pool, &ice->tx_uname, &username); 451 pj_strdup(ice->pool, &ice->tx_pass, remote_pass); 452 453 pj_strcpy(&username, local_ufrag); 454 pj_strcat2(&username, ":"); 455 pj_strcat(&username, remote_ufrag); 456 457 pj_strdup(ice->pool, &ice->rx_uname, &username); 458 pj_strdup(ice->pool, &ice->rx_pass, local_pass); 459 460 return PJ_SUCCESS; 461 } 462 463 262 464 static pj_status_t gather_host_cands(pj_ice *ice) 263 465 { … … 293 495 static pj_status_t gather_mapped_cands(pj_ice *ice) 294 496 { 497 PJ_UNUSED_ARG(ice); 295 498 return PJ_ENOTSUP; 296 499 } … … 298 501 static pj_status_t gather_relayed_cands(pj_ice *ice) 299 502 { 503 PJ_UNUSED_ARG(ice); 300 504 return PJ_ENOTSUP; 301 505 } … … 305 509 { 306 510 pj_status_t status; 511 512 PJ_UNUSED_ARG(flags); 307 513 308 514 /* Gather host candidate */ … … 348 554 unsigned *p_cand_id) 349 555 { 350 pj_ice_cand * cand;556 pj_ice_cand *lcand; 351 557 pj_status_t status = PJ_SUCCESS; 352 558 353 559 pj_mutex_lock(ice->mutex); 354 560 355 if (ice-> cand_cnt >= PJ_ARRAY_SIZE(ice->cand)) {561 if (ice->lcand_cnt >= PJ_ARRAY_SIZE(ice->lcand)) { 356 562 status = PJ_ETOOMANY; 357 563 goto on_error; 358 564 } 359 565 360 cand = &ice->cand[ice->cand_cnt];361 cand->comp_id = comp_id;362 cand->type = type;363 pj_strdup(ice->pool, & cand->foundation, foundation);364 cand->prio = CALC_CAND_PRIO(type, local_pref,cand->comp_id);365 pj_memcpy(& cand->addr, addr, addr_len);366 pj_memcpy(& cand->base_addr, base_addr, addr_len);566 lcand = &ice->lcand[ice->lcand_cnt]; 567 lcand->comp_id = comp_id; 568 lcand->type = type; 569 pj_strdup(ice->pool, &lcand->foundation, foundation); 570 lcand->prio = CALC_CAND_PRIO(type, local_pref, lcand->comp_id); 571 pj_memcpy(&lcand->addr, addr, addr_len); 572 pj_memcpy(&lcand->base_addr, base_addr, addr_len); 367 573 if (srv_addr) 368 pj_memcpy(& cand->srv_addr, srv_addr, addr_len);574 pj_memcpy(&lcand->srv_addr, srv_addr, addr_len); 369 575 else 370 pj_bzero(& cand->srv_addr, sizeof(cand->srv_addr));576 pj_bzero(&lcand->srv_addr, sizeof(lcand->srv_addr)); 371 577 372 578 if (p_cand_id) 373 *p_cand_id = ice-> cand_cnt;374 375 ++ice-> cand_cnt;579 *p_cand_id = ice->lcand_cnt; 580 581 ++ice->lcand_cnt; 376 582 377 583 on_error: … … 383 589 PJ_DEF(unsigned) pj_ice_get_cand_cnt(pj_ice *ice) 384 590 { 385 return ice-> cand_cnt;591 return ice->lcand_cnt; 386 592 } 387 593 … … 394 600 unsigned i, count; 395 601 602 PJ_UNUSED_ARG(sort_by); 603 396 604 pj_mutex_lock(ice->mutex); 397 605 398 count = (*p_count < ice-> cand_cnt) ? *p_count : ice->cand_cnt;606 count = (*p_count < ice->lcand_cnt) ? *p_count : ice->lcand_cnt; 399 607 for (i=0; i<count; ++i) 400 608 cand_ids[i] = i; … … 412 620 { 413 621 PJ_ASSERT_RETURN(ice && p_cand, PJ_EINVAL); 414 PJ_ASSERT_RETURN(cand_id <= ice-> cand_cnt, PJ_EINVAL);415 416 *p_cand = &ice-> cand[cand_id];622 PJ_ASSERT_RETURN(cand_id <= ice->lcand_cnt, PJ_EINVAL); 623 624 *p_cand = &ice->lcand[cand_id]; 417 625 418 626 return PJ_SUCCESS; … … 433 641 } 434 642 643 static const char *dump_check(char *buffer, unsigned bufsize, 644 const pj_ice *ice, 645 const pj_ice_check *check) 646 { 647 char local_addr[128]; 648 int len; 649 650 pj_ansi_strcpy(local_addr, 651 pj_inet_ntoa(ice->lcand[check->cand_id].addr.ipv4.sin_addr)); 652 653 len = pj_ansi_snprintf(buffer, bufsize, 654 "%s:%d-->%s:%d", 655 local_addr, 656 (int)pj_ntohs(ice->lcand[check->cand_id].addr.ipv4.sin_port), 657 pj_inet_ntoa(check->rem_addr.ipv4.sin_addr), 658 (int)pj_ntohs(check->rem_addr.ipv4.sin_port)); 659 if (len < 0) 660 len = 0; 661 else if (len >= (int)bufsize) 662 len = bufsize - 1; 663 664 buffer[len] = '\0'; 665 return buffer; 666 } 667 668 #if PJ_LOG_MAX_LEVEL >= 4 669 static void dump_checklist(const char *title, const pj_ice *ice, 670 const pj_ice_checklist *clist) 671 { 672 unsigned i; 673 char buffer[128]; 674 675 PJ_LOG(4,(ice->obj_name, "%s", title)); 676 for (i=0; i<clist->count; ++i) { 677 const pj_ice_check *c = &clist->checks[i]; 678 PJ_LOG(4,(ice->obj_name, " %d: %s (prio=%u, state=%s)", 679 i, dump_check(buffer, sizeof(buffer), ice, c), 680 c->check_prio, check_state_name[c->check_state])); 681 } 682 } 683 #else 684 #define dump_checklist(ice, clist) 685 #endif 686 687 static void sort_checklist(pj_ice_checklist *clist) 688 { 689 unsigned i; 690 691 for (i=0; i<clist->count-1; ++i) { 692 unsigned j, highest = i; 693 for (j=i+1; j<clist->count; ++j) { 694 if (clist->checks[j].check_prio > 695 clist->checks[highest].check_prio) 696 { 697 highest = j; 698 } 699 } 700 701 if (highest != i) { 702 pj_ice_check tmp; 703 704 pj_memcpy(&tmp, &clist->checks[i], sizeof(pj_ice_check)); 705 pj_memcpy(&clist->checks[i], &clist->checks[highest], 706 sizeof(pj_ice_check)); 707 pj_memcpy(&clist->checks[highest], &tmp, sizeof(pj_ice_check)); 708 } 709 } 710 } 435 711 436 712 PJ_DEF(pj_status_t) pj_ice_create_check_list(pj_ice *ice, … … 440 716 { 441 717 pj_ice_checklist *clist; 442 unsigned i, j , count;718 unsigned i, j; 443 719 444 720 PJ_ASSERT_RETURN(ice && rem_cand_cnt && rem_cand, PJ_EINVAL); 721 PJ_ASSERT_RETURN(rem_cand_cnt < PJ_ICE_MAX_CAND, PJ_ETOOMANY); 445 722 446 723 pj_mutex_lock(ice->mutex); 447 724 448 /* Create checklist */ 725 /* Save remote candidates */ 726 ice->rcand_cnt = 0; 727 for (i=0; i<rem_cand_cnt; ++i) { 728 pj_ice_cand *cn = &ice->rcand[ice->rcand_cnt++]; 729 pj_memcpy(cn, &rem_cand[i], sizeof(pj_ice_cand)); 730 pj_strdup(ice->pool, &cn->foundation, &rem_cand[i].foundation); 731 } 732 733 /* Generate checklist */ 449 734 clist = &ice->cklist; 450 clist->checks = pj_pool_calloc(ice->pool, 451 ice->cand_cnt * rem_cand_cnt, 452 sizeof(pj_ice_check)); 453 for (i=0, count=0; i<ice->cand_cnt; ++i) { 735 for (i=0; i<ice->lcand_cnt; ++i) { 454 736 for (j=0; j<rem_cand_cnt; ++j) { 455 737 456 pj_ice_check *c = &clist->checks[c ount++];738 pj_ice_check *c = &clist->checks[clist->count++]; 457 739 458 740 /* A local candidate is paired with a remote candidate if … … 460 742 * and have the same IP address version. 461 743 */ 462 if (ice-> cand[i].comp_id != rem_cand[j].comp_id ||463 pj_strcmp(&ice-> cand[i].foundation,&rem_cand[j].foundation)==0)744 if (ice->lcand[i].comp_id != rem_cand[j].comp_id || 745 pj_strcmp(&ice->lcand[i].foundation,&rem_cand[j].foundation)==0) 464 746 { 465 747 continue; 466 748 } 467 749 468 c->local_cand_id = i; 750 c->cand_id = i; 751 c->comp_id = ice->lcand[i].comp_id; 752 c->foundation = ice->lcand[i].foundation; 469 753 470 754 if (is_remote_offer) { 471 755 c->check_prio = CALC_CHECK_PRIO(rem_cand[j].prio, 472 ice-> cand[i].prio);756 ice->lcand[i].prio); 473 757 } else { 474 c->check_prio = CALC_CHECK_PRIO(ice-> cand[i].prio,758 c->check_prio = CALC_CHECK_PRIO(ice->lcand[i].prio, 475 759 rem_cand[j].prio); 476 760 } … … 486 770 } 487 771 488 clist->count = count;489 490 772 /* Sort checklist based on priority */ 491 for (i=0; i<clist->count-1; ++i) { 492 unsigned highest = i; 493 for (j=i+1; j<clist->count; ++j) { 494 if (clist->checks[j].check_prio > 495 clist->checks[highest].check_prio) 496 { 497 highest = j; 498 } 499 } 500 501 if (highest != i) { 502 pj_ice_check tmp; 503 504 pj_memcpy(&tmp, &clist->checks[i], sizeof(pj_ice_check)); 505 pj_memcpy(&clist->checks[i], &clist->checks[highest], 506 sizeof(pj_ice_check)); 507 pj_memcpy(&clist->checks[highest], &tmp, sizeof(pj_ice_check)); 508 } 509 } 773 sort_checklist(clist); 510 774 511 775 /* Prune the checklist */ … … 514 778 } 515 779 780 /* Log checklist */ 781 dump_checklist("Checklist created:", ice, clist); 782 516 783 pj_mutex_lock(ice->mutex); 517 784 … … 519 786 } 520 787 788 789 struct req_data 790 { 791 pj_ice *ice; 792 pj_ice_checklist *clist; 793 unsigned ckid; 794 }; 795 796 /* Perform check on the specified candidate pair */ 797 static pj_status_t perform_check(pj_ice *ice, pj_ice_checklist *clist, 798 unsigned check_id) 799 { 800 pj_stun_tx_data *tdata; 801 struct req_data *rd; 802 pj_ice_check *check; 803 pj_uint32_t prio; 804 char buffer[128]; 805 pj_status_t status; 806 807 check = &clist->checks[check_id]; 808 809 PJ_LOG(5,(ice->obj_name, 810 "Sending connectivity check for check %d: %s", 811 check_id, dump_check(buffer, sizeof(buffer), ice, check))); 812 813 /* Create request */ 814 status = pj_stun_session_create_req(ice->tx_sess, 815 PJ_STUN_BINDING_REQUEST, &tdata); 816 if (status != PJ_SUCCESS) 817 return status; 818 819 /* Attach data to be retrieved later when STUN request transaction 820 * completes and on_stun_request_complete() callback is called. 821 */ 822 rd = PJ_POOL_ZALLOC_T(tdata->pool, struct req_data); 823 rd->ice = ice; 824 rd->clist = clist; 825 rd->ckid = check_id; 826 tdata->user_data = (void*) rd; 827 828 /* Add PRIORITY */ 829 prio = CALC_CAND_PRIO(check->rem_type, 65535, check->comp_id); 830 pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg, PJ_STUN_ATTR_PRIORITY, 831 prio); 832 833 /* Add USE-CANDIDATE */ 834 if (ice->role == PJ_ICE_ROLE_CONTROLLING) { 835 pj_stun_msg_add_empty_attr(tdata->pool, tdata->msg, 836 PJ_STUN_ATTR_USE_CANDIDATE); 837 } 838 839 /* Initiate STUN transaction to send the request */ 840 status = pj_stun_session_send_msg(ice->tx_sess, PJ_FALSE, 841 &check->rem_addr, 842 sizeof(pj_sockaddr_in), tdata); 843 if (status != PJ_SUCCESS) 844 return status; 845 846 check->check_state = PJ_ICE_CHECK_STATE_IN_PROGRESS; 847 return PJ_SUCCESS; 848 } 521 849 522 850 /* Start periodic check for the specified checklist */ 523 851 static pj_status_t start_periodic_check(pj_ice *ice, pj_ice_checklist *clist) 524 852 { 853 unsigned i, start_count=0; 854 pj_status_t status; 855 856 /* Checklist state must be idle or completed */ 857 pj_assert(clist->state == PJ_ICE_CHECKLIST_ST_IDLE || 858 clist->state == PJ_ICE_CHECKLIST_ST_COMPLETED); 859 860 /* Set checklist state to Running */ 861 clist->state = PJ_ICE_CHECKLIST_ST_RUNNING; 862 863 PJ_LOG(4,(ice->obj_name, "Starting checklist periodic check")); 864 865 /* Send STUN Binding request for checks in Waiting list */ 866 for (i=0; i<clist->count; ++i) { 867 pj_ice_check *check = &clist->checks[i]; 868 869 if (check->check_state == PJ_ICE_CHECK_STATE_WAITING) { 870 status = perform_check(ice, clist, i); 871 if (status != PJ_SUCCESS) 872 return status; 873 874 ++start_count; 875 } 876 } 877 878 /* If we don't have anything in Waiting state, perform check to 879 * highest priority pair that is in Frozen state. 880 */ 881 if (start_count==0) { 882 for (i=0; i<clist->count; ++i) { 883 pj_ice_check *check = &clist->checks[i]; 884 885 if (check->check_state == PJ_ICE_CHECK_STATE_FROZEN) { 886 status = perform_check(ice, clist, i); 887 if (status != PJ_SUCCESS) 888 return status; 889 890 ++start_count; 891 break; 892 } 893 } 894 } 895 896 /* Cannot start check because there's no suitable candidate pair. 897 * Set checklist state to Completed. 898 */ 899 if (start_count==0) { 900 clist->state = PJ_ICE_CHECKLIST_ST_COMPLETED; 901 PJ_LOG(4,(ice->obj_name, "Checklist completed")); 902 } 903 904 return PJ_SUCCESS; 525 905 } 526 906 … … 530 910 { 531 911 pj_ice_checklist *clist; 532 unsigned i, comp_id; 533 pj_str_t fnd; 912 unsigned i; 534 913 535 914 PJ_ASSERT_RETURN(ice, PJ_EINVAL); … … 547 926 * states to Waiting as well. 548 927 */ 549 comp_id = ice->cand[clist->checks[0].local_cand_id].comp_id;550 fnd = ice->cand[clist->checks[0].local_cand_id].foundation;551 552 928 for (i=1; i<clist->count; ++i) { 553 929 pj_ice_check *cki = &clist->checks[i]; 554 930 555 if ( ice->cand[cki->local_cand_id].comp_id !=comp_id)931 if (cki->comp_id != clist->checks[0].comp_id) 556 932 continue; 557 933 558 if (pj_strcmp(& ice->cand[cki->local_cand_id].foundation, &fnd)==0)934 if (pj_strcmp(&cki->foundation, &clist->checks[0].foundation)==0) 559 935 continue; 560 936 … … 565 941 return start_periodic_check(ice, clist); 566 942 } 943 944 945 ////////////////////////////////////////////////////////////////////////////// 946 947 static pj_status_t on_stun_send_msg(pj_stun_session *sess, 948 const void *pkt, 949 pj_size_t pkt_size, 950 const pj_sockaddr_t *dst_addr, 951 unsigned addr_len) 952 { 953 pj_ice *ice = (pj_ice*) pj_stun_session_get_user_data(sess); 954 return (*ice->cb.on_send_pkt)(ice, pkt, pkt_size, dst_addr, addr_len); 955 } 956 957 958 static pj_status_t on_stun_rx_request(pj_stun_session *sess, 959 const pj_uint8_t *pkt, 960 unsigned pkt_len, 961 const pj_stun_msg *msg, 962 const pj_sockaddr_t *src_addr, 963 unsigned src_addr_len) 964 { 965 pj_stun_tx_data *tdata; 966 pj_status_t status; 967 968 /* 7.2.1.2. Learning Peer Reflexive Candidates */ 969 PJ_TODO(LEARN_PEER_REFLEXIVE_CANDIDATES); 970 971 /* Reject any requests except Binding request */ 972 if (msg->hdr.type != PJ_STUN_BINDING_REQUEST) { 973 status = pj_stun_session_create_response(sess, msg, 974 PJ_STUN_SC_BAD_REQUEST, 975 NULL, &tdata); 976 if (status != PJ_SUCCESS) 977 return status; 978 979 status = pj_stun_session_send_msg(sess, PJ_TRUE, 980 src_addr, src_addr_len, tdata); 981 return status; 982 } 983 984 status = pj_stun_session_create_response(sess, msg, 0, NULL, &tdata); 985 if (status != PJ_SUCCESS) 986 return status; 987 988 status = pj_stun_msg_add_sockaddr_attr(tdata->pool, msg, 989 PJ_STUN_ATTR_XOR_MAPPED_ADDR, 990 PJ_TRUE, src_addr, src_addr_len); 991 992 status = pj_stun_session_send_msg(sess, PJ_TRUE, 993 src_addr, src_addr_len, tdata); 994 995 /* 7.2.1.3. Triggered Checks: 996 * Next, the agent constructs a pair whose local candidate is equal to 997 * the transport address on which the STUN request was received, and a 998 * remote candidate equal to the source transport address where the 999 * request came from (which may be peer-reflexive remote candidate that 1000 * was just learned). 1001 */ 1002 1003 return status; 1004 } 1005 1006 /* This callback is called when outgoing STUN request completed */ 1007 static void on_stun_request_complete(pj_stun_session *sess, 1008 pj_status_t status, 1009 pj_stun_tx_data *tdata, 1010 const pj_stun_msg *response) 1011 { 1012 struct req_data *rd = (struct req_data*) tdata->user_data; 1013 pj_ice *ice; 1014 pj_ice_check *check, *valid_check; 1015 pj_ice_checklist *clist; 1016 char buffer[128]; 1017 1018 ice = rd->ice; 1019 check = &rd->clist->checks[rd->ckid]; 1020 clist = rd->clist; 1021 1022 PJ_LOG(5,(ice->obj_name, 1023 "Connectivity check %s for check %d: %s", 1024 (status==PJ_SUCCESS ? "SUCCESS" : "FAILED"), rd->ckid, 1025 dump_check(buffer, sizeof(buffer), ice, check))); 1026 1027 if (status != PJ_SUCCESS) { 1028 check->check_state = PJ_ICE_CHECK_STATE_FAILED; 1029 return; 1030 } 1031 1032 /* The agent MUST check that the source IP address and port of the 1033 * response equals the destination IP address and port that the Binding 1034 * Request was sent to, and that the destination IP address and port of 1035 * the response match the source IP address and port that the Binding 1036 * Request was sent from. 1037 */ 1038 PJ_TODO(CHECK_ICE_RESPONSE_SOURCE_ADDRESS); 1039 1040 /* Get the STUN MAPPED-ADDRESS attribute. If the 1041 * transport address does not match any of the local candidates that the 1042 * agent knows about, the mapped address represents a new candidate - a 1043 * peer reflexive candidate 1044 */ 1045 PJ_TODO(CHECK_ICE_RESPONSE_SOURCE_ADDRESS2); 1046 1047 /* Sets the state of the pair that generated the check to succeeded. */ 1048 check->check_state = PJ_ICE_CHECK_STATE_SUCCEEDED; 1049 1050 /* This is a valid pair, so add this to the valid list */ 1051 valid_check = &ice->valid_list.checks[ice->valid_list.count++]; 1052 pj_memcpy(valid_check, check, sizeof(*check)); 1053 1054 /* Sort valid_list */ 1055 sort_checklist(&ice->valid_list); 1056 1057 1058 /* If the pair had a component ID of 1, the agent MUST change the 1059 * states for all other Frozen pairs for the same media stream and 1060 * same foundation, but different component IDs, to Waiting. 1061 */ 1062 if (check->comp_id == 1) { 1063 unsigned i; 1064 for (i=0; i<clist->count; ++i) { 1065 pj_ice_check *c = &clist->checks[i]; 1066 1067 if (c->check_state == PJ_ICE_CHECK_STATE_FROZEN && 1068 c->comp_id != check->comp_id && 1069 pj_strcmp(&c->foundation, &check->foundation)==0) 1070 { 1071 /* Unfreeze and start check */ 1072 PJ_LOG(5,(ice->obj_name, "Unfreezing check %d", i)); 1073 c->check_state = PJ_ICE_CHECK_STATE_WAITING; 1074 perform_check(ice, clist, i); 1075 } 1076 } 1077 1078 } 1079 /* If the pair had a component ID equal to the number of components 1080 * for the media stream (where this is the actual number of 1081 * components being used, in cases where the number of components 1082 * signaled in the SDP differs from offerer to answerer), the agent 1083 * MUST change the state for all other Frozen pairs for the first 1084 * component of different media streams (and thus in different check 1085 * lists) but the same foundation, to Waiting. 1086 */ 1087 else if (0) { 1088 PJ_TODO(UNFREEZE_OTHER_COMPONENT_ID); 1089 } 1090 /* If the pair has any other component ID, no other pairs can be 1091 * unfrozen. 1092 */ 1093 else { 1094 PJ_TODO(UNFREEZE_OTHER_COMPONENT_ID1); 1095 } 1096 1097 } 1098 1099 static pj_status_t on_stun_rx_indication(pj_stun_session *sess, 1100 const pj_uint8_t *pkt, 1101 unsigned pkt_len, 1102 const pj_stun_msg *msg, 1103 const pj_sockaddr_t *src_addr, 1104 unsigned src_addr_len) 1105 { 1106 PJ_TODO(SUPPORT_RX_BIND_REQUEST_AS_INDICATION); 1107 return PJ_ENOTSUP; 1108 } 1109 -
pjproject/trunk/pjnath/src/pjnath/stun_msg.c
r1080 r1085 874 874 875 875 876 /* 877 * Create STUN empty attribute and add the attribute to the message. 878 */ 879 PJ_DEF(pj_status_t) pj_stun_msg_add_empty_attr( pj_pool_t *pool, 880 pj_stun_msg *msg, 881 int attr_type) 882 { 883 pj_stun_empty_attr *attr = NULL; 884 pj_status_t status; 885 886 status = pj_stun_empty_attr_create(pool, attr_type, &attr); 887 if (status != PJ_SUCCESS) 888 return status; 889 890 return pj_stun_msg_add_attr(msg, &attr->hdr); 891 } 892 876 893 static pj_status_t decode_empty_attr(pj_pool_t *pool, 877 894 const pj_uint8_t *buf,
Note: See TracChangeset
for help on using the changeset viewer.