diff options
Diffstat (limited to 'pjsip/src/pjsip/sip_util_statefull.c')
-rw-r--r-- | pjsip/src/pjsip/sip_util_statefull.c | 68 |
1 files changed, 62 insertions, 6 deletions
diff --git a/pjsip/src/pjsip/sip_util_statefull.c b/pjsip/src/pjsip/sip_util_statefull.c index 133dce32..8056989f 100644 --- a/pjsip/src/pjsip/sip_util_statefull.c +++ b/pjsip/src/pjsip/sip_util_statefull.c @@ -22,11 +22,16 @@ #include <pjsip/sip_transaction.h> #include <pjsip/sip_event.h> #include <pjsip/sip_errno.h> -#include <pj/pool.h> #include <pj/assert.h> +#include <pj/log.h> +#include <pj/pool.h> +#include <pj/string.h> struct tsx_data { + pj_time_val delay; + pj_timer_entry timeout_timer; + void *token; void (*cb)(void*, pjsip_event*); }; @@ -66,6 +71,12 @@ static void mod_util_on_tsx_state(pjsip_transaction *tsx, pjsip_event *event) if (tsx->status_code < 200) return; + /* Cancel timer if any */ + if (tsx_data->timeout_timer.id != 0) { + tsx_data->timeout_timer.id = 0; + pjsip_endpt_cancel_timer(tsx->endpt, &tsx_data->timeout_timer); + } + /* Call the callback, if any, and prevent the callback to be called again * by clearing the transaction's module_data. */ @@ -77,9 +88,32 @@ static void mod_util_on_tsx_state(pjsip_transaction *tsx, pjsip_event *event) } +static void mod_util_on_timeout(pj_timer_heap_t *th, pj_timer_entry *te) +{ + pjsip_transaction *tsx = (pjsip_transaction*) te->user_data; + struct tsx_data *tsx_data; + + PJ_UNUSED_ARG(th); + + tsx_data = tsx->mod_data[mod_stateful_util.id]; + if (tsx_data == NULL) { + pj_assert(!"Shouldn't happen"); + return; + } + + tsx_data->timeout_timer.id = 0; + + PJ_LOG(4,(tsx->obj_name, "Transaction timed out by user timer (%d.%d sec)", + (int)tsx_data->delay.sec, (int)tsx_data->delay.msec)); + + /* Terminate the transaction. This will call mod_util_on_tsx_state() */ + pjsip_tsx_terminate(tsx, PJSIP_SC_TSX_TIMEOUT); +} + + PJ_DEF(pj_status_t) pjsip_endpt_send_request( pjsip_endpoint *endpt, pjsip_tx_data *tdata, - int timeout, + pj_int32_t timeout, void *token, void (*cb)(void*,pjsip_event*)) { @@ -99,16 +133,38 @@ PJ_DEF(pj_status_t) pjsip_endpt_send_request( pjsip_endpoint *endpt, return status; } - tsx_data = pj_pool_alloc(tsx->pool, sizeof(struct tsx_data)); + tsx_data = pj_pool_zalloc(tsx->pool, sizeof(struct tsx_data)); tsx_data->token = token; tsx_data->cb = cb; - tsx->mod_data[mod_stateful_util.id] = tsx_data; - PJ_TODO(IMPLEMENT_TIMEOUT_FOR_SEND_REQUEST); + if (timeout >= 0) { + tsx_data->delay.sec = 0; + tsx_data->delay.msec = timeout; + pj_time_val_normalize(&tsx_data->delay); + + tsx_data->timeout_timer.id = PJ_TRUE; + tsx_data->timeout_timer.user_data = tsx; + tsx_data->timeout_timer.cb = &mod_util_on_timeout; + + status = pjsip_endpt_schedule_timer(endpt, &tsx_data->timeout_timer, + &tsx_data->delay); + if (status != PJ_SUCCESS) { + pjsip_tsx_terminate(tsx, PJSIP_SC_INTERNAL_SERVER_ERROR); + pjsip_tx_data_dec_ref(tdata); + return status; + } + } + + tsx->mod_data[mod_stateful_util.id] = tsx_data; status = pjsip_tsx_send_msg(tsx, NULL); - if (status != PJ_SUCCESS) + if (status != PJ_SUCCESS) { + if (tsx_data->timeout_timer.id != 0) { + pjsip_endpt_cancel_timer(endpt, &tsx_data->timeout_timer); + tsx_data->timeout_timer.id = PJ_FALSE; + } pjsip_tx_data_dec_ref(tdata); + } return status; } |