summaryrefslogtreecommitdiff
path: root/pjsip/src/pjsip-ua
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2008-02-21 19:28:21 +0000
committerBenny Prijono <bennylp@teluu.com>2008-02-21 19:28:21 +0000
commit9dafbac6b6e70d84ed1f925c1ec1ee00b5c4411d (patch)
treef1252b89503165c3f94ad3b275ffd604532035be /pjsip/src/pjsip-ua
parenteb85ed9665fbcf4fa5a500e67fb4e7865ba79aa9 (diff)
Ticket #488: When outgoing request within dialog is responded with 481 or 408, should send BYE after terminating dialog (thanks Philippe Leuba)
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@1814 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjsip/src/pjsip-ua')
-rw-r--r--pjsip/src/pjsip-ua/sip_inv.c109
1 files changed, 67 insertions, 42 deletions
diff --git a/pjsip/src/pjsip-ua/sip_inv.c b/pjsip/src/pjsip-ua/sip_inv.c
index ee5274fd..8b813fa2 100644
--- a/pjsip/src/pjsip-ua/sip_inv.c
+++ b/pjsip/src/pjsip-ua/sip_inv.c
@@ -2883,6 +2883,60 @@ static void inv_on_state_early( pjsip_inv_session *inv, pjsip_event *e)
}
/*
+ * Handle 408, 481, or any other responses that terminates dialog.
+ */
+static pj_bool_t handle_408_481_response(pjsip_inv_session *inv,
+ pjsip_event *e)
+{
+ /* RFC 3261 Section 12.2.1.2:
+ * If the response for a request within a dialog is a 481
+ * (Call/Transaction Does Not Exist) or a 408 (Request Timeout), the UAC
+ * SHOULD terminate the dialog. A UAC SHOULD also terminate a dialog if
+ * no response at all is received for the request (the client
+ * transaction would inform the TU about the timeout.)
+ *
+ * For INVITE initiated dialogs, terminating the dialog consists of
+ * sending a BYE.
+ *
+ * Note:
+ * according to X, this should terminate dialog usage only, not the
+ * dialog.
+ */
+ pjsip_transaction *tsx = e->body.tsx_state.tsx;
+
+ pj_assert(tsx->role == PJSIP_UAC_ROLE);
+
+ /* Note that 481 response to CANCEL does not terminate dialog usage,
+ * but only the transaction.
+ */
+ if ((tsx->status_code == PJSIP_SC_CALL_TSX_DOES_NOT_EXIST &&
+ tsx->method.id != PJSIP_CANCEL_METHOD) ||
+ tsx->status_code == PJSIP_SC_REQUEST_TIMEOUT ||
+ tsx->status_code == PJSIP_SC_TSX_TIMEOUT ||
+ tsx->status_code == PJSIP_SC_TSX_TRANSPORT_ERROR)
+ {
+ pjsip_tx_data *bye;
+ pj_status_t status;
+
+ inv_set_cause(inv, tsx->status_code, &tsx->status_text);
+ inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e);
+
+ /* Send BYE */
+ status = pjsip_dlg_create_request(inv->dlg, pjsip_get_bye_method(),
+ -1, &bye);
+ if (status == PJ_SUCCESS) {
+ pjsip_inv_send_msg(inv, bye);
+ }
+
+ return PJ_TRUE; /* Handled */
+
+ } else {
+ return PJ_FALSE; /* Unhandled */
+ }
+}
+
+
+/*
* State CONNECTING is after 2xx response to INVITE is sent/received.
*/
static void inv_on_state_connecting( pjsip_inv_session *inv, pjsip_event *e)
@@ -2993,7 +3047,8 @@ static void inv_on_state_connecting( pjsip_inv_session *inv, pjsip_event *e)
/*
* Handle response to outgoing UPDATE request.
*/
- inv_handle_update_response(inv, e);
+ if (handle_408_481_response(inv, e) == PJ_FALSE)
+ inv_handle_update_response(inv, e);
} else if (tsx->role == PJSIP_ROLE_UAS &&
tsx->state == PJSIP_TSX_STATE_TRYING &&
@@ -3005,22 +3060,8 @@ static void inv_on_state_connecting( pjsip_inv_session *inv, pjsip_event *e)
inv_respond_incoming_prack(inv, e->body.tsx_state.src.rdata);
} else if (tsx->role == PJSIP_ROLE_UAC) {
- /*
- * Handle case when outgoing request is answered with 481 (Call/
- * Transaction Does Not Exist), 408, or when it's timed out. In these
- * cases, disconnect session (i.e. dialog usage only).
- * Note that 481 response to CANCEL does not terminate dialog usage,
- * but only the transaction.
- */
- if ((tsx->status_code == PJSIP_SC_CALL_TSX_DOES_NOT_EXIST &&
- tsx->method.id != PJSIP_CANCEL_METHOD) ||
- tsx->status_code == PJSIP_SC_REQUEST_TIMEOUT ||
- tsx->status_code == PJSIP_SC_TSX_TIMEOUT ||
- tsx->status_code == PJSIP_SC_TSX_TRANSPORT_ERROR)
- {
- inv_set_cause(inv, tsx->status_code, &tsx->status_text);
- inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e);
- }
+
+ handle_408_481_response(inv, e);
}
}
@@ -3249,6 +3290,11 @@ static void inv_on_state_confirmed( pjsip_inv_session *inv, pjsip_event *e)
/* Send ACK */
inv_send_ack(inv, e);
+ } else if (handle_408_481_response(inv, e)) {
+
+ /* Handle response that terminates dialog */
+ /* Nothing to do (already handled) */
+
} else if (tsx->state == PJSIP_TSX_STATE_COMPLETED &&
(tsx->status_code==401 || tsx->status_code==407))
{
@@ -3266,16 +3312,6 @@ static void inv_on_state_confirmed( pjsip_inv_session *inv, pjsip_event *e)
/* Send re-INVITE */
status = pjsip_inv_send_msg( inv, tdata);
- } else if (tsx->status_code==PJSIP_SC_CALL_TSX_DOES_NOT_EXIST ||
- tsx->status_code==PJSIP_SC_REQUEST_TIMEOUT ||
- tsx->status_code >= 700)
- {
- /*
- * Handle responses that terminates dialog.
- */
- inv_set_cause(inv, tsx->status_code, &tsx->status_text);
- inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e);
-
} else if (tsx->status_code >= 300 && tsx->status_code < 700) {
pjmedia_sdp_neg_state neg_state;
@@ -3304,7 +3340,8 @@ static void inv_on_state_confirmed( pjsip_inv_session *inv, pjsip_event *e)
/*
* Handle response to outgoing UPDATE request.
*/
- inv_handle_update_response(inv, e);
+ if (handle_408_481_response(inv, e) == PJ_FALSE)
+ inv_handle_update_response(inv, e);
} else if (tsx->role == PJSIP_ROLE_UAS &&
tsx->state == PJSIP_TSX_STATE_TRYING &&
@@ -3317,21 +3354,9 @@ static void inv_on_state_confirmed( pjsip_inv_session *inv, pjsip_event *e)
} else if (tsx->role == PJSIP_ROLE_UAC) {
/*
- * Handle case when outgoing request is answered with 481 (Call/
- * Transaction Does Not Exist), 408, or when it's timed out. In these
- * cases, disconnect session (i.e. dialog usage only).
- * Note that 481 response to CANCEL does not terminate dialog usage,
- * but only the transaction.
+ * Handle 408/481 response
*/
- if ((tsx->status_code == PJSIP_SC_CALL_TSX_DOES_NOT_EXIST &&
- tsx->method.id != PJSIP_CANCEL_METHOD) ||
- tsx->status_code == PJSIP_SC_REQUEST_TIMEOUT ||
- tsx->status_code == PJSIP_SC_TSX_TIMEOUT ||
- tsx->status_code == PJSIP_SC_TSX_TRANSPORT_ERROR)
- {
- inv_set_cause(inv, tsx->status_code, &tsx->status_text);
- inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e);
- }
+ handle_408_481_response(inv, e);
}
}