Changeset 1852 for pjproject/trunk/pjnath/src/pjturn-srv/server.c
- Timestamp:
- Mar 9, 2008 12:55:00 PM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjnath/src/pjturn-srv/server.c
r1850 r1852 18 18 */ 19 19 #include "turn.h" 20 #include "auth.h" 20 21 21 22 #define MAX_CLIENTS 32 22 23 #define MAX_PEERS_PER_CLIENT 8 23 #define MAX_HANDLES (MAX_CLIENTS*MAX_PEERS_PER_CLIENT+MAX_LISTENERS) 24 //#define MAX_HANDLES (MAX_CLIENTS*MAX_PEERS_PER_CLIENT+MAX_LISTENERS) 25 #define MAX_HANDLES PJ_IOQUEUE_MAX_HANDLES 24 26 #define MAX_TIMER (MAX_HANDLES * 2) 25 27 #define MIN_PORT 49152 … … 27 29 #define MAX_LISTENERS 16 28 30 #define MAX_THREADS 2 29 30 #define MAX_CLIENT_BANDWIDTH 128 /* In Kbps */ 31 #define DEFA_CLIENT_BANDWIDTH 64 32 33 #define MIN_LIFETIME 32 34 #define MAX_LIFETIME 600 35 #define DEF_LIFETIME 300 36 31 #define MAX_NET_EVENTS 10 37 32 38 33 /* Prototypes */ 34 static int server_thread_proc(void *arg); 39 35 static pj_status_t on_tx_stun_msg( pj_stun_session *sess, 40 36 const void *pkt, … … 49 45 unsigned src_addr_len); 50 46 51 /* 52 * Get transport type name. 53 */ 54 PJ_DEF(const char*) pjturn_tp_type_name(int tp_type) 47 struct saved_cred 48 { 49 pj_str_t realm; 50 pj_str_t username; 51 pj_str_t nonce; 52 int data_type; 53 pj_str_t data; 54 }; 55 56 57 /* 58 * Get transport type name, normally for logging purpose only. 59 */ 60 PJ_DEF(const char*) pj_turn_tp_type_name(int tp_type) 55 61 { 56 62 /* Must be 3 characters long! */ 57 if (tp_type == PJ TURN_TP_UDP)63 if (tp_type == PJ_TURN_TP_UDP) { 58 64 return "UDP"; 59 else if (tp_type == PJTURN_TP_TCP)65 } else if (tp_type == PJ_TURN_TP_TCP) { 60 66 return "TCP"; 61 else 67 } else { 68 pj_assert(!"Unsupported transport"); 62 69 return "???"; 70 } 63 71 } 64 72 … … 66 74 * Create server. 67 75 */ 68 PJ_DEF(pj_status_t) pj turn_srv_create( pj_pool_factory *pf,69 pj turn_srv **p_srv)76 PJ_DEF(pj_status_t) pj_turn_srv_create(pj_pool_factory *pf, 77 pj_turn_srv **p_srv) 70 78 { 71 79 pj_pool_t *pool; 72 pjturn_srv *srv; 80 pj_turn_srv *srv; 81 unsigned i; 73 82 pj_status_t status; 74 83 … … 77 86 /* Create server and init core settings */ 78 87 pool = pj_pool_create(pf, "srv%p", 1000, 1000, NULL); 79 srv = PJ_POOL_ZALLOC_T(pool, pj turn_srv);80 srv-> core.obj_name = pool->obj_name;88 srv = PJ_POOL_ZALLOC_T(pool, pj_turn_srv); 89 srv->obj_name = pool->obj_name; 81 90 srv->core.pf = pf; 82 91 srv->core.pool = pool; 92 srv->core.tls_key = srv->core.tls_data = -1; 83 93 94 /* Create ioqueue */ 84 95 status = pj_ioqueue_create(pool, MAX_HANDLES, &srv->core.ioqueue); 85 96 if (status != PJ_SUCCESS) 86 97 goto on_error; 87 98 99 /* Server mutex */ 100 status = pj_lock_create_recursive_mutex(pool, srv->obj_name, 101 &srv->core.lock); 102 if (status != PJ_SUCCESS) 103 goto on_error; 104 105 /* Allocate TLS */ 106 status = pj_thread_local_alloc(&srv->core.tls_key); 107 if (status != PJ_SUCCESS) 108 goto on_error; 109 110 status = pj_thread_local_alloc(&srv->core.tls_data); 111 if (status != PJ_SUCCESS) 112 goto on_error; 113 114 /* Create timer heap */ 88 115 status = pj_timer_heap_create(pool, MAX_TIMER, &srv->core.timer_heap); 89 116 if (status != PJ_SUCCESS) 90 117 goto on_error; 91 118 92 srv->core.listener = pj_pool_calloc(pool, MAX_LISTENERS, 119 /* Configure lock for the timer heap */ 120 pj_timer_heap_set_lock(srv->core.timer_heap, srv->core.lock, PJ_FALSE); 121 122 /* Array of listeners */ 123 srv->core.listener = (pj_turn_listener**) 124 pj_pool_calloc(pool, MAX_LISTENERS, 93 125 sizeof(srv->core.listener[0])); 94 srv->core.stun_sess = pj_pool_calloc(pool, MAX_LISTENERS, 126 127 /* Array of STUN sessions, one for each listener */ 128 srv->core.stun_sess = (pj_stun_session**) 129 pj_pool_calloc(pool, MAX_LISTENERS, 95 130 (sizeof(srv->core.stun_sess[0]))); 96 97 srv->core.thread_cnt = MAX_THREADS;98 srv->core.thread = pj_pool_calloc(pool, srv->core.thread_cnt,99 sizeof(pj_thread_t*));100 101 status = pj_lock_create_recursive_mutex(pool, "srv%p", &srv->core.lock);102 if (status != PJ_SUCCESS)103 goto on_error;104 131 105 132 /* Create hash tables */ … … 117 144 srv->core.timer_heap); 118 145 146 /* Init STUN credential */ 147 srv->core.cred.type = PJ_STUN_AUTH_CRED_DYNAMIC; 148 srv->core.cred.data.dyn_cred.user_data = srv; 149 srv->core.cred.data.dyn_cred.get_auth = &pj_turn_get_auth; 150 srv->core.cred.data.dyn_cred.get_cred = &pj_turn_srv_get_cred; 151 srv->core.cred.data.dyn_cred.get_password = &pj_turn_get_password; 152 srv->core.cred.data.dyn_cred.verify_nonce = &pj_turn_verify_nonce; 153 154 /* Array of worker threads */ 155 srv->core.thread_cnt = MAX_THREADS; 156 srv->core.thread = (pj_thread_t**) 157 pj_pool_calloc(pool, srv->core.thread_cnt, 158 sizeof(pj_thread_t*)); 159 160 /* Start the worker threads */ 161 for (i=0; i<srv->core.thread_cnt; ++i) { 162 status = pj_thread_create(pool, srv->obj_name, &server_thread_proc, 163 srv, 0, 0, &srv->core.thread[i]); 164 if (status != PJ_SUCCESS) 165 goto on_error; 166 } 167 168 /* We're done. Application should add listeners now */ 169 PJ_LOG(4,(srv->obj_name, "TURN server v%s is running", 170 pj_get_version())); 171 119 172 *p_srv = srv; 120 173 return PJ_SUCCESS; 121 174 122 175 on_error: 123 pj turn_srv_destroy(srv);176 pj_turn_srv_destroy(srv); 124 177 return status; 125 178 } 126 179 127 /** 128 * Create server. 129 */ 130 PJ_DEF(pj_status_t) pjturn_srv_destroy(pjturn_srv *srv) 131 { 180 181 /* 182 * Handle timer and network events 183 */ 184 static void srv_handle_events(pj_turn_srv *srv, const pj_time_val *max_timeout) 185 { 186 /* timeout is 'out' var. This just to make compiler happy. */ 187 pj_time_val timeout = { 0, 0}; 188 unsigned net_event_count = 0; 189 int c; 190 191 /* Poll the timer. The timer heap has its own mutex for better 192 * granularity, so we don't need to lock the server. 193 */ 194 timeout.sec = timeout.msec = 0; 195 c = pj_timer_heap_poll( srv->core.timer_heap, &timeout ); 196 197 /* timer_heap_poll should never ever returns negative value, or otherwise 198 * ioqueue_poll() will block forever! 199 */ 200 pj_assert(timeout.sec >= 0 && timeout.msec >= 0); 201 if (timeout.msec >= 1000) timeout.msec = 999; 202 203 /* If caller specifies maximum time to wait, then compare the value with 204 * the timeout to wait from timer, and use the minimum value. 205 */ 206 if (max_timeout && PJ_TIME_VAL_GT(timeout, *max_timeout)) { 207 timeout = *max_timeout; 208 } 209 210 /* Poll ioqueue. 211 * Repeat polling the ioqueue while we have immediate events, because 212 * timer heap may process more than one events, so if we only process 213 * one network events at a time (such as when IOCP backend is used), 214 * the ioqueue may have trouble keeping up with the request rate. 215 * 216 * For example, for each send() request, one network event will be 217 * reported by ioqueue for the send() completion. If we don't poll 218 * the ioqueue often enough, the send() completion will not be 219 * reported in timely manner. 220 */ 221 do { 222 c = pj_ioqueue_poll( srv->core.ioqueue, &timeout); 223 if (c < 0) { 224 pj_thread_sleep(PJ_TIME_VAL_MSEC(timeout)); 225 return; 226 } else if (c == 0) { 227 break; 228 } else { 229 net_event_count += c; 230 timeout.sec = timeout.msec = 0; 231 } 232 } while (c > 0 && net_event_count < MAX_NET_EVENTS); 233 234 } 235 236 /* 237 * Server worker thread proc. 238 */ 239 static int server_thread_proc(void *arg) 240 { 241 pj_turn_srv *srv = (pj_turn_srv*)arg; 242 243 while (!srv->core.quit) { 244 pj_time_val timeout_max = {0, 500}; 245 srv_handle_events(srv, &timeout_max); 246 } 247 248 return 0; 249 } 250 251 /* 252 * Destroy the server. 253 */ 254 PJ_DEF(pj_status_t) pj_turn_srv_destroy(pj_turn_srv *srv) 255 { 256 pj_hash_iterator_t itbuf, *it; 257 unsigned i; 258 259 /* Stop all worker threads */ 260 srv->core.quit = PJ_TRUE; 261 for (i=0; i<srv->core.thread_cnt; ++i) { 262 if (srv->core.thread[i]) { 263 pj_thread_join(srv->core.thread[i]); 264 pj_thread_destroy(srv->core.thread[i]); 265 srv->core.thread[i] = NULL; 266 } 267 } 268 269 /* Destroy all listeners and STUN sessions associated with them. */ 270 for (i=0; i<srv->core.lis_cnt; ++i) { 271 if (srv->core.listener[i]) { 272 pj_turn_listener_destroy(srv->core.listener[i]); 273 srv->core.listener[i] = NULL; 274 } 275 if (srv->core.stun_sess[i]) { 276 pj_stun_session_destroy(srv->core.stun_sess[i]); 277 srv->core.stun_sess[i] = NULL; 278 } 279 } 280 281 /* Destroy all allocations */ 282 if (srv->tables.alloc) { 283 it = pj_hash_first(srv->tables.alloc, &itbuf); 284 while (it != NULL) { 285 pj_turn_allocation *alloc = (pj_turn_allocation*) 286 pj_hash_this(srv->tables.alloc, it); 287 pj_turn_allocation_destroy(alloc); 288 it = pj_hash_next(srv->tables.alloc, it); 289 } 290 } 291 292 293 /* Destroy hash tables (well, sort of) */ 294 if (srv->tables.alloc) { 295 srv->tables.alloc = NULL; 296 srv->tables.res = NULL; 297 } 298 299 /* Destroy timer heap */ 300 if (srv->core.timer_heap) { 301 pj_timer_heap_destroy(srv->core.timer_heap); 302 srv->core.timer_heap = NULL; 303 } 304 305 /* Destroy ioqueue */ 306 if (srv->core.ioqueue) { 307 pj_ioqueue_destroy(srv->core.ioqueue); 308 srv->core.ioqueue = NULL; 309 } 310 311 /* Destroy thread local IDs */ 312 if (srv->core.tls_key != -1) { 313 pj_thread_local_free(srv->core.tls_key); 314 srv->core.tls_key = -1; 315 } 316 if (srv->core.tls_data != -1) { 317 pj_thread_local_free(srv->core.tls_data); 318 srv->core.tls_data = -1; 319 } 320 321 /* Destroy server lock */ 322 if (srv->core.lock) { 323 pj_lock_destroy(srv->core.lock); 324 srv->core.lock = NULL; 325 } 326 327 /* Release pool */ 328 if (srv->core.pool) { 329 pj_pool_t *pool = srv->core.pool; 330 srv->core.pool = NULL; 331 pj_pool_release(pool); 332 } 333 334 /* Done */ 132 335 return PJ_SUCCESS; 133 336 } 134 337 135 /** 338 339 /* 136 340 * Add listener. 137 341 */ 138 PJ_DEF(pj_status_t) pj turn_srv_add_listener(pjturn_srv *srv,139 pjturn_listener *lis)342 PJ_DEF(pj_status_t) pj_turn_srv_add_listener(pj_turn_srv *srv, 343 pj_turn_listener *lis) 140 344 { 141 345 pj_stun_session_cb sess_cb; … … 157 361 sess_cb.on_send_msg = &on_tx_stun_msg; 158 362 159 status = pj_stun_session_create(&srv->core.stun_cfg, "lis%p", &sess_cb,160 PJ_FALSE, &sess);363 status = pj_stun_session_create(&srv->core.stun_cfg, lis->obj_name, 364 &sess_cb, PJ_FALSE, &sess); 161 365 if (status != PJ_SUCCESS) { 162 366 srv->core.listener[index] = NULL; … … 165 369 166 370 pj_stun_session_set_user_data(sess, lis); 371 pj_stun_session_set_credential(sess, &srv->core.cred); 167 372 168 373 srv->core.stun_sess[index] = sess; … … 170 375 srv->core.lis_cnt++; 171 376 377 PJ_LOG(4,(srv->obj_name, "Listener %s/%s added at index %d", 378 lis->obj_name, lis->info, lis->id)); 379 172 380 return PJ_SUCCESS; 173 381 } 174 382 175 /** 176 * Register an allocation. 177 */ 178 PJ_DEF(pj_status_t) pjturn_srv_register_allocation(pjturn_srv *srv, 179 pjturn_allocation *alloc) 383 384 /* 385 * Send packet with this listener. 386 */ 387 PJ_DEF(pj_status_t) pj_turn_listener_sendto(pj_turn_listener *listener, 388 const void *packet, 389 pj_size_t size, 390 unsigned flag, 391 const pj_sockaddr_t *addr, 392 int addr_len) 393 { 394 pj_assert(listener->id != PJ_TURN_INVALID_LIS_ID); 395 return listener->sendto(listener, packet, size, flag, addr, addr_len); 396 } 397 398 399 /* 400 * Destroy listener. 401 */ 402 PJ_DEF(pj_status_t) pj_turn_listener_destroy(pj_turn_listener *listener) 403 { 404 pj_turn_srv *srv = listener->server; 405 unsigned i; 406 407 /* Remove from our listener list */ 408 pj_lock_acquire(srv->core.lock); 409 for (i=0; i<srv->core.lis_cnt; ++i) { 410 if (srv->core.listener[i] == listener) { 411 srv->core.listener[i] = NULL; 412 srv->core.lis_cnt--; 413 listener->id = PJ_TURN_INVALID_LIS_ID; 414 if (srv->core.stun_sess[i]) { 415 pj_stun_session_destroy(srv->core.stun_sess[i]); 416 srv->core.stun_sess[i] = NULL; 417 } 418 break; 419 } 420 } 421 pj_lock_release(srv->core.lock); 422 423 /* Destroy */ 424 return listener->destroy(listener); 425 } 426 427 428 /* 429 * Register an allocation to the hash tables. 430 */ 431 PJ_DEF(pj_status_t) pj_turn_srv_register_allocation(pj_turn_srv *srv, 432 pj_turn_allocation *alloc) 180 433 { 181 434 /* Add to hash tables */ … … 191 444 } 192 445 193 /** 194 * Unregister an allocation. 195 */ 196 PJ_DEF(pj_status_t) pjturn_srv_unregister_allocation(pjturn_srv *srv, 197 pjturn_allocation *alloc) 446 447 /* 448 * Unregister an allocation from the hash tables. 449 */ 450 PJ_DEF(pj_status_t) pj_turn_srv_unregister_allocation(pj_turn_srv *srv, 451 pj_turn_allocation *alloc) 198 452 { 199 453 /* Unregister from hash tables */ … … 209 463 210 464 211 /* Callback from our own STUN session to send packet */ 465 /* Callback from our own STUN session whenever it needs to send 466 * outgoing STUN packet. 467 */ 212 468 static pj_status_t on_tx_stun_msg( pj_stun_session *sess, 213 469 const void *pkt, … … 216 472 unsigned addr_len) 217 473 { 218 pj turn_listener *listener;474 pj_turn_listener *listener; 219 475 220 listener = (pj turn_listener*) pj_stun_session_get_user_data(sess);476 listener = (pj_turn_listener*) pj_stun_session_get_user_data(sess); 221 477 222 478 PJ_ASSERT_RETURN(listener!=NULL, PJ_EINVALIDOP); 223 479 224 return pjturn_listener_sendto(listener, pkt, pkt_size, 0, 225 dst_addr, addr_len); 226 } 227 228 /* Create and send error response */ 229 static pj_status_t respond_error(pj_stun_session *sess, const pj_stun_msg *req, 230 pj_bool_t cache, int code, const char *errmsg, 231 const pj_sockaddr_t *dst_addr, 232 unsigned addr_len) 480 return pj_turn_listener_sendto(listener, pkt, pkt_size, 0, 481 dst_addr, addr_len); 482 } 483 484 485 /* Respond to STUN request */ 486 static pj_status_t stun_respond(pj_turn_srv *srv, 487 pj_stun_session *sess, 488 const pj_stun_msg *req, 489 unsigned code, 490 const char *errmsg, 491 pj_bool_t cache, 492 const pj_sockaddr_t *dst_addr, 493 unsigned addr_len) 233 494 { 234 495 pj_status_t status; … … 236 497 pj_stun_tx_data *tdata; 237 498 238 status = pj_stun_session_create_res(sess, req, 239 code, (errmsg?pj_cstr(&reason,errmsg):NULL), 499 /* Create response */ 500 status = pj_stun_session_create_res(sess, req, code, 501 (errmsg?pj_cstr(&reason,errmsg):NULL), 240 502 &tdata); 241 503 if (status != PJ_SUCCESS) 242 504 return status; 243 505 244 status = pj_stun_session_send_msg(sess, cache, dst_addr, addr_len, tdata); 245 return status; 246 247 } 248 249 /* Parse ALLOCATE request */ 250 static pj_status_t parse_allocate_req(pjturn_allocation_req *cfg, 251 pjturn_listener *listener, 252 pj_stun_session *sess, 253 const pj_stun_msg *req, 254 const pj_sockaddr_t *src_addr, 255 unsigned src_addr_len) 256 { 257 pj_stun_bandwidth_attr *attr_bw; 258 pj_stun_req_transport_attr *attr_req_tp; 259 pj_stun_req_ip_attr *attr_req_ip; 260 pj_stun_req_port_props_attr *attr_rpp; 261 pj_stun_lifetime_attr *attr_lifetime; 262 263 pj_bzero(cfg, sizeof(*cfg)); 264 265 /* Get BANDWIDTH attribute, if any. */ 266 attr_bw = (pj_stun_uint_attr*) 267 pj_stun_msg_find_attr(req, PJ_STUN_ATTR_BANDWIDTH, 0); 268 if (attr_bw) { 269 cfg->bandwidth = attr_bw->value; 270 } else { 271 cfg->bandwidth = DEFA_CLIENT_BANDWIDTH; 272 } 273 274 /* Check if we can satisfy the bandwidth */ 275 if (cfg->bandwidth > MAX_CLIENT_BANDWIDTH) { 276 respond_error(sess, req, PJ_FALSE, 277 PJ_STUN_SC_ALLOCATION_QUOTA_REACHED, 278 "Invalid bandwidth", src_addr, src_addr_len); 279 return -1; 280 } 281 282 /* Get REQUESTED-TRANSPORT attribute, is any */ 283 attr_req_tp = (pj_stun_uint_attr*) 284 pj_stun_msg_find_attr(req, PJ_STUN_ATTR_REQ_TRANSPORT, 0); 285 if (attr_req_tp) { 286 cfg->tp_type = PJ_STUN_GET_RT_PROTO(attr_req_tp->value); 287 } else { 288 cfg->tp_type = listener->tp_type; 289 } 290 291 /* Can only support UDP for now */ 292 if (cfg->tp_type != PJTURN_TP_UDP) { 293 respond_error(sess, req, PJ_FALSE, 294 PJ_STUN_SC_UNSUPP_TRANSPORT_PROTO, 295 NULL, src_addr, src_addr_len); 296 return -1; 297 } 298 299 /* Get REQUESTED-IP attribute, if any */ 300 attr_req_ip = (pj_stun_sockaddr_attr*) 301 pj_stun_msg_find_attr(req, PJ_STUN_ATTR_REQ_IP, 0); 302 if (attr_req_ip) { 303 pj_sockaddr_print(&attr_req_ip->sockaddr, cfg->addr, 304 sizeof(cfg->addr), 0); 305 } 306 307 /* Get REQUESTED-PORT-PROPS attribute, if any */ 308 attr_rpp = (pj_stun_uint_attr*) 309 pj_stun_msg_find_attr(req, PJ_STUN_ATTR_REQ_PORT_PROPS, 0); 310 if (attr_rpp) { 311 cfg->rpp_bits = PJ_STUN_GET_RPP_BITS(attr_rpp->value); 312 cfg->rpp_port = PJ_STUN_GET_RPP_PORT(attr_rpp->value); 313 } else { 314 cfg->rpp_bits = 0; 315 cfg->rpp_port = 0; 316 } 317 318 /* Get LIFETIME attribute */ 319 attr_lifetime = (pj_stun_uint_attr*) 320 pj_stun_msg_find_attr(req, PJ_STUN_ATTR_LIFETIME, 0); 321 if (attr_lifetime) { 322 cfg->lifetime = attr_lifetime->value; 323 if (cfg->lifetime < MIN_LIFETIME || cfg->lifetime > MAX_LIFETIME) { 324 respond_error(sess, req, PJ_FALSE, 325 PJ_STUN_SC_BAD_REQUEST, 326 "Invalid LIFETIME value", src_addr, 327 src_addr_len); 328 return -1; 329 } 330 } else { 331 cfg->lifetime = DEF_LIFETIME; 332 } 506 /* Store the credential for future lookup. */ 507 if (pj_stun_auth_valid_for_msg(tdata->msg)) { 508 pj_turn_srv_put_cred(srv, req, tdata); 509 } 510 511 /* Send the response */ 512 return pj_stun_session_send_msg(sess, cache, dst_addr, addr_len, tdata); 513 } 514 515 516 /* 517 * Store the credential to put placed for the specified message for 518 * future retrieval. 519 */ 520 PJ_DEF(pj_status_t) pj_turn_srv_put_cred(pj_turn_srv *srv, 521 const pj_stun_msg *req, 522 pj_stun_tx_data *response) 523 { 524 pj_stun_username_attr *user; 525 pj_stun_realm_attr *realm; 526 pj_stun_nonce_attr *nonce; 527 struct saved_cred *saved_cred; 528 pj_status_t status; 529 530 realm = (pj_stun_realm_attr*) 531 pj_stun_msg_find_attr(req, PJ_STUN_ATTR_REALM, 0); 532 PJ_ASSERT_RETURN(realm != NULL, PJ_EBUG); 533 534 user = (pj_stun_username_attr*) 535 pj_stun_msg_find_attr(req, PJ_STUN_ATTR_USERNAME, 0); 536 PJ_ASSERT_RETURN(user != NULL, PJ_EBUG); 537 538 nonce = (pj_stun_nonce_attr*) 539 pj_stun_msg_find_attr(req, PJ_STUN_ATTR_NONCE, 0); 540 PJ_ASSERT_RETURN(nonce != NULL, PJ_EBUG); 541 542 saved_cred = PJ_POOL_ALLOC_T(response->pool, struct saved_cred); 543 544 /* Lookup the password */ 545 status = pj_turn_get_password(response->msg, NULL, &realm->value, 546 &user->value, response->pool, 547 &saved_cred->data_type, 548 &saved_cred->data); 549 if (status != PJ_SUCCESS) 550 return status; 551 552 /* Store credential */ 553 pj_strdup(response->pool, &saved_cred->username, &user->value); 554 pj_strdup(response->pool, &saved_cred->realm, &realm->value); 555 pj_strdup(response->pool, &saved_cred->nonce, &nonce->value); 556 557 pj_thread_local_set(srv->core.tls_key, response->msg); 558 pj_thread_local_set(srv->core.tls_data, saved_cred); 333 559 334 560 return PJ_SUCCESS; 335 561 } 336 562 337 /* Callback from our own STUN session when incoming request arrives */ 563 564 /** 565 * Retrieve previously stored credential for the specified message. 566 */ 567 PJ_DEF(pj_status_t) pj_turn_srv_get_cred(const pj_stun_msg *msg, 568 void *user_data, 569 pj_pool_t *pool, 570 pj_str_t *realm, 571 pj_str_t *username, 572 pj_str_t *nonce, 573 int *data_type, 574 pj_str_t *data) 575 { 576 pj_turn_srv *srv; 577 const pj_stun_msg *saved_msg; 578 struct saved_cred *saved_cred; 579 580 PJ_UNUSED_ARG(pool); 581 582 srv = (pj_turn_srv*)user_data; 583 584 /* Lookup stored message and make sure it's for the same message */ 585 saved_msg = (const pj_stun_msg*) 586 pj_thread_local_get(srv->core.tls_key); 587 PJ_ASSERT_RETURN(saved_msg==msg, PJ_ENOTFOUND); 588 589 /* Lookup saved credential */ 590 saved_cred = (struct saved_cred*) 591 pj_thread_local_get(srv->core.tls_data); 592 PJ_ASSERT_RETURN(saved_cred != NULL, PJ_ENOTFOUND); 593 594 595 *realm = saved_cred->realm; 596 *username = saved_cred->username; 597 *nonce = saved_cred->nonce; 598 *data_type = saved_cred->data_type; 599 *data = saved_cred->data; 600 601 602 /* Don't clear saved_cred as this may be called more than once */ 603 604 return PJ_SUCCESS; 605 } 606 607 608 /* Callback from our own STUN session when incoming request arrives. 609 * This function is triggered by pj_stun_session_on_rx_pkt() call in 610 * pj_turn_srv_on_rx_pkt() function below. 611 */ 338 612 static pj_status_t on_rx_stun_request(pj_stun_session *sess, 339 613 const pj_uint8_t *pkt, … … 343 617 unsigned src_addr_len) 344 618 { 345 pjturn_listener *listener; 346 pjturn_srv *srv; 347 pjturn_allocation_req req; 348 pjturn_allocation *alloc; 349 pj_stun_tx_data *tdata; 619 pj_turn_listener *listener; 620 pj_turn_srv *srv; 621 pj_turn_allocation *alloc; 350 622 pj_status_t status; 351 623 352 listener = (pjturn_listener*) pj_stun_session_get_user_data(sess); 624 PJ_UNUSED_ARG(pkt); 625 PJ_UNUSED_ARG(pkt_len); 626 627 listener = (pj_turn_listener*) pj_stun_session_get_user_data(sess); 353 628 srv = listener->server; 354 629 355 /* Handle strayed REFRESH request */ 356 if (msg->hdr.type == PJ_STUN_REFRESH_REQUEST) { 357 return respond_error(sess, msg, PJ_FALSE, 358 PJ_STUN_SC_ALLOCATION_MISMATCH, 359 NULL, src_addr, src_addr_len); 360 } 361 362 /* Respond any other requests with Bad Request response */ 630 /* Respond any requests other than ALLOCATE with 437 response */ 363 631 if (msg->hdr.type != PJ_STUN_ALLOCATE_REQUEST) { 364 return respond_error(sess, msg, PJ_FALSE, PJ_STUN_SC_BAD_REQUEST, 365 NULL, src_addr, src_addr_len); 366 } 367 368 /* We have ALLOCATE request here, and it's authenticated. Parse the 369 * request. 370 */ 371 status = parse_allocate_req(&req, listener, sess, msg, src_addr, 372 src_addr_len); 373 if (status != PJ_SUCCESS) 374 return status; 632 stun_respond(srv, sess, msg, PJ_STUN_SC_ALLOCATION_MISMATCH, 633 NULL, PJ_FALSE, src_addr, src_addr_len); 634 return PJ_SUCCESS; 635 } 375 636 376 637 /* Create new allocation. The relay resource will be allocated 377 638 * in this function. 378 639 */ 379 status = pj turn_allocation_create(listener, src_addr, src_addr_len,380 msg, &req, &alloc);640 status = pj_turn_allocation_create(listener, src_addr, src_addr_len, 641 msg, sess, &alloc); 381 642 if (status != PJ_SUCCESS) { 382 char errmsg[PJ_ERR_MSG_SIZE]; 383 384 pj_strerror(status, errmsg, sizeof(errmsg)); 385 return respond_error(sess, msg, PJ_FALSE, PJ_STUN_SC_SERVER_ERROR, 386 errmsg, src_addr, src_addr_len); 387 } 388 389 /* Respond the original ALLOCATE request */ 390 status = pj_stun_session_create_res(srv->core.stun_sess[listener->id], 391 msg, 0, NULL, &tdata); 392 if (status != PJ_SUCCESS) { 393 char errmsg[PJ_ERR_MSG_SIZE]; 394 395 pjturn_allocation_destroy(alloc); 396 397 pj_strerror(status, errmsg, sizeof(errmsg)); 398 return respond_error(sess, msg, PJ_FALSE, PJ_STUN_SC_SERVER_ERROR, 399 errmsg, src_addr, src_addr_len); 400 } 401 402 /* Add RELAYED-ADDRESS attribute */ 403 pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg, 404 PJ_STUN_ATTR_RELAY_ADDR, PJ_TRUE, 405 &alloc->relay.hkey.addr, 406 pj_sockaddr_get_len(&alloc->relay.hkey.addr)); 407 408 /* Add LIFETIME. */ 409 pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg, 410 PJ_STUN_ATTR_LIFETIME, 411 (unsigned)alloc->relay.lifetime); 412 413 /* Add BANDWIDTH */ 414 pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg, 415 PJ_STUN_ATTR_BANDWIDTH, 416 alloc->bandwidth); 417 418 /* Add RESERVATION-TOKEN */ 419 PJ_TODO(ADD_RESERVATION_TOKEN); 420 421 /* Add XOR-MAPPED-ADDRESS */ 422 pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg, 423 PJ_STUN_ATTR_XOR_MAPPED_ADDR, PJ_TRUE, 424 &alloc->hkey.clt_addr, 425 pj_sockaddr_get_len(&alloc->hkey.clt_addr)); 426 427 /* Send the response */ 428 pj_stun_session_send_msg(srv->core.stun_sess[listener->id], PJ_TRUE, 429 src_addr, src_addr_len, tdata); 643 /* STUN response has been sent, no need to reply here */ 644 return PJ_SUCCESS; 645 } 430 646 431 647 /* Done. */ … … 434 650 435 651 436 /* Handle packet from new client address. */ 437 static void handle_new_client( pjturn_srv *srv, 438 pjturn_pkt *pkt) 439 { 440 unsigned options, lis_id; 441 pj_status_t status; 442 443 /* Check that this is a STUN message */ 444 options = PJ_STUN_CHECK_PACKET; 445 if (pkt->listener->tp_type == PJTURN_TP_UDP) 446 options |= PJ_STUN_IS_DATAGRAM; 447 448 status = pj_stun_msg_check(pkt->pkt, pkt->len, options); 449 if (status != PJ_SUCCESS) { 450 char errmsg[PJ_ERR_MSG_SIZE]; 451 char ip[PJ_INET6_ADDRSTRLEN+10]; 452 453 pj_strerror(status, errmsg, sizeof(errmsg)); 454 PJ_LOG(5,(srv->core.obj_name, 455 "Non STUN packet from %s is dropped: %s", 456 pj_sockaddr_print(&pkt->src.clt_addr, ip, sizeof(ip), 3), 457 errmsg)); 458 return; 459 } 460 461 lis_id = pkt->listener->id; 462 463 /* Hand over processing to STUN session */ 464 options &= ~PJ_STUN_CHECK_PACKET; 465 status = pj_stun_session_on_rx_pkt(srv->core.stun_sess[lis_id], pkt->pkt, 466 pkt->len, options, NULL, 467 &pkt->src.clt_addr, 468 pkt->src_addr_len); 469 if (status != PJ_SUCCESS) { 470 char errmsg[PJ_ERR_MSG_SIZE]; 471 char ip[PJ_INET6_ADDRSTRLEN+10]; 472 473 pj_strerror(status, errmsg, sizeof(errmsg)); 474 PJ_LOG(5,(srv->core.obj_name, 475 "Error processing STUN packet from %s: %s", 476 pj_sockaddr_print(&pkt->src.clt_addr, ip, sizeof(ip), 3), 477 errmsg)); 478 return; 479 } 480 } 481 482 483 /* 484 * This callback is called by UDP listener on incoming packet. 485 */ 486 PJ_DEF(void) pjturn_srv_on_rx_pkt( pjturn_srv *srv, 487 pjturn_pkt *pkt) 488 { 489 pjturn_allocation *alloc; 652 /* 653 * This callback is called by UDP listener on incoming packet. This is 654 * the first entry for incoming packet (from client) to the server. From 655 * here, the packet may be handed over to an allocation if an allocation 656 * is found for the client address, or handed over to owned STUN session 657 * if an allocation is not found. 658 */ 659 PJ_DEF(void) pj_turn_srv_on_rx_pkt(pj_turn_srv *srv, 660 pj_turn_pkt *pkt) 661 { 662 pj_turn_allocation *alloc; 490 663 491 664 /* Get TURN allocation from the source address */ … … 498 671 */ 499 672 if (alloc) { 500 pj turn_allocation_on_rx_client_pkt(alloc, pkt);673 pj_turn_allocation_on_rx_client_pkt(alloc, pkt); 501 674 } else { 502 675 /* Otherwise this is a new client */ 503 handle_new_client(srv, pkt); 504 } 505 } 506 507 676 unsigned options, lis_id; 677 pj_status_t status; 678 679 /* Check that this is a STUN message */ 680 options = PJ_STUN_CHECK_PACKET; 681 if (pkt->listener->tp_type == PJ_TURN_TP_UDP) 682 options |= PJ_STUN_IS_DATAGRAM; 683 684 status = pj_stun_msg_check(pkt->pkt, pkt->len, options); 685 if (status != PJ_SUCCESS) { 686 char errmsg[PJ_ERR_MSG_SIZE]; 687 char ip[PJ_INET6_ADDRSTRLEN+10]; 688 689 pj_strerror(status, errmsg, sizeof(errmsg)); 690 PJ_LOG(5,(srv->obj_name, 691 "Non STUN packet from %s is dropped: %s", 692 pj_sockaddr_print(&pkt->src.clt_addr, ip, sizeof(ip), 3), 693 errmsg)); 694 return; 695 } 696 697 lis_id = pkt->listener->id; 698 699 /* Hand over processing to STUN session. This will trigger 700 * on_rx_stun_request() callback to be called if the STUN 701 * message is a request. 702 */ 703 options &= ~PJ_STUN_CHECK_PACKET; 704 status = pj_stun_session_on_rx_pkt(srv->core.stun_sess[lis_id], 705 pkt->pkt, pkt->len, options, NULL, 706 &pkt->src.clt_addr, 707 pkt->src_addr_len); 708 if (status != PJ_SUCCESS) { 709 char errmsg[PJ_ERR_MSG_SIZE]; 710 char ip[PJ_INET6_ADDRSTRLEN+10]; 711 712 pj_strerror(status, errmsg, sizeof(errmsg)); 713 PJ_LOG(5,(srv->obj_name, 714 "Error processing STUN packet from %s: %s", 715 pj_sockaddr_print(&pkt->src.clt_addr, ip, sizeof(ip), 3), 716 errmsg)); 717 return; 718 } 719 } 720 } 721 722
Note: See TracChangeset
for help on using the changeset viewer.