diff options
-rw-r--r-- | pjsip/include/pjsip-ua/sip_inv.h | 3 | ||||
-rw-r--r-- | pjsip/include/pjsip/sip_transaction.h | 12 | ||||
-rw-r--r-- | pjsip/src/pjsip-ua/sip_inv.c | 16 | ||||
-rw-r--r-- | pjsip/src/pjsip/sip_transaction.c | 31 |
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, |