From: Eduard Bagdasaryan Date: Thu, 9 Jul 2020 12:24:40 +0000 (+0300) Subject: Must not start a new connection if the previous one is still in use X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=33c7a0e551e84717c6cbaf2ee5c7cab8b05b4765;p=thirdparty%2Fsquid.git Must not start a new connection if the previous one is still in use in tunnel.cc. FwdState.cc has been fixed already in 61dac1b. --- diff --git a/src/tunnel.cc b/src/tunnel.cc index 513730acec..63bca37985 100644 --- a/src/tunnel.cc +++ b/src/tunnel.cc @@ -180,6 +180,8 @@ public: SBuf preReadClientData; SBuf preReadServerData; time_t startTime; ///< object creation time, before any peer selection/connection attempts + /// whether we are waiting for the secure peer connection establishment answer + bool securingConnectionToPeer; /// Whether we are waiting for the CONNECT request/response exchange with the peer. bool waitingForConnectExchange; HappyConnOpenerPointer connOpener; ///< current connection opening job @@ -266,6 +268,9 @@ private: /// \returns whether the request should be retried (nil) or the description why it should not const char *checkRetry(); + /// whether the successfully selected path destination or the established + /// server connection is still in use + bool usingDestination() const; /// details of the "last tunneling attempt" failure (if it failed) ErrorState *savedError = nullptr; @@ -355,6 +360,7 @@ TunnelStateData::deleteThis() TunnelStateData::TunnelStateData(ClientHttpRequest *clientRequest) : startTime(squid_curtime), + securingConnectionToPeer(false), waitingForConnectExchange(false), destinations(new ResolvedPeers()), destinationsFound(false), @@ -1165,10 +1171,12 @@ TunnelStateData::connectToPeer(const Comm::ConnectionPointer &conn) void TunnelStateData::secureConnectionToPeer(const Comm::ConnectionPointer &conn) { + assert(!securingConnectionToPeer); AsyncCall::Pointer callback = asyncCall(5,4, "TunnelStateData::noteSecurityPeerConnectorAnswer", MyAnswerDialer(&TunnelStateData::noteSecurityPeerConnectorAnswer, this)); const auto connector = new Security::BlindPeerConnector(request, conn, callback, al); AsyncJob::Start(connector); // will call our callback + securingConnectionToPeer = true; } /// starts a preparation step for an established connection; retries on failures @@ -1195,6 +1203,8 @@ TunnelStateData::advanceDestination(const char *stepDescription, const Comm::Con void TunnelStateData::noteSecurityPeerConnectorAnswer(Security::EncryptorAnswer &answer) { + securingConnectionToPeer = false; + ErrorState *error = nullptr; if ((error = answer.error.get())) { Must(!Comm::IsConnOpen(answer.conn)); @@ -1253,7 +1263,7 @@ TunnelStateData::noteDestination(Comm::ConnectionPointer path) destinations->addPath(path); - if (Comm::IsConnOpen(server.conn)) { + if (usingDestination()) { // We are already using a previously opened connection but also // receiving destinations in case we need to re-forward. Must(!opening()); @@ -1290,7 +1300,7 @@ TunnelStateData::noteDestinationsEnd(ErrorState *selectionError) // if all of them fail, tunneling as whole will fail Must(!selectionError); // finding at least one path means selection succeeded - if (Comm::IsConnOpen(server.conn)) { + if (usingDestination()) { // We are already using a previously opened connection but also // receiving destinations in case we need to re-forward. Must(!opening()); @@ -1301,6 +1311,12 @@ TunnelStateData::noteDestinationsEnd(ErrorState *selectionError) notifyConnOpener(); } +bool +TunnelStateData::usingDestination() const +{ + return securingConnectionToPeer || waitingForConnectExchange || Comm::IsConnOpen(server.conn); +} + /// remembers an error to be used if there will be no more connection attempts void TunnelStateData::saveError(ErrorState *error) @@ -1362,6 +1378,7 @@ TunnelStateData::startConnecting() assert(!destinations->empty()); assert(!opening()); + assert(!usingDestination()); calls.connector = asyncCall(17, 5, "TunnelStateData::noteConnection", HappyConnOpener::CbDialer(&TunnelStateData::noteConnection, this)); const auto cs = new HappyConnOpener(destinations, calls.connector, request, startTime, 0, al); cs->setHost(request->url.host());