Changeset 4728 for pjproject/trunk/pjnath/src/pjturn-srv/allocation.c
- Timestamp:
- Feb 4, 2014 10:13:56 AM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjnath/src/pjturn-srv/allocation.c
r4360 r4728 1 1 /* $Id$ */ 2 /* 2 /* 3 3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) 4 4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> … … 16 16 * You should have received a copy of the GNU General Public License 17 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 19 */ 20 20 #include "turn.h" … … 63 63 pj_turn_relay_res *relay); 64 64 static void destroy_relay(pj_turn_relay_res *relay); 65 static void on_rx_from_peer(pj_ioqueue_key_t *key, 66 pj_ioqueue_op_key_t *op_key, 65 static void on_rx_from_peer(pj_ioqueue_key_t *key, 66 pj_ioqueue_op_key_t *op_key, 67 67 pj_ssize_t bytes_read); 68 68 static pj_status_t stun_on_send_msg(pj_stun_session *sess, … … 125 125 /* Check if we can satisfy the bandwidth */ 126 126 if (cfg->bandwidth > MAX_CLIENT_BANDWIDTH) { 127 pj_stun_session_respond(sess, rdata, 127 pj_stun_session_respond(sess, rdata, 128 128 PJ_STUN_SC_ALLOCATION_QUOTA_REACHED, 129 129 "Invalid bandwidth", NULL, PJ_TRUE, … … 137 137 if (attr_req_tp == NULL) { 138 138 pj_stun_session_respond(sess, rdata, PJ_STUN_SC_BAD_REQUEST, 139 "Missing REQUESTED-TRANSPORT attribute", 139 "Missing REQUESTED-TRANSPORT attribute", 140 140 NULL, PJ_TRUE, src_addr, src_addr_len); 141 141 return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_BAD_REQUEST); … … 157 157 if (attr_res_token) { 158 158 /* We don't support RESERVATION-TOKEN for now */ 159 pj_stun_session_respond(sess, rdata, 159 pj_stun_session_respond(sess, rdata, 160 160 PJ_STUN_SC_BAD_REQUEST, 161 "RESERVATION-TOKEN is not supported", NULL, 161 "RESERVATION-TOKEN is not supported", NULL, 162 162 PJ_TRUE, src_addr, src_addr_len); 163 163 return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_BAD_REQUEST); … … 171 171 if (cfg->lifetime < MIN_LIFETIME) { 172 172 pj_stun_session_respond(sess, rdata, PJ_STUN_SC_BAD_REQUEST, 173 "LIFETIME too short", NULL, 173 "LIFETIME too short", NULL, 174 174 PJ_TRUE, src_addr, src_addr_len); 175 175 return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_BAD_REQUEST); … … 207 207 /* Add LIFETIME. */ 208 208 pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg, 209 PJ_STUN_ATTR_LIFETIME, 209 PJ_STUN_ATTR_LIFETIME, 210 210 (unsigned)alloc->relay.lifetime); 211 211 … … 223 223 &alloc->hkey.clt_addr, 224 224 pj_sockaddr_get_len(&alloc->hkey.clt_addr)); 225 225 226 226 /* Send the response */ 227 227 return pj_stun_session_send_msg(srv_sess, transport, PJ_TRUE, 228 PJ_FALSE, &alloc->hkey.clt_addr, 228 PJ_FALSE, &alloc->hkey.clt_addr, 229 229 pj_sockaddr_get_len(&alloc->hkey.clt_addr), 230 230 tdata); … … 256 256 257 257 /* Lookup the password */ 258 status = pj_turn_get_password(NULL, NULL, &realm->value, 259 &user->value, alloc->pool, 260 &alloc->cred.data.static_cred.data_type, 258 status = pj_turn_get_password(NULL, NULL, &realm->value, 259 &user->value, alloc->pool, 260 &alloc->cred.data.static_cred.data_type, 261 261 &alloc->cred.data.static_cred.data); 262 262 if (status != PJ_SUCCESS) … … 315 315 pj_memcpy(&alloc->hkey.clt_addr, src_addr, src_addr_len); 316 316 317 status = pj_lock_create_recursive_mutex(pool, alloc->obj_name, 317 status = pj_lock_create_recursive_mutex(pool, alloc->obj_name, 318 318 &alloc->lock); 319 319 if (status != PJ_SUCCESS) { … … 328 328 329 329 /* Print info */ 330 pj_ansi_strcpy(alloc->info, 330 pj_ansi_strcpy(alloc->info, 331 331 pj_turn_tp_type_name(transport->listener->tp_type)); 332 332 alloc->info[3] = ':'; … … 372 372 373 373 /* Done */ 374 pj_sockaddr_print(&alloc->relay.hkey.addr, str_tmp, 374 pj_sockaddr_print(&alloc->relay.hkey.addr, str_tmp, 375 375 sizeof(str_tmp), 3); 376 PJ_LOG(4,(alloc->obj_name, "Client %s created, relay addr=%s:%s", 376 PJ_LOG(4,(alloc->obj_name, "Client %s created, relay addr=%s:%s", 377 377 alloc->info, pj_turn_tp_type_name(req.tp_type), str_tmp)); 378 378 … … 384 384 /* Send reply to the ALLOCATE request */ 385 385 pj_strerror(status, str_tmp, sizeof(str_tmp)); 386 pj_stun_session_respond(srv_sess, rdata, PJ_STUN_SC_BAD_REQUEST, str_tmp, 386 pj_stun_session_respond(srv_sess, rdata, PJ_STUN_SC_BAD_REQUEST, str_tmp, 387 387 transport, PJ_TRUE, src_addr, src_addr_len); 388 388 … … 397 397 { 398 398 if (relay->timer.id) { 399 pj_timer_heap_cancel(relay->allocation->server->core.timer_heap, 399 pj_timer_heap_cancel(relay->allocation->server->core.timer_heap, 400 400 &relay->timer); 401 401 relay->timer.id = PJ_FALSE; … … 483 483 484 484 /* Initiate shutdown sequence for this allocation and start destroy timer. 485 * Once allocation is marked as shutting down, any packets will be 486 * rejected/discarded 485 * Once allocation is marked as shutting down, any packets will be 486 * rejected/discarded 487 487 */ 488 488 static void alloc_shutdown(pj_turn_allocation *alloc) … … 502 502 */ 503 503 return; 504 } 504 } 505 505 506 506 pj_assert(alloc->relay.timer.id == TIMER_ID_NONE); … … 531 531 pj_assert(alloc->relay.timer.id != TIMER_ID_DESTROY); 532 532 if (alloc->relay.timer.id != 0) { 533 pj_timer_heap_cancel(alloc->server->core.timer_heap, 533 pj_timer_heap_cancel(alloc->server->core.timer_heap, 534 534 &alloc->relay.timer); 535 535 alloc->relay.timer.id = TIMER_ID_NONE; … … 540 540 541 541 alloc->relay.timer.id = TIMER_ID_TIMEOUT; 542 status = pj_timer_heap_schedule(alloc->server->core.timer_heap, 542 status = pj_timer_heap_schedule(alloc->server->core.timer_heap, 543 543 &alloc->relay.timer, &delay); 544 544 if (status != PJ_SUCCESS) { … … 566 566 e->id = TIMER_ID_NONE; 567 567 568 PJ_LOG(4,(alloc->obj_name, 569 "Client %s refresh timed-out, shutting down..", 568 PJ_LOG(4,(alloc->obj_name, 569 "Client %s refresh timed-out, shutting down..", 570 570 alloc->info)); 571 571 … … 575 575 e->id = TIMER_ID_NONE; 576 576 577 PJ_LOG(4,(alloc->obj_name, "Client %s destroying..", 577 PJ_LOG(4,(alloc->obj_name, "Client %s destroying..", 578 578 alloc->info)); 579 579 … … 601 601 602 602 pj_bzero(relay, sizeof(*relay)); 603 603 604 604 relay->allocation = alloc; 605 605 relay->tp.sock = PJ_INVALID_SOCKET; 606 606 607 607 /* TODO: get the requested address family from somewhere */ 608 608 af = alloc->transport->listener->addr.addr.sa_family; … … 622 622 /* Lifetime and timeout */ 623 623 relay->lifetime = req->lifetime; 624 pj_timer_entry_init(&relay->timer, TIMER_ID_NONE, relay, 624 pj_timer_entry_init(&relay->timer, TIMER_ID_NONE, relay, 625 625 &relay_timeout_cb); 626 626 resched_timeout(alloc); 627 627 628 628 /* Transport type */ 629 629 relay->hkey.tp_type = req->tp_type; … … 677 677 pj_sockaddr_init(af, &bound_addr, NULL, port); 678 678 679 status = pj_sock_bind(relay->tp.sock, &bound_addr, 679 status = pj_sock_bind(relay->tp.sock, &bound_addr, 680 680 pj_sockaddr_get_len(&bound_addr)); 681 681 if (status == PJ_SUCCESS) … … 685 685 if (status != PJ_SUCCESS) { 686 686 /* Unable to allocate port */ 687 PJ_LOG(4,(THIS_FILE, "Unable to allocate relay, giving up: err %d", 687 PJ_LOG(4,(THIS_FILE, "Unable to allocate relay, giving up: err %d", 688 688 status)); 689 689 pj_sock_close(relay->tp.sock); … … 696 696 status = pj_sock_getsockname(relay->tp.sock, &relay->hkey.addr, &namelen); 697 697 if (status != PJ_SUCCESS) { 698 PJ_LOG(4,(THIS_FILE, "pj_sock_getsockname() failed: err %d", 698 PJ_LOG(4,(THIS_FILE, "pj_sock_getsockname() failed: err %d", 699 699 status)); 700 700 pj_sock_close(relay->tp.sock); … … 703 703 } 704 704 if (!pj_sockaddr_has_addr(&relay->hkey.addr)) { 705 pj_sockaddr_copy_addr(&relay->hkey.addr, 705 pj_sockaddr_copy_addr(&relay->hkey.addr, 706 706 &alloc->transport->listener->addr); 707 707 } … … 719 719 relay, &icb, &relay->tp.key); 720 720 if (status != PJ_SUCCESS) { 721 PJ_LOG(4,(THIS_FILE, "pj_ioqueue_register_sock() failed: err %d", 721 PJ_LOG(4,(THIS_FILE, "pj_ioqueue_register_sock() failed: err %d", 722 722 status)); 723 723 pj_sock_close(relay->tp.sock); … … 737 737 static void send_reply_err(pj_turn_allocation *alloc, 738 738 const pj_stun_rx_data *rdata, 739 pj_bool_t cache, 739 pj_bool_t cache, 740 740 int code, const char *errmsg) 741 741 { 742 742 pj_status_t status; 743 743 744 status = pj_stun_session_respond(alloc->sess, rdata, code, errmsg, NULL, 744 status = pj_stun_session_respond(alloc->sess, rdata, code, errmsg, NULL, 745 745 cache, &alloc->hkey.clt_addr, 746 746 pj_sockaddr_get_len(&alloc->hkey.clt_addr.addr)); … … 787 787 } 788 788 789 status = pj_stun_session_send_msg(alloc->sess, NULL, PJ_TRUE, 790 PJ_FALSE, &alloc->hkey.clt_addr, 791 pj_sockaddr_get_len(&alloc->hkey.clt_addr), 789 status = pj_stun_session_send_msg(alloc->sess, NULL, PJ_TRUE, 790 PJ_FALSE, &alloc->hkey.clt_addr, 791 pj_sockaddr_get_len(&alloc->hkey.clt_addr), 792 792 tdata); 793 793 if (status != PJ_SUCCESS) { … … 807 807 perm = PJ_POOL_ZALLOC_T(alloc->pool, pj_turn_permission); 808 808 pj_memcpy(&perm->hkey.peer_addr, peer_addr, addr_len); 809 809 810 810 perm->allocation = alloc; 811 811 perm->channel = PJ_TURN_INVALID_CHANNEL; … … 815 815 816 816 /* Register to hash table (only the address part!) */ 817 pj_hash_set(alloc->pool, alloc->peer_table, 818 pj_sockaddr_get_addr(&perm->hkey.peer_addr), 817 pj_hash_set(alloc->pool, alloc->peer_table, 818 pj_sockaddr_get_addr(&perm->hkey.peer_addr), 819 819 pj_sockaddr_get_addr_len(&perm->hkey.peer_addr), 0, perm); 820 820 … … 835 835 836 836 /* Remove from permission hash table */ 837 pj_hash_set(NULL, alloc->peer_table, 838 pj_sockaddr_get_addr(&perm->hkey.peer_addr), 837 pj_hash_set(NULL, alloc->peer_table, 838 pj_sockaddr_get_addr(&perm->hkey.peer_addr), 839 839 pj_sockaddr_get_addr_len(&perm->hkey.peer_addr), 0, NULL); 840 840 841 841 /* Remove from channel hash table, if assigned a channel number */ 842 842 if (perm->channel != PJ_TURN_INVALID_CHANNEL) { 843 pj_hash_set(NULL, alloc->ch_table, &perm->channel, 843 pj_hash_set(NULL, alloc->ch_table, &perm->channel, 844 844 sizeof(perm->channel), 0, NULL); 845 845 } … … 859 859 860 860 /* Lookup in peer hash table */ 861 perm = (pj_turn_permission*) 862 pj_hash_get(alloc->peer_table, 861 perm = (pj_turn_permission*) 862 pj_hash_get(alloc->peer_table, 863 863 pj_sockaddr_get_addr(peer_addr), 864 pj_sockaddr_get_addr_len(peer_addr), 864 pj_sockaddr_get_addr_len(peer_addr), 865 865 NULL); 866 866 return perm ? check_permission_expiry(perm) : NULL; … … 881 881 } 882 882 883 /* Update permission because of data from client to peer. 883 /* Update permission because of data from client to peer. 884 884 * Return PJ_TRUE is permission is found. 885 885 */ … … 917 917 * callbacks. 918 918 * 919 * Note: currently it is necessary to specify the 919 * Note: currently it is necessary to specify the 920 920 * PJ_STUN_NO_FINGERPRINT_CHECK otherwise the FINGERPRINT 921 921 * attribute inside STUN Send Indication message will mess up … … 930 930 status = pj_stun_session_on_rx_pkt(alloc->sess, pkt->pkt, pkt->len, 931 931 options, NULL, &parsed_len, 932 &pkt->src.clt_addr, 932 &pkt->src.clt_addr, 933 933 pkt->src_addr_len); 934 934 … … 963 963 if (alloc->transport->listener->tp_type == PJ_TURN_TP_UDP) { 964 964 if (pkt->len < pj_ntohs(cd->length)+sizeof(*cd)) { 965 PJ_LOG(4,(alloc->obj_name, 965 PJ_LOG(4,(alloc->obj_name, 966 966 "ChannelData from %s discarded: UDP size error", 967 967 alloc->info)); … … 976 976 if (!perm) { 977 977 /* Discard */ 978 PJ_LOG(4,(alloc->obj_name, 978 PJ_LOG(4,(alloc->obj_name, 979 979 "ChannelData from %s discarded: ch#0x%x not found", 980 980 alloc->info, pj_ntohs(cd->ch_number))); … … 999 999 1000 1000 /* 1001 * Handle incoming packet from peer. This function is called by 1001 * Handle incoming packet from peer. This function is called by 1002 1002 * on_rx_from_peer(). 1003 1003 */ … … 1010 1010 1011 1011 /* Lookup permission */ 1012 perm = lookup_permission_by_addr(alloc, src_addr, 1012 perm = lookup_permission_by_addr(alloc, src_addr, 1013 1013 pj_sockaddr_get_len(src_addr)); 1014 1014 if (perm == NULL) { … … 1050 1050 pj_status_t status; 1051 1051 1052 status = pj_stun_session_create_ind(alloc->sess, 1052 status = pj_stun_session_create_ind(alloc->sess, 1053 1053 PJ_STUN_DATA_INDICATION, &tdata); 1054 1054 if (status != PJ_SUCCESS) { … … 1057 1057 } 1058 1058 1059 pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg, 1059 pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg, 1060 1060 PJ_STUN_ATTR_XOR_PEER_ADDR, PJ_TRUE, 1061 1061 src_addr, pj_sockaddr_get_len(src_addr)); 1062 1062 pj_stun_msg_add_binary_attr(tdata->pool, tdata->msg, 1063 PJ_STUN_ATTR_DATA, 1063 PJ_STUN_ATTR_DATA, 1064 1064 (const pj_uint8_t*)pkt, len); 1065 1065 1066 pj_stun_session_send_msg(alloc->sess, NULL, PJ_FALSE, 1067 PJ_FALSE, &alloc->hkey.clt_addr, 1068 pj_sockaddr_get_len(&alloc->hkey.clt_addr), 1066 pj_stun_session_send_msg(alloc->sess, NULL, PJ_FALSE, 1067 PJ_FALSE, &alloc->hkey.clt_addr, 1068 pj_sockaddr_get_len(&alloc->hkey.clt_addr), 1069 1069 tdata); 1070 1070 } … … 1074 1074 * ioqueue notification on RX packets from the relay socket. 1075 1075 */ 1076 static void on_rx_from_peer(pj_ioqueue_key_t *key, 1077 pj_ioqueue_op_key_t *op_key, 1076 static void on_rx_from_peer(pj_ioqueue_key_t *key, 1077 pj_ioqueue_op_key_t *op_key, 1078 1078 pj_ssize_t bytes_read) 1079 1079 { … … 1097 1097 status = pj_ioqueue_recvfrom(key, op_key, 1098 1098 rel->tp.rx_pkt, &bytes_read, 0, 1099 &rel->tp.src_addr, 1099 &rel->tp.src_addr, 1100 1100 &rel->tp.src_addr_len); 1101 1101 … … 1157 1157 if (alloc->relay.lifetime == 0) { 1158 1158 /* Reject with 437 if we're shutting down */ 1159 send_reply_err(alloc, rdata, PJ_TRUE, 1159 send_reply_err(alloc, rdata, PJ_TRUE, 1160 1160 PJ_STUN_SC_ALLOCATION_MISMATCH, NULL); 1161 1161 return PJ_SUCCESS; … … 1163 1163 1164 1164 if (msg->hdr.type == PJ_STUN_REFRESH_REQUEST) { 1165 /* 1166 * Handle REFRESH request 1165 /* 1166 * Handle REFRESH request 1167 1167 */ 1168 1168 pj_stun_lifetime_attr *lifetime; … … 1176 1176 bandwidth = (pj_stun_bandwidth_attr*) 1177 1177 pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_BANDWIDTH, 0); 1178 1179 /* TODO: process bandwidth */ 1180 PJ_UNUSED_ARG(bandwidth); 1178 1181 1179 1182 if (lifetime && lifetime->value==0) { … … 1187 1190 1188 1191 /* Shutdown allocation */ 1189 PJ_LOG(4,(alloc->obj_name, 1192 PJ_LOG(4,(alloc->obj_name, 1190 1193 "Client %s request to dealloc, shutting down", 1191 1194 alloc->info)); … … 1197 1200 * This is a refresh request. 1198 1201 */ 1199 1202 1200 1203 /* Update lifetime */ 1201 1204 if (lifetime) { … … 1227 1230 1228 1231 if (!ch_attr || !peer_attr) { 1229 send_reply_err(alloc, rdata, PJ_TRUE, 1232 send_reply_err(alloc, rdata, PJ_TRUE, 1230 1233 PJ_STUN_SC_BAD_REQUEST, NULL); 1231 1234 return PJ_SUCCESS; … … 1235 1238 p1 = lookup_permission_by_chnum(alloc, PJ_STUN_GET_CH_NB(ch_attr->value)); 1236 1239 1237 /* If permission is found, this is supposed to be a channel bind 1240 /* If permission is found, this is supposed to be a channel bind 1238 1241 * refresh. Make sure it's for the same peer. 1239 1242 */ … … 1241 1244 if (pj_sockaddr_cmp(&p1->hkey.peer_addr, &peer_attr->sockaddr)) { 1242 1245 /* Address mismatch. Send 400 */ 1243 send_reply_err(alloc, rdata, PJ_TRUE, 1244 PJ_STUN_SC_BAD_REQUEST, 1246 send_reply_err(alloc, rdata, PJ_TRUE, 1247 PJ_STUN_SC_BAD_REQUEST, 1245 1248 "Peer address mismatch"); 1246 1249 return PJ_SUCCESS; … … 1263 1266 pj_sockaddr_get_len(&peer_attr->sockaddr)); 1264 1267 if (p2 && p2->channel != PJ_TURN_INVALID_CHANNEL) { 1265 send_reply_err(alloc, rdata, PJ_TRUE, PJ_STUN_SC_BAD_REQUEST, 1268 send_reply_err(alloc, rdata, PJ_TRUE, PJ_STUN_SC_BAD_REQUEST, 1266 1269 "Peer address already assigned a channel number"); 1267 1270 return PJ_SUCCESS; … … 1281 1284 /* Register to hash table */ 1282 1285 pj_assert(sizeof(p2->channel==2)); 1283 pj_hash_set(alloc->pool, alloc->ch_table, &p2->channel, 1286 pj_hash_set(alloc->pool, alloc->ch_table, &p2->channel, 1284 1287 sizeof(p2->channel), 0, p2); 1285 1288 … … 1368 1371 /* Relay the data to peer */ 1369 1372 len = data_attr->length; 1370 pj_sock_sendto(alloc->relay.tp.sock, data_attr->data, 1373 pj_sock_sendto(alloc->relay.tp.sock, data_attr->data, 1371 1374 &len, 0, &peer_attr->sockaddr, 1372 1375 pj_sockaddr_get_len(&peer_attr->sockaddr));
Note: See TracChangeset
for help on using the changeset viewer.