diff options
-rw-r--r-- | pjsip/include/pjsip/sip_transaction.h | 29 | ||||
-rw-r--r-- | pjsip/src/pjsip-ua/sip_inv.c | 8 | ||||
-rw-r--r-- | pjsip/src/pjsip/sip_transaction.c | 41 | ||||
-rw-r--r-- | tests/pjsua/scripts-sipp/uas-cancel-no-final.xml | 62 |
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 a54a5f36..67d560b2 100644 --- a/pjsip/src/pjsip-ua/sip_inv.c +++ b/pjsip/src/pjsip-ua/sip_inv.c @@ -1886,6 +1886,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> + |