summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2007-05-30 04:26:40 +0000
committerBenny Prijono <bennylp@teluu.com>2007-05-30 04:26:40 +0000
commit2195f68b66250eb4b02b73ba40af959fa137c2ff (patch)
tree44f0e09c40b0d61c9a1175736bf0f6568f106f75
parent8d8e6b777d4a49d04ffe959a9ed5d92982a3f7aa (diff)
Fixed ticket #302: Behavior in cancelling INVITE session when no provisional response has been received (thanks Esbjörn Dominique)
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@1319 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r--pjsip/include/pjsip-ua/sip_inv.h3
-rw-r--r--pjsip/include/pjsip/sip_transaction.h12
-rw-r--r--pjsip/src/pjsip-ua/sip_inv.c16
-rw-r--r--pjsip/src/pjsip/sip_transaction.c31
4 files changed, 59 insertions, 3 deletions
diff --git a/pjsip/include/pjsip-ua/sip_inv.h b/pjsip/include/pjsip-ua/sip_inv.h
index 7ea1f27d..3a144f80 100644
--- a/pjsip/include/pjsip-ua/sip_inv.h
+++ b/pjsip/include/pjsip-ua/sip_inv.h
@@ -223,7 +223,8 @@ struct pjsip_inv_session
char obj_name[PJ_MAX_OBJ_NAME]; /**< Log identification */
pj_pool_t *pool; /**< Dialog's pool. */
pjsip_inv_state state; /**< Invite sess state. */
- pj_bool_t cancelling; /**< CANCEL sent? */
+ pj_bool_t cancelling; /**< CANCEL requested */
+ pj_bool_t pending_cancel; /**< Wait to send CANCEL*/
pjsip_status_code cause; /**< Disconnect cause. */
pj_str_t cause_text; /**< Cause text. */
pj_bool_t notify; /**< Internal. */
diff --git a/pjsip/include/pjsip/sip_transaction.h b/pjsip/include/pjsip/sip_transaction.h
index 1787f787..657e82ac 100644
--- a/pjsip/include/pjsip/sip_transaction.h
+++ b/pjsip/include/pjsip/sip_transaction.h
@@ -297,6 +297,18 @@ PJ_DECL(pj_status_t) pjsip_tsx_terminate( pjsip_transaction *tsx,
/**
+ * Cease retransmission on the UAC transaction. The UAC transaction is
+ * still considered running, and it will complete when either final
+ * response is received or the transaction times out.
+ *
+ * This operation normally is used for INVITE transaction only, when
+ * the transaction is cancelled before any provisional response has been
+ * received.
+ */
+PJ_DECL(pj_status_t) pjsip_tsx_stop_retransmit(pjsip_transaction *tsx);
+
+
+/**
* 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 3e4e546b..62d76d73 100644
--- a/pjsip/src/pjsip-ua/sip_inv.c
+++ b/pjsip/src/pjsip-ua/sip_inv.c
@@ -1512,8 +1512,12 @@ PJ_DEF(pj_status_t) pjsip_inv_end_session( pjsip_inv_session *inv,
*/
if (inv->invite_tsx->status_code < 100) {
- pjsip_tsx_terminate(inv->invite_tsx, 487);
+ pjsip_tsx_stop_retransmit(inv->invite_tsx);
+ inv->cancelling = PJ_TRUE;
+ inv->pending_cancel = PJ_TRUE;
*p_tdata = NULL;
+ PJ_LOG(4, (inv->obj_name, "Stopping retransmission, "
+ "delaying CANCEL"));
return PJ_SUCCESS;
}
@@ -1925,6 +1929,16 @@ static void inv_on_state_calling( pjsip_inv_session *inv, pjsip_event *e)
break;
case PJSIP_TSX_STATE_PROCEEDING:
+ if (inv->pending_cancel) {
+ pjsip_tx_data *cancel;
+
+ inv->pending_cancel = PJ_FALSE;
+
+ status = pjsip_inv_end_session(inv, 487, NULL, &cancel);
+ if (status == PJ_SUCCESS && cancel)
+ status = pjsip_inv_send_msg(inv, cancel);
+ }
+
if (dlg->remote.info->tag.slen) {
inv_set_state(inv, PJSIP_INV_STATE_EARLY, e);
diff --git a/pjsip/src/pjsip/sip_transaction.c b/pjsip/src/pjsip/sip_transaction.c
index 20e7b8bc..0eb102c5 100644
--- a/pjsip/src/pjsip/sip_transaction.c
+++ b/pjsip/src/pjsip/sip_transaction.c
@@ -1419,9 +1419,10 @@ PJ_DEF(pj_status_t) pjsip_tsx_terminate( pjsip_transaction *tsx, int code )
{
struct tsx_lock_data lck;
+ PJ_ASSERT_RETURN(tsx != NULL, PJ_EINVAL);
+
PJ_LOG(5,(tsx->obj_name, "Request to terminate transaction"));
- PJ_ASSERT_RETURN(tsx != NULL, PJ_EINVAL);
PJ_ASSERT_RETURN(code >= 200, PJ_EINVAL);
if (tsx->state == PJSIP_TSX_STATE_TERMINATED)
@@ -1437,6 +1438,34 @@ PJ_DEF(pj_status_t) pjsip_tsx_terminate( pjsip_transaction *tsx, int code )
/*
+ * Cease retransmission on the UAC transaction. The UAC transaction is
+ * still considered running, and it will complete when either final
+ * response is received or the transaction times out.
+ */
+PJ_DEF(pj_status_t) pjsip_tsx_stop_retransmit(pjsip_transaction *tsx)
+{
+ struct tsx_lock_data lck;
+
+ PJ_ASSERT_RETURN(tsx != NULL, PJ_EINVAL);
+ PJ_ASSERT_RETURN(tsx->role == PJSIP_ROLE_UAC &&
+ tsx->method.id == PJSIP_INVITE_METHOD,
+ PJ_EINVALIDOP);
+
+ PJ_LOG(5,(tsx->obj_name, "Request to stop retransmission"));
+
+ lock_tsx(tsx, &lck);
+ /* Cancel retransmission timer. */
+ if (tsx->retransmit_timer.id != 0) {
+ pjsip_endpt_cancel_timer(tsx->endpt, &tsx->retransmit_timer);
+ tsx->retransmit_timer.id = 0;
+ }
+ 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,