From: Amos Jeffries Date: Sat, 20 Jun 2015 00:24:24 +0000 (-0700) Subject: Fix CONNECT failover to IPv4 after trying broken IPv6 servers X-Git-Tag: merge-candidate-3-v1~75 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=acfa923dfbd90d673b8ee2fbd0f7025f2b2613f4;p=thirdparty%2Fsquid.git Fix CONNECT failover to IPv4 after trying broken IPv6 servers This makes CONNECT tunnel connection attempts obey forward_timeout and continue retrying instead of aborting with a client error when one possible server hits a connect_timeout. --- diff --git a/src/tunnel.cc b/src/tunnel.cc index e67f8b403d..349e824a3f 100644 --- a/src/tunnel.cc +++ b/src/tunnel.cc @@ -160,6 +160,7 @@ public: MemBuf *connectRespBuf; ///< accumulates peer CONNECT response when we need it bool connectReqWriting; ///< whether we are writing a CONNECT request to a peer SBuf preReadClientData; + time_t started; ///< when this tunnel was initiated. void copyRead(Connection &from, IOCB *completion); @@ -892,13 +893,20 @@ tunnelConnectDone(const Comm::ConnectionPointer &conn, Comm::Flag status, int xe /* At this point only the TCP handshake has failed. no data has been passed. * we are allowed to re-try the TCP-level connection to alternate IPs for CONNECT. */ + debugs(26, 4, "removing server 1 of " << tunnelState->serverDestinations.size() << + " from destinations (" << tunnelState->serverDestinations[0] << ")"); tunnelState->serverDestinations.erase(tunnelState->serverDestinations.begin()); - if (status != Comm::TIMEOUT && tunnelState->serverDestinations.size() > 0) { + time_t fwdTimeout = tunnelState->started + Config.Timeout.forward; + if (fwdTimeout > squid_curtime && tunnelState->serverDestinations.size() > 0) { + // find remaining forward_timeout available for this attempt + fwdTimeout -= squid_curtime; + if (fwdTimeout > Config.Timeout.connect) + fwdTimeout = Config.Timeout.connect; /* Try another IP of this destination host */ GetMarkingsToServer(tunnelState->request.getRaw(), *tunnelState->serverDestinations[0]); debugs(26, 4, HERE << "retry with : " << tunnelState->serverDestinations[0]); AsyncCall::Pointer call = commCbCall(26,3, "tunnelConnectDone", CommConnectCbPtrFun(tunnelConnectDone, tunnelState)); - Comm::ConnOpener *cs = new Comm::ConnOpener(tunnelState->serverDestinations[0], call, Config.Timeout.connect); + Comm::ConnOpener *cs = new Comm::ConnOpener(tunnelState->serverDestinations[0], call, fwdTimeout); cs->setHost(tunnelState->url); AsyncJob::Start(cs); } else { @@ -998,6 +1006,7 @@ tunnelStart(ClientHttpRequest * http, int64_t * size_ptr, int *status_ptr, const tunnelState->client.conn = http->getConn()->clientConnection; tunnelState->http = http; tunnelState->al = al; + tunnelState->started = squid_curtime; comm_add_close_handler(tunnelState->client.conn->fd, tunnelClientClosed,