static void resolve_stun_entry(pjsua_stun_resolve *sess)
{
    pj_status_t status = PJ_EUNKNOWN;

    /* Loop while we have entry to try */
    for (; sess->idx < sess->count;
    	 (pjsua_var.ua_cfg.stun_try_ipv6 && sess->af == pj_AF_INET())?
	 sess->af = pj_AF_INET6(): (++sess->idx, sess->af = pj_AF_INET()))
    {
	int af;
	char target[64];
	pj_str_t hostpart;
	pj_uint16_t port;
	pj_stun_sock_cb stun_sock_cb;
	
	pj_assert(sess->idx < sess->count);

	if (pjsua_var.ua_cfg.stun_try_ipv6 &&
	    pjsua_var.stun_opt != PJSUA_NAT64_DISABLED &&
	    sess->af == pj_AF_INET())
	{
	    /* Skip IPv4 STUN resolution if NAT64 is not disabled. */
	    PJ_LOG(4,(THIS_FILE, "Skipping IPv4 resolution of STUN server "
	    			 "%s (%d of %d)", target,
	    			 sess->idx+1, sess->count));	    
	    continue;
	}

	pj_ansi_snprintf(target, sizeof(target), "%.*s",
			 (int)sess->srv[sess->idx].slen,
			 sess->srv[sess->idx].ptr);

	/* Parse the server entry into host:port */
	status = pj_sockaddr_parse2(pj_AF_UNSPEC(), 0, &sess->srv[sess->idx],
				    &hostpart, &port, &af);
	if (status != PJ_SUCCESS) {
    	    PJ_LOG(2,(THIS_FILE, "Invalid STUN server entry %s", target));
	    continue;
	}
	
	/* Use default port if not specified */
	if (port == 0)
	    port = PJ_STUN_PORT;

	pj_assert(sess->stun_sock == NULL);

	PJ_LOG(4,(THIS_FILE, "Trying STUN server %s %s (%d of %d)..",
		  target, (sess->af == pj_AF_INET()? "IPv4": "IPv6"),
		  sess->idx+1, sess->count));

	/* Use STUN_sock to test this entry */
	pj_bzero(&stun_sock_cb, sizeof(stun_sock_cb));
	stun_sock_cb.on_status = &test_stun_on_status;
	sess->async_wait = PJ_FALSE;
	status = pj_stun_sock_create(&pjsua_var.stun_cfg, "stunresolve",
				     sess->af, &stun_sock_cb,
				     NULL, sess, &sess->stun_sock);
	if (status != PJ_SUCCESS) {
	    char errmsg[PJ_ERR_MSG_SIZE];
	    pj_strerror(status, errmsg, sizeof(errmsg));
	    PJ_LOG(4,(THIS_FILE, 
		     "Error creating STUN socket for %s: %s",
		     target, errmsg));

	    continue;
	}

	status = pj_stun_sock_start(sess->stun_sock, &hostpart, port,
				    pjsua_var.resolver);
	if (status != PJ_SUCCESS) {
	    char errmsg[PJ_ERR_MSG_SIZE];
	    pj_strerror(status, errmsg, sizeof(errmsg));
	    PJ_LOG(4,(THIS_FILE, 
		     "Error starting STUN socket for %s: %s",
		     target, errmsg));

	    if (sess->stun_sock) {
		pj_stun_sock_destroy(sess->stun_sock);
		sess->stun_sock = NULL;
	    }
	    continue;
	}

	/* Done for now, testing will resume/complete asynchronously in
	 * stun_sock_cb()
	 */
	sess->async_wait = PJ_TRUE;
	return;
    }

    if (sess->idx >= sess->count) {
	/* No more entries to try */
	stun_resolve_add_ref(sess);
	pj_assert(status != PJ_SUCCESS || sess->status != PJ_EPENDING);
        if (sess->status == PJ_EPENDING)
            sess->status = status;
	stun_resolve_complete(sess);
	stun_resolve_dec_ref(sess);
    }
}
static void resolve_stun_entry(pjsua_stun_resolve *sess)
{
    pj_status_t status = PJ_EUNKNOWN;

     
    for (; sess->idx < sess->count;
    	 (pjsua_var.ua_cfg.stun_try_ipv6 && sess->af == pj_AF_INET())?
	 sess->af = pj_AF_INET6(): (++sess->idx, sess->af = pj_AF_INET()))
    {
	int af;
	char target[64];
	pj_str_t hostpart;
	pj_uint16_t port;
	pj_stun_sock_cb stun_sock_cb;
	
	pj_assert(sess->idx < sess->count);

	if (pjsua_var.ua_cfg.stun_try_ipv6 &&
	    pjsua_var.stun_opt != PJSUA_NAT64_DISABLED &&
	    sess->af == pj_AF_INET())
	{
	     
	    PJ_LOG(4,(THIS_FILE, "Skipping IPv4 resolution of STUN server "
	    			 "%s (%d of %d)", target,
	    			 sess->idx+1, sess->count));	    
	    continue;
	}

	pj_ansi_snprintf(target, sizeof(target), "%.*s",
			 (int)sess->srv[sess->idx].slen,
			 sess->srv[sess->idx].ptr);

	 
	status = pj_sockaddr_parse2(pj_AF_UNSPEC(), 0, &sess->srv[sess->idx],
				    &hostpart, &port, &af);
	if (status != PJ_SUCCESS) {
    	    PJ_LOG(2,(THIS_FILE, "Invalid STUN server entry %s", target));
	    continue;
	}
	
	 
	if (port == 0)
	    port = PJ_STUN_PORT;

	pj_assert(sess->stun_sock == NULL);

	PJ_LOG(4,(THIS_FILE, "Trying STUN server %s %s (%d of %d)..",
		  target, (sess->af == pj_AF_INET()? "IPv4": "IPv6"),
		  sess->idx+1, sess->count));

	 
	pj_bzero(&stun_sock_cb, sizeof(stun_sock_cb));
	stun_sock_cb.on_status = &test_stun_on_status;
	sess->async_wait = PJ_FALSE;
	status = pj_stun_sock_create(&pjsua_var.stun_cfg, "stunresolve",
				     sess->af, &stun_sock_cb,
				     NULL, sess, &sess->stun_sock);
	if (status != PJ_SUCCESS) {
	    char errmsg[PJ_ERR_MSG_SIZE];
	    pj_strerror(status, errmsg, sizeof(errmsg));
	    PJ_LOG(4,(THIS_FILE, 
		     "Error creating STUN socket for %s: %s",
		     target, errmsg));

	    continue;
	}

	status = pj_stun_sock_start(sess->stun_sock, &hostpart, port,
				    pjsua_var.resolver);
	if (status != PJ_SUCCESS) {
	    char errmsg[PJ_ERR_MSG_SIZE];
	    pj_strerror(status, errmsg, sizeof(errmsg));
	    PJ_LOG(4,(THIS_FILE, 
		     "Error starting STUN socket for %s: %s",
		     target, errmsg));

	    if (sess->stun_sock) {
		pj_stun_sock_destroy(sess->stun_sock);
		sess->stun_sock = NULL;
	    }
	    continue;
	}

	 
	sess->async_wait = PJ_TRUE;
	return;
    }

    if (sess->idx >= sess->count) {
	 
	stun_resolve_add_ref(sess);
	pj_assert(status != PJ_SUCCESS || sess->status != PJ_EPENDING);
        if (sess->status == PJ_EPENDING)
            sess->status = status;
	stun_resolve_complete(sess);
	stun_resolve_dec_ref(sess);
    }
}