summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2007-02-05 18:59:31 +0000
committerBenny Prijono <bennylp@teluu.com>2007-02-05 18:59:31 +0000
commit1ae33feae9a3f0af400b09dcfdf32a80fe97542c (patch)
tree0ea3df1ead2d7a81b655338a010e6b85ea42754a
parent7a7a50ebbab0f58b354489e4f7cbedb73fabaa31 (diff)
Fixed ticket #89: implement transaction timeout in REGISTER request (thanks Frank Wiersma for reporting the problem)
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@932 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r--pjsip/include/pjsip/sip_util.h3
-rw-r--r--pjsip/src/pjsip-ua/sip_reg.c9
-rw-r--r--pjsip/src/pjsip/sip_util_statefull.c68
3 files changed, 72 insertions, 8 deletions
diff --git a/pjsip/include/pjsip/sip_util.h b/pjsip/include/pjsip/sip_util.h
index 8a030fd6..4ae1a5f3 100644
--- a/pjsip/include/pjsip/sip_util.h
+++ b/pjsip/include/pjsip/sip_util.h
@@ -426,6 +426,7 @@ PJ_DECL(pj_status_t) pjsip_endpt_respond( pjsip_endpoint *endpt,
* @param tdata The transmit data to be sent.
* @param timeout Optional timeout for final response to be received, or -1
* if the transaction should not have a timeout restriction.
+ * The value is in miliseconds.
* @param token Optional token to be associated with the transaction, and
* to be passed to the callback.
* @param cb Optional callback to be called when the transaction has
@@ -437,7 +438,7 @@ PJ_DECL(pj_status_t) pjsip_endpt_respond( pjsip_endpoint *endpt,
*/
PJ_DECL(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*));
diff --git a/pjsip/src/pjsip-ua/sip_reg.c b/pjsip/src/pjsip-ua/sip_reg.c
index 45d2020c..9b6a68be 100644
--- a/pjsip/src/pjsip-ua/sip_reg.c
+++ b/pjsip/src/pjsip-ua/sip_reg.c
@@ -38,6 +38,12 @@
#define DELAY_BEFORE_REFRESH 5
#define THIS_FILE "sip_regc.c"
+/* Outgoing transaction timeout when server sends 100 but never replies
+ * with final response. Value is in MILISECONDS!
+ */
+#define REGC_TSX_TIMEOUT 33000
+
+
/**
* SIP client registration structure.
*/
@@ -742,7 +748,8 @@ PJ_DEF(pj_status_t) pjsip_regc_send(pjsip_regc *regc, pjsip_tx_data *tdata)
*/
regc->has_tsx = PJ_TRUE;
++regc->busy;
- status = pjsip_endpt_send_request(regc->endpt, tdata, -1, regc, &tsx_callback);
+ status = pjsip_endpt_send_request(regc->endpt, tdata, REGC_TSX_TIMEOUT,
+ regc, &tsx_callback);
if (status!=PJ_SUCCESS) {
PJ_LOG(4,(THIS_FILE, "Error sending request, status=%d", status));
}
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;
}