mirror of https://github.com/moparisthebest/curl
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:
parent
7f78bc3c6d
commit
b3b2ba31f7
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
Loading…
Reference in New Issue