tb_bool_t tb_dns_looker_done(tb_char_t const* name, tb_ipaddr_ref_t addr) { // check tb_assert_and_check_return_val(name && addr, tb_false); // try to lookup it from cache first if (tb_dns_cache_get(name, addr)) return tb_true; // init looker tb_dns_looker_ref_t looker = tb_dns_looker_init(name); tb_check_return_val(looker, tb_false); // spak tb_long_t r = -1; while (!(r = tb_dns_looker_spak(looker, addr))) { // wait r = tb_dns_looker_wait(looker, TB_DNS_LOOKER_TIMEOUT); tb_assert_and_check_break(r >= 0); } // exit tb_dns_looker_exit(looker); // ok return r > 0? tb_true : tb_false; }
tb_bool_t tb_aicp_dns_done(tb_aicp_dns_ref_t dns, tb_char_t const* host, tb_long_t timeout, tb_aicp_dns_done_func_t func, tb_cpointer_t priv) { // check tb_aicp_dns_impl_t* impl = (tb_aicp_dns_impl_t*)dns; tb_assert_and_check_return_val(impl && func && host && host[0], tb_false); // trace tb_trace_d("done: aico: %p, host: %s: ..", impl->aico, host); // init func impl->done.func = func; impl->done.priv = priv; // save host tb_strlcpy(impl->host, host, sizeof(impl->host)); // only address? ok tb_ipaddr_t addr = {0}; if (tb_ipaddr_ip_cstr_set(&addr, impl->host, TB_IPADDR_FAMILY_NONE)) { impl->done.func(dns, impl->host, &addr, impl->done.priv); return tb_true; } // try to lookup it from cache first if (tb_dns_cache_get(impl->host, &addr)) { impl->done.func(dns, impl->host, &addr, impl->done.priv); return tb_true; } // init server list if (!impl->size) impl->size = tb_dns_server_get(impl->list); tb_check_return_val(impl->size, tb_false); // get the server tb_ipaddr_ref_t server = &impl->list[impl->indx = 0]; tb_assert_and_check_return_val(!tb_ipaddr_is_empty(server), tb_false); // init reqt tb_size_t size = tb_aicp_dns_reqt_init(impl); tb_assert_and_check_return_val(size, tb_false); // init it first if no aico if (!impl->aico) { // init aico impl->aico = tb_aico_init(impl->aicp); tb_assert_and_check_return_val(impl->aico, tb_false); // open aico if (!tb_aico_open_sock_from_type(impl->aico, TB_SOCKET_TYPE_UDP, tb_ipaddr_family(server))) return tb_false; // init timeout tb_aico_timeout_set(impl->aico, TB_AICO_TIMEOUT_SEND, timeout); tb_aico_timeout_set(impl->aico, TB_AICO_TIMEOUT_RECV, timeout); } // post reqt return tb_aico_usend(impl->aico, server, impl->data, size, tb_aicp_dns_reqt_func, (tb_pointer_t)impl); }
static tb_bool_t tb_aicp_dns_resp_func(tb_aice_ref_t aice) { // check tb_assert_and_check_return_val(aice && aice->aico && aice->code == TB_AICE_CODE_URECV, tb_false); // the aicp tb_aicp_ref_t aicp = (tb_aicp_ref_t)tb_aico_aicp(aice->aico); tb_assert_and_check_return_val(aicp, tb_false); // the impl tb_aicp_dns_impl_t* impl = (tb_aicp_dns_impl_t*)aice->priv; tb_assert_and_check_return_val(impl, tb_false); // done tb_ipaddr_t addr = {0}; if (aice->state == TB_STATE_OK) { // trace tb_trace_d("resp[%s]: aico: %p, server: %{ipaddr}, real: %lu", impl->host, impl->aico, &aice->u.urecv.addr, aice->u.urecv.real); // check tb_assert_and_check_return_val(aice->u.urecv.real, tb_false); // done resp tb_aicp_dns_resp_done(impl, aice->u.urecv.real, &addr); } // timeout or failed? else { // trace tb_trace_d("resp[%s]: aico: %p, state: %s", impl->host, impl->aico, tb_state_cstr(aice->state)); } // ok or try to get ok from cache again if failed or timeout? tb_bool_t from_cache = tb_false; if (!tb_ipaddr_ip_is_empty(&addr) || (from_cache = tb_dns_cache_get(impl->host, &addr))) { // save to cache if (!from_cache) tb_dns_cache_set(impl->host, &addr); // done func impl->done.func((tb_aicp_dns_ref_t)impl, impl->host, &addr, impl->done.priv); return tb_true; } // try next server? tb_bool_t ok = tb_false; tb_ipaddr_ref_t server = &impl->list[impl->indx + 1]; if (!tb_ipaddr_is_empty(server)) { // indx++ impl->indx++; // init reqt tb_size_t size = tb_aicp_dns_reqt_init(impl); if (size) { // post reqt ok = tb_aico_usend(aice->aico, server, impl->data, size, tb_aicp_dns_reqt_func, (tb_pointer_t)impl); } } // failed? done func if (!ok) impl->done.func((tb_aicp_dns_ref_t)impl, impl->host, tb_null, impl->done.priv); // continue return tb_true; }