summaryrefslogtreecommitdiff
path: root/pjnath/src/pjnath/stun_transaction.c
diff options
context:
space:
mode:
Diffstat (limited to 'pjnath/src/pjnath/stun_transaction.c')
-rw-r--r--pjnath/src/pjnath/stun_transaction.c135
1 files changed, 77 insertions, 58 deletions
diff --git a/pjnath/src/pjnath/stun_transaction.c b/pjnath/src/pjnath/stun_transaction.c
index 8677d322..390f67f7 100644
--- a/pjnath/src/pjnath/stun_transaction.c
+++ b/pjnath/src/pjnath/stun_transaction.c
@@ -26,6 +26,8 @@
#include <pj/timer.h>
+#define THIS_FILE "stun_transaction.c"
+#define TIMER_INACTIVE 0
#define TIMER_ACTIVE 1
@@ -34,6 +36,7 @@ struct pj_stun_client_tsx
char obj_name[PJ_MAX_OBJ_NAME];
pj_stun_tsx_cb cb;
void *user_data;
+ pj_grp_lock_t *grp_lock;
pj_bool_t complete;
@@ -51,18 +54,24 @@ struct pj_stun_client_tsx
};
+#if 1
+# define TRACE_(expr) PJ_LOG(5,expr)
+#else
+# define TRACE_(expr)
+#endif
+
+
static void retransmit_timer_callback(pj_timer_heap_t *timer_heap,
pj_timer_entry *timer);
static void destroy_timer_callback(pj_timer_heap_t *timer_heap,
pj_timer_entry *timer);
-#define stun_perror(tsx,msg,rc) pjnath_perror(tsx->obj_name, msg, rc)
-
/*
* Create a STUN client transaction.
*/
PJ_DEF(pj_status_t) pj_stun_client_tsx_create(pj_stun_config *cfg,
pj_pool_t *pool,
+ pj_grp_lock_t *grp_lock,
const pj_stun_tsx_cb *cb,
pj_stun_client_tsx **p_tsx)
{
@@ -74,6 +83,7 @@ PJ_DEF(pj_status_t) pj_stun_client_tsx_create(pj_stun_config *cfg,
tsx = PJ_POOL_ZALLOC_T(pool, pj_stun_client_tsx);
tsx->rto_msec = cfg->rto_msec;
tsx->timer_heap = cfg->timer_heap;
+ tsx->grp_lock = grp_lock;
pj_memcpy(&tsx->cb, cb, sizeof(*cb));
tsx->retransmit_timer.cb = &retransmit_timer_callback;
@@ -82,7 +92,7 @@ PJ_DEF(pj_status_t) pj_stun_client_tsx_create(pj_stun_config *cfg,
tsx->destroy_timer.cb = &destroy_timer_callback;
tsx->destroy_timer.user_data = tsx;
- pj_ansi_snprintf(tsx->obj_name, sizeof(tsx->obj_name), "stuntsx%p", tsx);
+ pj_ansi_snprintf(tsx->obj_name, sizeof(tsx->obj_name), "utsx%p", tsx);
*p_tsx = tsx;
@@ -100,26 +110,30 @@ PJ_DEF(pj_status_t) pj_stun_client_tsx_schedule_destroy(
PJ_ASSERT_RETURN(tsx && delay, PJ_EINVAL);
PJ_ASSERT_RETURN(tsx->cb.on_destroy, PJ_EINVAL);
+ pj_grp_lock_acquire(tsx->grp_lock);
+
/* Cancel previously registered timer */
- if (tsx->destroy_timer.id != 0) {
- pj_timer_heap_cancel(tsx->timer_heap, &tsx->destroy_timer);
- tsx->destroy_timer.id = 0;
- }
+ pj_timer_heap_cancel_if_active(tsx->timer_heap, &tsx->destroy_timer,
+ TIMER_INACTIVE);
/* Stop retransmission, just in case */
- if (tsx->retransmit_timer.id != 0) {
- pj_timer_heap_cancel(tsx->timer_heap, &tsx->retransmit_timer);
- tsx->retransmit_timer.id = 0;
- }
+ pj_timer_heap_cancel_if_active(tsx->timer_heap, &tsx->retransmit_timer,
+ TIMER_INACTIVE);
- status = pj_timer_heap_schedule(tsx->timer_heap,
- &tsx->destroy_timer, delay);
- if (status != PJ_SUCCESS)
+ status = pj_timer_heap_schedule_w_grp_lock(tsx->timer_heap,
+ &tsx->destroy_timer, delay,
+ TIMER_ACTIVE, tsx->grp_lock);
+ if (status != PJ_SUCCESS) {
+ pj_grp_lock_release(tsx->grp_lock);
return status;
+ }
- tsx->destroy_timer.id = TIMER_ACTIVE;
tsx->cb.on_complete = NULL;
+ pj_grp_lock_release(tsx->grp_lock);
+
+ TRACE_((tsx->obj_name, "STUN transaction %p schedule destroy", tsx));
+
return PJ_SUCCESS;
}
@@ -127,20 +141,21 @@ PJ_DEF(pj_status_t) pj_stun_client_tsx_schedule_destroy(
/*
* Destroy transaction immediately.
*/
-PJ_DEF(pj_status_t) pj_stun_client_tsx_destroy(pj_stun_client_tsx *tsx)
+PJ_DEF(pj_status_t) pj_stun_client_tsx_stop(pj_stun_client_tsx *tsx)
{
PJ_ASSERT_RETURN(tsx, PJ_EINVAL);
- if (tsx->retransmit_timer.id != 0) {
- pj_timer_heap_cancel(tsx->timer_heap, &tsx->retransmit_timer);
- tsx->retransmit_timer.id = 0;
- }
- if (tsx->destroy_timer.id != 0) {
- pj_timer_heap_cancel(tsx->timer_heap, &tsx->destroy_timer);
- tsx->destroy_timer.id = 0;
- }
+ /* Don't call grp_lock_acquire() because we might be called on
+ * group lock's destructor.
+ */
+ pj_timer_heap_cancel_if_active(tsx->timer_heap, &tsx->retransmit_timer,
+ TIMER_INACTIVE);
+ pj_timer_heap_cancel_if_active(tsx->timer_heap, &tsx->destroy_timer,
+ TIMER_INACTIVE);
+
+ PJ_LOG(5,(tsx->obj_name, "STUN client transaction %p stopped, ref_cnt=%d",
+ tsx, pj_grp_lock_get_ref(tsx->grp_lock)));
- PJ_LOG(5,(tsx->obj_name, "STUN client transaction destroyed"));
return PJ_SUCCESS;
}
@@ -185,7 +200,7 @@ static pj_status_t tsx_transmit_msg(pj_stun_client_tsx *tsx,
{
pj_status_t status;
- PJ_ASSERT_RETURN(tsx->retransmit_timer.id == 0 ||
+ PJ_ASSERT_RETURN(tsx->retransmit_timer.id == TIMER_INACTIVE ||
!tsx->require_retransmit, PJ_EBUSY);
if (tsx->require_retransmit && mod_count) {
@@ -211,14 +226,15 @@ static pj_status_t tsx_transmit_msg(pj_stun_client_tsx *tsx,
* cancel it (as opposed to when schedule_timer() failed we cannot
* cancel transmission).
*/;
- status = pj_timer_heap_schedule(tsx->timer_heap,
- &tsx->retransmit_timer,
- &tsx->retransmit_time);
+ status = pj_timer_heap_schedule_w_grp_lock(tsx->timer_heap,
+ &tsx->retransmit_timer,
+ &tsx->retransmit_time,
+ TIMER_ACTIVE,
+ tsx->grp_lock);
if (status != PJ_SUCCESS) {
- tsx->retransmit_timer.id = 0;
+ tsx->retransmit_timer.id = TIMER_INACTIVE;
return status;
}
- tsx->retransmit_timer.id = TIMER_ACTIVE;
}
@@ -235,12 +251,12 @@ static pj_status_t tsx_transmit_msg(pj_stun_client_tsx *tsx,
if (status == PJNATH_ESTUNDESTROYED) {
/* We've been destroyed, don't access the object. */
} else if (status != PJ_SUCCESS) {
- if (tsx->retransmit_timer.id != 0 && mod_count) {
- pj_timer_heap_cancel(tsx->timer_heap,
- &tsx->retransmit_timer);
- tsx->retransmit_timer.id = 0;
+ if (mod_count) {
+ pj_timer_heap_cancel_if_active( tsx->timer_heap,
+ &tsx->retransmit_timer,
+ TIMER_INACTIVE);
}
- stun_perror(tsx, "STUN error sending message", status);
+ PJ_PERROR(4, (tsx->obj_name, status, "STUN error sending message"));
}
pj_log_pop_indent();
@@ -261,6 +277,8 @@ PJ_DEF(pj_status_t) pj_stun_client_tsx_send_msg(pj_stun_client_tsx *tsx,
PJ_ASSERT_RETURN(tsx && pkt && pkt_len, PJ_EINVAL);
PJ_ASSERT_RETURN(tsx->retransmit_timer.id == 0, PJ_EBUSY);
+ pj_grp_lock_acquire(tsx->grp_lock);
+
/* Encode message */
tsx->last_pkt = pkt;
tsx->last_pkt_size = pkt_len;
@@ -286,27 +304,29 @@ PJ_DEF(pj_status_t) pj_stun_client_tsx_send_msg(pj_stun_client_tsx *tsx,
* cancel it (as opposed to when schedule_timer() failed we cannot
* cancel transmission).
*/;
- status = pj_timer_heap_schedule(tsx->timer_heap,
- &tsx->retransmit_timer,
- &tsx->retransmit_time);
+ status = pj_timer_heap_schedule_w_grp_lock(tsx->timer_heap,
+ &tsx->retransmit_timer,
+ &tsx->retransmit_time,
+ TIMER_ACTIVE,
+ tsx->grp_lock);
if (status != PJ_SUCCESS) {
- tsx->retransmit_timer.id = 0;
+ tsx->retransmit_timer.id = TIMER_INACTIVE;
+ pj_grp_lock_release(tsx->grp_lock);
return status;
}
- tsx->retransmit_timer.id = TIMER_ACTIVE;
}
/* Send the message */
status = tsx_transmit_msg(tsx, PJ_TRUE);
if (status != PJ_SUCCESS) {
- if (tsx->retransmit_timer.id != 0) {
- pj_timer_heap_cancel(tsx->timer_heap,
- &tsx->retransmit_timer);
- tsx->retransmit_timer.id = 0;
- }
+ pj_timer_heap_cancel_if_active(tsx->timer_heap,
+ &tsx->retransmit_timer,
+ TIMER_INACTIVE);
+ pj_grp_lock_release(tsx->grp_lock);
return status;
}
+ pj_grp_lock_release(tsx->grp_lock);
return PJ_SUCCESS;
}
@@ -319,6 +339,7 @@ static void retransmit_timer_callback(pj_timer_heap_t *timer_heap,
pj_status_t status;
PJ_UNUSED_ARG(timer_heap);
+ pj_grp_lock_acquire(tsx->grp_lock);
if (tsx->transmit_count >= PJ_STUN_MAX_TRANSMIT_COUNT) {
/* Retransmission count exceeded. Transaction has failed */
@@ -331,6 +352,7 @@ static void retransmit_timer_callback(pj_timer_heap_t *timer_heap,
tsx->cb.on_complete(tsx, PJNATH_ESTUNTIMEDOUT, NULL, NULL, 0);
}
}
+ pj_grp_lock_release(tsx->grp_lock);
/* We might have been destroyed, don't try to access the object */
pj_log_pop_indent();
return;
@@ -338,9 +360,7 @@ static void retransmit_timer_callback(pj_timer_heap_t *timer_heap,
tsx->retransmit_timer.id = 0;
status = tsx_transmit_msg(tsx, PJ_TRUE);
- if (status == PJNATH_ESTUNDESTROYED) {
- /* We've been destroyed, don't try to access the object */
- } else if (status != PJ_SUCCESS) {
+ if (status != PJ_SUCCESS) {
tsx->retransmit_timer.id = 0;
if (!tsx->complete) {
tsx->complete = PJ_TRUE;
@@ -348,8 +368,10 @@ static void retransmit_timer_callback(pj_timer_heap_t *timer_heap,
tsx->cb.on_complete(tsx, status, NULL, NULL, 0);
}
}
- /* We might have been destroyed, don't try to access the object */
}
+
+ pj_grp_lock_release(tsx->grp_lock);
+ /* We might have been destroyed, don't try to access the object */
}
/*
@@ -362,10 +384,8 @@ PJ_DEF(pj_status_t) pj_stun_client_tsx_retransmit(pj_stun_client_tsx *tsx,
return PJ_SUCCESS;
}
- if (tsx->retransmit_timer.id != 0) {
- pj_timer_heap_cancel(tsx->timer_heap, &tsx->retransmit_timer);
- tsx->retransmit_timer.id = 0;
- }
+ pj_timer_heap_cancel_if_active(tsx->timer_heap, &tsx->retransmit_timer,
+ TIMER_INACTIVE);
return tsx_transmit_msg(tsx, mod_count);
}
@@ -379,6 +399,7 @@ static void destroy_timer_callback(pj_timer_heap_t *timer_heap,
PJ_UNUSED_ARG(timer_heap);
tsx->destroy_timer.id = PJ_FALSE;
+
tsx->cb.on_destroy(tsx);
/* Don't access transaction after this */
}
@@ -408,10 +429,8 @@ PJ_DEF(pj_status_t) pj_stun_client_tsx_on_rx_msg(pj_stun_client_tsx *tsx,
/* We have a response with matching transaction ID.
* We can cancel retransmit timer now.
*/
- if (tsx->retransmit_timer.id) {
- pj_timer_heap_cancel(tsx->timer_heap, &tsx->retransmit_timer);
- tsx->retransmit_timer.id = 0;
- }
+ pj_timer_heap_cancel_if_active(tsx->timer_heap, &tsx->retransmit_timer,
+ TIMER_INACTIVE);
/* Find STUN error code attribute */
err_attr = (pj_stun_errcode_attr*)