#if USE_SSL
static PF fwdNegotiateSSLWrapper;
#endif
- #if 0
--static PF fwdConnectTimeoutWrapper;
--static EVH fwdConnectStartWrapper;
- #endif
static CNCB fwdConnectDoneWrapper;
static OBJH fwdStats;
- #if 0
--static void fwdServerFree(FwdServer * fs);
- #endif
#define MAX_FWD_STATS_IDX 9
static int FwdReplyCodes[MAX_FWD_STATS_IDX + 1][HTTP_INVALID_HEADER + 1];
#endif
void
-FwdState::connectDone(int aServerFD, const DnsLookupDetails &dns, comm_err_t status, int xerrno)
+FwdState::connectDone(Comm::ConnectionPointer conn, Comm::PathsPointer result_paths, comm_err_t status, int xerrno)
{
- FwdServer *fs = servers;
- assert(server_fd == aServerFD);
-
- request->recordLookup(dns);
+ assert(result_paths == &paths);
- if (Config.onoff.log_ip_on_direct && status != COMM_ERR_DNS && fs->code == HIER_DIRECT)
- updateHierarchyInfo();
-
- if (status == COMM_ERR_DNS) {
- /*
- * Only set the dont_retry flag if the DNS lookup fails on
- * a direct connection. If DNS lookup fails when trying
- * a neighbor cache, we may want to retry another option.
- */
+ if (status != COMM_OK) {
+ ErrorState *anErr = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE, request);
+ anErr->xerrno = xerrno;
- if (NULL == fs->_peer)
- flags.dont_retry = 1;
+ fail(anErr);
- debugs(17, 4, "fwdConnectDone: Unknown host: " << request->GetHost());
+ /* it might have been a timeout with a partially open link */
+ if (paths.size() > 0) {
+ if (paths[0]->getPeer())
+ peerConnectFailed(paths[0]->getPeer());
- ErrorState *anErr = errorCon(ERR_DNS_FAIL, HTTP_SERVICE_UNAVAILABLE, request);
+ comm_close(paths[0]);
+ }
- anErr->dnsError = dns.error;
+ return;
+ }
- fail(anErr);
++#if REDUNDANT_NOW
+ if (Config.onoff.log_ip_on_direct && paths[0]->peer_type == HIER_DIRECT)
+ updateHierarchyInfo();
++#endif
- comm_close(server_fd);
- } else if (status != COMM_OK) {
- assert(fs);
- ErrorState *anErr = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE, request);
- anErr->xerrno = xerrno;
+ debugs(17, 3, "FD " << paths[0]->fd << ": '" << entry->url() << "'" );
- comm_add_close_handler(conn->fd, fwdServerClosedWrapper, this);
- fail(anErr);
++ comm_add_close_handler(paths[0]->fd, fwdServerClosedWrapper, this);
- if (fs->_peer)
- peerConnectFailed(fs->_peer);
+ if (paths[0]->getPeer())
+ peerConnectSucceded(paths[0]->getPeer());
- comm_close(server_fd);
- } else {
- debugs(17, 3, "fwdConnectDone: FD " << server_fd << ": '" << entry->url() << "'" );
++ // TODO: Avoid this if %<lp is not used? F->local_port is often cached.
++ request->hier.peer_local_port = comm_local_port(paths[0]->fd);
+
- if (fs->_peer)
- peerConnectSucceded(fs->_peer);
++ updateHierarchyInfo();
+
#if USE_SSL
-
- if ((fs->_peer && fs->_peer->use_ssl) ||
- (!fs->_peer && request->protocol == PROTO_HTTPS)) {
- initiateSSL();
- return;
- }
-
-#endif
- dispatch();
+ if ((paths[0]->getPeer() && paths[0]->getPeer()->use_ssl) ||
+ (!paths[0]->getPeer() && request->protocol == PROTO_HTTPS)) {
+ initiateSSL();
+ return;
}
+#endif
+
+ dispatch();
}
void
updateHierarchyInfo();
- comm_add_close_handler(fd, fwdServerClosedWrapper, this);
+ comm_add_close_handler(conn->fd, fwdServerClosedWrapper, this);
+
+ // TODO: Avoid this if %<lp is not used? F->local_port is often cached.
- request->hier.peer_local_port = comm_local_port(fd);
++ request->hier.peer_local_port = comm_local_port(conn->fd);
+
dispatch();
-
return;
}
entry->mem_obj->checkUrlChecksum();
#endif
- outgoing = getOutgoingAddr(request, fs->_peer);
-
- tos = getOutgoingTOS(request);
-
- debugs(17, 3, "fwdConnectStart: got outgoing addr " << outgoing << ", tos " << tos);
-
- int commFlags = COMM_NONBLOCKING;
- if (request->flags.spoof_client_ip) {
- if (!fs->_peer || !fs->_peer->options.no_tproxy)
- commFlags |= COMM_TRANSPARENT;
- // else no tproxy today ...
- }
-
- fd = comm_openex(SOCK_STREAM, IPPROTO_TCP, outgoing, commFlags, tos, url);
-
- debugs(17, 3, "fwdConnectStart: got TCP FD " << fd);
-
- if (fd < 0) {
- debugs(50, 4, "fwdConnectStart: " << xstrerror());
- ErrorState *anErr = errorCon(ERR_SOCKET_FAILURE, HTTP_INTERNAL_SERVER_ERROR, request);
- anErr->xerrno = errno;
- fail(anErr);
- self = NULL; // refcounted
- return;
- }
-
- server_fd = fd;
- n_tries++;
-
- if (!fs->_peer)
- origin_tries++;
-
- request->hier.peer_local_port = comm_local_port(fd);
-
- /*
- * stats.conn_open is used to account for the number of
- * connections that we have open to the peer, so we can limit
- * based on the max-conn option. We need to increment here,
- * even if the connection may fail.
- */
-
- if (fs->_peer) {
- fs->_peer->stats.conn_open++;
- comm_add_close_handler(fd, fwdPeerClosed, fs->_peer);
- }
-
- comm_add_close_handler(fd, fwdServerClosedWrapper, this);
-
- commSetTimeout(fd, ctimeout, fwdConnectTimeoutWrapper, this);
-
-- updateHierarchyInfo();
- commConnectStart(fd, host, port, fwdConnectDoneWrapper, this);
-}
-
-void
-FwdState::startComplete(FwdServer * theServers)
-{
- debugs(17, 3, "fwdStartComplete: " << entry->url() );
-
- if (theServers != NULL) {
- servers = theServers;
- connectStart();
- } else {
- startFail();
- }
-}
--
-void
-FwdState::startFail()
-{
- debugs(17, 3, "fwdStartFail: " << entry->url() );
- ErrorState *anErr = errorCon(ERR_CANNOT_FORWARD, HTTP_SERVICE_UNAVAILABLE, request);
- anErr->xerrno = errno;
- fail(anErr);
- self = NULL; // refcounted
+ AsyncCall::Pointer call = commCbCall(17,3, "fwdConnectDoneWrapper", CommConnectCbPtrFun(fwdConnectDoneWrapper, this));
+ ConnectStateData *cs = new ConnectStateData(&paths, call);
+ cs->host = xstrdup(host);
+ cs->connect_timeout = ctimeout;
+ cs->connect();
}
void