From 6ce589c3ee1b905d22d419531e8e2019134e833b Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Fri, 28 Sep 2007 14:46:51 +0000 Subject: [PATCH] Make the query callbacks return the number of timeouts that happened during the execution of a query, and update documentation accordingly. (Patch from the Google tree.) --- ares/adig.c | 6 ++++-- ares/ahost.c | 4 ++-- ares/ares.h | 8 ++++---- ares/ares_cancel.c | 2 +- ares/ares_destroy.c | 2 +- ares/ares_gethostbyaddr.3 | 7 ++++++- ares/ares_gethostbyaddr.c | 18 +++++++++++------- ares/ares_gethostbyname.3 | 7 ++++++- ares/ares_gethostbyname.c | 24 +++++++++++++----------- ares/ares_getnameinfo.3 | 7 ++++++- ares/ares_getnameinfo.c | 24 +++++++++++++----------- ares/ares_private.h | 3 +++ ares/ares_process.c | 2 +- ares/ares_query.3 | 7 ++++++- ares/ares_query.c | 13 +++++++------ ares/ares_search.3 | 7 ++++++- ares/ares_search.c | 22 +++++++++++++--------- ares/ares_send.3 | 7 ++++++- ares/ares_send.c | 9 +++++---- 19 files changed, 114 insertions(+), 65 deletions(-) diff --git a/ares/adig.c b/ares/adig.c index 1eea3df69..b4fd20536 100644 --- a/ares/adig.c +++ b/ares/adig.c @@ -127,7 +127,8 @@ static const char *rcodes[] = { "(unknown)", "(unknown)", "(unknown)", "(unknown)", "NOCHANGE" }; -static void callback(void *arg, int status, unsigned char *abuf, int alen); +static void callback(void *arg, int status, int timeouts, + unsigned char *abuf, int alen); static const unsigned char *display_question(const unsigned char *aptr, const unsigned char *abuf, int alen); @@ -294,7 +295,8 @@ int main(int argc, char **argv) return 0; } -static void callback(void *arg, int status, unsigned char *abuf, int alen) +static void callback(void *arg, int status, int timeouts, + unsigned char *abuf, int alen) { char *name = (char *) arg; int id, qr, opcode, aa, tc, rd, ra, rcode; diff --git a/ares/ahost.c b/ares/ahost.c index e381c1932..1e6cc8bd4 100644 --- a/ares/ahost.c +++ b/ares/ahost.c @@ -47,7 +47,7 @@ struct in6_addr }; #endif -static void callback(void *arg, int status, struct hostent *host); +static void callback(void *arg, int status, int timeouts, struct hostent *host); static void usage(void); int main(int argc, char **argv) @@ -142,7 +142,7 @@ int main(int argc, char **argv) return 0; } -static void callback(void *arg, int status, struct hostent *host) +static void callback(void *arg, int status, int timeouts, struct hostent *host) { char **p; diff --git a/ares/ares.h b/ares/ares.h index 61d5a5605..50ce7f850 100644 --- a/ares/ares.h +++ b/ares/ares.h @@ -193,11 +193,11 @@ struct timeval; struct sockaddr; struct ares_channeldata; typedef struct ares_channeldata *ares_channel; -typedef void (*ares_callback)(void *arg, int status, unsigned char *abuf, - int alen); -typedef void (*ares_host_callback)(void *arg, int status, +typedef void (*ares_callback)(void *arg, int status, int timeouts, + unsigned char *abuf, int alen); +typedef void (*ares_host_callback)(void *arg, int status, int timeouts, struct hostent *hostent); -typedef void (*ares_nameinfo_callback)(void *arg, int status, +typedef void (*ares_nameinfo_callback)(void *arg, int status, int timeouts, char *node, char *service); int ares_init(ares_channel *channelptr); diff --git a/ares/ares_cancel.c b/ares/ares_cancel.c index 65f86b966..c3d668e84 100644 --- a/ares/ares_cancel.c +++ b/ares/ares_cancel.c @@ -31,7 +31,7 @@ void ares_cancel(ares_channel channel) for (query = channel->queries; query; query = next) { next = query->next; - query->callback(query->arg, ARES_ETIMEOUT, NULL, 0); + query->callback(query->arg, ARES_ETIMEOUT, 0, NULL, 0); free(query->tcpbuf); free(query->server_info); free(query); diff --git a/ares/ares_destroy.c b/ares/ares_destroy.c index e844ea628..d1f82bdf6 100644 --- a/ares/ares_destroy.c +++ b/ares/ares_destroy.c @@ -62,7 +62,7 @@ void ares_destroy(ares_channel channel) while (channel->queries) { query = channel->queries; channel->queries = query->next; - query->callback(query->arg, ARES_EDESTRUCTION, NULL, 0); + query->callback(query->arg, ARES_EDESTRUCTION, 0, NULL, 0); if (query->tcpbuf) free(query->tcpbuf); if (query->server_info) diff --git a/ares/ares_gethostbyaddr.3 b/ares/ares_gethostbyaddr.3 index e3fc3c522..3782d4af5 100644 --- a/ares/ares_gethostbyaddr.3 +++ b/ares/ares_gethostbyaddr.3 @@ -22,7 +22,7 @@ ares_gethostbyaddr \- Initiate a host query by address .B #include .PP .B typedef void (*ares_host_callback)(void *\fIarg\fP, int \fIstatus\fP, -.B struct hostent *\fIhostent\fP) +.B int \fItimeouts\fP, struct hostent *\fIhostent\fP) .PP .B void ares_gethostbyaddr(ares_channel \fIchannel\fP, const void *\fIaddr\fP, .B int \fIaddrlen\fP, int \fIfamily\fP, ares_host_callback \fIcallback\fP, @@ -76,6 +76,11 @@ The name service channel .I channel is being destroyed; the query will not be completed. .PP +The callback argument +.I timeouts +reports how many times a query timed out during the execution of the +given request. +.PP On successful completion of the query, the callback argument .I hostent points to a diff --git a/ares/ares_gethostbyaddr.c b/ares/ares_gethostbyaddr.c index 7ea7ebbc0..b3abc093e 100644 --- a/ares/ares_gethostbyaddr.c +++ b/ares/ares_gethostbyaddr.c @@ -49,11 +49,12 @@ struct addr_query { void *arg; const char *remaining_lookups; + int timeouts; }; static void next_lookup(struct addr_query *aquery); -static void addr_callback(void *arg, int status, unsigned char *abuf, - int alen); +static void addr_callback(void *arg, int status, int timeouts, + unsigned char *abuf, int alen); static void end_aquery(struct addr_query *aquery, int status, struct hostent *host); static int file_lookup(union ares_addr *addr, int family, struct hostent **host); @@ -65,21 +66,21 @@ void ares_gethostbyaddr(ares_channel channel, const void *addr, int addrlen, if (family != AF_INET && family != AF_INET6) { - callback(arg, ARES_ENOTIMP, NULL); + callback(arg, ARES_ENOTIMP, 0, NULL); return; } if ((family == AF_INET && addrlen != sizeof(struct in_addr)) || (family == AF_INET6 && addrlen != sizeof(struct in6_addr))) { - callback(arg, ARES_ENOTIMP, NULL); + callback(arg, ARES_ENOTIMP, 0, NULL); return; } aquery = malloc(sizeof(struct addr_query)); if (!aquery) { - callback(arg, ARES_ENOMEM, NULL); + callback(arg, ARES_ENOMEM, 0, NULL); return; } aquery->channel = channel; @@ -91,6 +92,7 @@ void ares_gethostbyaddr(ares_channel channel, const void *addr, int addrlen, aquery->callback = callback; aquery->arg = arg; aquery->remaining_lookups = channel->lookups; + aquery->timeouts = 0; next_lookup(aquery); } @@ -151,11 +153,13 @@ static void next_lookup(struct addr_query *aquery) end_aquery(aquery, ARES_ENOTFOUND, NULL); } -static void addr_callback(void *arg, int status, unsigned char *abuf, int alen) +static void addr_callback(void *arg, int status, int timeouts, + unsigned char *abuf, int alen) { struct addr_query *aquery = (struct addr_query *) arg; struct hostent *host; + aquery->timeouts += timeouts; if (status == ARES_SUCCESS) { if (aquery->family == AF_INET) @@ -175,7 +179,7 @@ static void addr_callback(void *arg, int status, unsigned char *abuf, int alen) static void end_aquery(struct addr_query *aquery, int status, struct hostent *host) { - aquery->callback(aquery->arg, status, host); + aquery->callback(aquery->arg, status, aquery->timeouts, host); if (host) ares_free_hostent(host); free(aquery); diff --git a/ares/ares_gethostbyname.3 b/ares/ares_gethostbyname.3 index 680b213f3..c59c03851 100644 --- a/ares/ares_gethostbyname.3 +++ b/ares/ares_gethostbyname.3 @@ -22,7 +22,7 @@ ares_gethostbyname \- Initiate a host query by name .B #include .PP .B typedef void (*ares_host_callback)(void *\fIarg\fP, int \fIstatus\fP, -.B struct hostent *\fIhostent\fP) +.B int \fItimeouts\fP, struct hostent *\fIhostent\fP) .PP .B void ares_gethostbyname(ares_channel \fIchannel\fP, const char *\fIname\fP, .B int \fIfamily\fP, ares_host_callback \fIcallback\fP, void *\fIarg\fP) @@ -80,6 +80,11 @@ The name service channel .I channel is being destroyed; the query will not be completed. .PP +The callback argument +.I timeouts +reports how many times a query timed out during the execution of the +given request. +.PP On successful completion of the query, the callback argument .I hostent points to a diff --git a/ares/ares_gethostbyname.c b/ares/ares_gethostbyname.c index c0fa4743a..49ae53ed3 100644 --- a/ares/ares_gethostbyname.c +++ b/ares/ares_gethostbyname.c @@ -54,11 +54,12 @@ struct host_query { void *arg; int family; const char *remaining_lookups; + int timeouts; }; static void next_lookup(struct host_query *hquery); -static void host_callback(void *arg, int status, unsigned char *abuf, - int alen); +static void host_callback(void *arg, int status, int timeouts, + unsigned char *abuf, int alen); static void end_hquery(struct host_query *hquery, int status, struct hostent *host); static int fake_hostent(const char *name, int family, ares_host_callback callback, @@ -81,7 +82,7 @@ void ares_gethostbyname(ares_channel channel, const char *name, int family, /* Right now we only know how to look up Internet addresses. */ if (family != AF_INET && family != AF_INET6) { - callback(arg, ARES_ENOTIMP, NULL); + callback(arg, ARES_ENOTIMP, 0, NULL); return; } @@ -92,7 +93,7 @@ void ares_gethostbyname(ares_channel channel, const char *name, int family, hquery = malloc(sizeof(struct host_query)); if (!hquery) { - callback(arg, ARES_ENOMEM, NULL); + callback(arg, ARES_ENOMEM, 0, NULL); return; } hquery->channel = channel; @@ -101,12 +102,13 @@ void ares_gethostbyname(ares_channel channel, const char *name, int family, if (!hquery->name) { free(hquery); - callback(arg, ARES_ENOMEM, NULL); + callback(arg, ARES_ENOMEM, 0, NULL); return; } hquery->callback = callback; hquery->arg = arg; hquery->remaining_lookups = channel->lookups; + hquery->timeouts = 0; /* Start performing lookups according to channel->lookups. */ next_lookup(hquery); @@ -144,15 +146,16 @@ static void next_lookup(struct host_query *hquery) break; } } - end_hquery(hquery, ARES_ENOTFOUND, NULL); } -static void host_callback(void *arg, int status, unsigned char *abuf, int alen) +static void host_callback(void *arg, int status, int timeouts, + unsigned char *abuf, int alen) { struct host_query *hquery = (struct host_query *) arg; ares_channel channel = hquery->channel; struct hostent *host; + hquery->timeouts += timeouts; if (status == ARES_SUCCESS) { if (hquery->family == AF_INET) @@ -185,7 +188,7 @@ static void host_callback(void *arg, int status, unsigned char *abuf, int alen) static void end_hquery(struct host_query *hquery, int status, struct hostent *host) { - hquery->callback(hquery->arg, status, host); + hquery->callback(hquery->arg, status, hquery->timeouts, host); if (host) ares_free_hostent(host); free(hquery->name); @@ -227,7 +230,7 @@ static int fake_hostent(const char *name, int family, ares_host_callback callbac hostent.h_name = strdup(name); if (!hostent.h_name) { - callback(arg, ARES_ENOMEM, NULL); + callback(arg, ARES_ENOMEM, 0, NULL); return 1; } @@ -236,7 +239,7 @@ static int fake_hostent(const char *name, int family, ares_host_callback callbac hostent.h_aliases = aliases; hostent.h_addrtype = family; hostent.h_addr_list = addrs; - callback(arg, ARES_SUCCESS, &hostent); + callback(arg, ARES_SUCCESS, 0, &hostent); free((char *)(hostent.h_name)); return 1; @@ -416,4 +419,3 @@ static int get6_address_index(struct in6_addr *addr, struct apattern *sortlist, } return i; } - diff --git a/ares/ares_getnameinfo.3 b/ares/ares_getnameinfo.3 index 9b6bd73a9..55918ffba 100644 --- a/ares/ares_getnameinfo.3 +++ b/ares/ares_getnameinfo.3 @@ -22,7 +22,7 @@ ares_getnameinfo \- Address-to-nodename translation in protocol-independent mann .B #include .PP .B typedef void (*ares_nameinfo_callback)(void *\fIarg\fP, int \fIstatus\fP, -.B char *\fInode\fP, char *\fIservice\fP) +.B int \fItimeouts\fP, char *\fInode\fP, char *\fIservice\fP) .PP .B void ares_getnameinfo(ares_channel \fIchannel\fP, const struct sockaddr *\fIsa\fP, .B socklen_t \fIsalen\fP, int \fIflags\fP, ares_nameinfo_callback \fIcallback\fP, @@ -120,6 +120,11 @@ The .I flags parameter contains an illegal value. .PP +The callback argument +.I timeouts +reports how many times a query timed out during the execution of the +given request. +.PP On successful completion of the query, the callback argument .I node contains a string representing the hostname (assuming diff --git a/ares/ares_getnameinfo.c b/ares/ares_getnameinfo.c index 2c28cebf6..4f690f9d0 100644 --- a/ares/ares_getnameinfo.c +++ b/ares/ares_getnameinfo.c @@ -59,6 +59,7 @@ struct nameinfo_query { } addr; int family; int flags; + int timeouts; }; #ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID @@ -67,7 +68,7 @@ struct nameinfo_query { #define IPBUFSIZ 40 #endif -static void nameinfo_callback(void *arg, int status, struct hostent *host); +static void nameinfo_callback(void *arg, int status, int timeouts, struct hostent *host); static char *lookup_service(unsigned short port, int flags, char *buf, size_t buflen); #ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID @@ -90,7 +91,7 @@ void ares_getnameinfo(ares_channel channel, const struct sockaddr *sa, socklen_t addr6 = (struct sockaddr_in6 *)sa; else { - callback(arg, ARES_ENOTIMP, NULL, NULL); + callback(arg, ARES_ENOTIMP, 0, NULL, NULL); return; } @@ -110,7 +111,7 @@ void ares_getnameinfo(ares_channel channel, const struct sockaddr *sa, socklen_t port = addr6->sin6_port; service = lookup_service((unsigned short)(port & 0xffff), flags, buf, sizeof(buf)); - callback(arg, ARES_SUCCESS, NULL, service); + callback(arg, ARES_SUCCESS, 0, NULL, service); return; } @@ -131,7 +132,7 @@ void ares_getnameinfo(ares_channel channel, const struct sockaddr *sa, socklen_t */ if (flags & ARES_NI_NAMEREQD) { - callback(arg, ARES_EBADFLAGS, NULL, NULL); + callback(arg, ARES_EBADFLAGS, 0, NULL, NULL); return; } if (salen == sizeof(struct sockaddr_in6)) @@ -152,7 +153,7 @@ void ares_getnameinfo(ares_channel channel, const struct sockaddr *sa, socklen_t if (flags & ARES_NI_LOOKUPSERVICE) service = lookup_service((unsigned short)(port & 0xffff), flags, srvbuf, sizeof(srvbuf)); - callback(arg, ARES_SUCCESS, ipbuf, service); + callback(arg, ARES_SUCCESS, 0, ipbuf, service); return; } /* This is where a DNS lookup becomes necessary */ @@ -161,12 +162,13 @@ void ares_getnameinfo(ares_channel channel, const struct sockaddr *sa, socklen_t niquery = malloc(sizeof(struct nameinfo_query)); if (!niquery) { - callback(arg, ARES_ENOMEM, NULL, NULL); + callback(arg, ARES_ENOMEM, 0, NULL, NULL); return; } niquery->callback = callback; niquery->arg = arg; niquery->flags = flags; + niquery->timeouts = 0; if (sa->sa_family == AF_INET) { niquery->family = AF_INET; @@ -185,13 +187,13 @@ void ares_getnameinfo(ares_channel channel, const struct sockaddr *sa, socklen_t } } -static void nameinfo_callback(void *arg, int status, struct hostent *host) +static void nameinfo_callback(void *arg, int status, int timeouts, struct hostent *host) { struct nameinfo_query *niquery = (struct nameinfo_query *) arg; char srvbuf[33]; char *service = NULL; - + niquery->timeouts += timeouts; if (status == ARES_SUCCESS) { /* They want a service too */ @@ -220,7 +222,7 @@ static void nameinfo_callback(void *arg, int status, struct hostent *host) *end = 0; } } - niquery->callback(niquery->arg, ARES_SUCCESS, (char *)(host->h_name), + niquery->callback(niquery->arg, ARES_SUCCESS, niquery->timeouts, (char *)(host->h_name), service); return; } @@ -247,10 +249,10 @@ static void nameinfo_callback(void *arg, int status, struct hostent *host) service = lookup_service(niquery->addr.addr6.sin6_port, niquery->flags, srvbuf, sizeof(srvbuf)); } - niquery->callback(niquery->arg, ARES_SUCCESS, ipbuf, service); + niquery->callback(niquery->arg, ARES_SUCCESS, 0, ipbuf, service); return; } - niquery->callback(niquery->arg, status, NULL, NULL); + niquery->callback(niquery->arg, status, 0, NULL, NULL); free(niquery); } diff --git a/ares/ares_private.h b/ares/ares_private.h index dd9070aa7..e6ecaa251 100644 --- a/ares/ares_private.h +++ b/ares/ares_private.h @@ -152,6 +152,7 @@ struct query { /* Next query in chain */ struct query *next; + int timeouts; /* number of timeouts we saw for this request */ }; /* Per-server state for a query */ @@ -195,6 +196,8 @@ struct ares_channeldata { int ndots; int udp_port; int tcp_port; + int socket_send_buffer_size; + int socket_receive_buffer_size; char **domains; int ndomains; struct apattern *sortlist; diff --git a/ares/ares_process.c b/ares/ares_process.c index 15aa06e1c..d359b115a 100644 --- a/ares/ares_process.c +++ b/ares/ares_process.c @@ -936,7 +936,7 @@ static struct query *end_query (ares_channel channel, struct query *query, int s } /* Invoke the callback */ - query->callback(query->arg, status, abuf, alen); + query->callback(query->arg, status, query->timeouts, abuf, alen); for (q = &channel->queries; *q; q = &(*q)->next) { if (*q == query) diff --git a/ares/ares_query.3 b/ares/ares_query.3 index 4bd8b68bd..93f64b2f2 100644 --- a/ares/ares_query.3 +++ b/ares/ares_query.3 @@ -22,7 +22,7 @@ ares_query \- Initiate a single-question DNS query .B #include .PP .B typedef void (*ares_callback)(void *\fIarg\fP, int \fIstatus\fP, -.B unsigned char *\fIabuf\fP, int \fIalen\fP) +.B int \fItimeouts\fP, unsigned char *\fIabuf\fP, int \fIalen\fP) .PP .B void ares_query(ares_channel \fIchannel\fP, const char *\fIname\fP, .B int \fIdnsclass\fP, int \fItype\fP, ares_callback \fIcallback\fP, @@ -124,6 +124,11 @@ The name service channel .I channel is being destroyed; the query will not be completed. .PP +The callback argument +.I timeouts +reports how many times a query timed out during the execution of the +given request. +.PP If the query completed (even if there was something wrong with it, as indicated by some of the above error codes), the callback argument .I abuf diff --git a/ares/ares_query.c b/ares/ares_query.c index 0cd655709..c5fc12449 100644 --- a/ares/ares_query.c +++ b/ares/ares_query.c @@ -37,7 +37,7 @@ struct qquery { void *arg; }; -static void qcallback(void *arg, int status, unsigned char *abuf, int alen); +static void qcallback(void *arg, int status, int timeouts, unsigned char *abuf, int alen); void ares__rc4(rc4_key* key, unsigned char *buffer_ptr, int buffer_len) { @@ -110,7 +110,8 @@ void ares_query(ares_channel channel, const char *name, int dnsclass, &qlen); if (status != ARES_SUCCESS) { - callback(arg, status, NULL, 0); + if (qbuf != NULL) free(qbuf); + callback(arg, status, 0, NULL, 0); return; } @@ -121,7 +122,7 @@ void ares_query(ares_channel channel, const char *name, int dnsclass, if (!qquery) { ares_free_string(qbuf); - callback(arg, ARES_ENOMEM, NULL, 0); + callback(arg, ARES_ENOMEM, 0, NULL, 0); return; } qquery->callback = callback; @@ -132,14 +133,14 @@ void ares_query(ares_channel channel, const char *name, int dnsclass, ares_free_string(qbuf); } -static void qcallback(void *arg, int status, unsigned char *abuf, int alen) +static void qcallback(void *arg, int status, int timeouts, unsigned char *abuf, int alen) { struct qquery *qquery = (struct qquery *) arg; unsigned int ancount; int rcode; if (status != ARES_SUCCESS) - qquery->callback(qquery->arg, status, abuf, alen); + qquery->callback(qquery->arg, status, timeouts, abuf, alen); else { /* Pull the response code and answer count from the packet. */ @@ -168,7 +169,7 @@ static void qcallback(void *arg, int status, unsigned char *abuf, int alen) status = ARES_EREFUSED; break; } - qquery->callback(qquery->arg, status, abuf, alen); + qquery->callback(qquery->arg, status, timeouts, abuf, alen); } free(qquery); } diff --git a/ares/ares_search.3 b/ares/ares_search.3 index 2e93ba3da..f5bf80d9c 100644 --- a/ares/ares_search.3 +++ b/ares/ares_search.3 @@ -22,7 +22,7 @@ ares_search \- Initiate a DNS query with domain search .B #include .PP .B typedef void (*ares_callback)(void *\fIarg\fP, int \fIstatus\fP, -.B unsigned char *\fIabuf\fP, int \fIalen\fP) +.B int \fItimeouts\fP, unsigned char *\fIabuf\fP, int \fIalen\fP) .PP .B void ares_search(ares_channel \fIchannel\fP, const char *\fIname\fP, .B int \fIdnsclass\fP, int \fItype\fP, ares_callback \fIcallback\fP, @@ -125,6 +125,11 @@ The name service channel .I channel is being destroyed; the query will not be completed. .PP +The callback argument +.I timeouts +reports how many times a query timed out during the execution of the +given request. +.PP If a query completed successfully, the callback argument .I abuf points to a result buffer of length diff --git a/ares/ares_search.c b/ares/ares_search.c index 4ff54532e..ca703a3cb 100644 --- a/ares/ares_search.c +++ b/ares/ares_search.c @@ -41,10 +41,11 @@ struct search_query { int status_as_is; /* error status from trying as-is */ int next_domain; /* next search domain to try */ int trying_as_is; /* current query is for name as-is */ + int timeouts; /* number of timeouts we saw for this request */ }; -static void search_callback(void *arg, int status, unsigned char *abuf, - int alen); +static void search_callback(void *arg, int status, int timeouts, + unsigned char *abuf, int alen); static void end_squery(struct search_query *squery, int status, unsigned char *abuf, int alen); static int cat_domain(const char *name, const char *domain, char **s); @@ -64,7 +65,7 @@ void ares_search(ares_channel channel, const char *name, int dnsclass, status = single_domain(channel, name, &s); if (status != ARES_SUCCESS) { - callback(arg, status, NULL, 0); + callback(arg, status, 0, NULL, 0); return; } if (s) @@ -80,7 +81,7 @@ void ares_search(ares_channel channel, const char *name, int dnsclass, squery = malloc(sizeof(struct search_query)); if (!squery) { - callback(arg, ARES_ENOMEM, NULL, 0); + callback(arg, ARES_ENOMEM, 0, NULL, 0); return; } squery->channel = channel; @@ -88,7 +89,7 @@ void ares_search(ares_channel channel, const char *name, int dnsclass, if (!squery->name) { free(squery); - callback(arg, ARES_ENOMEM, NULL, 0); + callback(arg, ARES_ENOMEM, 0, NULL, 0); return; } squery->dnsclass = dnsclass; @@ -96,6 +97,7 @@ void ares_search(ares_channel channel, const char *name, int dnsclass, squery->status_as_is = -1; squery->callback = callback; squery->arg = arg; + squery->timeouts = 0; /* Count the number of dots in name. */ ndots = 0; @@ -132,18 +134,20 @@ void ares_search(ares_channel channel, const char *name, int dnsclass, /* failed, free the malloc()ed memory */ free(squery->name); free(squery); - callback(arg, status, NULL, 0); + callback(arg, status, 0, NULL, 0); } } } -static void search_callback(void *arg, int status, unsigned char *abuf, - int alen) +static void search_callback(void *arg, int status, int timeouts, + unsigned char *abuf, int alen) { struct search_query *squery = (struct search_query *) arg; ares_channel channel = squery->channel; char *s; + squery->timeouts += timeouts; + /* Stop searching unless we got a non-fatal error. */ if (status != ARES_ENODATA && status != ARES_ESERVFAIL && status != ARES_ENOTFOUND) @@ -184,7 +188,7 @@ static void search_callback(void *arg, int status, unsigned char *abuf, static void end_squery(struct search_query *squery, int status, unsigned char *abuf, int alen) { - squery->callback(squery->arg, status, abuf, alen); + squery->callback(squery->arg, status, squery->timeouts, abuf, alen); free(squery->name); free(squery); } diff --git a/ares/ares_send.3 b/ares/ares_send.3 index 2627b17ef..e8a240471 100644 --- a/ares/ares_send.3 +++ b/ares/ares_send.3 @@ -22,7 +22,7 @@ ares_send \- Initiate a DNS query .B #include .PP .B typedef void (*ares_callback)(void *\fIarg\fP, int \fIstatus\fP, -.B unsigned char *\fIabuf\fP, int \fIalen\fP) +.B int \fItimeouts\fP, unsigned char *\fIabuf\fP, int \fIalen\fP) .PP .B void ares_send(ares_channel \fIchannel\fP, const unsigned char *\fIqbuf\fP, .B int \fIqlen\fP, ares_callback \fIcallback\fP, void *\fIarg\fP) @@ -79,6 +79,11 @@ The name service channel .I channel is being destroyed; the query will not be completed. .PP +The callback argument +.I timeouts +reports how many times a query timed out during the execution of the +given request. +.PP If the query completed, the callback argument .I abuf points to a result buffer of length diff --git a/ares/ares_send.c b/ares/ares_send.c index fd1450b4a..c8015803b 100644 --- a/ares/ares_send.c +++ b/ares/ares_send.c @@ -44,7 +44,7 @@ void ares_send(ares_channel channel, const unsigned char *qbuf, int qlen, /* Verify that the query is at least long enough to hold the header. */ if (qlen < HFIXEDSZ || qlen >= (1 << 16)) { - callback(arg, ARES_EBADQUERY, NULL, 0); + callback(arg, ARES_EBADQUERY, 0, NULL, 0); return; } @@ -52,14 +52,14 @@ void ares_send(ares_channel channel, const unsigned char *qbuf, int qlen, query = malloc(sizeof(struct query)); if (!query) { - callback(arg, ARES_ENOMEM, NULL, 0); + callback(arg, ARES_ENOMEM, 0, NULL, 0); return; } query->tcpbuf = malloc(qlen + 2); if (!query->tcpbuf) { free(query); - callback(arg, ARES_ENOMEM, NULL, 0); + callback(arg, ARES_ENOMEM, 0, NULL, 0); return; } query->server_info = malloc(channel->nservers * @@ -68,7 +68,7 @@ void ares_send(ares_channel channel, const unsigned char *qbuf, int qlen, { free(query->tcpbuf); free(query); - callback(arg, ARES_ENOMEM, NULL, 0); + callback(arg, ARES_ENOMEM, 0, NULL, 0); return; } @@ -100,6 +100,7 @@ void ares_send(ares_channel channel, const unsigned char *qbuf, int qlen, } query->using_tcp = (channel->flags & ARES_FLAG_USEVC) || qlen > PACKETSZ; query->error_status = ARES_ECONNREFUSED; + query->timeouts = 0; /* Chain the query into this channel's query list. */ query->next = channel->queries;