From b3b2ba31f7f666f31e187db9c223062553966566 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 24 Jul 2004 21:47:49 +0000 Subject: [PATCH] Gisle Vanem: Basically in loops like handle_errors(), 'query->next' was assigned a local variable and then query was referenced after the memory was freed by next_server(). I've changed that so next_server() and end_query() returns the next query. So callers should use this ret-value. The next problem was that 'server->tcp_buffer_pos' had a random value at entry to 1st recv() (luckily causing Winsock to return ENOBUFS). I've also added a ares_writev() for Windows to streamline the code a bit more. --- ares/ares_process.c | 42 +++++++++++++++++++++++------------------- ares/nameser.h | 3 +++ ares/setup.h | 1 + ares/windows_port.c | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 61 insertions(+), 19 deletions(-) diff --git a/ares/ares_process.c b/ares/ares_process.c index 130d82ff3..df7c4573d 100644 --- a/ares/ares_process.c +++ b/ares/ares_process.c @@ -51,12 +51,12 @@ static void process_timeouts(ares_channel channel, time_t now); static void process_answer(ares_channel channel, unsigned char *abuf, int alen, int whichserver, int tcp, int now); static void handle_error(ares_channel channel, int whichserver, time_t now); -static void next_server(ares_channel channel, struct query *query, time_t now); +static struct query *next_server(ares_channel channel, struct query *query, time_t now); static int open_tcp_socket(ares_channel channel, struct server_state *server); static int open_udp_socket(ares_channel channel, struct server_state *server); static int same_questions(const unsigned char *qbuf, int qlen, const unsigned char *abuf, int alen); -static void end_query(ares_channel channel, struct query *query, int status, +static struct query *end_query(ares_channel channel, struct query *query, int status, unsigned char *abuf, int alen); /* Something interesting happened on the wire, or there was a timeout. @@ -98,16 +98,10 @@ static void write_tcp_data(ares_channel channel, fd_set *write_fds, time_t now) for (sendreq = server->qhead; sendreq; sendreq = sendreq->next) n++; -#ifdef WIN32 - vec = NULL; -#else /* Allocate iovecs so we can send all our data at once. */ vec = malloc(n * sizeof(struct iovec)); -#endif if (vec) { -#ifdef WIN32 -#else /* Fill in the iovecs and send. */ n = 0; for (sendreq = server->qhead; sendreq; sendreq = sendreq->next) @@ -143,7 +137,6 @@ static void write_tcp_data(ares_channel channel, fd_set *write_fds, time_t now) break; } } -#endif } else { @@ -284,7 +277,7 @@ static void process_timeouts(ares_channel channel, time_t now) if (query->timeout != 0 && now >= query->timeout) { query->error_status = ARES_ETIMEOUT; - next_server(channel, query, now); + next = next_server(channel, query, now); } } } @@ -360,7 +353,7 @@ static void process_answer(ares_channel channel, unsigned char *abuf, static void handle_error(ares_channel channel, int whichserver, time_t now) { - struct query *query; + struct query *query, *next; /* Reset communications with this server. */ ares__close_sockets(&channel->servers[whichserver]); @@ -368,17 +361,19 @@ static void handle_error(ares_channel channel, int whichserver, time_t now) /* Tell all queries talking to this server to move on and not try * this server again. */ - for (query = channel->queries; query; query = query->next) + + for (query = channel->queries; query; query = next) { + next = query->next; if (query->server == whichserver) { query->skip_server[whichserver] = 1; - next_server(channel, query, now); + next = next_server(channel, query, now); } } } -static void next_server(ares_channel channel, struct query *query, time_t now) +static struct query *next_server(ares_channel channel, struct query *query, time_t now) { /* Advance to the next server or try. */ query->server++; @@ -389,7 +384,7 @@ static void next_server(ares_channel channel, struct query *query, time_t now) if (!query->skip_server[query->server]) { ares__send_query(channel, query, now); - return; + return (query->next); } } query->server = 0; @@ -398,7 +393,7 @@ static void next_server(ares_channel channel, struct query *query, time_t now) if (query->using_tcp) break; } - end_query(channel, query, query->error_status, NULL, 0); + return end_query(channel, query, query->error_status, NULL, 0); } void ares__send_query(ares_channel channel, struct query *query, time_t now) @@ -421,9 +416,12 @@ void ares__send_query(ares_channel channel, struct query *query, time_t now) return; } } - sendreq = malloc(sizeof(struct send_request)); + sendreq = calloc(sizeof(struct send_request), 1); if (!sendreq) + { end_query(channel, query, ARES_ENOMEM, NULL, 0); + return; + } sendreq->data = query->tcpbuf; sendreq->len = query->tcplen; sendreq->next = NULL; @@ -503,6 +501,7 @@ static int open_tcp_socket(ares_channel channel, struct server_state *server) } } + server->tcp_buffer_pos = 0; server->tcp_socket = s; return 0; } @@ -611,10 +610,10 @@ static int same_questions(const unsigned char *qbuf, int qlen, return 1; } -static void end_query(ares_channel channel, struct query *query, int status, +static struct query *end_query (ares_channel channel, struct query *query, int status, unsigned char *abuf, int alen) { - struct query **q; + struct query **q, *next; int i; query->callback(query->arg, status, abuf, alen); @@ -624,6 +623,10 @@ static void end_query(ares_channel channel, struct query *query, int status, break; } *q = query->next; + if (*q) + next = (*q)->next; + else + next = NULL; free(query->tcpbuf); free(query->skip_server); free(query); @@ -636,4 +639,5 @@ static void end_query(ares_channel channel, struct query *query, int status, for (i = 0; i < channel->nservers; i++) ares__close_sockets(&channel->servers[i]); } + return (next); } diff --git a/ares/nameser.h b/ares/nameser.h index 77c76bf48..d3a95e8cc 100644 --- a/ares/nameser.h +++ b/ares/nameser.h @@ -26,6 +26,9 @@ struct iovec #define getpid() _getpid() +int ares_writev (SOCKET s, const struct iovec *vector, size_t count); +#define writev(s,vect,count) ares_writev(s,vect,count) + struct timezone { int dummy; }; int ares_gettimeofday(struct timeval *tv, struct timezone *tz); diff --git a/ares/setup.h b/ares/setup.h index eca1c90bb..a713ef9cb 100644 --- a/ares/setup.h +++ b/ares/setup.h @@ -34,6 +34,7 @@ /* now typedef our socket type */ #ifdef WIN32 +#include typedef SOCKET ares_socket_t; #define ARES_SOCKET_BAD INVALID_SOCKET #else diff --git a/ares/windows_port.c b/ares/windows_port.c index 9611e054e..ac6ffb272 100644 --- a/ares/windows_port.c +++ b/ares/windows_port.c @@ -5,6 +5,8 @@ #include #include #include +#include +#include #include "nameser.h" @@ -52,4 +54,36 @@ ares_gettimeofday(struct timeval *tv, struct timezone *tz) return 0; } +int +ares_writev (SOCKET s, const struct iovec *vector, size_t count) +{ + char *buffer, *bp; + size_t i, bytes = 0; + + /* Find the total number of bytes to write + */ + for (i = 0; i < count; i++) + bytes += vector[i].iov_len; + + if (bytes == 0) /* not an error */ + return (0); + + /* Allocate a temporary buffer to hold the data + */ + buffer = bp = (char*) alloca (bytes); + if (!buffer) + { + errno = ENOMEM; + return (-1); + } + + /* Copy the data into buffer. + */ + for (i = 0; i < count; ++i) + { + memcpy (bp, vector[i].iov_base, vector[i].iov_len); + bp += vector[i].iov_len; + } + return send (s, (const void*)buffer, bytes, 0); +} #endif /* WIN32 builds only */