<p>Some possible problems are:</p>
<ul>
-<li id="missing-dns">The domain name <q>%H</q> might not be found in DNS.</li>
<li id="network-down">An Internet connection needed to access this domains origin servers may be down.</li>
<li id="no-peer">All configured parent caches may be currently unreachable.</li>
<li id="permission-denied">The administrator may not allow this cache to make direct connections to origin servers.</li>
class HttpRequest;
class StoreEntry;
+class ErrorState;
-typedef void PSC(Comm::ConnectionList *, void *);
+typedef void PSC(Comm::ConnectionList *, ErrorState *, void *);
SQUIDCEXTERN void peerSelect(Comm::ConnectionList *, HttpRequest *, StoreEntry *, PSC *, void *data);
SQUIDCEXTERN void peerSelectInit(void);
int direct; // TODO: fold always_direct/never_direct/prefer_direct into this now that ACL can do a multi-state result.
PSC *callback;
void *callback_data;
+ ErrorState *lastError;
Comm::ConnectionList *paths; ///< the callers paths array. to be filled with our final results.
FwdServer *servers; ///< temporary linked list of peers we will pass back.
/**** CALLBACK WRAPPERS ************************************************************/
static void
-fwdPeerSelectionCompleteWrapper(Comm::ConnectionList * unused, void *data)
+fwdPeerSelectionCompleteWrapper(Comm::ConnectionList * unused, ErrorState *err, void *data)
{
FwdState *fwd = (FwdState *) data;
+ if (err)
+ fwd->fail(err);
fwd->startConnectionOrFail();
}
#include "squid.h"
#include "DnsLookupDetails.h"
+#include "errorpage.h"
#include "event.h"
#include "PeerSelectState.h"
#include "Store.h"
psstate->entry = NULL;
}
+ delete psstate->lastError;
+
cbdataFree(psstate);
}
void *cbdata;
if (cbdataReferenceValidDone(psstate->callback_data, &cbdata)) {
- callback(psstate->paths, cbdata);
+ callback(psstate->paths, psstate->lastError, cbdata);
+ psstate->lastError = NULL; // FwdState has taken control over the ErrorState object.
}
peerSelectStateFree(psstate);
}
} else {
debugs(44, 3, HERE << "Unknown host: " << fs->_peer ? fs->_peer->host : psstate->request->GetHost());
+ // discard any previous error.
+ delete psstate->lastError;
+ psstate->lastError = NULL;
+ if (fs->code == HIER_DIRECT) {
+ psstate->lastError = new ErrorState(ERR_DNS_FAIL, HTTP_SERVICE_UNAVAILABLE, psstate->request);
+ psstate->lastError->dnsError = details.error;
+ }
}
psstate->servers = fs->next;
direct(DIRECT_UNKNOWN),
callback (NULL),
callback_data (NULL),
+ lastError(NULL),
servers (NULL),
first_parent_miss(),
closest_parent_miss(),
}
static void
-tunnelPeerSelectComplete(Comm::ConnectionList *peer_paths, void *data)
+tunnelPeerSelectComplete(Comm::ConnectionList *peer_paths, ErrorState *err, void *data)
{
TunnelStateData *tunnelState = (TunnelStateData *)data;
if (peer_paths == NULL || peer_paths->size() < 1) {
debugs(26, 3, HERE << "No paths found. Aborting CONNECT");
- ErrorState *err;
- err = new ErrorState(ERR_CANNOT_FORWARD, HTTP_SERVICE_UNAVAILABLE, tunnelState->request);
- *tunnelState->status_ptr = HTTP_SERVICE_UNAVAILABLE;
+ if (!err) {
+ err = new ErrorState(ERR_CANNOT_FORWARD, HTTP_SERVICE_UNAVAILABLE, tunnelState->request);
+ }
+ *tunnelState->status_ptr = err->httpStatus;
err->callback = tunnelErrorComplete;
err->callback_data = tunnelState;
errorSend(tunnelState->client.conn, err);
return;
}
+ delete err;
+
debugs(26, 3, HERE << "paths=" << peer_paths->size() << ", p[0]={" << (*peer_paths)[0] << "}, serverDest[0]={" <<
tunnelState->serverDestinations[0] << "}");