summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2008-06-25 10:15:01 +0000
committerBenny Prijono <bennylp@teluu.com>2008-06-25 10:15:01 +0000
commitae37866d737f3f36a32a344bedf2a2b8ae0e66c5 (patch)
treed6d56eee2cd48338e23c6f7091546ce7a5163191
parent0c919efd7592e8bd58318cc4a9a39db00080ba68 (diff)
Fixed ticket #550: PRACK is not re-sent on 401/407 challenge (thanks Josh Benson)
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@2049 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r--pjsip/src/pjsip-ua/sip_inv.c193
1 files changed, 96 insertions, 97 deletions
diff --git a/pjsip/src/pjsip-ua/sip_inv.c b/pjsip/src/pjsip-ua/sip_inv.c
index 0438f2c3..2085adec 100644
--- a/pjsip/src/pjsip-ua/sip_inv.c
+++ b/pjsip/src/pjsip-ua/sip_inv.c
@@ -2360,7 +2360,7 @@ static void inv_handle_update_response( pjsip_inv_session *inv,
inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e);
} else {
- /* Re-send BYE. */
+ /* Re-send request. */
status = pjsip_inv_send_msg(inv, tdata);
}
@@ -2518,6 +2518,91 @@ static void inv_on_state_null( pjsip_inv_session *inv, pjsip_event *e)
}
/*
+ * Generic UAC transaction handler:
+ * - resend request on 401 or 407 response.
+ * - terminate dialog on 408 and 481 response.
+ */
+static pj_bool_t handle_uac_tsx_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 */
+
+ }
+ /* Handle 401/407 challenge. */
+ else if (tsx->state == PJSIP_TSX_STATE_COMPLETED &&
+ (tsx->status_code == PJSIP_SC_UNAUTHORIZED ||
+ tsx->status_code == PJSIP_SC_PROXY_AUTHENTICATION_REQUIRED))
+ {
+
+ pjsip_tx_data *tdata;
+ pj_status_t status;
+
+ status = pjsip_auth_clt_reinit_req( &inv->dlg->auth_sess,
+ e->body.tsx_state.src.rdata,
+ tsx->last_tx, &tdata);
+
+ if (status != PJ_SUCCESS) {
+ /* Does not have proper credentials. End the session. */
+ inv_set_cause(inv, PJSIP_SC_OK, NULL);
+ inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e);
+
+ } else {
+ /* Re-send request. */
+ if (tsx->method.id == PJSIP_INVITE_METHOD)
+ inv->invite_tsx = NULL;
+
+ status = pjsip_inv_send_msg(inv, tdata);
+ }
+
+ return PJ_TRUE; /* Handled */
+
+ } else {
+ return PJ_FALSE; /* Unhandled */
+ }
+}
+
+
+/*
* State CALLING is after sending initial INVITE request but before
* any response (with tag) is received.
*/
@@ -2873,79 +2958,12 @@ static void inv_on_state_early( 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, 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 */
+
+ /* Generic handling for UAC tsx completion */
+ handle_uac_tsx_response(inv, e);
}
}
-
/*
* State CONNECTING is after 2xx response to INVITE is sent/received.
*/
@@ -3057,7 +3075,7 @@ static void inv_on_state_connecting( pjsip_inv_session *inv, pjsip_event *e)
/*
* Handle response to outgoing UPDATE request.
*/
- if (handle_408_481_response(inv, e) == PJ_FALSE)
+ if (handle_uac_tsx_response(inv, e) == PJ_FALSE)
inv_handle_update_response(inv, e);
} else if (tsx->role == PJSIP_ROLE_UAS &&
@@ -3071,7 +3089,8 @@ static void inv_on_state_connecting( pjsip_inv_session *inv, pjsip_event *e)
} else if (tsx->role == PJSIP_ROLE_UAC) {
- handle_408_481_response(inv, e);
+ /* Generic handling for UAC tsx completion */
+ handle_uac_tsx_response(inv, e);
}
}
@@ -3308,31 +3327,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)) {
+ } else if (handle_uac_tsx_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))
- {
- pjsip_tx_data *tdata;
- pj_status_t status;
-
- /* Handle authentication challenge. */
- status = pjsip_auth_clt_reinit_req( &dlg->auth_sess,
- e->body.tsx_state.src.rdata,
- tsx->last_tx,
- &tdata);
- if (status != PJ_SUCCESS)
- return;
-
- /* Retry INVITE request */
- inv->invite_tsx = NULL;
-
- /* Send re-INVITE */
- status = pjsip_inv_send_msg( inv, tdata);
-
} else if (tsx->status_code >= 300 && tsx->status_code < 700) {
pjmedia_sdp_neg_state neg_state;
@@ -3361,7 +3360,7 @@ static void inv_on_state_confirmed( pjsip_inv_session *inv, pjsip_event *e)
/*
* Handle response to outgoing UPDATE request.
*/
- if (handle_408_481_response(inv, e) == PJ_FALSE)
+ if (handle_uac_tsx_response(inv, e) == PJ_FALSE)
inv_handle_update_response(inv, e);
} else if (tsx->role == PJSIP_ROLE_UAS &&
@@ -3375,9 +3374,9 @@ static void inv_on_state_confirmed( pjsip_inv_session *inv, pjsip_event *e)
} else if (tsx->role == PJSIP_ROLE_UAC) {
/*
- * Handle 408/481 response
+ * Handle 401/407/408/481 response
*/
- handle_408_481_response(inv, e);
+ handle_uac_tsx_response(inv, e);
}
}