Fix windows y2k38 issue by creating our own timeval datatype (#772)

As per Issue #760, the use of `struct timeval` is meant for only time
differentials, however it could be used to denote an exact timeout. This
could lead to y2k38 issues on some platforms.

Fixes Issue #760
Fix By: Brad House (@bradh352)
pull/774/head
Brad House 6 months ago committed by GitHub
parent 819cda99a3
commit f70f09f01c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 2
      src/lib/ares__close_sockets.c
  2. 14
      src/lib/ares__threads.c
  3. 89
      src/lib/ares__timeval.c
  4. 8
      src/lib/ares_init.c
  5. 48
      src/lib/ares_private.h
  6. 52
      src/lib/ares_process.c
  7. 18
      src/lib/ares_qcache.c
  8. 6
      src/lib/ares_rand.c
  9. 6
      src/lib/ares_send.c
  10. 59
      src/lib/ares_timeout.c
  11. 4
      src/lib/ares_update_servers.c
  12. 38
      test/ares-test.cc

@ -34,7 +34,7 @@
static void ares__requeue_queries(struct server_connection *conn)
{
struct query *query;
struct timeval now = ares__tvnow();
ares_timeval_t now = ares__tvnow();
while ((query = ares__llist_first_val(conn->queries_to_conn)) != NULL) {
ares__requeue_query(query, &now);

@ -551,7 +551,7 @@ void ares__channel_unlock(const ares_channel_t *channel)
ares_status_t ares_queue_wait_empty(ares_channel_t *channel, int timeout_ms)
{
ares_status_t status = ARES_SUCCESS;
struct timeval tout;
ares_timeval_t tout;
if (!ares_threadsafety()) {
return ARES_ENOTIMP;
@ -563,8 +563,8 @@ ares_status_t ares_queue_wait_empty(ares_channel_t *channel, int timeout_ms)
if (timeout_ms >= 0) {
tout = ares__tvnow();
tout.tv_sec += timeout_ms / 1000;
tout.tv_usec += (timeout_ms % 1000) * 1000;
tout.sec += (ares_int64_t)(timeout_ms / 1000);
tout.usec += (unsigned int)(timeout_ms % 1000) * 1000;
}
ares__thread_mutex_lock(channel->lock);
@ -572,13 +572,13 @@ ares_status_t ares_queue_wait_empty(ares_channel_t *channel, int timeout_ms)
if (timeout_ms < 0) {
ares__thread_cond_wait(channel->cond_empty, channel->lock);
} else {
struct timeval tv_remaining;
struct timeval tv_now = ares__tvnow();
ares_timeval_t tv_remaining;
ares_timeval_t tv_now = ares__tvnow();
unsigned long tms;
ares__timeval_remaining(&tv_remaining, &tv_now, &tout);
tms = (unsigned long)((tv_remaining.tv_sec * 1000) +
(tv_remaining.tv_usec / 1000));
tms = (unsigned long)((tv_remaining.sec * 1000) +
(tv_remaining.usec / 1000));
if (tms == 0) {
status = ARES_ETIMEOUT;
} else {

@ -30,79 +30,62 @@
#if defined(WIN32) && !defined(MSDOS)
struct timeval ares__tvnow(void)
ares_timeval_t ares__tvnow(void)
{
/*
** GetTickCount() is available on _all_ Windows versions from W95 up
** to nowadays. Returns milliseconds elapsed since last system boot,
** increases monotonically and wraps once 49.7 days have elapsed.
*/
struct timeval now;
/* GetTickCount() is available on _all_ Windows versions from W95 up
* to nowadays. Returns milliseconds elapsed since last system boot,
* increases monotonically and wraps once 49.7 days have elapsed. */
ares_timeval_t now;
DWORD milliseconds = GetTickCount();
now.tv_sec = (long)milliseconds / 1000;
now.tv_usec = (long)(milliseconds % 1000) * 1000;
now.sec = (ares_int64_t)milliseconds / 1000;
now.usec = (unsigned int)(milliseconds % 1000) * 1000;
return now;
}
#elif defined(HAVE_CLOCK_GETTIME_MONOTONIC)
struct timeval ares__tvnow(void)
ares_timeval_t ares__tvnow(void)
{
/*
** clock_gettime() is granted to be increased monotonically when the
** monotonic clock is queried. Time starting point is unspecified, it
** could be the system start-up time, the Epoch, or something else,
** in any case the time starting point does not change once that the
** system has started up.
*/
struct timeval now;
/* clock_gettime() is guaranteed to be increased monotonically when the
* monotonic clock is queried. Time starting point is unspecified, it
* could be the system start-up time, the Epoch, or something else,
* in any case the time starting point does not change once that the
* system has started up. */
ares_timeval_t now;
struct timespec tsnow;
if (0 == clock_gettime(CLOCK_MONOTONIC, &tsnow)) {
now.tv_sec = tsnow.tv_sec;
now.tv_usec = (int)(tsnow.tv_nsec / 1000);
}
/*
** Even when the configure process has truly detected monotonic clock
** availability, it might happen that it is not actually available at
** run-time. When this occurs simply fallback to other time source.
*/
# ifdef HAVE_GETTIMEOFDAY
else
(void)gettimeofday(&now, NULL); /* LCOV_EXCL_LINE */
# else
else {
now.tv_sec = (long)time(NULL);
now.tv_usec = 0;
if (clock_gettime(CLOCK_MONOTONIC, &tsnow) == 0) {
now.sec = (ares_int64_t)tsnow.tv_sec;
now.usec = (unsigned int)(tsnow.tv_nsec / 1000);
} else {
struct timeval tv;
(void)gettimeofday(&tv, NULL);
now.sec = (ares_int64_t)tv.tv_sec;
now.usec = (unsigned int)tv.tv_usec;
}
# endif
return now;
}
#elif defined(HAVE_GETTIMEOFDAY)
struct timeval ares__tvnow(void)
ares_timeval_t ares__tvnow(void)
{
/*
** gettimeofday() is not granted to be increased monotonically, due to
** clock drifting and external source time synchronization it can jump
** forward or backward in time.
*/
struct timeval now;
(void)gettimeofday(&now, NULL);
/* gettimeofday() is not granted to be increased monotonically, due to
* clock drifting and external source time synchronization it can jump
* forward or backward in time. */
ares_timeval_t now;
struct timeval tv;
(void)gettimeofday(&tv, NULL);
now.sec = (ares_int64_t)tv.tv_sec;
now.usec = (unsigned int)tv.tv_usec;
return now;
}
#else
struct timeval ares__tvnow(void)
{
/*
** time() returns the value of time in seconds since the Epoch.
*/
struct timeval now;
now.tv_sec = (long)time(NULL);
now.tv_usec = 0;
return now;
}
# error missing sub-second time retrieval function
#endif

@ -82,17 +82,17 @@ static int ares_query_timeout_cmp_cb(const void *arg1, const void *arg2)
const struct query *q1 = arg1;
const struct query *q2 = arg2;
if (q1->timeout.tv_sec > q2->timeout.tv_sec) {
if (q1->timeout.sec > q2->timeout.sec) {
return 1;
}
if (q1->timeout.tv_sec < q2->timeout.tv_sec) {
if (q1->timeout.sec < q2->timeout.sec) {
return -1;
}
if (q1->timeout.tv_usec > q2->timeout.tv_usec) {
if (q1->timeout.usec > q2->timeout.usec) {
return 1;
}
if (q1->timeout.tv_usec < q2->timeout.tv_usec) {
if (q1->timeout.usec < q2->timeout.usec) {
return -1;
}

@ -167,6 +167,22 @@ struct server_connection {
ares__llist_t *queries_to_conn;
};
#ifdef _MSC_VER
typedef __int64 ares_int64_t;
typedef unsigned __int64 ares_uint64_t;
#else
typedef long long ares_int64_t;
typedef unsigned long long ares_uint64_t;
#endif
/*! struct timeval on some systems like Windows doesn't support 64bit time so
* therefore can't be used due to Y2K38 issues. Make our own that does have
* 64bit time. */
typedef struct {
ares_int64_t sec; /*!< Seconds */
unsigned int usec; /*!< Microseconds. Can't be negative. */
} ares_timeval_t;
struct server_state {
/* Configuration */
size_t idx; /* index for server in system configuration */
@ -183,7 +199,7 @@ struct server_state {
struct server_connection *tcp_conn;
/* The next time when we will retry this server if it has hit failures */
struct timeval next_retry_time;
ares_timeval_t next_retry_time;
/* TCP buffer since multiple responses can come back in one read, or partial
* in a read */
@ -200,7 +216,7 @@ struct server_state {
struct query {
/* Query ID from qbuf, for faster lookup, and current timeout */
unsigned short qid; /* host byte order */
struct timeval timeout;
ares_timeval_t timeout;
ares_channel_t *channel;
/*
@ -358,12 +374,12 @@ void *ares_malloc_zero(size_t size);
void *ares_realloc_zero(void *ptr, size_t orig_size, size_t new_size);
/* return true if now is exactly check time or later */
ares_bool_t ares__timedout(const struct timeval *now,
const struct timeval *check);
ares_bool_t ares__timedout(const ares_timeval_t *now,
const ares_timeval_t *check);
/* Returns one of the normal ares status codes like ARES_SUCCESS */
ares_status_t ares__send_query(struct query *query, struct timeval *now);
ares_status_t ares__requeue_query(struct query *query, struct timeval *now);
ares_status_t ares__send_query(struct query *query, const ares_timeval_t *now);
ares_status_t ares__requeue_query(struct query *query, const ares_timeval_t *now);
/*! Retrieve a list of names to use for searching. The first successful
* query in the list wins. This function also uses the HOSTSALIASES file
@ -402,10 +418,10 @@ void ares__destroy_rand_state(ares_rand_state *state);
void ares__rand_bytes(ares_rand_state *state, unsigned char *buf, size_t len);
unsigned short ares__generate_new_id(ares_rand_state *state);
struct timeval ares__tvnow(void);
void ares__timeval_remaining(struct timeval *remaining,
const struct timeval *now,
const struct timeval *tout);
ares_timeval_t ares__tvnow(void);
void ares__timeval_remaining(ares_timeval_t *remaining,
const ares_timeval_t *now,
const ares_timeval_t *tout);
ares_status_t ares__expand_name_validated(const unsigned char *encoded,
const unsigned char *abuf,
size_t alen, char **s, size_t *enclen,
@ -640,11 +656,11 @@ ares_status_t ares__qcache_create(ares_rand_state *rand_state,
ares__qcache_t **cache_out);
void ares__qcache_flush(ares__qcache_t *cache);
ares_status_t ares_qcache_insert(ares_channel_t *channel,
const struct timeval *now,
const ares_timeval_t *now,
const struct query *query,
ares_dns_record_t *dnsrec);
ares_status_t ares_qcache_fetch(ares_channel_t *channel,
const struct timeval *now,
const ares_timeval_t *now,
const ares_dns_record_t *dnsrec,
const ares_dns_record_t **dnsrec_resp);
@ -660,14 +676,6 @@ void ares_event_thread_destroy(ares_channel_t *channel);
ares_status_t ares_event_thread_init(ares_channel_t *channel);
#ifdef _MSC_VER
typedef __int64 ares_int64_t;
typedef unsigned __int64 ares_uint64_t;
#else
typedef long long ares_int64_t;
typedef unsigned long long ares_uint64_t;
#endif
#ifdef _WIN32
# define HOSTENT_ADDRTYPE_TYPE short
# define HOSTENT_LENGTH_TYPE short

@ -50,17 +50,17 @@
#include "ares_nameser.h"
#include "ares_dns.h"
static void timeadd(struct timeval *now, size_t millisecs);
static void timeadd(ares_timeval_t *now, size_t millisecs);
static ares_bool_t try_again(int errnum);
static void write_tcp_data(ares_channel_t *channel, fd_set *write_fds,
ares_socket_t write_fd);
static void read_packets(ares_channel_t *channel, fd_set *read_fds,
ares_socket_t read_fd, struct timeval *now);
static void process_timeouts(ares_channel_t *channel, struct timeval *now);
ares_socket_t read_fd, ares_timeval_t *now);
static void process_timeouts(ares_channel_t *channel, ares_timeval_t *now);
static ares_status_t process_answer(ares_channel_t *channel,
const unsigned char *abuf, size_t alen,
struct server_connection *conn,
ares_bool_t tcp, struct timeval *now);
ares_bool_t tcp, ares_timeval_t *now);
static void handle_conn_error(struct server_connection *conn,
ares_bool_t critical_failure);
@ -111,7 +111,7 @@ static void server_increment_failures(struct server_state *server,
{
ares__slist_node_t *node;
const ares_channel_t *channel = server->channel;
struct timeval next_retry_time;
ares_timeval_t next_retry_time;
node = ares__slist_node_find(channel->servers, server);
if (node == NULL) {
@ -145,8 +145,8 @@ static void server_set_good(struct server_state *server, ares_bool_t used_tcp)
ares__slist_node_reinsert(node);
}
server->next_retry_time.tv_sec = 0;
server->next_retry_time.tv_usec = 0;
server->next_retry_time.sec = 0;
server->next_retry_time.usec = 0;
invoke_server_state_cb(server, ARES_TRUE,
used_tcp == ARES_TRUE ? ARES_SERV_STATE_TCP
@ -154,10 +154,10 @@ static void server_set_good(struct server_state *server, ares_bool_t used_tcp)
}
/* return true if now is exactly check time or later */
ares_bool_t ares__timedout(const struct timeval *now,
const struct timeval *check)
ares_bool_t ares__timedout(const ares_timeval_t *now,
const ares_timeval_t *check)
{
ares_int64_t secs = ((ares_int64_t)now->tv_sec - (ares_int64_t)check->tv_sec);
ares_int64_t secs = (now->sec - check->sec);
if (secs > 0) {
return ARES_TRUE; /* yes, timed out */
@ -167,20 +167,20 @@ ares_bool_t ares__timedout(const struct timeval *now,
}
/* if the full seconds were identical, check the sub second parts */
return ((ares_int64_t)now->tv_usec - (ares_int64_t)check->tv_usec) >= 0
return ((ares_int64_t)now->usec - (ares_int64_t)check->usec) >= 0
? ARES_TRUE
: ARES_FALSE;
}
/* add the specific number of milliseconds to the time in the first argument */
static void timeadd(struct timeval *now, size_t millisecs)
static void timeadd(ares_timeval_t *now, size_t millisecs)
{
now->tv_sec += (time_t)millisecs / 1000;
now->tv_usec += (time_t)((millisecs % 1000) * 1000);
now->sec += (ares_int64_t)millisecs / 1000;
now->usec += (unsigned int)((millisecs % 1000) * 1000);
if (now->tv_usec >= 1000000) {
++(now->tv_sec);
now->tv_usec -= 1000000;
if (now->usec >= 1000000) {
now->sec += now->usec / 1000000;
now->usec %= 1000000;
}
}
@ -191,7 +191,7 @@ static void processfds(ares_channel_t *channel, fd_set *read_fds,
ares_socket_t read_fd, fd_set *write_fds,
ares_socket_t write_fd)
{
struct timeval now;
ares_timeval_t now;
if (channel == NULL) {
return;
@ -324,7 +324,7 @@ static void write_tcp_data(ares_channel_t *channel, fd_set *write_fds,
* a packet if we finish reading one.
*/
static void read_tcp_data(ares_channel_t *channel,
struct server_connection *conn, struct timeval *now)
struct server_connection *conn, ares_timeval_t *now)
{
ares_ssize_t count;
struct server_state *server = conn->server;
@ -463,7 +463,7 @@ fail:
/* If any UDP sockets select true for reading, process them. */
static void read_udp_packets_fd(ares_channel_t *channel,
struct server_connection *conn,
struct timeval *now)
ares_timeval_t *now)
{
ares_ssize_t read_len;
unsigned char buf[MAXENDSSZ + 1];
@ -527,7 +527,7 @@ static void read_udp_packets_fd(ares_channel_t *channel,
}
static void read_packets(ares_channel_t *channel, fd_set *read_fds,
ares_socket_t read_fd, struct timeval *now)
ares_socket_t read_fd, ares_timeval_t *now)
{
size_t i;
ares_socket_t *socketlist = NULL;
@ -594,7 +594,7 @@ static void read_packets(ares_channel_t *channel, fd_set *read_fds,
}
/* If any queries have timed out, note the timeout and move them on. */
static void process_timeouts(ares_channel_t *channel, struct timeval *now)
static void process_timeouts(ares_channel_t *channel, ares_timeval_t *now)
{
ares__slist_node_t *node =
ares__slist_node_first(channel->queries_by_timeout);
@ -667,7 +667,7 @@ done:
static ares_status_t process_answer(ares_channel_t *channel,
const unsigned char *abuf, size_t alen,
struct server_connection *conn,
ares_bool_t tcp, struct timeval *now)
ares_bool_t tcp, ares_timeval_t *now)
{
struct query *query;
/* Cache these as once ares__send_query() gets called, it may end up
@ -814,7 +814,7 @@ static void handle_conn_error(struct server_connection *conn,
ares__close_connection(conn);
}
ares_status_t ares__requeue_query(struct query *query, struct timeval *now)
ares_status_t ares__requeue_query(struct query *query, const ares_timeval_t *now)
{
ares_channel_t *channel = query->channel;
size_t max_tries = ares__slist_len(channel->servers) * channel->tries;
@ -912,7 +912,7 @@ static struct server_state *ares__failover_server(ares_channel_t *channel)
ares__rand_bytes(channel->rand_state, (unsigned char *)&r, sizeof(r));
if (r % channel->server_retry_chance == 0) {
/* Select a suitable failed server to retry. */
struct timeval now = ares__tvnow();
ares_timeval_t now = ares__tvnow();
ares__slist_node_t *node;
for (node = ares__slist_node_first(channel->servers); node != NULL;
node = ares__slist_node_next(node)) {
@ -989,7 +989,7 @@ static size_t ares__calc_query_timeout(const struct query *query)
return timeplus;
}
ares_status_t ares__send_query(struct query *query, struct timeval *now)
ares_status_t ares__send_query(struct query *query, const ares_timeval_t *now)
{
ares_channel_t *channel = query->channel;
struct server_state *server;

@ -137,7 +137,7 @@ fail:
}
static void ares__qcache_expire(ares__qcache_t *cache,
const struct timeval *now)
const ares_timeval_t *now)
{
ares__slist_node_t *node;
@ -147,7 +147,7 @@ static void ares__qcache_expire(ares__qcache_t *cache,
while ((node = ares__slist_node_first(cache->expire)) != NULL) {
const ares__qcache_entry_t *entry = ares__slist_node_val(node);
if (entry->expire_ts > now->tv_sec) {
if (entry->expire_ts > now->sec) {
break;
}
@ -158,7 +158,7 @@ static void ares__qcache_expire(ares__qcache_t *cache,
void ares__qcache_flush(ares__qcache_t *cache)
{
struct timeval now;
ares_timeval_t now;
memset(&now, 0, sizeof(now));
ares__qcache_expire(cache, &now);
}
@ -319,7 +319,7 @@ done:
static ares_status_t ares__qcache_insert(ares__qcache_t *qcache,
ares_dns_record_t *dnsrec,
const unsigned char *qbuf, size_t qlen,
const struct timeval *now)
const ares_timeval_t *now)
{
ares__qcache_entry_t *entry;
unsigned int ttl;
@ -362,8 +362,8 @@ static ares_status_t ares__qcache_insert(ares__qcache_t *qcache,
}
entry->dnsrec = dnsrec;
entry->expire_ts = now->tv_sec + (time_t)ttl;
entry->insert_ts = now->tv_sec;
entry->expire_ts = now->sec + (time_t)ttl;
entry->insert_ts = now->sec;
/* We can't guarantee the server responded with the same flags as the
* request had, so we have to re-parse the request in order to generate the
@ -394,7 +394,7 @@ fail:
}
ares_status_t ares_qcache_fetch(ares_channel_t *channel,
const struct timeval *now,
const ares_timeval_t *now,
const ares_dns_record_t *dnsrec,
const ares_dns_record_t **dnsrec_resp)
{
@ -425,7 +425,7 @@ ares_status_t ares_qcache_fetch(ares_channel_t *channel,
}
ares_dns_record_write_ttl_decrement(
entry->dnsrec, (unsigned int)(now->tv_sec - entry->insert_ts));
entry->dnsrec, (unsigned int)(now->sec - entry->insert_ts));
*dnsrec_resp = entry->dnsrec;
@ -435,7 +435,7 @@ done:
}
ares_status_t ares_qcache_insert(ares_channel_t *channel,
const struct timeval *now,
const ares_timeval_t *now,
const struct query *query,
ares_dns_record_t *dnsrec)
{

@ -70,7 +70,7 @@ static void ares_rc4_generate_key(ares_rand_rc4 *rc4_state, unsigned char *key,
size_t i;
size_t len = 0;
unsigned int data;
struct timeval tv;
ares_timeval_t tv;
if (key_len != ARES_RC4_KEY_LEN) {
return;
@ -89,12 +89,12 @@ static void ares_rc4_generate_key(ares_rand_rc4 *rc4_state, unsigned char *key,
len += sizeof(data);
tv = ares__tvnow();
data = (unsigned int)((tv.tv_sec | tv.tv_usec) & 0xFFFFFFFF);
data = (unsigned int)((tv.sec | tv.usec) & 0xFFFFFFFF);
memcpy(key + len, &data, sizeof(data));
len += sizeof(data);
srand(ares_u32_from_ptr(rc4_state) | ares_u32_from_ptr(&i) |
(unsigned int)((tv.tv_sec | tv.tv_usec) & 0xFFFFFFFF));
(unsigned int)((tv.sec | tv.usec) & 0xFFFFFFFF));
for (i = len; i < key_len; i++) {
key[i] = (unsigned char)(rand() % 256); /* LCOV_EXCL_LINE */

@ -55,7 +55,7 @@ static ares_status_t ares_send_dnsrec_int(ares_channel_t *channel,
{
struct query *query;
size_t packetsz;
struct timeval now = ares__tvnow();
ares_timeval_t now = ares__tvnow();
ares_status_t status;
unsigned short id = generate_unique_qid(channel);
const ares_dns_record_t *dnsrec_resp = NULL;
@ -92,8 +92,8 @@ static ares_status_t ares_send_dnsrec_int(ares_channel_t *channel,
}
query->qid = id;
query->timeout.tv_sec = 0;
query->timeout.tv_usec = 0;
query->timeout.sec = 0;
query->timeout.usec = 0;
/* Ignore first 2 bytes, assign our own query id */
query->qbuf[0] = (unsigned char)((id >> 8) & 0xFF);

@ -34,62 +34,89 @@
#include "ares.h"
#include "ares_private.h"
void ares__timeval_remaining(struct timeval *remaining,
const struct timeval *now,
const struct timeval *tout)
void ares__timeval_remaining(ares_timeval_t *remaining,
const ares_timeval_t *now,
const ares_timeval_t *tout)
{
memset(remaining, 0, sizeof(*remaining));
/* Expired! */
if (tout->tv_sec < now->tv_sec ||
(tout->tv_sec == now->tv_sec && tout->tv_usec < now->tv_usec)) {
if (tout->sec < now->sec ||
(tout->sec == now->sec && tout->usec < now->usec)) {
return;
}
remaining->tv_sec = tout->tv_sec - now->tv_sec;
if (tout->tv_usec < now->tv_usec) {
remaining->tv_sec -= 1;
remaining->tv_usec = (tout->tv_usec + 1000000) - now->tv_usec;
remaining->sec = tout->sec - now->sec;
if (tout->usec < now->usec) {
remaining->sec -= 1;
remaining->usec = (tout->usec + 1000000) - now->usec;
} else {
remaining->tv_usec = tout->tv_usec - now->tv_usec;
remaining->usec = tout->usec - now->usec;
}
}
static struct timeval ares_timeval_to_struct_timeval(const ares_timeval_t *atv)
{
struct timeval tv;
tv.tv_sec = (time_t)atv->sec;
tv.tv_usec = (int)atv->usec;
return tv;
}
static ares_timeval_t struct_timeval_to_ares_timeval(const struct timeval *tv)
{
ares_timeval_t atv;
atv.sec = (ares_int64_t)tv->tv_sec;
atv.usec = (unsigned int)tv->tv_usec;
return atv;
}
struct timeval *ares_timeout(const ares_channel_t *channel,
struct timeval *maxtv, struct timeval *tvbuf)
{
const struct query *query;
ares__slist_node_t *node;
struct timeval now;
ares_timeval_t now;
ares_timeval_t atvbuf;
ares_timeval_t amaxtv;
/* The minimum timeout of all queries is always the first entry in
* channel->queries_by_timeout */
node = ares__slist_node_first(channel->queries_by_timeout);
/* no queries/timeout */
if (node == NULL) {
return maxtv; /* <-- maxtv can be null though, hrm */
return maxtv;
}
query = ares__slist_node_val(node);
now = ares__tvnow();
ares__timeval_remaining(tvbuf, &now, &query->timeout);
ares__timeval_remaining(&atvbuf, &now, &query->timeout);
*tvbuf = ares_timeval_to_struct_timeval(&atvbuf);
if (maxtv == NULL) {
return tvbuf;
}
/* Return the minimum time between maxtv and tvbuf */
amaxtv = struct_timeval_to_ares_timeval(maxtv);
if (tvbuf->tv_sec > maxtv->tv_sec) {
if (atvbuf.sec > amaxtv.sec) {
return maxtv;
}
if (tvbuf->tv_sec < maxtv->tv_sec) {
if (atvbuf.sec < amaxtv.sec) {
return tvbuf;
}
if (tvbuf->tv_usec > maxtv->tv_usec) {
if (atvbuf.usec > amaxtv.usec) {
return maxtv;
}

@ -593,8 +593,8 @@ static ares_status_t ares__server_create(ares_channel_t *channel,
server->udp_port = ares__sconfig_get_port(channel, sconfig, ARES_FALSE);
server->tcp_port = ares__sconfig_get_port(channel, sconfig, ARES_TRUE);
server->addr.family = sconfig->addr.family;
server->next_retry_time.tv_sec = 0;
server->next_retry_time.tv_usec = 0;
server->next_retry_time.sec = 0;
server->next_retry_time.usec = 0;
if (sconfig->addr.family == AF_INET) {
memcpy(&server->addr.addr.addr4, &sconfig->addr.addr.addr4,

38
test/ares-test.cc vendored

@ -257,13 +257,13 @@ void ProcessWork(ares_channel_t *channel,
fd_set readers, writers;
#ifndef CARES_SYMBOL_HIDING
struct timeval tv_begin = ares__tvnow();
struct timeval tv_cancel = tv_begin;
ares_timeval_t tv_begin = ares__tvnow();
ares_timeval_t tv_cancel = tv_begin;
if (cancel_ms) {
if (verbose) std::cerr << "ares_cancel will be called after " << cancel_ms << "ms" << std::endl;
tv_cancel.tv_sec += (cancel_ms / 1000);
tv_cancel.tv_usec += ((cancel_ms % 1000) * 1000);
tv_cancel.sec += (cancel_ms / 1000);
tv_cancel.usec += ((cancel_ms % 1000) * 1000);
}
#else
if (cancel_ms) {
@ -274,8 +274,8 @@ void ProcessWork(ares_channel_t *channel,
while (true) {
#ifndef CARES_SYMBOL_HIDING
struct timeval tv_now = ares__tvnow();
struct timeval tv_remaining;
ares_timeval_t tv_now = ares__tvnow();
ares_timeval_t atv_remaining;
#endif
struct timeval tv;
struct timeval *tv_select;
@ -305,15 +305,21 @@ void ProcessWork(ares_channel_t *channel,
#ifndef CARES_SYMBOL_HIDING
if (cancel_ms) {
unsigned int remaining_ms;
ares__timeval_remaining(&tv_remaining,
ares__timeval_remaining(&atv_remaining,
&tv_now,
&tv_cancel);
remaining_ms = (unsigned int)((tv_remaining.tv_sec * 1000) + (tv_remaining.tv_usec / 1000));
remaining_ms = (unsigned int)((atv_remaining.sec * 1000) + (atv_remaining.usec / 1000));
if (remaining_ms == 0) {
if (verbose) std::cerr << "Issuing ares_cancel()" << std::endl;
ares_cancel(channel);
cancel_ms = 0; /* Disable issuing cancel again */
} else {
struct timeval tv_remaining;
tv_remaining.tv_sec = atv_remaining.sec;
tv_remaining.tv_usec = (int)atv_remaining.usec;
/* Recalculate proper timeout since we also have a cancel to wait on */
tv_select = ares_timeout(channel, &tv_remaining, &tv);
}
@ -831,8 +837,8 @@ void MockEventThreadOptsTest::ProcessThread() {
#ifndef CARES_SYMBOL_HIDING
bool has_cancel_ms = false;
struct timeval tv_begin;
struct timeval tv_cancel;
ares_timeval_t tv_begin;
ares_timeval_t tv_cancel;
#endif
mutex.lock();
@ -841,14 +847,14 @@ void MockEventThreadOptsTest::ProcessThread() {
int nfds = 0;
fd_set readers;
#ifndef CARES_SYMBOL_HIDING
struct timeval tv_now = ares__tvnow();
struct timeval tv_remaining;
ares_timeval_t tv_now = ares__tvnow();
ares_timeval_t atv_remaining;
if (cancel_ms_ && !has_cancel_ms) {
tv_begin = ares__tvnow();
tv_cancel = tv_begin;
if (verbose) std::cerr << "ares_cancel will be called after " << cancel_ms_ << "ms" << std::endl;
tv_cancel.tv_sec += (cancel_ms_ / 1000);
tv_cancel.tv_usec += ((cancel_ms_ % 1000) * 1000);
tv_cancel.sec += (cancel_ms_ / 1000);
tv_cancel.usec += ((cancel_ms_ % 1000) * 1000);
has_cancel_ms = true;
}
#else
@ -873,10 +879,10 @@ void MockEventThreadOptsTest::ProcessThread() {
#ifndef CARES_SYMBOL_HIDING
if (has_cancel_ms) {
unsigned int remaining_ms;
ares__timeval_remaining(&tv_remaining,
ares__timeval_remaining(&atv_remaining,
&tv_now,
&tv_cancel);
remaining_ms = (unsigned int)((tv_remaining.tv_sec * 1000) + (tv_remaining.tv_usec / 1000));
remaining_ms = (unsigned int)((atv_remaining.sec * 1000) + (atv_remaining.usec / 1000));
if (remaining_ms == 0) {
if (verbose) std::cerr << "Issuing ares_cancel()" << std::endl;
ares_cancel(channel_);

Loading…
Cancel
Save