mirror of
https://github.com/curl/curl.git
synced 2024-11-21 01:16:58 +08:00
- Introducing millisecond resolution support for the timeout option. See
ares_init_options()'s ARES_OPT_TIMEOUTMS.
This commit is contained in:
parent
80afddacc8
commit
76c251513e
@ -1,5 +1,10 @@
|
||||
Changelog for the c-ares project
|
||||
|
||||
* May 13 2008 (Daniel Stenberg)
|
||||
|
||||
- Introducing millisecond resolution support for the timeout option. See
|
||||
ares_init_options()'s ARES_OPT_TIMEOUTMS.
|
||||
|
||||
* May 9 2008 (Yang Tse)
|
||||
|
||||
- Use monotonic time source if available, for private function ares__tvnow()
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* $Id$ */
|
||||
|
||||
/* Copyright 1998 by the Massachusetts Institute of Technology.
|
||||
* Copyright (C) 2007 by Daniel Stenberg
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose and without
|
||||
@ -112,6 +113,7 @@ extern "C" {
|
||||
#define ARES_OPT_SORTLIST (1 << 10)
|
||||
#define ARES_OPT_SOCK_SNDBUF (1 << 11)
|
||||
#define ARES_OPT_SOCK_RCVBUF (1 << 12)
|
||||
#define ARES_OPT_TIMEOUTMS (1 << 13)
|
||||
|
||||
/* Nameinfo flag values */
|
||||
#define ARES_NI_NOFQDN (1 << 0)
|
||||
@ -179,7 +181,7 @@ struct apattern;
|
||||
|
||||
struct ares_options {
|
||||
int flags;
|
||||
int timeout;
|
||||
int timeout; /* in seconds or milliseconds, depending on options */
|
||||
int tries;
|
||||
int ndots;
|
||||
unsigned short udp_port;
|
||||
|
@ -1,6 +1,7 @@
|
||||
.\" $Id$
|
||||
.\"
|
||||
.\" Copyright 1998 by the Massachusetts Institute of Technology.
|
||||
.\" Copyright (C) 2007-2008 by Daniel Stenberg
|
||||
.\"
|
||||
.\" Permission to use, copy, modify, and distribute this
|
||||
.\" software and its documentation for any purpose and without
|
||||
@ -14,7 +15,7 @@
|
||||
.\" this software for any purpose. It is provided "as is"
|
||||
.\" without express or implied warranty.
|
||||
.\"
|
||||
.TH ARES_INIT 3 "7 December 2004"
|
||||
.TH ARES_INIT 3 "13 May 2008"
|
||||
.SH NAME
|
||||
ares_init, ares_init_options \- Initialize a resolver channel
|
||||
.SH SYNOPSIS
|
||||
@ -49,10 +50,22 @@ description of possible flag values.
|
||||
.B ARES_OPT_TIMEOUT
|
||||
.B int \fItimeout\fP;
|
||||
.br
|
||||
The number of seconds each name server is given to respond to a query
|
||||
on the first try. (After the first try, the timeout algorithm becomes
|
||||
more complicated, but scales linearly with the value of
|
||||
\fItimeout\fP.) The default is five seconds.
|
||||
The number of seconds each name server is given to respond to a query on the
|
||||
first try. (After the first try, the timeout algorithm becomes more
|
||||
complicated, but scales linearly with the value of \fItimeout\fP.) The
|
||||
default is five seconds. This option is being deprecated by
|
||||
\fIARES_OPT_TIMEOUTMS\fP starting in c-ares 1.5.2.
|
||||
.TP 18
|
||||
.B ARES_OPT_TIMEOUTMS
|
||||
.B int \fItimeout\fP;
|
||||
.br
|
||||
The number of milliseconds each name server is given to respond to a query on
|
||||
the first try. (After the first try, the timeout algorithm becomes more
|
||||
complicated, but scales linearly with the value of \fItimeout\fP.) The
|
||||
default is five seconds. Note that this option is specified with the same
|
||||
struct field as the former \fIARES_OPT_TIMEOUT\fP, it is but the option bits
|
||||
that tell c-ares how to interpret the number. This option was added in c-ares
|
||||
1.5.2.
|
||||
.TP 18
|
||||
.B ARES_OPT_TRIES
|
||||
.B int \fItries\fP;
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* $Id$ */
|
||||
|
||||
/* Copyright 1998 by the Massachusetts Institute of Technology.
|
||||
* Copyright (C) 2007-2008 by Daniel Stenberg
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose and without
|
||||
@ -254,13 +255,16 @@ int ares_save_options(ares_channel channel, struct ares_options *options,
|
||||
if (!ARES_CONFIG_CHECK(channel))
|
||||
return ARES_ENODATA;
|
||||
|
||||
(*optmask) = (ARES_OPT_FLAGS|ARES_OPT_TIMEOUT|ARES_OPT_TRIES|ARES_OPT_NDOTS|
|
||||
(*optmask) = (ARES_OPT_FLAGS|ARES_OPT_TRIES|ARES_OPT_NDOTS|
|
||||
ARES_OPT_UDP_PORT|ARES_OPT_TCP_PORT|ARES_OPT_SOCK_STATE_CB|
|
||||
ARES_OPT_SERVERS|ARES_OPT_DOMAINS|ARES_OPT_LOOKUPS|
|
||||
ARES_OPT_SORTLIST);
|
||||
ARES_OPT_SORTLIST|ARES_OPT_TIMEOUTMS);
|
||||
|
||||
/* Copy easy stuff */
|
||||
options->flags = channel->flags;
|
||||
|
||||
/* We return full millisecond resolution but that's only because we don't
|
||||
set the ARES_OPT_TIMEOUT anymore, only the new ARES_OPT_TIMEOUTMS */
|
||||
options->timeout = channel->timeout;
|
||||
options->tries = channel->tries;
|
||||
options->ndots = channel->ndots;
|
||||
@ -328,8 +332,10 @@ static int init_by_options(ares_channel channel,
|
||||
/* Easy stuff. */
|
||||
if ((optmask & ARES_OPT_FLAGS) && channel->flags == -1)
|
||||
channel->flags = options->flags;
|
||||
if ((optmask & ARES_OPT_TIMEOUT) && channel->timeout == -1)
|
||||
if ((optmask & ARES_OPT_TIMEOUTMS) && channel->timeout == -1)
|
||||
channel->timeout = options->timeout;
|
||||
else if ((optmask & ARES_OPT_TIMEOUT) && channel->timeout == -1)
|
||||
channel->timeout = options->timeout * 1000;
|
||||
if ((optmask & ARES_OPT_TRIES) && channel->tries == -1)
|
||||
channel->tries = options->tries;
|
||||
if ((optmask & ARES_OPT_NDOTS) && channel->ndots == -1)
|
||||
|
@ -4,6 +4,7 @@
|
||||
/* $Id$ */
|
||||
|
||||
/* Copyright 1998 by the Massachusetts Institute of Technology.
|
||||
* Copyright (C) 2004-2008 by Daniel Stenberg
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose and without
|
||||
@ -48,7 +49,7 @@
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
#define DEFAULT_TIMEOUT 5
|
||||
#define DEFAULT_TIMEOUT 5000 /* milliseconds */
|
||||
#define DEFAULT_TRIES 4
|
||||
#ifndef INADDR_NONE
|
||||
#define INADDR_NONE 0xffffffff
|
||||
@ -149,7 +150,7 @@ struct server_state {
|
||||
struct query {
|
||||
/* Query ID from qbuf, for faster lookup, and current timeout */
|
||||
unsigned short qid;
|
||||
time_t timeout;
|
||||
struct timeval timeout;
|
||||
|
||||
/*
|
||||
* Links for the doubly-linked lists in which we insert a query.
|
||||
@ -217,7 +218,7 @@ typedef struct rc4_key
|
||||
struct ares_channeldata {
|
||||
/* Configuration data */
|
||||
int flags;
|
||||
int timeout;
|
||||
int timeout; /* in milliseconds */
|
||||
int tries;
|
||||
int ndots;
|
||||
int udp_port;
|
||||
@ -242,7 +243,8 @@ struct ares_channeldata {
|
||||
/* Generation number to use for the next TCP socket open/close */
|
||||
int tcp_connection_generation;
|
||||
|
||||
/* The time at which we last called process_timeouts() */
|
||||
/* The time at which we last called process_timeouts(). Uses integer seconds
|
||||
just to draw the line somewhere. */
|
||||
time_t last_timeout_processed;
|
||||
|
||||
/* Circular, doubly-linked list of queries, bucketed various ways.... */
|
||||
@ -259,8 +261,18 @@ struct ares_channeldata {
|
||||
void *sock_state_cb_data;
|
||||
};
|
||||
|
||||
/* return true if now is exactly check time or later */
|
||||
int ares__timedout(struct timeval *now,
|
||||
struct timeval *check);
|
||||
/* add the specific number of milliseconds to the time in the first argument */
|
||||
int ares__timeadd(struct timeval *now,
|
||||
int millisecs);
|
||||
/* return time offset between now and (future) check, in milliseconds */
|
||||
int ares__timeoffset(struct timeval *now,
|
||||
struct timeval *check);
|
||||
void ares__rc4(rc4_key* key,unsigned char *buffer_ptr, int buffer_len);
|
||||
void ares__send_query(ares_channel channel, struct query *query, time_t now);
|
||||
void ares__send_query(ares_channel channel, struct query *query,
|
||||
struct timeval *now);
|
||||
void ares__close_sockets(ares_channel channel, struct server_state *server);
|
||||
int ares__get_hostent(FILE *fp, int family, struct hostent **host);
|
||||
int ares__read_line(FILE *fp, char **buf, int *bufsize);
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* $Id$ */
|
||||
|
||||
/* Copyright 1998 by the Massachusetts Institute of Technology.
|
||||
* Copyright (C) 2004-2008 by Daniel Stenberg
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose and without
|
||||
@ -42,6 +43,9 @@
|
||||
#ifdef HAVE_ARPA_NAMESER_COMPAT_H
|
||||
#include <arpa/nameser_compat.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#endif /* WIN32 && !WATT32 */
|
||||
|
||||
#ifdef HAVE_STRINGS_H
|
||||
@ -71,21 +75,25 @@
|
||||
|
||||
static int try_again(int errnum);
|
||||
static void write_tcp_data(ares_channel channel, fd_set *write_fds,
|
||||
ares_socket_t write_fd, time_t now);
|
||||
ares_socket_t write_fd, struct timeval *now);
|
||||
static void read_tcp_data(ares_channel channel, fd_set *read_fds,
|
||||
ares_socket_t read_fd, time_t now);
|
||||
ares_socket_t read_fd, struct timeval *now);
|
||||
static void read_udp_packets(ares_channel channel, fd_set *read_fds,
|
||||
ares_socket_t read_fd, time_t now);
|
||||
ares_socket_t read_fd, struct timeval *now);
|
||||
static void advance_tcp_send_queue(ares_channel channel, int whichserver,
|
||||
ssize_t num_bytes);
|
||||
static void process_timeouts(ares_channel channel, time_t now);
|
||||
static void process_broken_connections(ares_channel channel, time_t now);
|
||||
static void process_timeouts(ares_channel channel, struct timeval *now);
|
||||
static void process_broken_connections(ares_channel channel,
|
||||
struct timeval *now);
|
||||
static void process_answer(ares_channel channel, unsigned char *abuf,
|
||||
int alen, int whichserver, int tcp, time_t now);
|
||||
static void handle_error(ares_channel channel, int whichserver, time_t now);
|
||||
int alen, int whichserver, int tcp,
|
||||
struct timeval *now);
|
||||
static void handle_error(ares_channel channel, int whichserver,
|
||||
struct timeval *now);
|
||||
static void skip_server(ares_channel channel, struct query *query,
|
||||
int whichserver);
|
||||
static void next_server(ares_channel channel, struct query *query, time_t now);
|
||||
static void next_server(ares_channel channel, struct query *query,
|
||||
struct timeval *now);
|
||||
static int configure_socket(int s, ares_channel channel);
|
||||
static int open_tcp_socket(ares_channel channel, struct server_state *server);
|
||||
static int open_udp_socket(ares_channel channel, struct server_state *server);
|
||||
@ -94,19 +102,59 @@ static int same_questions(const unsigned char *qbuf, int qlen,
|
||||
static void end_query(ares_channel channel, struct query *query, int status,
|
||||
unsigned char *abuf, int alen);
|
||||
|
||||
/* return true if now is exactly check time or later */
|
||||
int ares__timedout(struct timeval *now,
|
||||
struct timeval *check)
|
||||
{
|
||||
int secs = (now->tv_sec - check->tv_sec);
|
||||
|
||||
if(secs > 0)
|
||||
return 1; /* yes, timed out */
|
||||
if(secs < -1)
|
||||
return 0; /* nope, not timed out */
|
||||
|
||||
/* if the full seconds were identical, check the sub second parts */
|
||||
return (now->tv_usec - check->tv_usec >= 0);
|
||||
}
|
||||
|
||||
/* add the specific number of milliseconds to the time in the first argument */
|
||||
int ares__timeadd(struct timeval *now,
|
||||
int millisecs)
|
||||
{
|
||||
now->tv_sec += millisecs/1000;
|
||||
now->tv_usec += (millisecs%1000)*1000;
|
||||
|
||||
if(now->tv_usec >= 1000000) {
|
||||
++(now->tv_sec);
|
||||
now->tv_usec -= 1000000;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* return time offset between now and (future) check, in milliseconds */
|
||||
int ares__timeoffset(struct timeval *now,
|
||||
struct timeval *check)
|
||||
{
|
||||
int secs = (check->tv_sec - now->tv_sec); /* this many seconds */
|
||||
int us = (check->tv_usec - now->tv_usec); /* this many microseconds */
|
||||
|
||||
return secs*1000 + us/1000; /* return them combined as milliseconds */
|
||||
}
|
||||
|
||||
|
||||
/* Something interesting happened on the wire, or there was a timeout.
|
||||
* See what's up and respond accordingly.
|
||||
*/
|
||||
void ares_process(ares_channel channel, fd_set *read_fds, fd_set *write_fds)
|
||||
{
|
||||
time_t now;
|
||||
struct timeval now = ares__tvnow();
|
||||
|
||||
time(&now);
|
||||
write_tcp_data(channel, write_fds, ARES_SOCKET_BAD, now);
|
||||
read_tcp_data(channel, read_fds, ARES_SOCKET_BAD, now);
|
||||
read_udp_packets(channel, read_fds, ARES_SOCKET_BAD, now);
|
||||
process_timeouts(channel, now);
|
||||
process_broken_connections(channel, now);
|
||||
write_tcp_data(channel, write_fds, ARES_SOCKET_BAD, &now);
|
||||
read_tcp_data(channel, read_fds, ARES_SOCKET_BAD, &now);
|
||||
read_udp_packets(channel, read_fds, ARES_SOCKET_BAD, &now);
|
||||
process_timeouts(channel, &now);
|
||||
process_broken_connections(channel, &now);
|
||||
}
|
||||
|
||||
/* Something interesting happened on the wire, or there was a timeout.
|
||||
@ -117,13 +165,12 @@ void ares_process_fd(ares_channel channel,
|
||||
file descriptors */
|
||||
ares_socket_t write_fd)
|
||||
{
|
||||
time_t now;
|
||||
struct timeval now = ares__tvnow();
|
||||
|
||||
time(&now);
|
||||
write_tcp_data(channel, NULL, write_fd, now);
|
||||
read_tcp_data(channel, NULL, read_fd, now);
|
||||
read_udp_packets(channel, NULL, read_fd, now);
|
||||
process_timeouts(channel, now);
|
||||
write_tcp_data(channel, NULL, write_fd, &now);
|
||||
read_tcp_data(channel, NULL, read_fd, &now);
|
||||
read_udp_packets(channel, NULL, read_fd, &now);
|
||||
process_timeouts(channel, &now);
|
||||
}
|
||||
|
||||
|
||||
@ -158,7 +205,7 @@ static int try_again(int errnum)
|
||||
static void write_tcp_data(ares_channel channel,
|
||||
fd_set *write_fds,
|
||||
ares_socket_t write_fd,
|
||||
time_t now)
|
||||
struct timeval *now)
|
||||
{
|
||||
struct server_state *server;
|
||||
struct send_request *sendreq;
|
||||
@ -177,7 +224,8 @@ static void write_tcp_data(ares_channel channel,
|
||||
/* Make sure server has data to send and is selected in write_fds or
|
||||
write_fd. */
|
||||
server = &channel->servers[i];
|
||||
if (!server->qhead || server->tcp_socket == ARES_SOCKET_BAD || server->is_broken)
|
||||
if (!server->qhead || server->tcp_socket == ARES_SOCKET_BAD ||
|
||||
server->is_broken)
|
||||
continue;
|
||||
|
||||
if(write_fds) {
|
||||
@ -281,7 +329,7 @@ static void advance_tcp_send_queue(ares_channel channel, int whichserver,
|
||||
* a packet if we finish reading one.
|
||||
*/
|
||||
static void read_tcp_data(ares_channel channel, fd_set *read_fds,
|
||||
ares_socket_t read_fd, time_t now)
|
||||
ares_socket_t read_fd, struct timeval *now)
|
||||
{
|
||||
struct server_state *server;
|
||||
int i;
|
||||
@ -377,7 +425,7 @@ static void read_tcp_data(ares_channel channel, fd_set *read_fds,
|
||||
|
||||
/* If any UDP sockets select true for reading, process them. */
|
||||
static void read_udp_packets(ares_channel channel, fd_set *read_fds,
|
||||
ares_socket_t read_fd, time_t now)
|
||||
ares_socket_t read_fd, struct timeval *now)
|
||||
{
|
||||
struct server_state *server;
|
||||
int i;
|
||||
@ -428,7 +476,7 @@ static void read_udp_packets(ares_channel channel, fd_set *read_fds,
|
||||
}
|
||||
|
||||
/* If any queries have timed out, note the timeout and move them on. */
|
||||
static void process_timeouts(ares_channel channel, time_t now)
|
||||
static void process_timeouts(ares_channel channel, struct timeval *now)
|
||||
{
|
||||
time_t t; /* the time of the timeouts we're processing */
|
||||
struct query *query;
|
||||
@ -441,14 +489,14 @@ static void process_timeouts(ares_channel channel, time_t now)
|
||||
* only a handful of requests that fall into the "now" bucket, so
|
||||
* this should be quite quick.
|
||||
*/
|
||||
for (t = channel->last_timeout_processed; t <= now; t++)
|
||||
for (t = channel->last_timeout_processed; t <= now->tv_sec; t++)
|
||||
{
|
||||
list_head = &(channel->queries_by_timeout[t % ARES_TIMEOUT_TABLE_SIZE]);
|
||||
for (list_node = list_head->next; list_node != list_head; )
|
||||
{
|
||||
query = list_node->data;
|
||||
list_node = list_node->next; /* in case the query gets deleted */
|
||||
if (query->timeout != 0 && now >= query->timeout)
|
||||
if (query->timeout.tv_sec && ares__timedout(now, &query->timeout))
|
||||
{
|
||||
query->error_status = ARES_ETIMEOUT;
|
||||
++query->timeouts;
|
||||
@ -456,12 +504,13 @@ static void process_timeouts(ares_channel channel, time_t now)
|
||||
}
|
||||
}
|
||||
}
|
||||
channel->last_timeout_processed = now;
|
||||
channel->last_timeout_processed = now->tv_sec;
|
||||
}
|
||||
|
||||
/* Handle an answer from a server. */
|
||||
static void process_answer(ares_channel channel, unsigned char *abuf,
|
||||
int alen, int whichserver, int tcp, time_t now)
|
||||
int alen, int whichserver, int tcp,
|
||||
struct timeval *now)
|
||||
{
|
||||
int tc, rcode;
|
||||
unsigned short id;
|
||||
@ -539,7 +588,8 @@ static void process_answer(ares_channel channel, unsigned char *abuf,
|
||||
}
|
||||
|
||||
/* Close all the connections that are no longer usable. */
|
||||
static void process_broken_connections(ares_channel channel, time_t now)
|
||||
static void process_broken_connections(ares_channel channel,
|
||||
struct timeval *now)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < channel->nservers; i++)
|
||||
@ -552,7 +602,8 @@ static void process_broken_connections(ares_channel channel, time_t now)
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_error(ares_channel channel, int whichserver, time_t now)
|
||||
static void handle_error(ares_channel channel, int whichserver,
|
||||
struct timeval *now)
|
||||
{
|
||||
struct server_state *server;
|
||||
struct query *query;
|
||||
@ -603,7 +654,8 @@ static void skip_server(ares_channel channel, struct query *query,
|
||||
}
|
||||
}
|
||||
|
||||
static void next_server(ares_channel channel, struct query *query, time_t now)
|
||||
static void next_server(ares_channel channel, struct query *query,
|
||||
struct timeval *now)
|
||||
{
|
||||
/* Advance to the next server or try. */
|
||||
query->server++;
|
||||
@ -640,7 +692,8 @@ static void next_server(ares_channel channel, struct query *query, time_t now)
|
||||
end_query(channel, query, query->error_status, NULL, 0);
|
||||
}
|
||||
|
||||
void ares__send_query(ares_channel channel, struct query *query, time_t now)
|
||||
void ares__send_query(ares_channel channel, struct query *query,
|
||||
struct timeval *now)
|
||||
{
|
||||
struct send_request *sendreq;
|
||||
struct server_state *server;
|
||||
@ -707,16 +760,17 @@ void ares__send_query(ares_channel channel, struct query *query, time_t now)
|
||||
return;
|
||||
}
|
||||
}
|
||||
query->timeout = now
|
||||
+ ((query->try == 0) ? channel->timeout
|
||||
: channel->timeout << query->try / channel->nservers);
|
||||
query->timeout = *now;
|
||||
ares__timeadd(&query->timeout,
|
||||
(query->try == 0) ? channel->timeout
|
||||
: channel->timeout << query->try / channel->nservers);
|
||||
/* Keep track of queries bucketed by timeout, so we can process
|
||||
* timeout events quickly.
|
||||
*/
|
||||
ares__remove_from_list(&(query->queries_by_timeout));
|
||||
ares__insert_in_list(
|
||||
&(query->queries_by_timeout),
|
||||
&(channel->queries_by_timeout[query->timeout %
|
||||
&(channel->queries_by_timeout[query->timeout.tv_sec %
|
||||
ARES_TIMEOUT_TABLE_SIZE]));
|
||||
|
||||
/* Keep track of queries bucketed by server, so we can process server
|
||||
|
@ -39,7 +39,7 @@ void ares_send(ares_channel channel, const unsigned char *qbuf, int qlen,
|
||||
{
|
||||
struct query *query;
|
||||
int i;
|
||||
time_t now;
|
||||
struct timeval now;
|
||||
|
||||
/* Verify that the query is at least long enough to hold the header. */
|
||||
if (qlen < HFIXEDSZ || qlen >= (1 << 16))
|
||||
@ -74,7 +74,7 @@ void ares_send(ares_channel channel, const unsigned char *qbuf, int qlen,
|
||||
|
||||
/* Compute the query ID. Start with no timeout. */
|
||||
query->qid = (unsigned short)DNS_HEADER_QID(qbuf);
|
||||
query->timeout = 0;
|
||||
query->timeout.tv_sec = query->timeout.tv_usec = 0;
|
||||
|
||||
/* Form the TCP query buffer by prepending qlen (as two
|
||||
* network-order bytes) to qbuf.
|
||||
@ -107,17 +107,17 @@ void ares_send(ares_channel channel, const unsigned char *qbuf, int qlen,
|
||||
ares__init_list_node(&(query->queries_by_timeout), query);
|
||||
ares__init_list_node(&(query->queries_to_server), query);
|
||||
ares__init_list_node(&(query->all_queries), query);
|
||||
|
||||
|
||||
/* Chain the query into the list of all queries. */
|
||||
ares__insert_in_list(&(query->all_queries), &(channel->all_queries));
|
||||
/* Keep track of queries bucketed by qid, so we can process DNS
|
||||
* responses quickly.
|
||||
*/
|
||||
ares__insert_in_list(
|
||||
&(query->queries_by_qid),
|
||||
&(channel->queries_by_qid[query->qid % ARES_QID_TABLE_SIZE]));
|
||||
&(query->queries_by_qid),
|
||||
&(channel->queries_by_qid[query->qid % ARES_QID_TABLE_SIZE]));
|
||||
|
||||
/* Perform the first query action. */
|
||||
time(&now);
|
||||
ares__send_query(channel, query, now);
|
||||
now = ares__tvnow();
|
||||
ares__send_query(channel, query, &now);
|
||||
}
|
||||
|
@ -37,16 +37,16 @@ struct timeval *ares_timeout(ares_channel channel, struct timeval *maxtv,
|
||||
struct query *query;
|
||||
struct list_node* list_head;
|
||||
struct list_node* list_node;
|
||||
time_t now;
|
||||
time_t offset, min_offset; /* these use time_t since some 32 bit systems
|
||||
still use 64 bit time_t! (like VS2005) */
|
||||
struct timeval now;
|
||||
struct timeval nextstop;
|
||||
long offset, min_offset;
|
||||
|
||||
/* No queries, no timeout (and no fetch of the current time). */
|
||||
if (ares__is_list_empty(&(channel->all_queries)))
|
||||
return maxtv;
|
||||
|
||||
/* Find the minimum timeout for the current set of queries. */
|
||||
time(&now);
|
||||
now = ares__tvnow();
|
||||
min_offset = -1;
|
||||
|
||||
list_head = &(channel->all_queries);
|
||||
@ -54,23 +54,26 @@ struct timeval *ares_timeout(ares_channel channel, struct timeval *maxtv,
|
||||
list_node = list_node->next)
|
||||
{
|
||||
query = list_node->data;
|
||||
if (query->timeout == 0)
|
||||
if (query->timeout.tv_sec == 0)
|
||||
continue;
|
||||
offset = query->timeout - now;
|
||||
offset = ares__timeoffset(&now, &query->timeout);
|
||||
if (offset < 0)
|
||||
offset = 0;
|
||||
if (min_offset == -1 || offset < min_offset)
|
||||
min_offset = offset;
|
||||
}
|
||||
|
||||
/* If we found a minimum timeout and it's sooner than the one
|
||||
* specified in maxtv (if any), return it. Otherwise go with
|
||||
* maxtv.
|
||||
if(min_offset != -1) {
|
||||
nextstop = now;
|
||||
ares__timeadd(&now, min_offset);
|
||||
}
|
||||
|
||||
/* If we found a minimum timeout and it's sooner than the one specified in
|
||||
* maxtv (if any), return it. Otherwise go with maxtv.
|
||||
*/
|
||||
if (min_offset != -1 && (!maxtv || min_offset <= maxtv->tv_sec))
|
||||
if (min_offset != -1 && (!maxtv || ares__timedout(maxtv, &nextstop)))
|
||||
{
|
||||
tvbuf->tv_sec = (long)min_offset;
|
||||
tvbuf->tv_usec = 0;
|
||||
*tvbuf = nextstop;
|
||||
return tvbuf;
|
||||
}
|
||||
else
|
||||
|
Loading…
Reference in New Issue
Block a user