summaryrefslogtreecommitdiff
path: root/pjsip/src/pjsip/sip_util_statefull.c
diff options
context:
space:
mode:
Diffstat (limited to 'pjsip/src/pjsip/sip_util_statefull.c')
-rw-r--r--pjsip/src/pjsip/sip_util_statefull.c68
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;
}