From 9b6a95bfd505ef587bd2c5d44c69cf203e2755af Mon Sep 17 00:00:00 2001 From: Benny Prijono Date: Fri, 13 Apr 2012 04:28:26 +0000 Subject: 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 --- pjsip/src/pjsip-ua/sip_inv.c | 65 +++++++++++++++++++++++++++++++------------- 1 file 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 && -- cgit v1.2.3