aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2004-07-24 21:47:49 +0000
committerDaniel Stenberg <daniel@haxx.se>2004-07-24 21:47:49 +0000
commitb3b2ba31f7f666f31e187db9c223062553966566 (patch)
tree6acdfb45246bcf76087412ae8cbdd4cf31dd3e17
parent7f78bc3c6d167760a41a5183d21b3ecfe2718a7c (diff)
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.
-rw-r--r--ares/ares_process.c42
-rw-r--r--ares/nameser.h3
-rw-r--r--ares/setup.h1
-rw-r--r--ares/windows_port.c34
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 <winsock.h>
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 <stdlib.h>
#include <ctype.h>
#include <string.h>
+#include <errno.h>
+#include <malloc.h>
#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 */