summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ares_process.c28
1 files changed, 23 insertions, 5 deletions
diff --git a/ares_process.c b/ares_process.c
index b4073bf..1b58029 100644
--- a/ares_process.c
+++ b/ares_process.c
@@ -65,6 +65,8 @@ 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, time_t now);
static void handle_error(ares_channel channel, int whichserver, time_t now);
+static void skip_server(ares_channel channel, struct query *query,
+ int whichserver);
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);
@@ -474,7 +476,7 @@ static void process_answer(ares_channel channel, unsigned char *abuf,
{
if (rcode == SERVFAIL || rcode == NOTIMP || rcode == REFUSED)
{
- query->skip_server[whichserver] = 1;
+ skip_server(channel, query, whichserver);
if (query->server == whichserver)
next_server(channel, query, now);
return;
@@ -506,12 +508,28 @@ static void handle_error(ares_channel channel, int whichserver, time_t now)
next = query->next;
if (query->server == whichserver)
{
- query->skip_server[whichserver] = 1;
+ skip_server(channel, query, whichserver);
next = next_server(channel, query, now);
}
}
}
+static void skip_server(ares_channel channel, struct query *query,
+ int whichserver) {
+ /* The given server gave us problems with this query, so if we have
+ * the luxury of using other servers, then let's skip the
+ * potentially broken server and just use the others. If we only
+ * have one server and we need to retry then we should just go ahead
+ * and re-use that server, since it's our only hope; perhaps we
+ * just got unlucky, and retrying will work (eg, the server timed
+ * out our TCP connection just as we were sending another request).
+ */
+ if (channel->nservers > 1)
+ {
+ query->skip_server[whichserver] = 1;
+ }
+}
+
static struct query *next_server(ares_channel channel, struct query *query, time_t now)
{
/* Advance to the next server or try. */
@@ -553,7 +571,7 @@ void ares__send_query(ares_channel channel, struct query *query, time_t now)
{
if (open_tcp_socket(channel, server) == -1)
{
- query->skip_server[query->server] = 1;
+ skip_server(channel, query, query->server);
next_server(channel, query, now);
return;
}
@@ -583,7 +601,7 @@ void ares__send_query(ares_channel channel, struct query *query, time_t now)
{
if (open_udp_socket(channel, server) == -1)
{
- query->skip_server[query->server] = 1;
+ skip_server(channel, query, query->server);
next_server(channel, query, now);
return;
}
@@ -591,7 +609,7 @@ void ares__send_query(ares_channel channel, struct query *query, time_t now)
if (swrite(server->udp_socket, query->qbuf, query->qlen) == -1)
{
/* FIXME: Handle EAGAIN here since it likely can happen. */
- query->skip_server[query->server] = 1;
+ skip_server(channel, query, query->server);
next_server(channel, query, now);
return;
}