PJ_DEF(pj_status_t) pjsip_dlg_create_uac2(
				const pjsip_dlg_create_uac_param *create_param,
				pjsip_dialog **p_dlg)
{
    pj_status_t status;
    pj_str_t tmp;
    pjsip_dialog *dlg;

    /* Check arguments. */
    PJ_ASSERT_RETURN(create_param->ua && create_param->local_uri.slen &&
		     create_param->remote_uri.slen && p_dlg, PJ_EINVAL);

    /* Create dialog instance. */
    status = create_dialog(create_param->ua, create_param->grp_lock, &dlg);
    if (status != PJ_SUCCESS)
	return status;

    /* Parse target. */
    pj_strdup_with_null(dlg->pool, &tmp, create_param->target.slen ?
			&create_param->target : &create_param->remote_uri);
    dlg->target = pjsip_parse_uri(dlg->pool, tmp.ptr, tmp.slen, 0);
    if (!dlg->target) {
	status = PJSIP_EINVALIDURI;
	goto on_error;
    }

    /* Put any header param in the target URI into INVITE header list. */
    if (PJSIP_URI_SCHEME_IS_SIP(dlg->target) ||
	PJSIP_URI_SCHEME_IS_SIPS(dlg->target))
    {
	pjsip_param *param;
	pjsip_sip_uri *uri = (pjsip_sip_uri*)pjsip_uri_get_uri(dlg->target);

	param = uri->header_param.next;
	while (param != &uri->header_param) {
	    if (param->value.ptr) {
		pjsip_hdr *hdr;
		int c;

		c = param->value.ptr[param->value.slen];
		param->value.ptr[param->value.slen] = '\0';

		hdr = (pjsip_hdr*)
		    pjsip_parse_hdr(dlg->pool, &param->name, param->value.ptr,
				    param->value.slen, NULL);

		param->value.ptr[param->value.slen] = (char)c;

		if (hdr == NULL) {
		    status = PJSIP_EINVALIDURI;
		    goto on_error;
		}
		pj_list_push_back(&dlg->inv_hdr, hdr);
	    }

	    param = param->next;
	}

	/* Now must remove any header params from URL, since that would
	 * create another header in pjsip_endpt_create_request().
	 */
	pj_list_init(&uri->header_param);
    }

    /* Add target to the target set */
    pjsip_target_set_add_uri(&dlg->target_set, dlg->pool, dlg->target, 0);

    /* Init local info. */
    dlg->local.info = pjsip_from_hdr_create(dlg->pool);
    pj_strdup_with_null(dlg->pool, &dlg->local.info_str,
			&create_param->local_uri);
    dlg->local.info->uri = pjsip_parse_uri(dlg->pool,
					   dlg->local.info_str.ptr,
					   dlg->local.info_str.slen, 0);
    if (!dlg->local.info->uri) {
	status = PJSIP_EINVALIDURI;
	goto on_error;
    }

    /* Generate local tag. */
    pj_create_unique_string(dlg->pool, &dlg->local.info->tag);

    /* Calculate hash value of local tag. */
    dlg->local.tag_hval = pj_hash_calc_tolower(0, NULL,
                                               &dlg->local.info->tag);

    /* Randomize local CSeq. */
    dlg->local.first_cseq = pj_rand() & 0x7FFF;
    dlg->local.cseq = dlg->local.first_cseq;

    /* Init local contact. */
    pj_strdup_with_null(dlg->pool, &tmp,
		    create_param->local_contact.slen ?
		    &create_param->local_contact : &create_param->local_uri);
    dlg->local.contact = (pjsip_contact_hdr*)
			 pjsip_parse_hdr(dlg->pool, &HCONTACT, tmp.ptr,
					 tmp.slen, NULL);
    if (!dlg->local.contact) {
	status = PJSIP_EINVALIDURI;
	goto on_error;
    }

    /* Init remote info. */
    dlg->remote.info = pjsip_to_hdr_create(dlg->pool);
    pj_strdup_with_null(dlg->pool, &dlg->remote.info_str,
			&create_param->remote_uri);
    dlg->remote.info->uri = pjsip_parse_uri(dlg->pool,
					    dlg->remote.info_str.ptr,
					    dlg->remote.info_str.slen, 0);
    if (!dlg->remote.info->uri) {
	status = PJSIP_EINVALIDURI;
	goto on_error;
    }

    /* Remove header param from remote.info_str, if any */
    if (PJSIP_URI_SCHEME_IS_SIP(dlg->remote.info->uri) ||
	PJSIP_URI_SCHEME_IS_SIPS(dlg->remote.info->uri))
    {
	pjsip_sip_uri *sip_uri = (pjsip_sip_uri *)
				 pjsip_uri_get_uri(dlg->remote.info->uri);
	if (!pj_list_empty(&sip_uri->header_param)) {
	    pj_str_t tmp2;

	    /* Remove all header param */
	    pj_list_init(&sip_uri->header_param);

	    /* Print URI */
	    tmp2.ptr = (char*) pj_pool_alloc(dlg->pool,
	    				    dlg->remote.info_str.slen);
	    tmp2.slen = pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR,
				       sip_uri, tmp2.ptr,
				       dlg->remote.info_str.slen);

	    if (tmp2.slen < 1) {
		status = PJSIP_EURITOOLONG;
		goto on_error;
	    }

	    /* Assign remote.info_str */
	    dlg->remote.info_str = tmp2;
	}
    }


    /* Initialize remote's CSeq to -1. */
    dlg->remote.cseq = dlg->remote.first_cseq = -1;

    /* Initial role is UAC. */
    dlg->role = PJSIP_ROLE_UAC;

    /* Secure? */
    dlg->secure = PJSIP_URI_SCHEME_IS_SIPS(dlg->target);

    /* Generate Call-ID header. */
    dlg->call_id = pjsip_cid_hdr_create(dlg->pool);
    pj_create_unique_string(dlg->pool, &dlg->call_id->id);

    /* Initial route set is empty. */
    pj_list_init(&dlg->route_set);

    /* Register this dialog to user agent. */
    status = pjsip_ua_register_dlg( create_param->ua, dlg );
    if (status != PJ_SUCCESS)
	goto on_error;

    /* Done! */
    *p_dlg = dlg;

    PJ_LOG(5,(dlg->obj_name, "UAC dialog created"));

    return PJ_SUCCESS;

on_error:
    destroy_dialog(dlg, PJ_FALSE);
    return status;
}
PJ_DEF(pj_status_t) pjsip_dlg_create_uac2(
				const pjsip_dlg_create_uac_param *create_param,
				pjsip_dialog **p_dlg)
{
    pj_status_t status;
    pj_str_t tmp;
    pjsip_dialog *dlg;

     
    PJ_ASSERT_RETURN(create_param->ua && create_param->local_uri.slen &&
		     create_param->remote_uri.slen && p_dlg, PJ_EINVAL);

     
    status = create_dialog(create_param->ua, create_param->grp_lock, &dlg);
    if (status != PJ_SUCCESS)
	return status;

     
    pj_strdup_with_null(dlg->pool, &tmp, create_param->target.slen ?
			&create_param->target : &create_param->remote_uri);
    dlg->target = pjsip_parse_uri(dlg->pool, tmp.ptr, tmp.slen, 0);
    if (!dlg->target) {
	status = PJSIP_EINVALIDURI;
	goto on_error;
    }

     
    if (PJSIP_URI_SCHEME_IS_SIP(dlg->target) ||
	PJSIP_URI_SCHEME_IS_SIPS(dlg->target))
    {
	pjsip_param *param;
	pjsip_sip_uri *uri = (pjsip_sip_uri*)pjsip_uri_get_uri(dlg->target);

	param = uri->header_param.next;
	while (param != &uri->header_param) {
	    if (param->value.ptr) {
		pjsip_hdr *hdr;
		int c;

		c = param->value.ptr[param->value.slen];
		param->value.ptr[param->value.slen] = '\0';

		hdr = (pjsip_hdr*)
		    pjsip_parse_hdr(dlg->pool, &param->name, param->value.ptr,
				    param->value.slen, NULL);

		param->value.ptr[param->value.slen] = (char)c;

		if (hdr == NULL) {
		    status = PJSIP_EINVALIDURI;
		    goto on_error;
		}
		pj_list_push_back(&dlg->inv_hdr, hdr);
	    }

	    param = param->next;
	}

	 
	pj_list_init(&uri->header_param);
    }

     
    pjsip_target_set_add_uri(&dlg->target_set, dlg->pool, dlg->target, 0);

     
    dlg->local.info = pjsip_from_hdr_create(dlg->pool);
    pj_strdup_with_null(dlg->pool, &dlg->local.info_str,
			&create_param->local_uri);
    dlg->local.info->uri = pjsip_parse_uri(dlg->pool,
					   dlg->local.info_str.ptr,
					   dlg->local.info_str.slen, 0);
    if (!dlg->local.info->uri) {
	status = PJSIP_EINVALIDURI;
	goto on_error;
    }

     
    pj_create_unique_string(dlg->pool, &dlg->local.info->tag);

     
    dlg->local.tag_hval = pj_hash_calc_tolower(0, NULL,
                                               &dlg->local.info->tag);

     
    dlg->local.first_cseq = pj_rand() & 0x7FFF;
    dlg->local.cseq = dlg->local.first_cseq;

     
    pj_strdup_with_null(dlg->pool, &tmp,
		    create_param->local_contact.slen ?
		    &create_param->local_contact : &create_param->local_uri);
    dlg->local.contact = (pjsip_contact_hdr*)
			 pjsip_parse_hdr(dlg->pool, &HCONTACT, tmp.ptr,
					 tmp.slen, NULL);
    if (!dlg->local.contact) {
	status = PJSIP_EINVALIDURI;
	goto on_error;
    }

     
    dlg->remote.info = pjsip_to_hdr_create(dlg->pool);
    pj_strdup_with_null(dlg->pool, &dlg->remote.info_str,
			&create_param->remote_uri);
    dlg->remote.info->uri = pjsip_parse_uri(dlg->pool,
					    dlg->remote.info_str.ptr,
					    dlg->remote.info_str.slen, 0);
    if (!dlg->remote.info->uri) {
	status = PJSIP_EINVALIDURI;
	goto on_error;
    }

     
    if (PJSIP_URI_SCHEME_IS_SIP(dlg->remote.info->uri) ||
	PJSIP_URI_SCHEME_IS_SIPS(dlg->remote.info->uri))
    {
	pjsip_sip_uri *sip_uri = (pjsip_sip_uri *)
				 pjsip_uri_get_uri(dlg->remote.info->uri);
	if (!pj_list_empty(&sip_uri->header_param)) {
	    pj_str_t tmp2;

	     
	    pj_list_init(&sip_uri->header_param);

	     
	    tmp2.ptr = (char*) pj_pool_alloc(dlg->pool,
	    				    dlg->remote.info_str.slen);
	    tmp2.slen = pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR,
				       sip_uri, tmp2.ptr,
				       dlg->remote.info_str.slen);

	    if (tmp2.slen < 1) {
		status = PJSIP_EURITOOLONG;
		goto on_error;
	    }

	     
	    dlg->remote.info_str = tmp2;
	}
    }


     
    dlg->remote.cseq = dlg->remote.first_cseq = -1;

     
    dlg->role = PJSIP_ROLE_UAC;

     
    dlg->secure = PJSIP_URI_SCHEME_IS_SIPS(dlg->target);

     
    dlg->call_id = pjsip_cid_hdr_create(dlg->pool);
    pj_create_unique_string(dlg->pool, &dlg->call_id->id);

     
    pj_list_init(&dlg->route_set);

     
    status = pjsip_ua_register_dlg( create_param->ua, dlg );
    if (status != PJ_SUCCESS)
	goto on_error;

     
    *p_dlg = dlg;

    PJ_LOG(5,(dlg->obj_name, "UAC dialog created"));

    return PJ_SUCCESS;

on_error:
    destroy_dialog(dlg, PJ_FALSE);
    return status;
}