Commit c202b9f4 authored by Mark Andrews's avatar Mark Andrews

1773. [bug] Fast retry on host / net unreachable. [RT #13153]

parent cf74c9cc
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
1774. [port] Aix: Silence compiler warnings / build failures. 1774. [port] Aix: Silence compiler warnings / build failures.
[RT #13154] [RT #13154]
1773. [placeholder] rt13153 1773. [bug] Fast retry on host / net unreachable. [RT #13153]
1772. [placeholder] 1772. [placeholder]
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE. * PERFORMANCE OF THIS SOFTWARE.
*/ */
/* $Id: resolver.c,v 1.298 2004/11/10 21:57:46 marka Exp $ */ /* $Id: resolver.c,v 1.299 2004/12/03 01:59:28 marka Exp $ */
#include <config.h> #include <config.h>
...@@ -762,6 +762,9 @@ static void ...@@ -762,6 +762,9 @@ static void
resquery_senddone(isc_task_t *task, isc_event_t *event) { resquery_senddone(isc_task_t *task, isc_event_t *event) {
isc_socketevent_t *sevent = (isc_socketevent_t *)event; isc_socketevent_t *sevent = (isc_socketevent_t *)event;
resquery_t *query = event->ev_arg; resquery_t *query = event->ev_arg;
isc_boolean_t retry = ISC_FALSE;
isc_result_t result;
fetchctx_t *fctx;
REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE); REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
...@@ -780,6 +783,7 @@ resquery_senddone(isc_task_t *task, isc_event_t *event) { ...@@ -780,6 +783,7 @@ resquery_senddone(isc_task_t *task, isc_event_t *event) {
INSIST(RESQUERY_SENDING(query)); INSIST(RESQUERY_SENDING(query));
query->sends--; query->sends--;
fctx = query->fctx;
if (RESQUERY_CANCELED(query)) { if (RESQUERY_CANCELED(query)) {
if (query->sends == 0) { if (query->sends == 0) {
...@@ -791,16 +795,43 @@ resquery_senddone(isc_task_t *task, isc_event_t *event) { ...@@ -791,16 +795,43 @@ resquery_senddone(isc_task_t *task, isc_event_t *event) {
isc_socket_detach(&query->tcpsocket); isc_socket_detach(&query->tcpsocket);
resquery_destroy(&query); resquery_destroy(&query);
} }
} else if (sevent->result == ISC_R_HOSTUNREACH || } else
sevent->result == ISC_R_NETUNREACH) switch (sevent->result) {
/* case ISC_R_SUCCESS:
* No route to remote. break;
*/
fctx_cancelquery(&query, NULL, NULL, ISC_TRUE); case ISC_R_HOSTUNREACH:
else if (sevent->result != ISC_R_SUCCESS) case ISC_R_NETUNREACH:
fctx_cancelquery(&query, NULL, NULL, ISC_FALSE); case ISC_R_NOPERM:
case ISC_R_ADDRNOTAVAIL:
case ISC_R_CONNREFUSED:
/*
* No route to remote.
*/
fctx_cancelquery(&query, NULL, NULL, ISC_TRUE);
retry = ISC_TRUE;
break;
default:
fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
break;
}
isc_event_free(&event); isc_event_free(&event);
if (retry) {
/*
* Behave as if the idle timer has expired. For TCP
* this may not actually reflect the latest timer.
*/
fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
result = fctx_stopidletimer(fctx);
if (result != ISC_R_SUCCESS)
fctx_done(fctx, result);
else
fctx_try(fctx);
}
} }
static inline isc_result_t static inline isc_result_t
...@@ -1317,7 +1348,10 @@ static void ...@@ -1317,7 +1348,10 @@ static void
resquery_connected(isc_task_t *task, isc_event_t *event) { resquery_connected(isc_task_t *task, isc_event_t *event) {
isc_socketevent_t *sevent = (isc_socketevent_t *)event; isc_socketevent_t *sevent = (isc_socketevent_t *)event;
resquery_t *query = event->ev_arg; resquery_t *query = event->ev_arg;
isc_boolean_t retry = ISC_FALSE;
isc_result_t result; isc_result_t result;
unsigned int attrs;
fetchctx_t *fctx;
REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT); REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
REQUIRE(VALID_QUERY(query)); REQUIRE(VALID_QUERY(query));
...@@ -1335,6 +1369,7 @@ resquery_connected(isc_task_t *task, isc_event_t *event) { ...@@ -1335,6 +1369,7 @@ resquery_connected(isc_task_t *task, isc_event_t *event) {
*/ */
query->connects--; query->connects--;
fctx = query->fctx;
if (RESQUERY_CANCELED(query)) { if (RESQUERY_CANCELED(query)) {
/* /*
...@@ -1344,9 +1379,8 @@ resquery_connected(isc_task_t *task, isc_event_t *event) { ...@@ -1344,9 +1379,8 @@ resquery_connected(isc_task_t *task, isc_event_t *event) {
isc_socket_detach(&query->tcpsocket); isc_socket_detach(&query->tcpsocket);
resquery_destroy(&query); resquery_destroy(&query);
} else { } else {
if (sevent->result == ISC_R_SUCCESS) { switch (sevent->result) {
unsigned int attrs; case ISC_R_SUCCESS:
/* /*
* We are connected. Create a dispatcher and * We are connected. Create a dispatcher and
* send the query. * send the query.
...@@ -1379,25 +1413,46 @@ resquery_connected(isc_task_t *task, isc_event_t *event) { ...@@ -1379,25 +1413,46 @@ resquery_connected(isc_task_t *task, isc_event_t *event) {
result = resquery_send(query); result = resquery_send(query);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
fetchctx_t *fctx = query->fctx;
fctx_cancelquery(&query, NULL, NULL, fctx_cancelquery(&query, NULL, NULL,
ISC_FALSE); ISC_FALSE);
fctx_done(fctx, result); fctx_done(fctx, result);
} }
} else if (sevent->result == ISC_R_HOSTUNREACH || break;
sevent->result == ISC_R_NETUNREACH) {
case ISC_R_NETUNREACH:
case ISC_R_HOSTUNREACH:
case ISC_R_CONNREFUSED:
case ISC_R_NOPERM:
case ISC_R_ADDRNOTAVAIL:
/* /*
* No route to remote. * No route to remote.
*/ */
isc_socket_detach(&query->tcpsocket); isc_socket_detach(&query->tcpsocket);
fctx_cancelquery(&query, NULL, NULL, ISC_TRUE); fctx_cancelquery(&query, NULL, NULL, ISC_TRUE);
} else { retry = ISC_TRUE;
break;
default:
isc_socket_detach(&query->tcpsocket); isc_socket_detach(&query->tcpsocket);
fctx_cancelquery(&query, NULL, NULL, ISC_FALSE); fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
break;
} }
} }
isc_event_free(&event); isc_event_free(&event);
if (retry) {
/*
* Behave as if the idle timer has expired. For TCP
* connections this may not actually reflect the latest timer.
*/
fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
result = fctx_stopidletimer(fctx);
if (result != ISC_R_SUCCESS)
fctx_done(fctx, result);
else
fctx_try(fctx);
}
} }
static void static void
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment