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.)

This commit is contained in:
Steinar H. Gunderson 2007-09-28 14:46:51 +00:00
parent d426c20c0a
commit 6ce589c3ee
19 changed files with 114 additions and 65 deletions

View File

@ -127,7 +127,8 @@ static const char *rcodes[] = {
"(unknown)", "(unknown)", "(unknown)", "(unknown)", "NOCHANGE" "(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, static const unsigned char *display_question(const unsigned char *aptr,
const unsigned char *abuf, const unsigned char *abuf,
int alen); int alen);
@ -294,7 +295,8 @@ int main(int argc, char **argv)
return 0; 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; char *name = (char *) arg;
int id, qr, opcode, aa, tc, rd, ra, rcode; int id, qr, opcode, aa, tc, rd, ra, rcode;

View File

@ -47,7 +47,7 @@ struct in6_addr
}; };
#endif #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); static void usage(void);
int main(int argc, char **argv) int main(int argc, char **argv)
@ -142,7 +142,7 @@ int main(int argc, char **argv)
return 0; 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; char **p;

View File

@ -193,11 +193,11 @@ struct timeval;
struct sockaddr; struct sockaddr;
struct ares_channeldata; struct ares_channeldata;
typedef struct ares_channeldata *ares_channel; typedef struct ares_channeldata *ares_channel;
typedef void (*ares_callback)(void *arg, int status, unsigned char *abuf, typedef void (*ares_callback)(void *arg, int status, int timeouts,
int alen); unsigned char *abuf, int alen);
typedef void (*ares_host_callback)(void *arg, int status, typedef void (*ares_host_callback)(void *arg, int status, int timeouts,
struct hostent *hostent); 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); char *node, char *service);
int ares_init(ares_channel *channelptr); int ares_init(ares_channel *channelptr);

View File

@ -31,7 +31,7 @@ void ares_cancel(ares_channel channel)
for (query = channel->queries; query; query = next) for (query = channel->queries; query; query = next)
{ {
next = 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->tcpbuf);
free(query->server_info); free(query->server_info);
free(query); free(query);

View File

@ -62,7 +62,7 @@ void ares_destroy(ares_channel channel)
while (channel->queries) { while (channel->queries) {
query = channel->queries; query = channel->queries;
channel->queries = query->next; channel->queries = query->next;
query->callback(query->arg, ARES_EDESTRUCTION, NULL, 0); query->callback(query->arg, ARES_EDESTRUCTION, 0, NULL, 0);
if (query->tcpbuf) if (query->tcpbuf)
free(query->tcpbuf); free(query->tcpbuf);
if (query->server_info) if (query->server_info)

View File

@ -22,7 +22,7 @@ ares_gethostbyaddr \- Initiate a host query by address
.B #include <ares.h> .B #include <ares.h>
.PP .PP
.B typedef void (*ares_host_callback)(void *\fIarg\fP, int \fIstatus\fP, .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 .PP
.B void ares_gethostbyaddr(ares_channel \fIchannel\fP, const void *\fIaddr\fP, .B void ares_gethostbyaddr(ares_channel \fIchannel\fP, const void *\fIaddr\fP,
.B int \fIaddrlen\fP, int \fIfamily\fP, ares_host_callback \fIcallback\fP, .B int \fIaddrlen\fP, int \fIfamily\fP, ares_host_callback \fIcallback\fP,
@ -76,6 +76,11 @@ The name service channel
.I channel .I channel
is being destroyed; the query will not be completed. is being destroyed; the query will not be completed.
.PP .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 On successful completion of the query, the callback argument
.I hostent .I hostent
points to a points to a

View File

@ -49,11 +49,12 @@ struct addr_query {
void *arg; void *arg;
const char *remaining_lookups; const char *remaining_lookups;
int timeouts;
}; };
static void next_lookup(struct addr_query *aquery); static void next_lookup(struct addr_query *aquery);
static void addr_callback(void *arg, int status, unsigned char *abuf, static void addr_callback(void *arg, int status, int timeouts,
int alen); unsigned char *abuf, int alen);
static void end_aquery(struct addr_query *aquery, int status, static void end_aquery(struct addr_query *aquery, int status,
struct hostent *host); struct hostent *host);
static int file_lookup(union ares_addr *addr, int family, 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) if (family != AF_INET && family != AF_INET6)
{ {
callback(arg, ARES_ENOTIMP, NULL); callback(arg, ARES_ENOTIMP, 0, NULL);
return; return;
} }
if ((family == AF_INET && addrlen != sizeof(struct in_addr)) || if ((family == AF_INET && addrlen != sizeof(struct in_addr)) ||
(family == AF_INET6 && addrlen != sizeof(struct in6_addr))) (family == AF_INET6 && addrlen != sizeof(struct in6_addr)))
{ {
callback(arg, ARES_ENOTIMP, NULL); callback(arg, ARES_ENOTIMP, 0, NULL);
return; return;
} }
aquery = malloc(sizeof(struct addr_query)); aquery = malloc(sizeof(struct addr_query));
if (!aquery) if (!aquery)
{ {
callback(arg, ARES_ENOMEM, NULL); callback(arg, ARES_ENOMEM, 0, NULL);
return; return;
} }
aquery->channel = channel; aquery->channel = channel;
@ -91,6 +92,7 @@ void ares_gethostbyaddr(ares_channel channel, const void *addr, int addrlen,
aquery->callback = callback; aquery->callback = callback;
aquery->arg = arg; aquery->arg = arg;
aquery->remaining_lookups = channel->lookups; aquery->remaining_lookups = channel->lookups;
aquery->timeouts = 0;
next_lookup(aquery); next_lookup(aquery);
} }
@ -151,11 +153,13 @@ static void next_lookup(struct addr_query *aquery)
end_aquery(aquery, ARES_ENOTFOUND, NULL); 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 addr_query *aquery = (struct addr_query *) arg;
struct hostent *host; struct hostent *host;
aquery->timeouts += timeouts;
if (status == ARES_SUCCESS) if (status == ARES_SUCCESS)
{ {
if (aquery->family == AF_INET) 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, static void end_aquery(struct addr_query *aquery, int status,
struct hostent *host) struct hostent *host)
{ {
aquery->callback(aquery->arg, status, host); aquery->callback(aquery->arg, status, aquery->timeouts, host);
if (host) if (host)
ares_free_hostent(host); ares_free_hostent(host);
free(aquery); free(aquery);

View File

@ -22,7 +22,7 @@ ares_gethostbyname \- Initiate a host query by name
.B #include <ares.h> .B #include <ares.h>
.PP .PP
.B typedef void (*ares_host_callback)(void *\fIarg\fP, int \fIstatus\fP, .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 .PP
.B void ares_gethostbyname(ares_channel \fIchannel\fP, const char *\fIname\fP, .B void ares_gethostbyname(ares_channel \fIchannel\fP, const char *\fIname\fP,
.B int \fIfamily\fP, ares_host_callback \fIcallback\fP, void *\fIarg\fP) .B int \fIfamily\fP, ares_host_callback \fIcallback\fP, void *\fIarg\fP)
@ -80,6 +80,11 @@ The name service channel
.I channel .I channel
is being destroyed; the query will not be completed. is being destroyed; the query will not be completed.
.PP .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 On successful completion of the query, the callback argument
.I hostent .I hostent
points to a points to a

View File

@ -54,11 +54,12 @@ struct host_query {
void *arg; void *arg;
int family; int family;
const char *remaining_lookups; const char *remaining_lookups;
int timeouts;
}; };
static void next_lookup(struct host_query *hquery); static void next_lookup(struct host_query *hquery);
static void host_callback(void *arg, int status, unsigned char *abuf, static void host_callback(void *arg, int status, int timeouts,
int alen); unsigned char *abuf, int alen);
static void end_hquery(struct host_query *hquery, int status, static void end_hquery(struct host_query *hquery, int status,
struct hostent *host); struct hostent *host);
static int fake_hostent(const char *name, int family, ares_host_callback callback, 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. */ /* Right now we only know how to look up Internet addresses. */
if (family != AF_INET && family != AF_INET6) if (family != AF_INET && family != AF_INET6)
{ {
callback(arg, ARES_ENOTIMP, NULL); callback(arg, ARES_ENOTIMP, 0, NULL);
return; return;
} }
@ -92,7 +93,7 @@ void ares_gethostbyname(ares_channel channel, const char *name, int family,
hquery = malloc(sizeof(struct host_query)); hquery = malloc(sizeof(struct host_query));
if (!hquery) if (!hquery)
{ {
callback(arg, ARES_ENOMEM, NULL); callback(arg, ARES_ENOMEM, 0, NULL);
return; return;
} }
hquery->channel = channel; hquery->channel = channel;
@ -101,12 +102,13 @@ void ares_gethostbyname(ares_channel channel, const char *name, int family,
if (!hquery->name) if (!hquery->name)
{ {
free(hquery); free(hquery);
callback(arg, ARES_ENOMEM, NULL); callback(arg, ARES_ENOMEM, 0, NULL);
return; return;
} }
hquery->callback = callback; hquery->callback = callback;
hquery->arg = arg; hquery->arg = arg;
hquery->remaining_lookups = channel->lookups; hquery->remaining_lookups = channel->lookups;
hquery->timeouts = 0;
/* Start performing lookups according to channel->lookups. */ /* Start performing lookups according to channel->lookups. */
next_lookup(hquery); next_lookup(hquery);
@ -144,15 +146,16 @@ static void next_lookup(struct host_query *hquery)
break; 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; struct host_query *hquery = (struct host_query *) arg;
ares_channel channel = hquery->channel; ares_channel channel = hquery->channel;
struct hostent *host; struct hostent *host;
hquery->timeouts += timeouts;
if (status == ARES_SUCCESS) if (status == ARES_SUCCESS)
{ {
if (hquery->family == AF_INET) 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, static void end_hquery(struct host_query *hquery, int status,
struct hostent *host) struct hostent *host)
{ {
hquery->callback(hquery->arg, status, host); hquery->callback(hquery->arg, status, hquery->timeouts, host);
if (host) if (host)
ares_free_hostent(host); ares_free_hostent(host);
free(hquery->name); 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); hostent.h_name = strdup(name);
if (!hostent.h_name) if (!hostent.h_name)
{ {
callback(arg, ARES_ENOMEM, NULL); callback(arg, ARES_ENOMEM, 0, NULL);
return 1; 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_aliases = aliases;
hostent.h_addrtype = family; hostent.h_addrtype = family;
hostent.h_addr_list = addrs; hostent.h_addr_list = addrs;
callback(arg, ARES_SUCCESS, &hostent); callback(arg, ARES_SUCCESS, 0, &hostent);
free((char *)(hostent.h_name)); free((char *)(hostent.h_name));
return 1; return 1;
@ -416,4 +419,3 @@ static int get6_address_index(struct in6_addr *addr, struct apattern *sortlist,
} }
return i; return i;
} }

View File

@ -22,7 +22,7 @@ ares_getnameinfo \- Address-to-nodename translation in protocol-independent mann
.B #include <ares.h> .B #include <ares.h>
.PP .PP
.B typedef void (*ares_nameinfo_callback)(void *\fIarg\fP, int \fIstatus\fP, .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 .PP
.B void ares_getnameinfo(ares_channel \fIchannel\fP, const struct sockaddr *\fIsa\fP, .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, .B socklen_t \fIsalen\fP, int \fIflags\fP, ares_nameinfo_callback \fIcallback\fP,
@ -120,6 +120,11 @@ The
.I flags .I flags
parameter contains an illegal value. parameter contains an illegal value.
.PP .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 On successful completion of the query, the callback argument
.I node .I node
contains a string representing the hostname (assuming contains a string representing the hostname (assuming

View File

@ -59,6 +59,7 @@ struct nameinfo_query {
} addr; } addr;
int family; int family;
int flags; int flags;
int timeouts;
}; };
#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID #ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
@ -67,7 +68,7 @@ struct nameinfo_query {
#define IPBUFSIZ 40 #define IPBUFSIZ 40
#endif #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, static char *lookup_service(unsigned short port, int flags,
char *buf, size_t buflen); char *buf, size_t buflen);
#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID #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; addr6 = (struct sockaddr_in6 *)sa;
else else
{ {
callback(arg, ARES_ENOTIMP, NULL, NULL); callback(arg, ARES_ENOTIMP, 0, NULL, NULL);
return; return;
} }
@ -110,7 +111,7 @@ void ares_getnameinfo(ares_channel channel, const struct sockaddr *sa, socklen_t
port = addr6->sin6_port; port = addr6->sin6_port;
service = lookup_service((unsigned short)(port & 0xffff), service = lookup_service((unsigned short)(port & 0xffff),
flags, buf, sizeof(buf)); flags, buf, sizeof(buf));
callback(arg, ARES_SUCCESS, NULL, service); callback(arg, ARES_SUCCESS, 0, NULL, service);
return; return;
} }
@ -131,7 +132,7 @@ void ares_getnameinfo(ares_channel channel, const struct sockaddr *sa, socklen_t
*/ */
if (flags & ARES_NI_NAMEREQD) if (flags & ARES_NI_NAMEREQD)
{ {
callback(arg, ARES_EBADFLAGS, NULL, NULL); callback(arg, ARES_EBADFLAGS, 0, NULL, NULL);
return; return;
} }
if (salen == sizeof(struct sockaddr_in6)) 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) if (flags & ARES_NI_LOOKUPSERVICE)
service = lookup_service((unsigned short)(port & 0xffff), service = lookup_service((unsigned short)(port & 0xffff),
flags, srvbuf, sizeof(srvbuf)); flags, srvbuf, sizeof(srvbuf));
callback(arg, ARES_SUCCESS, ipbuf, service); callback(arg, ARES_SUCCESS, 0, ipbuf, service);
return; return;
} }
/* This is where a DNS lookup becomes necessary */ /* 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)); niquery = malloc(sizeof(struct nameinfo_query));
if (!niquery) if (!niquery)
{ {
callback(arg, ARES_ENOMEM, NULL, NULL); callback(arg, ARES_ENOMEM, 0, NULL, NULL);
return; return;
} }
niquery->callback = callback; niquery->callback = callback;
niquery->arg = arg; niquery->arg = arg;
niquery->flags = flags; niquery->flags = flags;
niquery->timeouts = 0;
if (sa->sa_family == AF_INET) if (sa->sa_family == AF_INET)
{ {
niquery->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; struct nameinfo_query *niquery = (struct nameinfo_query *) arg;
char srvbuf[33]; char srvbuf[33];
char *service = NULL; char *service = NULL;
niquery->timeouts += timeouts;
if (status == ARES_SUCCESS) if (status == ARES_SUCCESS)
{ {
/* They want a service too */ /* They want a service too */
@ -220,7 +222,7 @@ static void nameinfo_callback(void *arg, int status, struct hostent *host)
*end = 0; *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); service);
return; return;
} }
@ -247,10 +249,10 @@ static void nameinfo_callback(void *arg, int status, struct hostent *host)
service = lookup_service(niquery->addr.addr6.sin6_port, service = lookup_service(niquery->addr.addr6.sin6_port,
niquery->flags, srvbuf, sizeof(srvbuf)); niquery->flags, srvbuf, sizeof(srvbuf));
} }
niquery->callback(niquery->arg, ARES_SUCCESS, ipbuf, service); niquery->callback(niquery->arg, ARES_SUCCESS, 0, ipbuf, service);
return; return;
} }
niquery->callback(niquery->arg, status, NULL, NULL); niquery->callback(niquery->arg, status, 0, NULL, NULL);
free(niquery); free(niquery);
} }

View File

@ -152,6 +152,7 @@ struct query {
/* Next query in chain */ /* Next query in chain */
struct query *next; struct query *next;
int timeouts; /* number of timeouts we saw for this request */
}; };
/* Per-server state for a query */ /* Per-server state for a query */
@ -195,6 +196,8 @@ struct ares_channeldata {
int ndots; int ndots;
int udp_port; int udp_port;
int tcp_port; int tcp_port;
int socket_send_buffer_size;
int socket_receive_buffer_size;
char **domains; char **domains;
int ndomains; int ndomains;
struct apattern *sortlist; struct apattern *sortlist;

View File

@ -936,7 +936,7 @@ static struct query *end_query (ares_channel channel, struct query *query, int s
} }
/* Invoke the callback */ /* 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) for (q = &channel->queries; *q; q = &(*q)->next)
{ {
if (*q == query) if (*q == query)

View File

@ -22,7 +22,7 @@ ares_query \- Initiate a single-question DNS query
.B #include <ares.h> .B #include <ares.h>
.PP .PP
.B typedef void (*ares_callback)(void *\fIarg\fP, int \fIstatus\fP, .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 .PP
.B void ares_query(ares_channel \fIchannel\fP, const char *\fIname\fP, .B void ares_query(ares_channel \fIchannel\fP, const char *\fIname\fP,
.B int \fIdnsclass\fP, int \fItype\fP, ares_callback \fIcallback\fP, .B int \fIdnsclass\fP, int \fItype\fP, ares_callback \fIcallback\fP,
@ -124,6 +124,11 @@ The name service channel
.I channel .I channel
is being destroyed; the query will not be completed. is being destroyed; the query will not be completed.
.PP .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 If the query completed (even if there was something wrong with it, as
indicated by some of the above error codes), the callback argument indicated by some of the above error codes), the callback argument
.I abuf .I abuf

View File

@ -37,7 +37,7 @@ struct qquery {
void *arg; 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) 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); &qlen);
if (status != ARES_SUCCESS) if (status != ARES_SUCCESS)
{ {
callback(arg, status, NULL, 0); if (qbuf != NULL) free(qbuf);
callback(arg, status, 0, NULL, 0);
return; return;
} }
@ -121,7 +122,7 @@ void ares_query(ares_channel channel, const char *name, int dnsclass,
if (!qquery) if (!qquery)
{ {
ares_free_string(qbuf); ares_free_string(qbuf);
callback(arg, ARES_ENOMEM, NULL, 0); callback(arg, ARES_ENOMEM, 0, NULL, 0);
return; return;
} }
qquery->callback = callback; qquery->callback = callback;
@ -132,14 +133,14 @@ void ares_query(ares_channel channel, const char *name, int dnsclass,
ares_free_string(qbuf); 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; struct qquery *qquery = (struct qquery *) arg;
unsigned int ancount; unsigned int ancount;
int rcode; int rcode;
if (status != ARES_SUCCESS) if (status != ARES_SUCCESS)
qquery->callback(qquery->arg, status, abuf, alen); qquery->callback(qquery->arg, status, timeouts, abuf, alen);
else else
{ {
/* Pull the response code and answer count from the packet. */ /* 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; status = ARES_EREFUSED;
break; break;
} }
qquery->callback(qquery->arg, status, abuf, alen); qquery->callback(qquery->arg, status, timeouts, abuf, alen);
} }
free(qquery); free(qquery);
} }

View File

@ -22,7 +22,7 @@ ares_search \- Initiate a DNS query with domain search
.B #include <ares.h> .B #include <ares.h>
.PP .PP
.B typedef void (*ares_callback)(void *\fIarg\fP, int \fIstatus\fP, .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 .PP
.B void ares_search(ares_channel \fIchannel\fP, const char *\fIname\fP, .B void ares_search(ares_channel \fIchannel\fP, const char *\fIname\fP,
.B int \fIdnsclass\fP, int \fItype\fP, ares_callback \fIcallback\fP, .B int \fIdnsclass\fP, int \fItype\fP, ares_callback \fIcallback\fP,
@ -125,6 +125,11 @@ The name service channel
.I channel .I channel
is being destroyed; the query will not be completed. is being destroyed; the query will not be completed.
.PP .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 If a query completed successfully, the callback argument
.I abuf .I abuf
points to a result buffer of length points to a result buffer of length

View File

@ -41,10 +41,11 @@ struct search_query {
int status_as_is; /* error status from trying as-is */ int status_as_is; /* error status from trying as-is */
int next_domain; /* next search domain to try */ int next_domain; /* next search domain to try */
int trying_as_is; /* current query is for name as-is */ 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, static void search_callback(void *arg, int status, int timeouts,
int alen); unsigned char *abuf, int alen);
static void end_squery(struct search_query *squery, int status, static void end_squery(struct search_query *squery, int status,
unsigned char *abuf, int alen); unsigned char *abuf, int alen);
static int cat_domain(const char *name, const char *domain, char **s); 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); status = single_domain(channel, name, &s);
if (status != ARES_SUCCESS) if (status != ARES_SUCCESS)
{ {
callback(arg, status, NULL, 0); callback(arg, status, 0, NULL, 0);
return; return;
} }
if (s) if (s)
@ -80,7 +81,7 @@ void ares_search(ares_channel channel, const char *name, int dnsclass,
squery = malloc(sizeof(struct search_query)); squery = malloc(sizeof(struct search_query));
if (!squery) if (!squery)
{ {
callback(arg, ARES_ENOMEM, NULL, 0); callback(arg, ARES_ENOMEM, 0, NULL, 0);
return; return;
} }
squery->channel = channel; squery->channel = channel;
@ -88,7 +89,7 @@ void ares_search(ares_channel channel, const char *name, int dnsclass,
if (!squery->name) if (!squery->name)
{ {
free(squery); free(squery);
callback(arg, ARES_ENOMEM, NULL, 0); callback(arg, ARES_ENOMEM, 0, NULL, 0);
return; return;
} }
squery->dnsclass = dnsclass; squery->dnsclass = dnsclass;
@ -96,6 +97,7 @@ void ares_search(ares_channel channel, const char *name, int dnsclass,
squery->status_as_is = -1; squery->status_as_is = -1;
squery->callback = callback; squery->callback = callback;
squery->arg = arg; squery->arg = arg;
squery->timeouts = 0;
/* Count the number of dots in name. */ /* Count the number of dots in name. */
ndots = 0; ndots = 0;
@ -132,18 +134,20 @@ void ares_search(ares_channel channel, const char *name, int dnsclass,
/* failed, free the malloc()ed memory */ /* failed, free the malloc()ed memory */
free(squery->name); free(squery->name);
free(squery); free(squery);
callback(arg, status, NULL, 0); callback(arg, status, 0, NULL, 0);
} }
} }
} }
static void search_callback(void *arg, int status, unsigned char *abuf, static void search_callback(void *arg, int status, int timeouts,
int alen) unsigned char *abuf, int alen)
{ {
struct search_query *squery = (struct search_query *) arg; struct search_query *squery = (struct search_query *) arg;
ares_channel channel = squery->channel; ares_channel channel = squery->channel;
char *s; char *s;
squery->timeouts += timeouts;
/* Stop searching unless we got a non-fatal error. */ /* Stop searching unless we got a non-fatal error. */
if (status != ARES_ENODATA && status != ARES_ESERVFAIL if (status != ARES_ENODATA && status != ARES_ESERVFAIL
&& status != ARES_ENOTFOUND) && 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, static void end_squery(struct search_query *squery, int status,
unsigned char *abuf, int alen) 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->name);
free(squery); free(squery);
} }

View File

@ -22,7 +22,7 @@ ares_send \- Initiate a DNS query
.B #include <ares.h> .B #include <ares.h>
.PP .PP
.B typedef void (*ares_callback)(void *\fIarg\fP, int \fIstatus\fP, .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 .PP
.B void ares_send(ares_channel \fIchannel\fP, const unsigned char *\fIqbuf\fP, .B void ares_send(ares_channel \fIchannel\fP, const unsigned char *\fIqbuf\fP,
.B int \fIqlen\fP, ares_callback \fIcallback\fP, void *\fIarg\fP) .B int \fIqlen\fP, ares_callback \fIcallback\fP, void *\fIarg\fP)
@ -79,6 +79,11 @@ The name service channel
.I channel .I channel
is being destroyed; the query will not be completed. is being destroyed; the query will not be completed.
.PP .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 If the query completed, the callback argument
.I abuf .I abuf
points to a result buffer of length points to a result buffer of length

View File

@ -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. */ /* Verify that the query is at least long enough to hold the header. */
if (qlen < HFIXEDSZ || qlen >= (1 << 16)) if (qlen < HFIXEDSZ || qlen >= (1 << 16))
{ {
callback(arg, ARES_EBADQUERY, NULL, 0); callback(arg, ARES_EBADQUERY, 0, NULL, 0);
return; return;
} }
@ -52,14 +52,14 @@ void ares_send(ares_channel channel, const unsigned char *qbuf, int qlen,
query = malloc(sizeof(struct query)); query = malloc(sizeof(struct query));
if (!query) if (!query)
{ {
callback(arg, ARES_ENOMEM, NULL, 0); callback(arg, ARES_ENOMEM, 0, NULL, 0);
return; return;
} }
query->tcpbuf = malloc(qlen + 2); query->tcpbuf = malloc(qlen + 2);
if (!query->tcpbuf) if (!query->tcpbuf)
{ {
free(query); free(query);
callback(arg, ARES_ENOMEM, NULL, 0); callback(arg, ARES_ENOMEM, 0, NULL, 0);
return; return;
} }
query->server_info = malloc(channel->nservers * 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->tcpbuf);
free(query); free(query);
callback(arg, ARES_ENOMEM, NULL, 0); callback(arg, ARES_ENOMEM, 0, NULL, 0);
return; 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->using_tcp = (channel->flags & ARES_FLAG_USEVC) || qlen > PACKETSZ;
query->error_status = ARES_ECONNREFUSED; query->error_status = ARES_ECONNREFUSED;
query->timeouts = 0;
/* Chain the query into this channel's query list. */ /* Chain the query into this channel's query list. */
query->next = channel->queries; query->next = channel->queries;