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.
This commit is contained in:
Daniel Stenberg 2004-07-24 21:47:49 +00:00
parent 7f78bc3c6d
commit b3b2ba31f7
4 changed files with 61 additions and 19 deletions

View File

@ -51,12 +51,12 @@ static void process_timeouts(ares_channel channel, time_t now);
static void process_answer(ares_channel channel, unsigned char *abuf, static void process_answer(ares_channel channel, unsigned char *abuf,
int alen, int whichserver, int tcp, int now); int alen, int whichserver, int tcp, int now);
static void handle_error(ares_channel channel, int whichserver, time_t 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_tcp_socket(ares_channel channel, struct server_state *server);
static int open_udp_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, static int same_questions(const unsigned char *qbuf, int qlen,
const unsigned char *abuf, int alen); 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); unsigned char *abuf, int alen);
/* Something interesting happened on the wire, or there was a timeout. /* 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) for (sendreq = server->qhead; sendreq; sendreq = sendreq->next)
n++; n++;
#ifdef WIN32
vec = NULL;
#else
/* Allocate iovecs so we can send all our data at once. */ /* Allocate iovecs so we can send all our data at once. */
vec = malloc(n * sizeof(struct iovec)); vec = malloc(n * sizeof(struct iovec));
#endif
if (vec) if (vec)
{ {
#ifdef WIN32
#else
/* Fill in the iovecs and send. */ /* Fill in the iovecs and send. */
n = 0; n = 0;
for (sendreq = server->qhead; sendreq; sendreq = sendreq->next) 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; break;
} }
} }
#endif
} }
else else
{ {
@ -284,7 +277,7 @@ static void process_timeouts(ares_channel channel, time_t now)
if (query->timeout != 0 && now >= query->timeout) if (query->timeout != 0 && now >= query->timeout)
{ {
query->error_status = ARES_ETIMEOUT; 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) static void handle_error(ares_channel channel, int whichserver, time_t now)
{ {
struct query *query; struct query *query, *next;
/* Reset communications with this server. */ /* Reset communications with this server. */
ares__close_sockets(&channel->servers[whichserver]); 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 /* Tell all queries talking to this server to move on and not try
* this server again. * 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) if (query->server == whichserver)
{ {
query->skip_server[whichserver] = 1; 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. */ /* Advance to the next server or try. */
query->server++; 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]) if (!query->skip_server[query->server])
{ {
ares__send_query(channel, query, now); ares__send_query(channel, query, now);
return; return (query->next);
} }
} }
query->server = 0; query->server = 0;
@ -398,7 +393,7 @@ static void next_server(ares_channel channel, struct query *query, time_t now)
if (query->using_tcp) if (query->using_tcp)
break; 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) 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; return;
} }
} }
sendreq = malloc(sizeof(struct send_request)); sendreq = calloc(sizeof(struct send_request), 1);
if (!sendreq) if (!sendreq)
{
end_query(channel, query, ARES_ENOMEM, NULL, 0); end_query(channel, query, ARES_ENOMEM, NULL, 0);
return;
}
sendreq->data = query->tcpbuf; sendreq->data = query->tcpbuf;
sendreq->len = query->tcplen; sendreq->len = query->tcplen;
sendreq->next = NULL; 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; server->tcp_socket = s;
return 0; return 0;
} }
@ -611,10 +610,10 @@ static int same_questions(const unsigned char *qbuf, int qlen,
return 1; 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) unsigned char *abuf, int alen)
{ {
struct query **q; struct query **q, *next;
int i; int i;
query->callback(query->arg, status, abuf, alen); query->callback(query->arg, status, abuf, alen);
@ -624,6 +623,10 @@ static void end_query(ares_channel channel, struct query *query, int status,
break; break;
} }
*q = query->next; *q = query->next;
if (*q)
next = (*q)->next;
else
next = NULL;
free(query->tcpbuf); free(query->tcpbuf);
free(query->skip_server); free(query->skip_server);
free(query); 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++) for (i = 0; i < channel->nservers; i++)
ares__close_sockets(&channel->servers[i]); ares__close_sockets(&channel->servers[i]);
} }
return (next);
} }

View File

@ -26,6 +26,9 @@ struct iovec
#define getpid() _getpid() #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; }; struct timezone { int dummy; };
int ares_gettimeofday(struct timeval *tv, struct timezone *tz); int ares_gettimeofday(struct timeval *tv, struct timezone *tz);

View File

@ -34,6 +34,7 @@
/* now typedef our socket type */ /* now typedef our socket type */
#ifdef WIN32 #ifdef WIN32
#include <winsock.h>
typedef SOCKET ares_socket_t; typedef SOCKET ares_socket_t;
#define ARES_SOCKET_BAD INVALID_SOCKET #define ARES_SOCKET_BAD INVALID_SOCKET
#else #else

View File

@ -5,6 +5,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <ctype.h> #include <ctype.h>
#include <string.h> #include <string.h>
#include <errno.h>
#include <malloc.h>
#include "nameser.h" #include "nameser.h"
@ -52,4 +54,36 @@ ares_gettimeofday(struct timeval *tv, struct timezone *tz)
return 0; 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 */ #endif /* WIN32 builds only */