Fixed ticket #89: implement transaction timeout in REGISTER request (thanks Frank Wiersma for reporting the problem)

git-svn-id: https://svn.pjsip.org/repos/pjproject/trunk@932 74dad513-b988-da41-8d7b-12977e46ad98
This commit is contained in:
Benny Prijono 2007-02-05 18:59:31 +00:00
parent 400e58c295
commit 0f35f91aec
3 changed files with 72 additions and 8 deletions

View File

@ -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*));

View File

@ -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));
}

View File

@ -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;
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;
PJ_TODO(IMPLEMENT_TIMEOUT_FOR_SEND_REQUEST);
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;
}