Changeset 1988 for pjproject/trunk/pjnath/src/pjnath/stun_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/stun_session.c
r1913 r1988 30 30 void *user_data; 31 31 32 pj_atomic_t *busy; 33 pj_bool_t destroy_request; 34 32 35 pj_bool_t use_fingerprint; 33 36 37 pj_pool_t *rx_pool; 38 39 #if PJ_LOG_MAX_LEVEL >= 5 34 40 char dump_buf[1000]; 41 #endif 42 unsigned log_flag; 35 43 36 44 pj_stun_auth_type auth_type; … … 38 46 int auth_retry; 39 47 pj_str_t next_nonce; 48 pj_str_t server_realm; 40 49 41 50 pj_str_t srv_name; … … 80 89 pj_stun_tx_data *tdata) 81 90 { 82 pj_list_push_ back(&sess->pending_request_list, tdata);91 pj_list_push_front(&sess->pending_request_list, tdata); 83 92 return PJ_SUCCESS; 84 93 } … … 139 148 140 149 tdata = (pj_stun_tx_data*) pj_stun_client_tsx_get_data(tsx); 150 tsx_erase(tdata->sess, tdata); 151 141 152 pj_stun_client_tsx_destroy(tsx); 142 153 pj_pool_release(tdata->pool); 143 154 } 144 155 145 static void destroy_tdata(pj_stun_tx_data *tdata )156 static void destroy_tdata(pj_stun_tx_data *tdata, pj_bool_t force) 146 157 { 147 158 if (tdata->res_timer.id != PJ_FALSE) { … … 152 163 } 153 164 154 if (tdata->client_tsx) { 155 pj_time_val delay = {2, 0}; 156 tsx_erase(tdata->sess, tdata); 157 pj_stun_client_tsx_schedule_destroy(tdata->client_tsx, &delay); 158 tdata->client_tsx = NULL; 165 if (force) { 166 if (tdata->client_tsx) { 167 tsx_erase(tdata->sess, tdata); 168 pj_stun_client_tsx_destroy(tdata->client_tsx); 169 } 170 pj_pool_release(tdata->pool); 159 171 160 172 } else { 161 pj_pool_release(tdata->pool); 173 if (tdata->client_tsx) { 174 pj_time_val delay = {2, 0}; 175 pj_stun_client_tsx_schedule_destroy(tdata->client_tsx, &delay); 176 177 } else { 178 pj_pool_release(tdata->pool); 179 } 162 180 } 163 181 } … … 170 188 { 171 189 PJ_UNUSED_ARG(sess); 172 destroy_tdata(tdata );190 destroy_tdata(tdata, PJ_FALSE); 173 191 } 174 192 … … 290 308 { 291 309 const pj_stun_nonce_attr *anonce; 310 const pj_stun_realm_attr *arealm; 292 311 pj_stun_tx_data *tdata; 293 312 unsigned i; … … 317 336 pj_strdup(sess->pool, &sess->next_nonce, &anonce->value); 318 337 338 /* Copy the realm from the response */ 339 arealm = (pj_stun_realm_attr*) 340 pj_stun_msg_find_attr(response, PJ_STUN_ATTR_REALM, 0); 341 if (arealm) { 342 pj_strdup(sess->pool, &sess->server_realm, &arealm->value); 343 } 344 319 345 /* Create new request */ 320 346 status = pj_stun_session_create_req(sess, request->msg->hdr.type, … … 325 351 326 352 /* Duplicate all the attributes in the old request, except 327 * USERNAME, REALM, M-I, and NONCE 353 * USERNAME, REALM, M-I, and NONCE, which will be filled in 354 * later. 328 355 */ 329 356 for (i=0; i<request->msg->attr_count; ++i) { … … 374 401 sess = tdata->sess; 375 402 403 /* Lock the session and prevent user from destroying us in the callback */ 404 pj_atomic_inc(sess->busy); 405 pj_lock_acquire(sess->lock); 406 376 407 /* Handle authentication challenge */ 377 408 handle_auth_challenge(sess, tdata, response, src_addr, … … 388 419 pj_stun_msg_destroy_tdata(sess, tdata); 389 420 tdata = NULL; 421 422 pj_lock_release(sess->lock); 423 424 if (pj_atomic_dec_and_get(sess->busy)==0 && sess->destroy_request) { 425 pj_stun_session_destroy(sess); 426 return; 427 } 390 428 } 391 429 … … 395 433 { 396 434 pj_stun_tx_data *tdata; 435 pj_stun_session *sess; 436 pj_status_t status; 397 437 398 438 tdata = (pj_stun_tx_data*) pj_stun_client_tsx_get_data(tsx); 399 400 return tdata->sess->cb.on_send_msg(tdata->sess, tdata->token, stun_pkt, 401 pkt_size, tdata->dst_addr, 402 tdata->addr_len); 439 sess = tdata->sess; 440 441 /* Lock the session and prevent user from destroying us in the callback */ 442 pj_atomic_inc(sess->busy); 443 pj_lock_acquire(sess->lock); 444 445 status = sess->cb.on_send_msg(tdata->sess, tdata->token, stun_pkt, 446 pkt_size, tdata->dst_addr, 447 tdata->addr_len); 448 pj_lock_release(sess->lock); 449 450 if (pj_atomic_dec_and_get(sess->busy)==0 && sess->destroy_request) { 451 pj_stun_session_destroy(sess); 452 return PJNATH_ESTUNDESTROYED; 453 } else { 454 return status; 455 } 403 456 } 404 457 … … 429 482 pj_memcpy(&sess->cb, cb, sizeof(*cb)); 430 483 sess->use_fingerprint = fingerprint; 484 sess->log_flag = 0xFFFF; 431 485 432 486 sess->srv_name.ptr = (char*) pj_pool_alloc(pool, 32); … … 434 488 "pj_stun-%s", pj_get_version()); 435 489 490 sess->rx_pool = pj_pool_create(sess->cfg->pf, "name", 491 PJNATH_POOL_LEN_STUN_TDATA, 492 PJNATH_POOL_INC_STUN_TDATA, NULL); 493 436 494 pj_list_init(&sess->pending_request_list); 437 495 pj_list_init(&sess->cached_response_list); … … 444 502 sess->delete_lock = PJ_TRUE; 445 503 504 status = pj_atomic_create(pool, 0, &sess->busy); 505 if (status != PJ_SUCCESS) { 506 pj_lock_destroy(sess->lock); 507 pj_pool_release(pool); 508 return status; 509 } 510 446 511 *p_sess = sess; 447 512 … … 454 519 455 520 pj_lock_acquire(sess->lock); 521 522 /* Can't destroy if we're in a callback */ 523 sess->destroy_request = PJ_TRUE; 524 if (pj_atomic_get(sess->busy)) { 525 pj_lock_release(sess->lock); 526 return PJ_EPENDING; 527 } 528 456 529 while (!pj_list_empty(&sess->pending_request_list)) { 457 530 pj_stun_tx_data *tdata = sess->pending_request_list.next; 458 destroy_tdata(tdata); 459 } 531 destroy_tdata(tdata, PJ_TRUE); 532 } 533 460 534 while (!pj_list_empty(&sess->cached_response_list)) { 461 535 pj_stun_tx_data *tdata = sess->cached_response_list.next; 462 destroy_tdata(tdata );536 destroy_tdata(tdata, PJ_TRUE); 463 537 } 464 538 pj_lock_release(sess->lock); … … 466 540 if (sess->delete_lock) { 467 541 pj_lock_destroy(sess->lock); 542 } 543 544 if (sess->rx_pool) { 545 pj_pool_release(sess->rx_pool); 546 sess->rx_pool = NULL; 468 547 } 469 548 … … 539 618 } 540 619 620 PJ_DEF(void) pj_stun_session_set_log( pj_stun_session *sess, 621 unsigned flags) 622 { 623 PJ_ASSERT_ON_FAIL(sess, return); 624 sess->log_flag = flags; 625 } 541 626 542 627 static pj_status_t get_auth(pj_stun_session *sess, … … 544 629 { 545 630 if (sess->cred.type == PJ_STUN_AUTH_CRED_STATIC) { 546 tdata->auth_info.realm = sess->cred.data.static_cred.realm; 631 //tdata->auth_info.realm = sess->cred.data.static_cred.realm; 632 tdata->auth_info.realm = sess->server_realm; 547 633 tdata->auth_info.username = sess->cred.data.static_cred.username; 548 634 tdata->auth_info.nonce = sess->cred.data.static_cred.nonce; … … 634 720 } 635 721 tdata->auth_info.nonce = sess->next_nonce; 722 tdata->auth_info.realm = sess->server_realm; 636 723 } 637 724 … … 715 802 unsigned pkt_size, const pj_sockaddr_t *addr) 716 803 { 717 char dst_name[ 80];804 char dst_name[PJ_INET6_ADDRSTRLEN+10]; 718 805 806 if ((PJ_STUN_IS_REQUEST(msg->hdr.type) && 807 (sess->log_flag & PJ_STUN_SESS_LOG_TX_REQ)==0) || 808 (PJ_STUN_IS_RESPONSE(msg->hdr.type) && 809 (sess->log_flag & PJ_STUN_SESS_LOG_TX_RES)==0) || 810 (PJ_STUN_IS_INDICATION(msg->hdr.type) && 811 (sess->log_flag & PJ_STUN_SESS_LOG_TX_IND)==0)) 812 { 813 return; 814 } 815 719 816 pj_sockaddr_print(addr, dst_name, sizeof(dst_name), 3); 720 817 … … 750 847 tdata->retransmit = retransmit; 751 848 752 /* Start locking the session now */ 849 /* Lock the session and prevent user from destroying us in the callback */ 850 pj_atomic_inc(sess->busy); 753 851 pj_lock_acquire(sess->lock); 754 852 … … 758 856 if (status != PJ_SUCCESS) { 759 857 pj_stun_msg_destroy_tdata(sess, tdata); 760 pj_lock_release(sess->lock);761 858 LOG_ERR_(sess, "Error applying options", status); 762 return status;859 goto on_return; 763 860 } 764 861 … … 770 867 if (status != PJ_SUCCESS) { 771 868 pj_stun_msg_destroy_tdata(sess, tdata); 772 pj_lock_release(sess->lock);773 869 LOG_ERR_(sess, "STUN encode() error", status); 774 return status;870 goto on_return; 775 871 } 776 872 … … 798 894 if (status != PJ_SUCCESS && status != PJ_EPENDING) { 799 895 pj_stun_msg_destroy_tdata(sess, tdata); 800 pj_lock_release(sess->lock);801 896 LOG_ERR_(sess, "Error sending STUN request", status); 802 return status;897 goto on_return; 803 898 } 804 899 … … 825 920 &timeout); 826 921 if (status != PJ_SUCCESS) { 922 tdata->res_timer.id = PJ_FALSE; 827 923 pj_stun_msg_destroy_tdata(sess, tdata); 828 pj_lock_release(sess->lock);829 924 LOG_ERR_(sess, "Error scheduling response timer", status); 830 return status;925 goto on_return; 831 926 } 832 927 … … 839 934 840 935 if (status != PJ_SUCCESS && status != PJ_EPENDING) { 936 pj_stun_msg_destroy_tdata(sess, tdata); 841 937 LOG_ERR_(sess, "Error sending STUN request", status); 938 goto on_return; 842 939 } 843 940 … … 848 945 } 849 946 850 947 on_return: 851 948 pj_lock_release(sess->lock); 949 950 /* Check if application has called destroy() in the callback */ 951 if (pj_atomic_dec_and_get(sess->busy)==0 && sess->destroy_request) { 952 pj_stun_session_destroy(sess); 953 return PJNATH_ESTUNDESTROYED; 954 } 955 852 956 return status; 853 957 } … … 893 997 PJ_ASSERT_RETURN(PJ_STUN_IS_REQUEST(tdata->msg->hdr.type), PJ_EINVAL); 894 998 999 /* Lock the session and prevent user from destroying us in the callback */ 1000 pj_atomic_inc(sess->busy); 895 1001 pj_lock_acquire(sess->lock); 896 1002 … … 904 1010 905 1011 pj_lock_release(sess->lock); 1012 1013 if (pj_atomic_dec_and_get(sess->busy)==0 && sess->destroy_request) { 1014 pj_stun_session_destroy(sess); 1015 return PJNATH_ESTUNDESTROYED; 1016 } 1017 906 1018 return PJ_SUCCESS; 907 1019 } … … 918 1030 PJ_ASSERT_RETURN(PJ_STUN_IS_REQUEST(tdata->msg->hdr.type), PJ_EINVAL); 919 1031 1032 /* Lock the session and prevent user from destroying us in the callback */ 1033 pj_atomic_inc(sess->busy); 920 1034 pj_lock_acquire(sess->lock); 921 1035 … … 923 1037 924 1038 pj_lock_release(sess->lock); 1039 1040 if (pj_atomic_dec_and_get(sess->busy)==0 && sess->destroy_request) { 1041 pj_stun_session_destroy(sess); 1042 return PJNATH_ESTUNDESTROYED; 1043 } 925 1044 926 1045 return status; … … 1166 1285 1167 1286 1287 /* Print outgoing message to log */ 1288 static void dump_rx_msg(pj_stun_session *sess, const pj_stun_msg *msg, 1289 unsigned pkt_size, const pj_sockaddr_t *addr) 1290 { 1291 char src_info[PJ_INET6_ADDRSTRLEN+10]; 1292 1293 if ((PJ_STUN_IS_REQUEST(msg->hdr.type) && 1294 (sess->log_flag & PJ_STUN_SESS_LOG_RX_REQ)==0) || 1295 (PJ_STUN_IS_RESPONSE(msg->hdr.type) && 1296 (sess->log_flag & PJ_STUN_SESS_LOG_RX_RES)==0) || 1297 (PJ_STUN_IS_INDICATION(msg->hdr.type) && 1298 (sess->log_flag & PJ_STUN_SESS_LOG_RX_IND)==0)) 1299 { 1300 return; 1301 } 1302 1303 pj_sockaddr_print(addr, src_info, sizeof(src_info), 3); 1304 1305 PJ_LOG(5,(SNAME(sess), 1306 "RX %d bytes STUN message from %s:\n" 1307 "--- begin STUN message ---\n" 1308 "%s" 1309 "--- end of STUN message ---\n", 1310 pkt_size, src_info, 1311 pj_stun_msg_dump(msg, sess->dump_buf, sizeof(sess->dump_buf), 1312 NULL))); 1313 1314 } 1315 1316 /* Incoming packet */ 1168 1317 PJ_DEF(pj_status_t) pj_stun_session_on_rx_pkt(pj_stun_session *sess, 1169 1318 const void *packet, … … 1176 1325 { 1177 1326 pj_stun_msg *msg, *response; 1178 pj_pool_t *tmp_pool;1179 char *dump;1180 1327 pj_status_t status; 1181 1328 1182 1329 PJ_ASSERT_RETURN(sess && packet && pkt_size, PJ_EINVAL); 1183 1330 1184 tmp_pool = pj_pool_create(sess->cfg->pf, "tmpstun", 1185 PJNATH_POOL_LEN_STUN_TDATA, 1186 PJNATH_POOL_INC_STUN_TDATA, NULL); 1187 if (!tmp_pool) 1188 return PJ_ENOMEM; 1331 /* Lock the session and prevent user from destroying us in the callback */ 1332 pj_atomic_inc(sess->busy); 1333 pj_lock_acquire(sess->lock); 1334 1335 /* Reset pool */ 1336 pj_pool_reset(sess->rx_pool); 1189 1337 1190 1338 /* Try to parse the message */ 1191 status = pj_stun_msg_decode( tmp_pool, (const pj_uint8_t*)packet,1339 status = pj_stun_msg_decode(sess->rx_pool, (const pj_uint8_t*)packet, 1192 1340 pkt_size, options, 1193 1341 &msg, parsed_len, &response); … … 1195 1343 LOG_ERR_(sess, "STUN msg_decode() error", status); 1196 1344 if (response) { 1197 send_response(sess, token, tmp_pool, response, NULL,1345 send_response(sess, token, sess->rx_pool, response, NULL, 1198 1346 PJ_FALSE, src_addr, src_addr_len); 1199 1347 } 1200 pj_pool_release(tmp_pool); 1201 return status; 1202 } 1203 1204 dump = (char*) pj_pool_alloc(tmp_pool, PJ_STUN_MAX_PKT_LEN); 1205 1206 PJ_LOG(5,(SNAME(sess), 1207 "RX STUN message from %s:%d:\n" 1208 "--- begin STUN message ---\n" 1209 "%s" 1210 "--- end of STUN message ---\n", 1211 pj_inet_ntoa(((pj_sockaddr_in*)src_addr)->sin_addr), 1212 pj_ntohs(((pj_sockaddr_in*)src_addr)->sin_port), 1213 pj_stun_msg_dump(msg, dump, PJ_STUN_MAX_PKT_LEN, NULL))); 1214 1215 pj_lock_acquire(sess->lock); 1348 goto on_return; 1349 } 1350 1351 dump_rx_msg(sess, msg, pkt_size, src_addr); 1216 1352 1217 1353 /* For requests, check if we have cached response */ 1218 status = check_cached_response(sess, tmp_pool, msg,1354 status = check_cached_response(sess, sess->rx_pool, msg, 1219 1355 src_addr, src_addr_len); 1220 1356 if (status == PJ_SUCCESS) { … … 1232 1368 } else if (PJ_STUN_IS_REQUEST(msg->hdr.type)) { 1233 1369 1234 status = on_incoming_request(sess, options, token, tmp_pool,1370 status = on_incoming_request(sess, options, token, sess->rx_pool, 1235 1371 (const pj_uint8_t*) packet, pkt_size, 1236 1372 msg, src_addr, src_addr_len); … … 1238 1374 } else if (PJ_STUN_IS_INDICATION(msg->hdr.type)) { 1239 1375 1240 status = on_incoming_indication(sess, token, tmp_pool,1376 status = on_incoming_indication(sess, token, sess->rx_pool, 1241 1377 (const pj_uint8_t*) packet, pkt_size, 1242 1378 msg, src_addr, src_addr_len); … … 1250 1386 pj_lock_release(sess->lock); 1251 1387 1252 pj_pool_release(tmp_pool); 1388 /* If we've received destroy request while we're on the callback, 1389 * destroy the session now. 1390 */ 1391 if (pj_atomic_dec_and_get(sess->busy)==0 && sess->destroy_request) { 1392 pj_stun_session_destroy(sess); 1393 return PJNATH_ESTUNDESTROYED; 1394 } 1395 1253 1396 return status; 1254 1397 } 1255 1398 1256 1257
Note: See TracChangeset
for help on using the changeset viewer.