]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Fix CONNECT failover to IPv4 after trying broken IPv6 servers
authorAmos Jeffries <squid3@treenet.co.nz>
Sat, 20 Jun 2015 00:24:24 +0000 (17:24 -0700)
committerAmos Jeffries <squid3@treenet.co.nz>
Sat, 20 Jun 2015 00:24:24 +0000 (17:24 -0700)
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.

src/tunnel.cc

index e67f8b403d05fbf69f272b630cbb69c78737c168..349e824a3fdd5ebb508356df2f7fc0b1559084ba 100644 (file)
@@ -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,