summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2009-06-25 10:48:08 +0000
committerBenny Prijono <bennylp@teluu.com>2009-06-25 10:48:08 +0000
commit148568dd94cfad0a74adf1258168923c86b88404 (patch)
treeebe3d59e78213645d34c9c5f26d736337cd89a63
parent9e87cf617bf01284f69f2fa3e0ce2c83b50b5465 (diff)
Ticket #796: Handle the case when CANCEL is responded with 200/OK but 487 is not sent
- merged changes from ticket #503 git-svn-id: http://svn.pjsip.org/repos/pjproject/branches/1.0@2798 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r--pjsip/include/pjsip/sip_transaction.h29
-rw-r--r--pjsip/src/pjsip-ua/sip_inv.c8
-rw-r--r--pjsip/src/pjsip/sip_transaction.c41
-rw-r--r--tests/pjsua/scripts-sipp/uas-cancel-no-final.xml62
4 files changed, 139 insertions, 1 deletions
diff --git a/pjsip/include/pjsip/sip_transaction.h b/pjsip/include/pjsip/sip_transaction.h
index b94f8991..eb8510ae 100644
--- a/pjsip/include/pjsip/sip_transaction.h
+++ b/pjsip/include/pjsip/sip_transaction.h
@@ -311,7 +311,6 @@ PJ_DECL(pj_status_t) pjsip_tsx_create_key( pj_pool_t *pool,
const pjsip_method *method,
const pjsip_rx_data *rdata );
-
/**
* Force terminate transaction.
*
@@ -330,11 +329,39 @@ PJ_DECL(pj_status_t) pjsip_tsx_terminate( pjsip_transaction *tsx,
* This operation normally is used for INVITE transaction only, when
* the transaction is cancelled before any provisional response has been
* received.
+ *
+ * @param tsx The transaction.
+ *
+ * @return PJ_SUCCESS or the appropriate error code.
*/
PJ_DECL(pj_status_t) pjsip_tsx_stop_retransmit(pjsip_transaction *tsx);
/**
+ * Start a timer to terminate transaction after the specified time
+ * has elapsed. This function is only valid for INVITE transaction,
+ * and only before final response is received for the INVITE transaction.
+ * It is normally called after the UAC has sent CANCEL for this
+ * INVITE transaction.
+ *
+ * The purpose of this function is to terminate the transaction if UAS
+ * does not send final response to this INVITE transaction even after
+ * it sends 200/OK to CANCEL (for example when the UAS complies to RFC
+ * 2543).
+ *
+ * Once this timer is set, the transaction will be terminated either when
+ * a final response is received or the timer expires.
+ *
+ * @param tsx The transaction.
+ * @param millisec Timeout value in milliseconds.
+ *
+ * @return PJ_SUCCESS or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsip_tsx_set_timeout(pjsip_transaction *tsx,
+ unsigned millisec);
+
+
+/**
* Get the transaction instance in the incoming message. If the message
* has a corresponding transaction, this function will return non NULL
* value.
diff --git a/pjsip/src/pjsip-ua/sip_inv.c b/pjsip/src/pjsip-ua/sip_inv.c
index fca25670..72f1afa4 100644
--- a/pjsip/src/pjsip-ua/sip_inv.c
+++ b/pjsip/src/pjsip-ua/sip_inv.c
@@ -1884,6 +1884,14 @@ PJ_DEF(pj_status_t) pjsip_inv_end_session( pjsip_inv_session *inv,
status = pjsip_endpt_create_cancel(inv->dlg->endpt,
inv->invite_tsx->last_tx,
&tdata);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ /* Set timeout for the INVITE transaction, in case UAS is not
+ * able to respond the INVITE with 487 final response. The
+ * timeout value is 64*T1.
+ */
+ pjsip_tsx_set_timeout(inv->invite_tsx, 64 * pjsip_cfg()->tsx.t1);
} else {
diff --git a/pjsip/src/pjsip/sip_transaction.c b/pjsip/src/pjsip/sip_transaction.c
index 5a6f7dc6..525f9e37 100644
--- a/pjsip/src/pjsip/sip_transaction.c
+++ b/pjsip/src/pjsip/sip_transaction.c
@@ -1503,6 +1503,47 @@ PJ_DEF(pj_status_t) pjsip_tsx_stop_retransmit(pjsip_transaction *tsx)
/*
+ * Start a timer to terminate transaction after the specified time
+ * has elapsed.
+ */
+PJ_DEF(pj_status_t) pjsip_tsx_set_timeout( pjsip_transaction *tsx,
+ unsigned millisec)
+{
+ struct tsx_lock_data lck;
+ pj_time_val timeout;
+
+ PJ_ASSERT_RETURN(tsx != NULL, PJ_EINVAL);
+ PJ_ASSERT_RETURN(tsx->role == PJSIP_ROLE_UAC &&
+ tsx->method.id == PJSIP_INVITE_METHOD,
+ PJ_EINVALIDOP);
+
+ lock_tsx(tsx, &lck);
+
+ /* Transaction must not have got final response */
+ PJ_ASSERT_ON_FAIL(tsx->status_code < 200,
+ { unlock_tsx(tsx, &lck); return PJ_EINVALIDOP; });
+
+ if (tsx->timeout_timer.id != 0) {
+ pjsip_endpt_cancel_timer(tsx->endpt, &tsx->timeout_timer);
+ tsx->timeout_timer.id = 0;
+ }
+
+ timeout.sec = 0;
+ timeout.msec = millisec;
+ pj_time_val_normalize(&timeout);
+
+ tsx->timeout_timer.id = TIMER_ACTIVE;
+ pjsip_endpt_schedule_timer(tsx->endpt, &tsx->timeout_timer,
+ &timeout);
+
+
+ unlock_tsx(tsx, &lck);
+
+ return PJ_SUCCESS;
+}
+
+
+/*
* This function is called by TU to send a message.
*/
PJ_DEF(pj_status_t) pjsip_tsx_send_msg( pjsip_transaction *tsx,
diff --git a/tests/pjsua/scripts-sipp/uas-cancel-no-final.xml b/tests/pjsua/scripts-sipp/uas-cancel-no-final.xml
new file mode 100644
index 00000000..e96f2a37
--- /dev/null
+++ b/tests/pjsua/scripts-sipp/uas-cancel-no-final.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE scenario SYSTEM "sipp.dtd">
+
+<scenario name="Basic UAS responder">
+ <recv request="INVITE" crlf="true">
+ </recv>
+
+ <send>
+ <![CDATA[
+
+ SIP/2.0 100 Trying
+ [last_Via:]
+ [last_From:]
+ [last_To:]
+ [last_Call-ID:]
+ [last_CSeq:]
+ Content-Length: 0
+
+ ]]>
+ </send>
+
+ <send>
+ <![CDATA[
+
+ SIP/2.0 180 Ringing
+ [last_Via:]
+ [last_From:]
+ [last_To:];tag=[call_number]
+ [last_Call-ID:]
+ [last_CSeq:]
+ Contact: <sip:192.168.0.15>
+ Content-Length: 0
+
+ ]]>
+ </send>
+
+ <!-- Wait for CANCEL -->
+ <recv request="CANCEL" crlf="true">
+ </recv>
+
+ <send>
+ <![CDATA[
+ SIP/2.0 200 OK
+ [last_Via:]
+ [last_From:]
+ [last_To:]
+ [last_Call-ID:]
+ [last_CSeq:]
+ Content-Length: 0
+
+ ]]>
+ </send>
+
+
+ <!-- definition of the response time repartition table (unit is ms) -->
+ <ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/>
+
+ <!-- definition of the call length repartition table (unit is ms) -->
+ <CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/>
+
+</scenario>
+