PJ_DEF(pj_status_t) pjsip_auth_clt_reinit_req(	pjsip_auth_clt_sess *sess,
						const pjsip_rx_data *rdata,
						pjsip_tx_data *old_request,
						pjsip_tx_data **new_request )
{
    pjsip_tx_data *tdata;
    const pjsip_hdr *hdr;
    unsigned chal_cnt, auth_cnt;
    pjsip_via_hdr *via;
    pj_status_t status;
    pj_status_t last_auth_err;

    PJ_ASSERT_RETURN(sess && rdata && old_request && new_request,
		     PJ_EINVAL);
    PJ_ASSERT_RETURN(sess->pool, PJSIP_ENOTINITIALIZED);
    PJ_ASSERT_RETURN(rdata->msg_info.msg->type == PJSIP_RESPONSE_MSG,
		     PJSIP_ENOTRESPONSEMSG);
    PJ_ASSERT_RETURN(old_request->msg->type == PJSIP_REQUEST_MSG,
		     PJSIP_ENOTREQUESTMSG);
    PJ_ASSERT_RETURN(rdata->msg_info.msg->line.status.code == 401 ||
		     rdata->msg_info.msg->line.status.code == 407,
		     PJSIP_EINVALIDSTATUS);

    tdata = old_request;
    tdata->auth_retry = PJ_FALSE;

    /*
     * Respond to each authentication challenge.
     */
    hdr = rdata->msg_info.msg->hdr.next;
    chal_cnt = 0;
    auth_cnt = 0;
    last_auth_err = PJSIP_EAUTHNOAUTH;
    while (hdr != &rdata->msg_info.msg->hdr && auth_cnt == 0) {
	pjsip_cached_auth *cached_auth;
	const pjsip_www_authenticate_hdr *hchal;
	pjsip_authorization_hdr *hauth;

	/* Find WWW-Authenticate or Proxy-Authenticate header. */
	while (hdr != &rdata->msg_info.msg->hdr &&
	       hdr->type != PJSIP_H_WWW_AUTHENTICATE &&
	       hdr->type != PJSIP_H_PROXY_AUTHENTICATE)
	{
	    hdr = hdr->next;
	}
	if (hdr == &rdata->msg_info.msg->hdr)
	    break;

	hchal = (const pjsip_www_authenticate_hdr*)hdr;
	++chal_cnt;

	/* Find authentication session for this realm, create a new one
	 * if not present.
	 */
	cached_auth = find_cached_auth(sess, &hchal->challenge.common.realm);
	if (!cached_auth) {
	    cached_auth = PJ_POOL_ZALLOC_T(sess->pool, pjsip_cached_auth);
	    cached_auth->pool = pjsip_endpt_create_pool(sess->endpt,
							"auth_cli%p",
							1024,
							1024);
	    pj_strdup(cached_auth->pool, &cached_auth->realm,
		      &hchal->challenge.common.realm);
	    cached_auth->is_proxy = (hchal->type == PJSIP_H_PROXY_AUTHENTICATE);
#	    if (PJSIP_AUTH_HEADER_CACHING)
	    {
		pj_list_init(&cached_auth->cached_hdr);
	    }
#	    endif
	    pj_list_insert_before(&sess->cached_auth, cached_auth);
	}

	/* Create authorization header for this challenge, and update
	 * authorization session.
	 */
	status = process_auth(tdata->pool, hchal, tdata->msg->line.req.uri,
			      tdata, sess, cached_auth, &hauth);
	if (status != PJ_SUCCESS) {
	    last_auth_err = status;

	    /* Process next header. */
	    hdr = hdr->next;
	    continue;
	}

	if (pj_pool_get_used_size(cached_auth->pool) >
	    PJSIP_AUTH_CACHED_POOL_MAX_SIZE) 
	{
	    recreate_cached_auth_pool(sess->endpt, cached_auth);
	}	

	/* Add to the message. */
	pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)hauth);

	/* Process next header. */
	hdr = hdr->next;
	auth_cnt++;
    }

    /* Check if challenge is present */
    if (chal_cnt == 0)
	return PJSIP_EAUTHNOCHAL;

    /* Check if any authorization header has been created */
    if (auth_cnt == 0)
	return last_auth_err;

    /* Remove branch param in Via header. */
    via = (pjsip_via_hdr*) pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL);
    via->branch_param.slen = 0;

    /* Restore strict route set.
     * See http://trac.pjsip.org/repos/ticket/492
     */
    pjsip_restore_strict_route_set(tdata);

    /* Must invalidate the message! */
    pjsip_tx_data_invalidate_msg(tdata);

    /* Retrying.. */
    tdata->auth_retry = PJ_TRUE;

    /* Increment reference counter. */
    pjsip_tx_data_add_ref(tdata);

    /* Done. */
    *new_request = tdata;
    return PJ_SUCCESS;

}
PJ_DEF(pj_status_t) pjsip_auth_clt_reinit_req(	pjsip_auth_clt_sess *sess,
						const pjsip_rx_data *rdata,
						pjsip_tx_data *old_request,
						pjsip_tx_data **new_request )
{
    pjsip_tx_data *tdata;
    const pjsip_hdr *hdr;
    unsigned chal_cnt, auth_cnt;
    pjsip_via_hdr *via;
    pj_status_t status;
    pj_status_t last_auth_err;

    PJ_ASSERT_RETURN(sess && rdata && old_request && new_request,
		     PJ_EINVAL);
    PJ_ASSERT_RETURN(sess->pool, PJSIP_ENOTINITIALIZED);
    PJ_ASSERT_RETURN(rdata->msg_info.msg->type == PJSIP_RESPONSE_MSG,
		     PJSIP_ENOTRESPONSEMSG);
    PJ_ASSERT_RETURN(old_request->msg->type == PJSIP_REQUEST_MSG,
		     PJSIP_ENOTREQUESTMSG);
    PJ_ASSERT_RETURN(rdata->msg_info.msg->line.status.code == 401 ||
		     rdata->msg_info.msg->line.status.code == 407,
		     PJSIP_EINVALIDSTATUS);

    tdata = old_request;
    tdata->auth_retry = PJ_FALSE;

     
    hdr = rdata->msg_info.msg->hdr.next;
    chal_cnt = 0;
    auth_cnt = 0;
    last_auth_err = PJSIP_EAUTHNOAUTH;
    while (hdr != &rdata->msg_info.msg->hdr && auth_cnt == 0) {
	pjsip_cached_auth *cached_auth;
	const pjsip_www_authenticate_hdr *hchal;
	pjsip_authorization_hdr *hauth;

	 
	while (hdr != &rdata->msg_info.msg->hdr &&
	       hdr->type != PJSIP_H_WWW_AUTHENTICATE &&
	       hdr->type != PJSIP_H_PROXY_AUTHENTICATE)
	{
	    hdr = hdr->next;
	}
	if (hdr == &rdata->msg_info.msg->hdr)
	    break;

	hchal = (const pjsip_www_authenticate_hdr*)hdr;
	++chal_cnt;

	 
	cached_auth = find_cached_auth(sess, &hchal->challenge.common.realm);
	if (!cached_auth) {
	    cached_auth = PJ_POOL_ZALLOC_T(sess->pool, pjsip_cached_auth);
	    cached_auth->pool = pjsip_endpt_create_pool(sess->endpt,
							"auth_cli%p",
							1024,
							1024);
	    pj_strdup(cached_auth->pool, &cached_auth->realm,
		      &hchal->challenge.common.realm);
	    cached_auth->is_proxy = (hchal->type == PJSIP_H_PROXY_AUTHENTICATE);
#	    if (PJSIP_AUTH_HEADER_CACHING)
	    {
		pj_list_init(&cached_auth->cached_hdr);
	    }
#	    endif
	    pj_list_insert_before(&sess->cached_auth, cached_auth);
	}

	 
	status = process_auth(tdata->pool, hchal, tdata->msg->line.req.uri,
			      tdata, sess, cached_auth, &hauth);
	if (status != PJ_SUCCESS) {
	    last_auth_err = status;

	     
	    hdr = hdr->next;
	    continue;
	}

	if (pj_pool_get_used_size(cached_auth->pool) >
	    PJSIP_AUTH_CACHED_POOL_MAX_SIZE) 
	{
	    recreate_cached_auth_pool(sess->endpt, cached_auth);
	}	

	 
	pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)hauth);

	 
	hdr = hdr->next;
	auth_cnt++;
    }

     
    if (chal_cnt == 0)
	return PJSIP_EAUTHNOCHAL;

     
    if (auth_cnt == 0)
	return last_auth_err;

     
    via = (pjsip_via_hdr*) pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL);
    via->branch_param.slen = 0;

     
    pjsip_restore_strict_route_set(tdata);

     
    pjsip_tx_data_invalidate_msg(tdata);

     
    tdata->auth_retry = PJ_TRUE;

     
    pjsip_tx_data_add_ref(tdata);

     
    *new_request = tdata;
    return PJ_SUCCESS;

}