summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2012-04-13 04:28:26 +0000
committerBenny Prijono <bennylp@teluu.com>2012-04-13 04:28:26 +0000
commit9b6a95bfd505ef587bd2c5d44c69cf203e2755af (patch)
treea3d9af847ba58c98c4a97621eccc68dddf12f703
parenta38217fcdc1150a3afb22c9984f3d9d785eb6af6 (diff)
Fixed #1487: Wrong SDP negotiator state if outgoing UPDATE or re-INVITE is challenged with 401 or 407
git-svn-id: http://svn.pjsip.org/repos/pjproject/branches/1.x@4046 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r--pjsip/src/pjsip-ua/sip_inv.c65
1 files changed, 46 insertions, 19 deletions
diff --git a/pjsip/src/pjsip-ua/sip_inv.c b/pjsip/src/pjsip-ua/sip_inv.c
index dc3ffb22..550300ca 100644
--- a/pjsip/src/pjsip-ua/sip_inv.c
+++ b/pjsip/src/pjsip-ua/sip_inv.c
@@ -155,6 +155,7 @@ struct tsx_inv_data
{
pjsip_inv_session *inv; /* The invite session */
pj_bool_t sdp_done; /* SDP negotiation done for this tsx? */
+ pj_bool_t retrying; /* Resend (e.g. due to 401/407) */
pj_str_t done_tag; /* To tag in RX response with answer */
pj_bool_t done_early;/* Negotiation was done for early med? */
};
@@ -2808,6 +2809,12 @@ static void inv_handle_bye_response( pjsip_inv_session *inv,
inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e);
} else {
+ struct tsx_inv_data *tsx_inv_data;
+
+ tsx_inv_data = (struct tsx_inv_data*)tsx->mod_data[mod_inv.mod.id];
+ if (tsx_inv_data)
+ tsx_inv_data->retrying = PJ_TRUE;
+
/* Re-send BYE. */
status = pjsip_inv_send_msg(inv, tdata);
}
@@ -2920,19 +2927,23 @@ on_return:
/*
* Handle incoming response to UAC UPDATE request.
*/
-static void inv_handle_update_response( pjsip_inv_session *inv,
- pjsip_event *e)
+static pj_bool_t inv_handle_update_response( pjsip_inv_session *inv,
+ pjsip_event *e)
{
pjsip_transaction *tsx = e->body.tsx_state.tsx;
- struct tsx_inv_data *tsx_inv_data = NULL;
+ struct tsx_inv_data *tsx_inv_data;
+ pj_bool_t handled = PJ_FALSE;
pj_status_t status = -1;
+ tsx_inv_data = (struct tsx_inv_data*)tsx->mod_data[mod_inv.mod.id];
+ pj_assert(tsx_inv_data);
+
/* Handle 401/407 challenge. */
if (tsx->state == PJSIP_TSX_STATE_COMPLETED &&
(tsx->status_code == 401 || tsx->status_code == 407))
{
pjsip_tx_data *tdata;
-
+
status = pjsip_auth_clt_reinit_req( &inv->dlg->auth_sess,
e->body.tsx_state.src.rdata,
tsx->last_tx,
@@ -2950,9 +2961,14 @@ static void inv_handle_update_response( pjsip_inv_session *inv,
*/
} else {
+ if (tsx_inv_data)
+ tsx_inv_data->retrying = PJ_TRUE;
+
/* Re-send request. */
status = pjsip_inv_send_msg(inv, tdata);
}
+
+ handled = PJ_TRUE;
}
/* Process 422 response */
@@ -2961,6 +2977,7 @@ static void inv_handle_update_response( pjsip_inv_session *inv,
{
status = handle_timer_response(inv, e->body.tsx_state.src.rdata,
PJ_FALSE);
+ handled = PJ_TRUE;
}
/* Process 2xx response */
@@ -2972,6 +2989,7 @@ static void inv_handle_update_response( pjsip_inv_session *inv,
PJ_FALSE);
status = inv_check_sdp_in_incoming_msg(inv, tsx,
e->body.tsx_state.src.rdata);
+ handled = PJ_TRUE;
}
/* Get/attach invite session's transaction data */
@@ -2985,26 +3003,25 @@ static void inv_handle_update_response( pjsip_inv_session *inv,
{
status = handle_timer_response(inv, e->body.tsx_state.src.rdata,
PJ_FALSE);
- }
-
- tsx_inv_data = (struct tsx_inv_data*)tsx->mod_data[mod_inv.mod.id];
- if (tsx_inv_data == NULL) {
- tsx_inv_data=PJ_POOL_ZALLOC_T(tsx->pool, struct tsx_inv_data);
- tsx_inv_data->inv = inv;
- tsx->mod_data[mod_inv.mod.id] = tsx_inv_data;
+ handled = PJ_TRUE;
}
}
- /* Cancel the negotiation if we don't get successful negotiation by now */
+ /* Cancel the negotiation if we don't get successful negotiation by now,
+ * unless it's authentication challenge and the request is being retried.
+ */
if (pjmedia_sdp_neg_get_state(inv->neg) ==
PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER &&
- tsx_inv_data && tsx_inv_data->sdp_done == PJ_FALSE)
+ tsx_inv_data && tsx_inv_data->sdp_done == PJ_FALSE &&
+ !tsx_inv_data->retrying)
{
pjmedia_sdp_neg_cancel_offer(inv->neg);
/* Prevent from us cancelling different offer! */
tsx_inv_data->sdp_done = PJ_TRUE;
}
+
+ return handled;
}
@@ -3204,7 +3221,6 @@ static pj_bool_t handle_uac_tsx_response(pjsip_inv_session *inv,
(tsx->status_code == PJSIP_SC_UNAUTHORIZED ||
tsx->status_code == PJSIP_SC_PROXY_AUTHENTICATION_REQUIRED))
{
-
pjsip_tx_data *tdata;
pj_status_t status;
@@ -3226,6 +3242,12 @@ static pj_bool_t handle_uac_tsx_response(pjsip_inv_session *inv,
*/
} else {
+ struct tsx_inv_data *tsx_inv_data;
+
+ tsx_inv_data = (struct tsx_inv_data*)tsx->mod_data[mod_inv.mod.id];
+ if (tsx_inv_data)
+ tsx_inv_data->retrying = PJ_TRUE;
+
/* Re-send request. */
status = pjsip_inv_send_msg(inv, tdata);
}
@@ -3902,8 +3924,8 @@ static void inv_on_state_connecting( pjsip_inv_session *inv, pjsip_event *e)
/*
* Handle response to outgoing UPDATE request.
*/
- if (handle_uac_tsx_response(inv, e) == PJ_FALSE)
- inv_handle_update_response(inv, e);
+ if (inv_handle_update_response(inv, e) == PJ_FALSE)
+ handle_uac_tsx_response(inv, e);
} else if (tsx->role == PJSIP_ROLE_UAS &&
tsx->state == PJSIP_TSX_STATE_TRYING &&
@@ -4259,10 +4281,15 @@ static void inv_on_state_confirmed( pjsip_inv_session *inv, pjsip_event *e)
} else if (tsx->status_code >= 300 && tsx->status_code < 700) {
pjmedia_sdp_neg_state neg_state;
+ struct tsx_inv_data *tsx_inv_data;
+
+ tsx_inv_data = (struct tsx_inv_data*)tsx->mod_data[mod_inv.mod.id];
/* Outgoing INVITE transaction has failed, cancel SDP nego */
neg_state = pjmedia_sdp_neg_get_state(inv->neg);
- if (neg_state == PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER) {
+ if (neg_state == PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER &&
+ tsx_inv_data->retrying == PJ_FALSE)
+ {
pjmedia_sdp_neg_cancel_offer(inv->neg);
}
@@ -4287,8 +4314,8 @@ static void inv_on_state_confirmed( pjsip_inv_session *inv, pjsip_event *e)
/*
* Handle response to outgoing UPDATE request.
*/
- if (handle_uac_tsx_response(inv, e) == PJ_FALSE)
- inv_handle_update_response(inv, e);
+ if (inv_handle_update_response(inv, e) == PJ_FALSE)
+ handle_uac_tsx_response(inv, e);
} else if (tsx->role == PJSIP_ROLE_UAS &&
tsx->state == PJSIP_TSX_STATE_TRYING &&