pj_status_t resolve_stun_server(pj_bool_t wait, pj_bool_t retry_if_cur_error,
				unsigned options)
{
    pjsua_var.stun_opt = options;

    /* Retry resolving if currently the STUN status is error */
    if (pjsua_var.stun_status != PJ_EPENDING &&
	pjsua_var.stun_status != PJ_SUCCESS &&
	retry_if_cur_error)
    {
	pjsua_var.stun_status = PJ_EUNKNOWN;
    }

    if (pjsua_var.stun_status == PJ_EUNKNOWN) {
	pj_status_t status;

	/* Initialize STUN configuration */
	pj_stun_config_init(&pjsua_var.stun_cfg, &pjsua_var.cp.factory, 0,
			    pjsip_endpt_get_ioqueue(pjsua_var.endpt),
			    pjsip_endpt_get_timer_heap(pjsua_var.endpt));

	/* Start STUN server resolution */
	if (pjsua_var.ua_cfg.stun_srv_cnt) {
	    pjsua_var.stun_status = PJ_EPENDING;
	    status = pjsua_resolve_stun_servers(pjsua_var.ua_cfg.stun_srv_cnt,
						pjsua_var.ua_cfg.stun_srv,
						wait, NULL,
						&internal_stun_resolve_cb);
	    if (wait || status != PJ_SUCCESS) {
		pjsua_var.stun_status = status;
	    }
	} else {
	    pjsua_var.stun_status = PJ_SUCCESS;
	}

    } else if (pjsua_var.stun_status == PJ_EPENDING) {
	/* STUN server resolution has been started, wait for the
	 * result.
	 */
	if (wait) {
	    unsigned max_wait_ms;
	    pj_timestamp start, now;

	    /* Should limit the wait time to avoid deadlock. For example,
	     * if app holds dlg/tsx lock, pjsua worker thread will block on
	     * any dlg/tsx state change.
	     */
	    max_wait_ms = pjsua_var.ua_cfg.stun_srv_cnt *
			  pjsua_var.stun_cfg.rto_msec * (1 << 7);
	    pj_get_timestamp(&start);

	    while (pjsua_var.stun_status == PJ_EPENDING) {		
                /* If there is no worker thread or
                 * the function is called from the only worker thread,
                 * we have to handle the events here.
                 */
		if (pjsua_var.thread[0] == NULL ||
                    (pj_thread_this() == pjsua_var.thread[0] &&
                     pjsua_var.ua_cfg.thread_cnt == 1))
                {
		    pjsua_handle_events(10);
                } else {
		    pj_thread_sleep(10);
                }

		pj_get_timestamp(&now);
		if (pj_elapsed_msec(&start, &now) > max_wait_ms)
		    return PJ_ETIMEDOUT;
	    }
	}
    }

    if (pjsua_var.stun_status != PJ_EPENDING &&
	pjsua_var.stun_status != PJ_SUCCESS &&
	pjsua_var.ua_cfg.stun_ignore_failure)
    {
	PJ_LOG(2,(THIS_FILE, 
		  "Ignoring STUN resolution failure (by setting)"));
	//pjsua_var.stun_status = PJ_SUCCESS;
	return PJ_SUCCESS;
    }

    return pjsua_var.stun_status;
}
pj_status_t resolve_stun_server(pj_bool_t wait, pj_bool_t retry_if_cur_error,
				unsigned options)
{
    pjsua_var.stun_opt = options;

     
    if (pjsua_var.stun_status != PJ_EPENDING &&
	pjsua_var.stun_status != PJ_SUCCESS &&
	retry_if_cur_error)
    {
	pjsua_var.stun_status = PJ_EUNKNOWN;
    }

    if (pjsua_var.stun_status == PJ_EUNKNOWN) {
	pj_status_t status;

	 
	pj_stun_config_init(&pjsua_var.stun_cfg, &pjsua_var.cp.factory, 0,
			    pjsip_endpt_get_ioqueue(pjsua_var.endpt),
			    pjsip_endpt_get_timer_heap(pjsua_var.endpt));

	 
	if (pjsua_var.ua_cfg.stun_srv_cnt) {
	    pjsua_var.stun_status = PJ_EPENDING;
	    status = pjsua_resolve_stun_servers(pjsua_var.ua_cfg.stun_srv_cnt,
						pjsua_var.ua_cfg.stun_srv,
						wait, NULL,
						&internal_stun_resolve_cb);
	    if (wait || status != PJ_SUCCESS) {
		pjsua_var.stun_status = status;
	    }
	} else {
	    pjsua_var.stun_status = PJ_SUCCESS;
	}

    } else if (pjsua_var.stun_status == PJ_EPENDING) {
	 
	if (wait) {
	    unsigned max_wait_ms;
	    pj_timestamp start, now;

	     
	    max_wait_ms = pjsua_var.ua_cfg.stun_srv_cnt *
			  pjsua_var.stun_cfg.rto_msec * (1 << 7);
	    pj_get_timestamp(&start);

	    while (pjsua_var.stun_status == PJ_EPENDING) {		
                 
		if (pjsua_var.thread[0] == NULL ||
                    (pj_thread_this() == pjsua_var.thread[0] &&
                     pjsua_var.ua_cfg.thread_cnt == 1))
                {
		    pjsua_handle_events(10);
                } else {
		    pj_thread_sleep(10);
                }

		pj_get_timestamp(&now);
		if (pj_elapsed_msec(&start, &now) > max_wait_ms)
		    return PJ_ETIMEDOUT;
	    }
	}
    }

    if (pjsua_var.stun_status != PJ_EPENDING &&
	pjsua_var.stun_status != PJ_SUCCESS &&
	pjsua_var.ua_cfg.stun_ignore_failure)
    {
	PJ_LOG(2,(THIS_FILE, 
		  "Ignoring STUN resolution failure (by setting)"));
	 
	return PJ_SUCCESS;
    }

    return pjsua_var.stun_status;
}