- Timestamp:
- Apr 14, 2008 1:48:39 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/branches/projects/ice-turn07/pjnath/src/pjnath/ice_strans.c
r1913 r1926 41 41 static pj_status_t ice_tx_pkt(pj_ice_sess *ice, 42 42 unsigned comp_id, 43 unsigned cand_id, 43 44 const void *pkt, pj_size_t size, 44 45 const pj_sockaddr_t *dst_addr, … … 74 75 unsigned src_addr_len); 75 76 77 /* TURN callbacks */ 78 static void turn_on_rx_data(pj_turn_sock *turn_sock, 79 void *pkt, 80 unsigned pkt_len, 81 const pj_sockaddr_t *peer_addr, 82 unsigned addr_len); 83 static void turn_on_state(pj_turn_sock *turn_sock, pj_turn_state_t old_state, 84 pj_turn_state_t new_state); 85 86 76 87 /* Keep-alive timer */ 77 88 static void start_ka_timer(pj_ice_strans *ice_st); … … 81 92 #define ice_st_perror(ice_st,msg,rc) pjnath_perror(ice_st->obj_name,msg,rc) 82 93 94 /* Validate configuration */ 95 static pj_status_t pj_ice_strans_cfg_check_valid(const pj_ice_strans_cfg *cfg) 96 { 97 pj_status_t status; 98 99 status = pj_stun_config_check_valid(&cfg->stun_cfg); 100 if (!status) 101 return status; 102 103 /* If TURN is specified then TURN credential must be specified */ 104 PJ_ASSERT_RETURN(!pj_sockaddr_has_addr(&cfg->turn_srv) || 105 cfg->turn_cred.type != PJ_STUN_AUTH_NONE, 106 PJ_EINVAL); 107 108 return PJ_SUCCESS; 109 } 110 111 83 112 /* 84 113 * Create ICE stream transport 85 114 */ 86 PJ_DEF(pj_status_t) pj_ice_strans_create( pj_stun_config *stun_cfg,115 PJ_DEF(pj_status_t) pj_ice_strans_create( const pj_ice_strans_cfg *cfg, 87 116 const char *name, 88 117 unsigned comp_cnt, … … 93 122 pj_pool_t *pool; 94 123 pj_ice_strans *ice_st; 95 96 PJ_ASSERT_RETURN(stun_cfg && comp_cnt && cb && p_ice_st, PJ_EINVAL); 97 PJ_ASSERT_RETURN(stun_cfg->ioqueue && stun_cfg->timer_heap, PJ_EINVAL); 124 pj_status_t status; 125 126 status = pj_ice_strans_cfg_check_valid(cfg); 127 if (status != PJ_SUCCESS) 128 return status; 129 130 PJ_ASSERT_RETURN(comp_cnt && cb && p_ice_st, PJ_EINVAL); 98 131 99 132 if (name == NULL) 100 133 name = "icstr%p"; 101 134 102 pool = pj_pool_create( stun_cfg->pf, name, PJNATH_POOL_LEN_ICE_STRANS,135 pool = pj_pool_create(cfg->stun_cfg.pf, name, PJNATH_POOL_LEN_ICE_STRANS, 103 136 PJNATH_POOL_INC_ICE_STRANS, NULL); 104 137 ice_st = PJ_POOL_ZALLOC_T(pool, pj_ice_strans); 105 138 ice_st->pool = pool; 139 pj_memcpy(&ice_st->cfg, cfg, sizeof(*cfg)); 140 pj_stun_auth_cred_dup(pool, &ice_st->cfg.turn_cred, &cfg->turn_cred); 106 141 pj_memcpy(ice_st->obj_name, pool->obj_name, PJ_MAX_OBJ_NAME); 107 142 ice_st->user_data = user_data; … … 112 147 113 148 pj_memcpy(&ice_st->cb, cb, sizeof(*cb)); 114 pj_memcpy(&ice_st->stun_cfg, stun_cfg, sizeof(*stun_cfg));115 149 116 150 … … 179 213 PJ_UNUSED_ARG(domain); 180 214 return -1; 181 }182 183 /*184 * Set STUN server address.185 */186 PJ_DEF(pj_status_t) pj_ice_strans_set_stun_srv( pj_ice_strans *ice_st,187 const pj_sockaddr_in *stun_srv,188 const pj_sockaddr_in *turn_srv)189 {190 PJ_ASSERT_RETURN(ice_st, PJ_EINVAL);191 /* Must not have pending resolver job */192 PJ_ASSERT_RETURN(ice_st->has_rjob==PJ_FALSE, PJ_EINVALIDOP);193 194 if (stun_srv) {195 pj_memcpy(&ice_st->stun_srv, stun_srv, sizeof(pj_sockaddr_in));196 } else {197 pj_bzero(&ice_st->stun_srv, sizeof(pj_sockaddr_in));198 }199 200 if (turn_srv) {201 pj_memcpy(&ice_st->turn_srv, turn_srv, sizeof(pj_sockaddr_in));202 } else {203 pj_bzero(&ice_st->turn_srv, sizeof(pj_sockaddr_in));204 }205 206 return PJ_SUCCESS;207 215 } 208 216 … … 328 336 pj_bzero(&ioqueue_cb, sizeof(ioqueue_cb)); 329 337 ioqueue_cb.on_read_complete = &on_read_complete; 330 status = pj_ioqueue_register_sock(ice_st->pool, ice_st->stun_cfg.ioqueue, 338 status = pj_ioqueue_register_sock(ice_st->pool, 339 ice_st->cfg.stun_cfg.ioqueue, 331 340 comp->sock, comp, &ioqueue_cb, 332 341 &comp->key); … … 388 397 * as default candidate. 389 398 */ 390 if (ifs[i].ipv4.sin_addr.s_addr == comp->local_addr.ipv4.sin_addr.s_addr) { 399 if (ifs[i].ipv4.sin_addr.s_addr == 400 comp->local_addr.ipv4.sin_addr.s_addr) 401 { 391 402 set_default = PJ_TRUE; 392 403 local_pref = 65535; … … 464 475 * the binding alive. 465 476 * 466 * 2) this could be a packet (STUN or not STUN) sent from the STUN 467 * relay server. In this case, still there are few options to do 468 * for this packet: a) process this locally if this packet is 469 * related to TURN session management (e.g. Allocate response), 470 * b) forward this packet to ICE if this is related to ICE 477 * 2) this could be a STUN request or response sent as part of ICE 471 478 * discovery process. 472 479 * 473 * 3) this could be a STUN request or response sent as part of ICE 474 * discovery process. 475 * 476 * 4) this could be application's packet, e.g. when ICE processing 480 * 3) this could be application's packet, e.g. when ICE processing 477 481 * is done and agents start sending RTP/RTCP packets to each 478 482 * other, or when ICE processing is not done and this ICE stream 479 483 * transport decides to allow sending data. 480 484 * 481 * So far we don't have good solution for this.482 * The process below is just a workaround.483 485 */ 486 unsigned cand_id; 487 488 /* Find candidate ID for this packet */ 489 for (cand_id=0; cand_id<comp->cand_cnt; ++cand_id) { 490 if (comp->cand_list[cand_id].type != PJ_ICE_CAND_TYPE_RELAYED) 491 break; 492 } 493 if (cand_id == comp->cand_cnt) { 494 //pj_assert(!"We should have at least one host/srflx candidate"); 495 //cand_id = 0; 496 PJ_LOG(2,(ice_st->obj_name, 497 "Received pkt on comp %d which doesn't have host/srflx " 498 "candidate", 499 comp->comp_id)); 500 goto next_packet; 501 } 502 503 /* Is this a STUN message? */ 484 504 status = pj_stun_msg_check(comp->pkt, bytes_read, 485 505 PJ_STUN_IS_DATAGRAM); … … 496 516 comp->src_addr_len); 497 517 } else if (ice_st->ice) { 498 PJ_TODO(DISTINGUISH_BETWEEN_LOCAL_AND_RELAY);499 500 518 TRACE_PKT((comp->ice_st->obj_name, 501 519 "Component %d RX packet from %s:%d", … … 505 523 506 524 status = pj_ice_sess_on_rx_pkt(ice_st->ice, comp->comp_id, 507 c omp->pkt, bytes_read,525 cand_id, comp->pkt, bytes_read, 508 526 &comp->src_addr, 509 527 comp->src_addr_len); … … 525 543 526 544 /* Read next packet */ 545 next_packet: 527 546 for (retry=0; retry<RETRY;) { 528 547 pkt_size = sizeof(comp->pkt); … … 552 571 static void destroy_component(pj_ice_strans_comp *comp) 553 572 { 573 if (comp->turn_relay) { 574 pj_turn_sock_destroy(comp->turn_relay); 575 comp->turn_relay = NULL; 576 } 577 554 578 if (comp->stun_sess) { 555 579 pj_stun_session_destroy(comp->stun_sess); … … 611 635 pj_ntohs(comp->local_addr.ipv4.sin_port))); 612 636 status = pj_stun_session_send_msg(comp->stun_sess, &comp->cand_list[j], 613 PJ_FALSE, PJ_TRUE, &ice_st->stun_srv, 637 PJ_FALSE, PJ_TRUE, 638 &ice_st->cfg.stun_srv, 614 639 sizeof(pj_sockaddr_in), tdata); 615 640 if (status != PJ_SUCCESS) { … … 638 663 ice_st->ka_timer.user_data = ice_st; 639 664 640 if (pj_timer_heap_schedule(ice_st-> stun_cfg.timer_heap,665 if (pj_timer_heap_schedule(ice_st->cfg.stun_cfg.timer_heap, 641 666 &ice_st->ka_timer, &delay)==PJ_SUCCESS) 642 667 { … … 653 678 return; 654 679 655 pj_timer_heap_cancel(ice_st-> stun_cfg.timer_heap, &ice_st->ka_timer);680 pj_timer_heap_cancel(ice_st->cfg.stun_cfg.timer_heap, &ice_st->ka_timer); 656 681 ice_st->ka_timer.id = PJ_FALSE; 657 682 } … … 671 696 PJ_ASSERT_RETURN(ice_st && comp, PJ_EINVAL); 672 697 673 /* Bail out if STUN server is still being resolved */674 if (ice_st->has_rjob)675 return PJ_EBUSY;676 677 698 /* Just return (successfully) if STUN server is not configured */ 678 if (ice_st-> stun_srv.sin_family == 0)699 if (ice_st->cfg.stun_srv.addr.sa_family == 0) 679 700 return PJ_SUCCESS; 680 701 … … 684 705 sess_cb.on_request_complete = &stun_on_request_complete; 685 706 sess_cb.on_send_msg = &stun_on_send_msg; 686 status = pj_stun_session_create(&ice_st-> stun_cfg, ice_st->obj_name,707 status = pj_stun_session_create(&ice_st->cfg.stun_cfg, ice_st->obj_name, 687 708 &sess_cb, PJ_FALSE, &comp->stun_sess); 688 709 if (status != PJ_SUCCESS) … … 711 732 /* Add new alias to this component */ 712 733 cand->type = PJ_ICE_CAND_TYPE_SRFLX; 713 cand->status = PJ_ EPENDING;734 cand->status = PJ_SUCCESS; 714 735 cand->ice_cand_id = -1; 715 736 cand->local_pref = 65535; … … 721 742 /* Send STUN binding request */ 722 743 status = pj_stun_session_send_msg(comp->stun_sess, (void*)cand, PJ_FALSE, 723 PJ_TRUE, &ice_st-> stun_srv,744 PJ_TRUE, &ice_st->cfg.stun_srv, 724 745 sizeof(pj_sockaddr_in), tdata); 725 746 if (status != PJ_SUCCESS) { … … 753 774 PJ_ASSERT_RETURN(ice_st->ice == NULL, PJ_EBUSY); 754 775 755 /* Can't add new component while resolver is running */756 PJ_ASSERT_RETURN(ice_st->has_rjob == PJ_FALSE, PJ_EBUSY);757 758 776 759 777 /* Create component */ … … 762 780 return status; 763 781 764 if ((options & PJ_ICE_ST_OPT_DISABLE_STUN) == 0) { 782 /* Start STUN mapped address resolution */ 783 if ((options & PJ_ICE_ST_OPT_DISABLE_STUN) == 0 && 784 pj_sockaddr_has_addr(&ice_st->cfg.stun_srv)) 785 { 765 786 status = get_stun_mapped_addr(ice_st, comp); 766 787 if (status != PJ_SUCCESS) { … … 769 790 } 770 791 } 792 793 /* Create TURN relay if wanted. */ 794 if ((options & PJ_ICE_ST_OPT_DISABLE_RELAY) == 0 && 795 pj_sockaddr_has_addr(&ice_st->cfg.turn_srv)) 796 { 797 pj_turn_sock_cb turn_sock_cb; 798 char ipaddr[PJ_INET6_ADDRSTRLEN+8]; 799 pj_str_t s; 800 801 pj_assert(comp->cand_cnt < PJ_ICE_ST_MAX_CAND); 802 803 /* Init TURN socket */ 804 pj_bzero(&turn_sock_cb, sizeof(turn_sock_cb)); 805 turn_sock_cb.on_rx_data = &turn_on_rx_data; 806 turn_sock_cb.on_state = &turn_on_state; 807 808 status = pj_turn_sock_create(&ice_st->cfg.stun_cfg, pj_AF_INET(), 809 ice_st->cfg.turn_conn_type, 810 &turn_sock_cb, 0, comp, 811 &comp->turn_relay); 812 if (status != PJ_SUCCESS) { 813 destroy_component(comp); 814 return status; 815 } 816 817 pj_sockaddr_print(&ice_st->cfg.turn_srv, ipaddr, sizeof(ipaddr), 0); 818 819 ++comp->pending_cnt; 820 821 /* Start allocation */ 822 status = pj_turn_sock_init(comp->turn_relay, pj_cstr(&s, ipaddr), 823 pj_sockaddr_get_port(&ice_st->cfg.turn_srv), 824 NULL, &ice_st->cfg.turn_cred, 825 &ice_st->cfg.turn_alloc_param); 826 if (status != PJ_SUCCESS) { 827 if (comp->turn_relay) { 828 pj_turn_sock_destroy(comp->turn_relay); 829 } 830 comp->turn_relay = NULL; 831 --comp->pending_cnt; 832 destroy_component(comp); 833 return status; 834 } 835 836 } 837 771 838 772 839 /* Store this component */ … … 849 916 850 917 /* Create! */ 851 status = pj_ice_sess_create(&ice_st-> stun_cfg, ice_st->obj_name, role,918 status = pj_ice_sess_create(&ice_st->cfg.stun_cfg, ice_st->obj_name, role, 852 919 ice_st->comp_cnt, &ice_cb, 853 920 local_ufrag, local_passwd, &ice_st->ice); … … 877 944 for (j=0; j<comp->cand_cnt; ++j) { 878 945 pj_ice_strans_cand *cand = &comp->cand_list[j]; 946 pj_sockaddr_t *local_addr, *relay_addr; 879 947 880 948 /* Skip if candidate is not ready */ … … 886 954 } 887 955 956 if (cand->type == PJ_ICE_CAND_TYPE_RELAYED) { 957 local_addr = &cand->addr; 958 relay_addr = &cand->addr; 959 } else { 960 local_addr = &comp->local_addr; 961 relay_addr = NULL; 962 } 888 963 status = pj_ice_sess_add_cand(ice_st->ice, comp->comp_id, 889 964 cand->type, cand->local_pref, … … 978 1053 979 1054 /* 980 * Send packet using non-ICE means (e.g. when ICE was not negotiated).1055 * Application wants to send outgoing packet. 981 1056 */ 982 1057 PJ_DEF(pj_status_t) pj_ice_strans_sendto( pj_ice_strans *ice_st, … … 998 1073 /* If ICE is available, send data with ICE */ 999 1074 if (ice_st->ice) { 1000 return pj_ice_sess_send_data(ice_st->ice, comp_id, data, data_len); 1075 if (comp->turn_relay) { 1076 pj_turn_sock_lock(comp->turn_relay); 1077 } 1078 status = pj_ice_sess_send_data(ice_st->ice, comp_id, data, data_len); 1079 if (comp->turn_relay) { 1080 pj_turn_sock_unlock(comp->turn_relay); 1081 } 1082 return status; 1001 1083 } 1002 1084 … … 1029 1111 static pj_status_t ice_tx_pkt(pj_ice_sess *ice, 1030 1112 unsigned comp_id, 1113 unsigned cand_id, 1031 1114 const void *pkt, pj_size_t size, 1032 1115 const pj_sockaddr_t *dst_addr, … … 1034 1117 { 1035 1118 pj_ice_strans *ice_st = (pj_ice_strans*)ice->user_data; 1036 pj_ice_strans_comp *comp = NULL;1037 pj_ ssize_t pkt_size;1119 pj_ice_strans_comp *comp; 1120 pj_ice_strans_cand *cand; 1038 1121 pj_status_t status; 1039 1122 1040 PJ_TODO(TX_TO_RELAY);1041 1042 1123 PJ_ASSERT_RETURN(comp_id && comp_id <= ice_st->comp_cnt, PJ_EINVAL); 1124 1043 1125 comp = ice_st->comp[comp_id-1]; 1126 cand = &comp->cand_list[cand_id]; 1044 1127 1045 1128 TRACE_PKT((comp->ice_st->obj_name, 1046 "Component %d TX packet to %s:%d",1047 comp_id, 1129 "Component %d candidate %d TX packet to %s:%d", 1130 comp_id, cand_id, 1048 1131 pj_inet_ntoa(((pj_sockaddr_in*)dst_addr)->sin_addr), 1049 1132 (int)pj_ntohs(((pj_sockaddr_in*)dst_addr)->sin_port))); 1050 1133 1051 pkt_size = size; 1052 status = pj_ioqueue_sendto(comp->key, &comp->write_op, 1053 pkt, &pkt_size, 0, 1054 dst_addr, dst_addr_len); 1134 if (cand->type == PJ_ICE_CAND_TYPE_RELAYED) { 1135 if (comp->turn_relay) { 1136 status = pj_turn_sock_sendto(comp->turn_relay, pkt, size, 1137 dst_addr, dst_addr_len); 1138 } else { 1139 status = PJ_EINVALIDOP; 1140 } 1141 } else { 1142 pj_ssize_t pkt_size = size; 1143 status = pj_ioqueue_sendto(comp->key, &comp->write_op, 1144 pkt, &pkt_size, 0, 1145 dst_addr, dst_addr_len); 1146 } 1055 1147 1056 1148 return (status==PJ_SUCCESS||status==PJ_EPENDING) ? PJ_SUCCESS : status; … … 1207 1299 } 1208 1300 1301 1302 /* Callback when TURN client has received a packet */ 1303 static void turn_on_rx_data(pj_turn_sock *turn_sock, 1304 void *pkt, 1305 unsigned pkt_len, 1306 const pj_sockaddr_t *peer_addr, 1307 unsigned addr_len) 1308 { 1309 pj_ice_strans_comp *comp; 1310 unsigned cand_id; 1311 pj_status_t status; 1312 1313 comp = (pj_ice_strans_comp*) pj_turn_sock_get_user_data(turn_sock); 1314 if (comp == NULL) { 1315 return; 1316 } 1317 1318 /* Find candidate ID for this packet */ 1319 for (cand_id=0; cand_id<comp->cand_cnt; ++cand_id) { 1320 if (comp->cand_list[cand_id].type == PJ_ICE_CAND_TYPE_RELAYED) 1321 break; 1322 } 1323 if (cand_id == comp->cand_cnt) { 1324 pj_assert(!"Missing relay candidate"); 1325 return; 1326 } 1327 1328 /* Hand over the packet to ICE */ 1329 status = pj_ice_sess_on_rx_pkt(comp->ice_st->ice, comp->comp_id, 1330 cand_id, pkt, pkt_len, 1331 peer_addr, addr_len); 1332 1333 if (status != PJ_SUCCESS) { 1334 ice_st_perror(comp->ice_st, "Error processing packet from TURN relay", 1335 status); 1336 } 1337 } 1338 1339 1340 /* Callback when TURN client state has changed */ 1341 static void turn_on_state(pj_turn_sock *turn_sock, pj_turn_state_t old_state, 1342 pj_turn_state_t new_state) 1343 { 1344 pj_ice_strans_comp *comp; 1345 1346 comp = (pj_ice_strans_comp*) pj_turn_sock_get_user_data(turn_sock); 1347 if (comp == NULL) { 1348 /* Not interested in further state notification once the relay is 1349 * disconnecting. 1350 */ 1351 return; 1352 } 1353 1354 PJ_LOG(5,(comp->ice_st->obj_name, "TURN client state changed %s --> %s", 1355 pj_turn_state_name(old_state), pj_turn_state_name(new_state))); 1356 1357 if (old_state < PJ_TURN_STATE_READY && 1358 new_state >= PJ_TURN_STATE_READY) 1359 { 1360 pj_assert(comp->pending_cnt > 0); 1361 comp->pending_cnt--; 1362 } 1363 1364 if (new_state == PJ_TURN_STATE_READY) { 1365 pj_turn_session_info rel_info; 1366 char ipaddr[PJ_INET6_ADDRSTRLEN+8]; 1367 pj_ice_strans_cand *cand; 1368 1369 /* Get allocation info */ 1370 pj_turn_sock_get_info(turn_sock, &rel_info); 1371 1372 /* Add a relay candidate to this component */ 1373 pj_assert(comp->cand_cnt < PJ_ICE_ST_MAX_CAND); 1374 cand = &comp->cand_list[comp->cand_cnt++]; 1375 1376 /* Add new candidate to this component */ 1377 cand->type = PJ_ICE_CAND_TYPE_RELAYED; 1378 cand->status = PJ_SUCCESS; 1379 cand->ice_cand_id = -1; 1380 cand->local_pref = 65535; 1381 pj_sockaddr_cp(&cand->addr, &rel_info.relay_addr); 1382 pj_ice_calc_foundation(comp->ice_st->pool, &cand->foundation, 1383 PJ_ICE_CAND_TYPE_RELAYED, 1384 &rel_info.relay_addr); 1385 1386 PJ_LOG(4,(comp->ice_st->obj_name, 1387 "Component %d cand %d: relay address: %s", 1388 comp->comp_id, cand - comp->cand_list, 1389 pj_sockaddr_print(&rel_info.relay_addr, ipaddr, 1390 sizeof(ipaddr), 3))); 1391 1392 } else if (new_state >= PJ_TURN_STATE_DEALLOCATING) { 1393 /* Unregister ourself from the TURN relay */ 1394 pj_turn_sock_set_user_data(turn_sock, NULL); 1395 comp->turn_relay = NULL; 1396 1397 PJ_LOG(4,(comp->ice_st->obj_name, "Relay destroyed")); 1398 } 1399 } 1400
Note: See TracChangeset
for help on using the changeset viewer.