Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8ac099a4 authored by Luke Huang's avatar Luke Huang Committed by Gerrit Code Review
Browse files

Merge "res_nsend() refactor"

parents f034067a 43cc1b15
Loading
Loading
Loading
Loading
+67 −108
Original line number Original line Diff line number Diff line
@@ -397,24 +397,20 @@ static DnsQueryEvent* addDnsQueryEvent(NetworkDnsEventReported* event) {


int res_nsend(res_state statp, const uint8_t* buf, int buflen, uint8_t* ans, int anssiz, int* rcode,
int res_nsend(res_state statp, const uint8_t* buf, int buflen, uint8_t* ans, int anssiz, int* rcode,
              uint32_t flags) {
              uint32_t flags) {
    int gotsomewhere, terrno, v_circuit, resplen, n;
    LOG(DEBUG) << __func__;
    ResolvCacheStatus cache_status = RESOLV_CACHE_UNSUPPORTED;


    // Should not happen
    if (anssiz < HFIXEDSZ) {
    if (anssiz < HFIXEDSZ) {
        // TODO: Remove errno once callers stop using it
        // TODO: Remove errno once callers stop using it
        errno = EINVAL;
        errno = EINVAL;
        return -EINVAL;
        return -EINVAL;
    }
    }
    LOG(DEBUG) << __func__;
    res_pquery(buf, buflen);
    res_pquery(buf, buflen);


    v_circuit = buflen > PACKETSZ;
    gotsomewhere = 0;
    terrno = ETIMEDOUT;

    int anslen = 0;
    int anslen = 0;
    Stopwatch cacheStopwatch;
    Stopwatch cacheStopwatch;
    cache_status = resolv_cache_lookup(statp->netid, buf, buflen, ans, anssiz, &anslen, flags);
    ResolvCacheStatus cache_status =
            resolv_cache_lookup(statp->netid, buf, buflen, ans, anssiz, &anslen, flags);
    const int32_t cacheLatencyUs = saturate_cast<int32_t>(cacheStopwatch.timeTakenUs());
    const int32_t cacheLatencyUs = saturate_cast<int32_t>(cacheStopwatch.timeTakenUs());
    if (cache_status == RESOLV_CACHE_FOUND) {
    if (cache_status == RESOLV_CACHE_FOUND) {
        HEADER* hp = (HEADER*)(void*)ans;
        HEADER* hp = (HEADER*)(void*)ans;
@@ -442,8 +438,8 @@ int res_nsend(res_state statp, const uint8_t* buf, int buflen, uint8_t* ans, int
    // DoT
    // DoT
    if (!(statp->netcontext_flags & NET_CONTEXT_FLAG_USE_LOCAL_NAMESERVERS)) {
    if (!(statp->netcontext_flags & NET_CONTEXT_FLAG_USE_LOCAL_NAMESERVERS)) {
        bool fallback = false;
        bool fallback = false;
        resplen = res_tls_send(statp, Slice(const_cast<uint8_t*>(buf), buflen), Slice(ans, anssiz),
        int resplen = res_tls_send(statp, Slice(const_cast<uint8_t*>(buf), buflen),
                               rcode, &fallback);
                                   Slice(ans, anssiz), rcode, &fallback);
        if (resplen > 0) {
        if (resplen > 0) {
            LOG(DEBUG) << __func__ << ": got answer from DoT";
            LOG(DEBUG) << __func__ << ": got answer from DoT";
            res_pquery(ans, resplen);
            res_pquery(ans, resplen);
@@ -454,7 +450,7 @@ int res_nsend(res_state statp, const uint8_t* buf, int buflen, uint8_t* ans, int
        }
        }
        if (!fallback) {
        if (!fallback) {
            _resolv_cache_query_failed(statp->netid, buf, buflen, flags);
            _resolv_cache_query_failed(statp->netid, buf, buflen, flags);
            return -terrno;
            return -ETIMEDOUT;
        }
        }
    }
    }


@@ -478,90 +474,62 @@ int res_nsend(res_state statp, const uint8_t* buf, int buflen, uint8_t* ans, int
        res_set_usable_server(selectedServer, statp->nscount, usable_servers);
        res_set_usable_server(selectedServer, statp->nscount, usable_servers);
    }
    }


    /*
    // Send request, RETRY times, or until successful.
     * Send request, RETRY times, or until successful.
     */
    int retryTimes = (flags & ANDROID_RESOLV_NO_RETRY) ? 1 : params.retry_count;
    int retryTimes = (flags & ANDROID_RESOLV_NO_RETRY) ? 1 : params.retry_count;
    int useTcp = buflen > PACKETSZ;
    int gotsomewhere = 0;
    int terrno = ETIMEDOUT;


    for (int attempt = 0; attempt < retryTimes; ++attempt) {
    for (int attempt = 0; attempt < retryTimes; ++attempt) {

        for (int ns = 0; ns < statp->nscount; ++ns) {
        for (int ns = 0; ns < statp->nscount; ns++) {
            if (!usable_servers[ns]) continue;
            if (!usable_servers[ns]) continue;
            int nsaplen;

            time_t now = 0;
            int delay = 0;
            *rcode = RCODE_INTERNAL_ERROR;
            *rcode = RCODE_INTERNAL_ERROR;

            // Get server addr
            const sockaddr* nsap = get_nsaddr(statp, ns);
            const sockaddr* nsap = get_nsaddr(statp, ns);
            nsaplen = sockaddrSize(nsap);
            const int nsaplen = sockaddrSize(nsap);


        same_ns:
            static const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
            static const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
            char abuf[NI_MAXHOST];
            char abuf[NI_MAXHOST];
            DnsQueryEvent* dnsQueryEvent = addDnsQueryEvent(statp->event);
            dnsQueryEvent->set_cache_hit(static_cast<CacheStatus>(cache_status));

            if (getnameinfo(nsap, (socklen_t)nsaplen, abuf, sizeof(abuf), NULL, 0, niflags) == 0)
            if (getnameinfo(nsap, (socklen_t)nsaplen, abuf, sizeof(abuf), NULL, 0, niflags) == 0)
                LOG(DEBUG) << __func__ << ": Querying server (# " << ns + 1
                LOG(DEBUG) << __func__ << ": Querying server (# " << ns + 1
                           << ") address = " << abuf;
                           << ") address = " << abuf;


            ::android::net::Protocol query_proto = useTcp ? PROTO_TCP : PROTO_UDP;
            time_t now = 0;
            int delay = 0;
            bool fallbackTCP = false;
            const bool shouldRecordStats = (attempt == 0);
            int resplen;
            Stopwatch queryStopwatch;
            Stopwatch queryStopwatch;
            if (v_circuit) {
            if (useTcp) {
                /* Use VC; at most one attempt per server. */
                // TCP; at most one attempt per server.
                bool shouldRecordStats = (attempt == 0);
                attempt = retryTimes;
                attempt = retryTimes;

                resplen = send_vc(statp, &params, buf, buflen, ans, anssiz, &terrno, ns, &now,
                n = send_vc(statp, &params, buf, buflen, ans, anssiz, &terrno, ns, &now, rcode,
                                  rcode, &delay);
                            &delay);

                dnsQueryEvent->set_latency_micros(
                        saturate_cast<int32_t>(queryStopwatch.timeTakenUs()));
                dnsQueryEvent->set_dns_server_index(ns);
                dnsQueryEvent->set_ip_version(ipFamilyToIPVersion(nsap->sa_family));
                dnsQueryEvent->set_retry_times(attempt);
                dnsQueryEvent->set_rcode(static_cast<NsRcode>(*rcode));
                dnsQueryEvent->set_protocol(PROTO_TCP);
                dnsQueryEvent->set_type(getQueryType(buf, buflen));

                /*
                 * Only record stats the first time we try a query. This ensures that
                 * queries that deterministically fail (e.g., a name that always returns
                 * SERVFAIL or times out) do not unduly affect the stats.
                 */
                if (shouldRecordStats) {
                    res_sample sample;
                    _res_stats_set_sample(&sample, now, *rcode, delay);
                    resolv_cache_add_resolver_stats_sample(statp->netid, revision_id, nsap, sample,
                                                           params.max_samples);
                    resolv_stats_add(statp->netid, IPSockAddr::toIPSockAddr(*nsap), dnsQueryEvent);
                }

                LOG(INFO) << __func__ << ": used send_vc " << n;

                if (n < 0) {
                    _resolv_cache_query_failed(statp->netid, buf, buflen, flags);
                    res_nclose(statp);
                    return -terrno;
                };
                if (n == 0) goto next_ns;
                resplen = n;
            } else {
            } else {
                /* Use datagrams. */
                // UDP
                LOG(INFO) << __func__ << ": using send_dg";
                resplen = send_dg(statp, &params, buf, buflen, ans, anssiz, &terrno, ns, &useTcp,

                n = send_dg(statp, &params, buf, buflen, ans, anssiz, &terrno, ns, &v_circuit,
                                  &gotsomewhere, &now, rcode, &delay);
                                  &gotsomewhere, &now, rcode, &delay);
                fallbackTCP = useTcp ? true : false;
            }
            LOG(INFO) << __func__ << ": used send_" << ((useTcp) ? "vc " : "dg ") << resplen;


                dnsQueryEvent->set_latency_micros(
            DnsQueryEvent* dnsQueryEvent = addDnsQueryEvent(statp->event);
                        saturate_cast<int32_t>(queryStopwatch.timeTakenUs()));
            dnsQueryEvent->set_cache_hit(static_cast<CacheStatus>(cache_status));
            dnsQueryEvent->set_latency_micros(saturate_cast<int32_t>(queryStopwatch.timeTakenUs()));
            dnsQueryEvent->set_dns_server_index(ns);
            dnsQueryEvent->set_dns_server_index(ns);
            dnsQueryEvent->set_ip_version(ipFamilyToIPVersion(nsap->sa_family));
            dnsQueryEvent->set_ip_version(ipFamilyToIPVersion(nsap->sa_family));
            dnsQueryEvent->set_retry_times(attempt);
            dnsQueryEvent->set_retry_times(attempt);
            dnsQueryEvent->set_rcode(static_cast<NsRcode>(*rcode));
            dnsQueryEvent->set_rcode(static_cast<NsRcode>(*rcode));
                dnsQueryEvent->set_protocol(PROTO_UDP);
            dnsQueryEvent->set_protocol(query_proto);
            dnsQueryEvent->set_type(getQueryType(buf, buflen));
            dnsQueryEvent->set_type(getQueryType(buf, buflen));


                /* Only record stats the first time we try a query. See above. */
            // Only record stats the first time we try a query. This ensures that
                if (attempt == 0) {
            // queries that deterministically fail (e.g., a name that always returns
            // SERVFAIL or times out) do not unduly affect the stats.
            if (shouldRecordStats) {
                res_sample sample;
                res_sample sample;
                _res_stats_set_sample(&sample, now, *rcode, delay);
                _res_stats_set_sample(&sample, now, *rcode, delay);
                resolv_cache_add_resolver_stats_sample(statp->netid, revision_id, nsap, sample,
                resolv_cache_add_resolver_stats_sample(statp->netid, revision_id, nsap, sample,
@@ -569,17 +537,16 @@ int res_nsend(res_state statp, const uint8_t* buf, int buflen, uint8_t* ans, int
                resolv_stats_add(statp->netid, IPSockAddr::toIPSockAddr(*nsap), dnsQueryEvent);
                resolv_stats_add(statp->netid, IPSockAddr::toIPSockAddr(*nsap), dnsQueryEvent);
            }
            }


                LOG(INFO) << __func__ << ": used send_dg " << n;
            if (resplen == 0) continue;

            if (fallbackTCP) {
                if (n < 0) {
                ns--;
                continue;
            }
            if (resplen < 0) {
                _resolv_cache_query_failed(statp->netid, buf, buflen, flags);
                _resolv_cache_query_failed(statp->netid, buf, buflen, flags);
                res_nclose(statp);
                res_nclose(statp);
                return -terrno;
                return -terrno;
            };
            };
                if (n == 0) goto next_ns;
                if (v_circuit) goto same_ns;
                resplen = n;
            }


            LOG(DEBUG) << __func__ << ": got answer:";
            LOG(DEBUG) << __func__ << ": got answer:";
            res_pquery(ans, (resplen > anssiz) ? anssiz : resplen);
            res_pquery(ans, (resplen > anssiz) ? anssiz : resplen);
@@ -589,23 +556,15 @@ int res_nsend(res_state statp, const uint8_t* buf, int buflen, uint8_t* ans, int
            }
            }
            res_nclose(statp);
            res_nclose(statp);
            return (resplen);
            return (resplen);
        next_ns:;
        }  // for each ns
        }  // for each ns
    }  // for each retry
    }  // for each retry
    res_nclose(statp);
    res_nclose(statp);
    if (!v_circuit) {
    terrno = useTcp ? terrno : gotsomewhere ? ETIMEDOUT : ECONNREFUSED;
        if (!gotsomewhere) {
            // TODO: Remove errno once callers stop using it
            errno = ECONNREFUSED; /* no nameservers found */
            terrno = ECONNREFUSED;
        } else {
    // TODO: Remove errno once callers stop using it
    // TODO: Remove errno once callers stop using it
            errno = ETIMEDOUT; /* no answer obtained */
    errno = useTcp ? terrno
            terrno = ETIMEDOUT;
                   : gotsomewhere ? ETIMEDOUT /* no answer obtained */
        }
                                  : ECONNREFUSED /* no nameservers found */;
    } else {

        errno = terrno;
    }
    _resolv_cache_query_failed(statp->netid, buf, buflen, flags);
    _resolv_cache_query_failed(statp->netid, buf, buflen, flags);
    return -terrno;
    return -terrno;
}
}