From 483805f79570115ab95c69698792d238c1719b1b Mon Sep 17 00:00:00 2001 From: Jason Parker Date: Mon, 11 Mar 2013 15:09:56 -0500 Subject: Import pjproject-2.1 --- pjnath/src/pjnath/turn_session.c | 184 ++++++++++++++++++++------------------- 1 file changed, 94 insertions(+), 90 deletions(-) (limited to 'pjnath/src/pjnath/turn_session.c') diff --git a/pjnath/src/pjnath/turn_session.c b/pjnath/src/pjnath/turn_session.c index cbe8f5c..7031cd3 100644 --- a/pjnath/src/pjnath/turn_session.c +++ b/pjnath/src/pjnath/turn_session.c @@ -1,4 +1,4 @@ -/* $Id: turn_session.c 3844 2011-10-24 15:03:43Z bennylp $ */ +/* $Id: turn_session.c 4368 2013-02-21 21:53:28Z bennylp $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -112,8 +112,9 @@ struct pj_turn_session pj_turn_session_cb cb; void *user_data; pj_stun_config stun_cfg; + pj_bool_t is_destroying; - pj_lock_t *lock; + pj_grp_lock_t *grp_lock; int busy; pj_turn_state_t state; @@ -161,6 +162,7 @@ struct pj_turn_session */ static void sess_shutdown(pj_turn_session *sess, pj_status_t status); +static void turn_sess_on_destroy(void *comp); static void do_destroy(pj_turn_session *sess); static void send_refresh(pj_turn_session *sess, int lifetime); static pj_status_t stun_on_send_msg(pj_stun_session *sess, @@ -236,6 +238,7 @@ PJ_DEF(pj_status_t) pj_turn_session_create( const pj_stun_config *cfg, const char *name, int af, pj_turn_tp_type conn_type, + pj_grp_lock_t *grp_lock, const pj_turn_session_cb *cb, unsigned options, void *user_data, @@ -244,7 +247,6 @@ PJ_DEF(pj_status_t) pj_turn_session_create( const pj_stun_config *cfg, pj_pool_t *pool; pj_turn_session *sess; pj_stun_session_cb stun_cb; - pj_lock_t *null_lock; pj_status_t status; PJ_ASSERT_RETURN(cfg && cfg->pf && cb && p_sess, PJ_EINVAL); @@ -281,13 +283,20 @@ PJ_DEF(pj_status_t) pj_turn_session_create( const pj_stun_config *cfg, sess->perm_table = pj_hash_create(pool, PJ_TURN_PERM_HTABLE_SIZE); /* Session lock */ - status = pj_lock_create_recursive_mutex(pool, sess->obj_name, - &sess->lock); - if (status != PJ_SUCCESS) { - do_destroy(sess); - return status; + if (grp_lock) { + sess->grp_lock = grp_lock; + } else { + status = pj_grp_lock_create(pool, NULL, &sess->grp_lock); + if (status != PJ_SUCCESS) { + pj_pool_release(pool); + return status; + } } + pj_grp_lock_add_ref(sess->grp_lock); + pj_grp_lock_add_handler(sess->grp_lock, pool, sess, + &turn_sess_on_destroy); + /* Timer */ pj_timer_entry_init(&sess->timer, TIMER_NONE, sess, &on_timer_event); @@ -297,7 +306,7 @@ PJ_DEF(pj_status_t) pj_turn_session_create( const pj_stun_config *cfg, stun_cb.on_request_complete = &stun_on_request_complete; stun_cb.on_rx_indication = &stun_on_rx_indication; status = pj_stun_session_create(&sess->stun_cfg, sess->obj_name, &stun_cb, - PJ_FALSE, &sess->stun); + PJ_FALSE, sess->grp_lock, &sess->stun); if (status != PJ_SUCCESS) { do_destroy(sess); return status; @@ -306,16 +315,6 @@ PJ_DEF(pj_status_t) pj_turn_session_create( const pj_stun_config *cfg, /* Attach ourself to STUN session */ pj_stun_session_set_user_data(sess->stun, sess); - /* Replace mutex in STUN session with a NULL mutex, since access to - * STUN session is serialized. - */ - status = pj_lock_create_null_mutex(pool, name, &null_lock); - if (status != PJ_SUCCESS) { - do_destroy(sess); - return status; - } - pj_stun_session_set_lock(sess->stun, null_lock, PJ_TRUE); - /* Done */ PJ_LOG(4,(sess->obj_name, "TURN client session created")); @@ -325,32 +324,9 @@ PJ_DEF(pj_status_t) pj_turn_session_create( const pj_stun_config *cfg, } -/* Destroy */ -static void do_destroy(pj_turn_session *sess) +static void turn_sess_on_destroy(void *comp) { - /* Lock session */ - if (sess->lock) { - pj_lock_acquire(sess->lock); - } - - /* Cancel pending timer, if any */ - if (sess->timer.id != TIMER_NONE) { - pj_timer_heap_cancel(sess->timer_heap, &sess->timer); - sess->timer.id = TIMER_NONE; - } - - /* Destroy STUN session */ - if (sess->stun) { - pj_stun_session_destroy(sess->stun); - sess->stun = NULL; - } - - /* Destroy lock */ - if (sess->lock) { - pj_lock_release(sess->lock); - pj_lock_destroy(sess->lock); - sess->lock = NULL; - } + pj_turn_session *sess = (pj_turn_session*) comp; /* Destroy pool */ if (sess->pool) { @@ -363,6 +339,26 @@ static void do_destroy(pj_turn_session *sess) } } +/* Destroy */ +static void do_destroy(pj_turn_session *sess) +{ + PJ_LOG(4,(sess->obj_name, "TURN session destroy request, ref_cnt=%d", + pj_grp_lock_get_ref(sess->grp_lock))); + + pj_grp_lock_acquire(sess->grp_lock); + if (sess->is_destroying) { + pj_grp_lock_release(sess->grp_lock); + return; + } + + sess->is_destroying = PJ_TRUE; + pj_timer_heap_cancel_if_active(sess->timer_heap, &sess->timer, TIMER_NONE); + pj_stun_session_destroy(sess->stun); + + pj_grp_lock_dec_ref(sess->grp_lock); + pj_grp_lock_release(sess->grp_lock); +} + /* Set session state */ static void set_state(pj_turn_session *sess, enum pj_turn_state_t state) @@ -421,7 +417,10 @@ static void sess_shutdown(pj_turn_session *sess, /* This may recursively call this function again with * state==PJ_TURN_STATE_DEALLOCATED. */ + /* No need to deallocate as we're already deallocating! + * See https://trac.pjsip.org/repos/ticket/1551 send_refresh(sess, 0); + */ break; case PJ_TURN_STATE_DEALLOCATED: case PJ_TURN_STATE_DESTROYING: @@ -434,13 +433,11 @@ static void sess_shutdown(pj_turn_session *sess, set_state(sess, PJ_TURN_STATE_DESTROYING); - if (sess->timer.id != TIMER_NONE) { - pj_timer_heap_cancel(sess->timer_heap, &sess->timer); - sess->timer.id = TIMER_NONE; - } - - sess->timer.id = TIMER_DESTROY; - pj_timer_heap_schedule(sess->timer_heap, &sess->timer, &delay); + pj_timer_heap_cancel_if_active(sess->timer_heap, &sess->timer, + TIMER_NONE); + pj_timer_heap_schedule_w_grp_lock(sess->timer_heap, &sess->timer, + &delay, TIMER_DESTROY, + sess->grp_lock); } } @@ -452,11 +449,11 @@ PJ_DEF(pj_status_t) pj_turn_session_shutdown(pj_turn_session *sess) { PJ_ASSERT_RETURN(sess, PJ_EINVAL); - pj_lock_acquire(sess->lock); + pj_grp_lock_acquire(sess->grp_lock); sess_shutdown(sess, PJ_SUCCESS); - pj_lock_release(sess->lock); + pj_grp_lock_release(sess->grp_lock); return PJ_SUCCESS; } @@ -550,9 +547,9 @@ PJ_DEF(pj_status_t) pj_turn_session_set_software_name( pj_turn_session *sess, { pj_status_t status; - pj_lock_acquire(sess->lock); + pj_grp_lock_acquire(sess->grp_lock); status = pj_stun_session_set_software_name(sess->stun, sw); - pj_lock_release(sess->lock); + pj_grp_lock_release(sess->grp_lock); return status; } @@ -573,7 +570,7 @@ PJ_DEF(pj_status_t) pj_turn_session_set_server( pj_turn_session *sess, PJ_ASSERT_RETURN(sess && domain, PJ_EINVAL); PJ_ASSERT_RETURN(sess->state == PJ_TURN_STATE_NULL, PJ_EINVALIDOP); - pj_lock_acquire(sess->lock); + pj_grp_lock_acquire(sess->grp_lock); /* See if "domain" contains just IP address */ tmp_addr.addr.sa_family = sess->af; @@ -673,7 +670,7 @@ PJ_DEF(pj_status_t) pj_turn_session_set_server( pj_turn_session *sess, } on_return: - pj_lock_release(sess->lock); + pj_grp_lock_release(sess->grp_lock); return status; } @@ -687,11 +684,11 @@ PJ_DEF(pj_status_t) pj_turn_session_set_credential(pj_turn_session *sess, PJ_ASSERT_RETURN(sess && cred, PJ_EINVAL); PJ_ASSERT_RETURN(sess->stun, PJ_EINVALIDOP); - pj_lock_acquire(sess->lock); + pj_grp_lock_acquire(sess->grp_lock); pj_stun_session_set_credential(sess->stun, PJ_STUN_AUTH_LONG_TERM, cred); - pj_lock_release(sess->lock); + pj_grp_lock_release(sess->grp_lock); return PJ_SUCCESS; } @@ -712,7 +709,7 @@ PJ_DEF(pj_status_t) pj_turn_session_alloc(pj_turn_session *sess, sess->state<=PJ_TURN_STATE_RESOLVED, PJ_EINVALIDOP); - pj_lock_acquire(sess->lock); + pj_grp_lock_acquire(sess->grp_lock); if (param && param != &sess->alloc_param) pj_turn_alloc_param_copy(sess->pool, &sess->alloc_param, param); @@ -723,7 +720,7 @@ PJ_DEF(pj_status_t) pj_turn_session_alloc(pj_turn_session *sess, PJ_LOG(4,(sess->obj_name, "Pending ALLOCATE in state %s", state_names[sess->state])); - pj_lock_release(sess->lock); + pj_grp_lock_release(sess->grp_lock); return PJ_SUCCESS; } @@ -735,7 +732,7 @@ PJ_DEF(pj_status_t) pj_turn_session_alloc(pj_turn_session *sess, status = pj_stun_session_create_req(sess->stun, PJ_STUN_ALLOCATE_REQUEST, PJ_STUN_MAGIC, NULL, &tdata); if (status != PJ_SUCCESS) { - pj_lock_release(sess->lock); + pj_grp_lock_release(sess->grp_lock); return status; } @@ -775,7 +772,7 @@ PJ_DEF(pj_status_t) pj_turn_session_alloc(pj_turn_session *sess, set_state(sess, PJ_TURN_STATE_RESOLVED); } - pj_lock_release(sess->lock); + pj_grp_lock_release(sess->grp_lock); return status; } @@ -796,14 +793,14 @@ PJ_DEF(pj_status_t) pj_turn_session_set_perm( pj_turn_session *sess, PJ_ASSERT_RETURN(sess && addr_cnt && addr, PJ_EINVAL); - pj_lock_acquire(sess->lock); + pj_grp_lock_acquire(sess->grp_lock); /* Create a bare CreatePermission request */ status = pj_stun_session_create_req(sess->stun, PJ_STUN_CREATE_PERM_REQUEST, PJ_STUN_MAGIC, NULL, &tdata); if (status != PJ_SUCCESS) { - pj_lock_release(sess->lock); + pj_grp_lock_release(sess->grp_lock); return status; } @@ -854,7 +851,7 @@ PJ_DEF(pj_status_t) pj_turn_session_set_perm( pj_turn_session *sess, goto on_error; } - pj_lock_release(sess->lock); + pj_grp_lock_release(sess->grp_lock); return PJ_SUCCESS; on_error: @@ -871,7 +868,7 @@ on_error: if (perm->req_token == req_token) invalidate_perm(sess, perm); } - pj_lock_release(sess->lock); + pj_grp_lock_release(sess->grp_lock); return status; } @@ -942,7 +939,7 @@ PJ_DEF(pj_status_t) pj_turn_session_sendto( pj_turn_session *sess, } /* Lock session now */ - pj_lock_acquire(sess->lock); + pj_grp_lock_acquire(sess->grp_lock); /* Lookup permission first */ perm = lookup_perm(sess, addr, pj_sockaddr_get_len(addr), PJ_FALSE); @@ -957,7 +954,7 @@ PJ_DEF(pj_status_t) pj_turn_session_sendto( pj_turn_session *sess, status = pj_turn_session_set_perm(sess, 1, (const pj_sockaddr*)addr, 0); if (status != PJ_SUCCESS) { - pj_lock_release(sess->lock); + pj_grp_lock_release(sess->grp_lock); return status; } } @@ -1032,7 +1029,7 @@ PJ_DEF(pj_status_t) pj_turn_session_sendto( pj_turn_session *sess, } on_return: - pj_lock_release(sess->lock); + pj_grp_lock_release(sess->grp_lock); return status; } @@ -1052,7 +1049,7 @@ PJ_DEF(pj_status_t) pj_turn_session_bind_channel(pj_turn_session *sess, PJ_ASSERT_RETURN(sess && peer_adr && addr_len, PJ_EINVAL); PJ_ASSERT_RETURN(sess->state == PJ_TURN_STATE_READY, PJ_EINVALIDOP); - pj_lock_acquire(sess->lock); + pj_grp_lock_acquire(sess->grp_lock); /* Create blank ChannelBind request */ status = pj_stun_session_create_req(sess->stun, @@ -1095,7 +1092,7 @@ PJ_DEF(pj_status_t) pj_turn_session_bind_channel(pj_turn_session *sess, tdata); on_return: - pj_lock_release(sess->lock); + pj_grp_lock_release(sess->grp_lock); return status; } @@ -1118,7 +1115,7 @@ PJ_DEF(pj_status_t) pj_turn_session_on_rx_pkt(pj_turn_session *sess, */ /* Start locking the session */ - pj_lock_acquire(sess->lock); + pj_grp_lock_acquire(sess->grp_lock); is_datagram = (sess->conn_type==PJ_TURN_TP_UDP); @@ -1190,7 +1187,7 @@ PJ_DEF(pj_status_t) pj_turn_session_on_rx_pkt(pj_turn_session *sess, } on_return: - pj_lock_release(sess->lock); + pj_grp_lock_release(sess->grp_lock); return status; } @@ -1382,20 +1379,22 @@ static void on_allocate_success(pj_turn_session *sess, /* Cancel existing keep-alive timer, if any */ pj_assert(sess->timer.id != TIMER_DESTROY); - - if (sess->timer.id != TIMER_NONE) { - pj_timer_heap_cancel(sess->timer_heap, &sess->timer); - sess->timer.id = TIMER_NONE; + if (sess->timer.id == TIMER_KEEP_ALIVE) { + pj_timer_heap_cancel_if_active(sess->timer_heap, &sess->timer, + TIMER_NONE); } /* Start keep-alive timer once allocation succeeds */ - timeout.sec = sess->ka_interval; - timeout.msec = 0; + if (sess->state < PJ_TURN_STATE_DEALLOCATING) { + timeout.sec = sess->ka_interval; + timeout.msec = 0; - sess->timer.id = TIMER_KEEP_ALIVE; - pj_timer_heap_schedule(sess->timer_heap, &sess->timer, &timeout); + pj_timer_heap_schedule_w_grp_lock(sess->timer_heap, &sess->timer, + &timeout, TIMER_KEEP_ALIVE, + sess->grp_lock); - set_state(sess, PJ_TURN_STATE_READY); + set_state(sess, PJ_TURN_STATE_READY); + } } /* @@ -1945,7 +1944,7 @@ static void on_timer_event(pj_timer_heap_t *th, pj_timer_entry *e) PJ_UNUSED_ARG(th); - pj_lock_acquire(sess->lock); + pj_grp_lock_acquire(sess->grp_lock); eid = (enum timer_id_t) e->id; e->id = TIMER_NONE; @@ -1956,6 +1955,11 @@ static void on_timer_event(pj_timer_heap_t *th, pj_timer_entry *e) pj_bool_t resched = PJ_TRUE; pj_bool_t pkt_sent = PJ_FALSE; + if (sess->state >= PJ_TURN_STATE_DEALLOCATING) { + /* Ignore if we're deallocating */ + goto on_return; + } + pj_gettimeofday(&now); /* Refresh allocation if it's time to do so */ @@ -2022,19 +2026,19 @@ static void on_timer_event(pj_timer_heap_t *th, pj_timer_entry *e) delay.sec = sess->ka_interval; delay.msec = 0; - sess->timer.id = TIMER_KEEP_ALIVE; - pj_timer_heap_schedule(sess->timer_heap, &sess->timer, &delay); + pj_timer_heap_schedule_w_grp_lock(sess->timer_heap, &sess->timer, + &delay, TIMER_KEEP_ALIVE, + sess->grp_lock); } - pj_lock_release(sess->lock); - } else if (eid == TIMER_DESTROY) { /* Time to destroy */ - pj_lock_release(sess->lock); do_destroy(sess); } else { pj_assert(!"Unknown timer event"); - pj_lock_release(sess->lock); } + +on_return: + pj_grp_lock_release(sess->grp_lock); } -- cgit v1.2.3