Index: pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c	(revision 3999)
+++ pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c	(revision 4054)
@@ -156,4 +156,5 @@
     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?  */
@@ -2912,4 +2913,10 @@
 	    
 	} 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);
@@ -3024,10 +3031,14 @@
  * 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. */
@@ -3036,5 +3047,5 @@
     {
 	pjsip_tx_data *tdata;
-	
+
 	status = pjsip_auth_clt_reinit_req( &inv->dlg->auth_sess, 
 					    e->body.tsx_state.src.rdata,
@@ -3054,7 +3065,12 @@
 	    
 	} else {
+	    if (tsx_inv_data)
+		tsx_inv_data->retrying = PJ_TRUE;
+
 	    /* Re-send request. */
 	    status = pjsip_inv_send_msg(inv, tdata);
 	}
+
+	handled = PJ_TRUE;
     }
 
@@ -3065,4 +3081,5 @@
 	status = handle_timer_response(inv, e->body.tsx_state.src.rdata,
 				       PJ_FALSE);
+	handled = PJ_TRUE;
     }
 
@@ -3076,4 +3093,5 @@
 	status = inv_check_sdp_in_incoming_msg(inv, tsx, 
 					     e->body.tsx_state.src.rdata);
+	handled = PJ_TRUE;
     }
     
@@ -3089,18 +3107,15 @@
 	    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;
-	}
-    }
-
-    /* Cancel the negotiation if we don't get successful negotiation by now */
+	    handled = PJ_TRUE;
+	}
+    }
+
+    /* 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);
@@ -3109,4 +3124,6 @@
 	tsx_inv_data->sdp_done = PJ_TRUE;
     }
+
+    return handled;
 }
 
@@ -3308,5 +3325,4 @@
 	      tsx->status_code == PJSIP_SC_PROXY_AUTHENTICATION_REQUIRED)) 
     {
-
 	pjsip_tx_data *tdata;
 	pj_status_t status;
@@ -3330,4 +3346,10 @@
 	    
 	} 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);
@@ -4006,6 +4028,6 @@
 	 * 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 &&
@@ -4363,8 +4385,13 @@
 
 	    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);
 	    }
@@ -4391,6 +4418,6 @@
 	 * 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 &&
