コード例 #1
0
ファイル: dns.c プロジェクト: AlexShiLucky/tbox
static tb_bool_t tb_aicp_dns_reqt_func(tb_aice_ref_t aice)
{
    // check
    tb_assert_and_check_return_val(aice && aice->aico && aice->code == TB_AICE_CODE_USEND, 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 && impl->done.func, tb_false);

    // done
    tb_bool_t ok = tb_false;
    if (aice->state == TB_STATE_OK)
    {
        // trace
        tb_trace_d("reqt[%s]: aico: %p, server: %{ipaddr}, real: %lu", impl->host, impl->aico, &aice->u.usend.addr, aice->u.usend.real);

        // check
        tb_assert_and_check_return_val(aice->u.usend.real, tb_false);

        // post resp
        ok = tb_aico_urecv(aice->aico, impl->data, sizeof(impl->data), tb_aicp_dns_resp_func, (tb_pointer_t)impl);
    }
    // timeout or failed?
    else
    {
        // trace
        tb_trace_d("reqt[%s]: aico: %p, server: %{ipaddr}, state: %s", impl->host, impl->aico, &aice->u.usend.addr, tb_state_cstr(aice->state));
            
        // the next server 
        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;
}
コード例 #2
0
ファイル: aicp_aiop.c プロジェクト: ZuckerB/tbox
static tb_long_t tb_aiop_spak_conn(tb_aiop_ptor_impl_t* impl, tb_aice_ref_t aice)
{
    // check
    tb_assert_and_check_return_val(impl && aice, -1);
    tb_assert_and_check_return_val(aice->code == TB_AICE_CODE_CONN, -1);

    // the aico
    tb_aiop_aico_t* aico = (tb_aiop_aico_t*)aice->aico;
    tb_assert_and_check_return_val(aico && aico->base.handle, -1);

    // check address
    tb_assert(!tb_ipaddr_is_empty(&aice->u.conn.addr));

    // try to connect it
    tb_long_t ok = tb_socket_connect(aico->base.handle, &aice->u.conn.addr);

    // trace
    tb_trace_d("conn[%p]: %{ipaddr}: %ld", aico, &aice->u.conn.addr, ok);

    // no connected? wait it
    if (!ok)
    {
        // wait it
        if (!aico->waiting)
        {
            // wait ok?
            if (tb_aiop_spak_wait(impl, aice)) return 0;
            // wait failed
            else aice->state = TB_STATE_FAILED;
        }
        // closed
        else aice->state = TB_STATE_FAILED;
    }

    // save it
    aice->state = ok > 0? TB_STATE_OK : TB_STATE_FAILED;

    // reset wait
    aico->waiting = 0;
    aico->aice.code = TB_AICE_CODE_NONE;

    // ok
    return 1;
}
コード例 #3
0
ファイル: looker.c プロジェクト: waruqi/tbox
/* //////////////////////////////////////////////////////////////////////////////////////
 * implementation
 */
static tb_long_t tb_dns_looker_reqt(tb_dns_looker_t* looker)
{
    // check
    tb_check_return_val(!(looker->step & TB_DNS_LOOKER_STEP_REQT), 1);
    
    // format it first if the request is null
    if (!tb_static_buffer_size(&looker->rpkt))
    {
        // check size
        tb_assert_and_check_return_val(!looker->size, -1);

        // format query
        tb_static_stream_t  stream;
        tb_byte_t           rpkt[TB_DNS_RPKT_MAXN];
        tb_size_t           size = 0;
        tb_byte_t*          p = tb_null;
        tb_static_stream_init(&stream, rpkt, TB_DNS_RPKT_MAXN);

        // identification number
        tb_static_stream_writ_u16_be(&stream, TB_DNS_HEADER_MAGIC);

        /* 0x2104: 0 0000 001 0000 0000
         *
         * tb_uint16_t qr     :1;       // query/response flag
         * tb_uint16_t opcode :4;       // purpose of message
         * tb_uint16_t aa     :1;       // authoritive answer
         * tb_uint16_t tc     :1;       // truncated message
         * tb_uint16_t rd     :1;       // recursion desired

         * tb_uint16_t ra     :1;       // recursion available
         * tb_uint16_t z      :1;       // its z! reserved
         * tb_uint16_t ad     :1;       // authenticated data
         * tb_uint16_t cd     :1;       // checking disabled
         * tb_uint16_t rcode  :4;       // response code
         *
         * this is a query 
         * this is a standard query 
         * not authoritive answer 
         * not truncated 
         * recursion desired
         *
         * recursion not available! hey we dont have it (lol)
         *
         */
#if 1
        tb_static_stream_writ_u16_be(&stream, 0x0100);
#else
        tb_static_stream_writ_u1(&stream, 0);          // this is a query
        tb_static_stream_writ_ubits32(&stream, 0, 4);  // this is a standard query
        tb_static_stream_writ_u1(&stream, 0);          // not authoritive answer
        tb_static_stream_writ_u1(&stream, 0);          // not truncated
        tb_static_stream_writ_u1(&stream, 1);          // recursion desired

        tb_static_stream_writ_u1(&stream, 0);          // recursion not available! hey we dont have it (lol)
        tb_static_stream_writ_u1(&stream, 0);
        tb_static_stream_writ_u1(&stream, 0);
        tb_static_stream_writ_u1(&stream, 0);
        tb_static_stream_writ_ubits32(&stream, 0, 4);
#endif

        /* we have only one question
         *
         * tb_uint16_t question;        // number of question entries
         * tb_uint16_t answer;          // number of answer entries
         * tb_uint16_t authority;       // number of authority entries
         * tb_uint16_t resource;        // number of resource entries
         *
         */
        tb_static_stream_writ_u16_be(&stream, 1); 
        tb_static_stream_writ_u16_be(&stream, 0);
        tb_static_stream_writ_u16_be(&stream, 0);
        tb_static_stream_writ_u16_be(&stream, 0);

        // set questions, see as tb_dns_question_t
        // name + question1 + question2 + ...
        tb_static_stream_writ_u8(&stream, '.');
        p = (tb_byte_t*)tb_static_stream_writ_cstr(&stream, tb_static_string_cstr(&looker->name));

        // only one question now.
        tb_static_stream_writ_u16_be(&stream, 1);      // we are requesting the ipv4 address
        tb_static_stream_writ_u16_be(&stream, 1);      // it's internet (lol)

        // encode dns name
        if (!p || !tb_dns_encode_name((tb_char_t*)p - 1)) return -1;

        // size
        size = tb_static_stream_offset(&stream);
        tb_assert_and_check_return_val(size, -1);

        // copy
        tb_static_buffer_memncpy(&looker->rpkt, rpkt, size);
    }

    // data && size
    tb_byte_t const*    data = tb_static_buffer_data(&looker->rpkt);
    tb_size_t           size = tb_static_buffer_size(&looker->rpkt);

    // check
    tb_assert_and_check_return_val(data && size && looker->size < size, -1);

    // try get addr from the dns list
    tb_ipaddr_ref_t addr = tb_null;
    if (looker->maxn && looker->itor && looker->itor <= looker->maxn)
        addr = &looker->list[looker->itor - 1];

    // check
    tb_assert_and_check_return_val(addr && !tb_ipaddr_is_empty(addr), -1);

    // family have been changed? reinit socket
    if (tb_ipaddr_family(addr) != looker->family)
    {
        // exit the previous socket
        if (looker->sock) tb_socket_exit(looker->sock);

        // init a new socket for the family
        looker->sock = tb_socket_init(TB_SOCKET_TYPE_UDP, tb_ipaddr_family(addr));
        tb_assert_and_check_return_val(looker->sock, -1);

        // update the new family
        looker->family = (tb_uint8_t)tb_ipaddr_family(addr);
    }

    // need wait if no data
    looker->step &= ~TB_DNS_LOOKER_STEP_NEVT;

    // trace
    tb_trace_d("request: try %{ipaddr}", addr);

    // send request
    while (looker->size < size)
    {
        // writ data
        tb_long_t writ = tb_socket_usend(looker->sock, addr, data + looker->size, size - looker->size);
        tb_assert_and_check_return_val(writ >= 0, -1);

        // no data? 
        if (!writ)
        {
            // abort?
            tb_check_return_val(!looker->size && !looker->tryn, -1);

            // tryn++
            looker->tryn++;

            // continue
            return 0;
        }
        else looker->tryn = 0;

        // update size
        looker->size += writ;
    }

    // finish it
    looker->step |= TB_DNS_LOOKER_STEP_REQT;
    looker->tryn = 0;

    // reset rpkt
    looker->size = 0;
    tb_static_buffer_clear(&looker->rpkt);

    // ok
    tb_trace_d("request: ok");
    return 1;
}
コード例 #4
0
ファイル: dns.c プロジェクト: AlexShiLucky/tbox
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);
}
コード例 #5
0
ファイル: dns.c プロジェクト: AlexShiLucky/tbox
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;
}