]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Improved Async implementation.
authorAmos Jeffries <squid3@treenet.co.nz>
Fri, 16 Jul 2010 12:10:38 +0000 (00:10 +1200)
committerAmos Jeffries <squid3@treenet.co.nz>
Fri, 16 Jul 2010 12:10:38 +0000 (00:10 +1200)
* use AsyncJob::AsyncStart instead of start()

* implements doneAll()

* handle timeouts on INPROGRESS states

src/adaptation/icap/Xaction.cc
src/comm/ConnOpener.cc
src/comm/ConnOpener.h
src/dns_internal.cc
src/forward.cc
src/ftp.cc
src/ident/Ident.cc
src/neighbors.cc
src/tunnel.cc

index 8f7d7bec402d70a85340681490612f7bda2ccbb1..74eb3b22b03bb70578e7f076d00ef41dc42ac311 100644 (file)
@@ -132,7 +132,7 @@ void Adaptation::Icap::Xaction::openConnection()
     ConnOpener *cs = new ConnOpener(connection, connector);
     cs->setHost(s.cfg().host.termedBuf());
     cs->connect_timeout = TheConfig.connect_timeout(service().cfg().bypass);
-    cs->start();
+    AsyncJob::AsyncStart(cs);
 }
 
 /*
index 62b82e6b85d6b5568525cfea1f6544397f73b491..4a4659ebd558f47ffec4a15aa80d99b5dfddf139 100644 (file)
@@ -26,6 +26,20 @@ ConnOpener::~ConnOpener()
     solo = NULL;
 }
 
+bool
+ConnOpener::doneAll() const
+{
+    // is the conn to be opened still waiting?
+    if (solo != NULL)
+        return false;
+
+    // is the callback still to be called?
+    if (callback != NULL)
+        return false;
+
+    return true;
+}
+
 void
 ConnOpener::setHost(const char * new_host)
 {
@@ -47,19 +61,24 @@ ConnOpener::getHost() const
 void
 ConnOpener::callCallback(comm_err_t status, int xerrno)
 {
-    /* remove handlers we don't want to happen now */
-    comm_remove_close_handler(solo->fd, ConnOpener::EarlyAbort, this);
-    commSetTimeout(solo->fd, -1, NULL, NULL);
-
-    typedef CommConnectCbParams Params;
-    Params &params = GetCommParams<Params>(callback);
-    params.conn = solo;
-    params.flag = status;
-    params.xerrno = xerrno;
-    ScheduleCallHere(callback);
-
-    callback = NULL;
-    delete this;
+    /* remove handlers we don't want to happen anymore */
+    if (solo != NULL && solo->fd > 0) {
+        comm_remove_close_handler(solo->fd, ConnOpener::EarlyAbort, this);
+        commSetTimeout(solo->fd, -1, NULL, NULL);
+    }
+
+    if (callback != NULL) {
+        typedef CommConnectCbParams Params;
+        Params &params = GetCommParams<Params>(callback);
+        params.conn = solo;
+        params.flag = status;
+        params.xerrno = xerrno;
+        ScheduleCallHere(callback);
+        callback = NULL;
+    }
+
+    /* ensure cleared local state, we are done. */
+    solo = NULL;
 }
 
 void
@@ -74,7 +93,7 @@ ConnOpener::start()
         }
 #endif
         solo->fd = comm_openex(SOCK_STREAM, IPPROTO_TCP, solo->local, solo->flags, solo->tos, host);
-        if (solo->fd <= 0) {
+        if (solo->fd < 0) {
             callCallback(COMM_ERR_CONNECT, 0);
             return;
         }
@@ -98,8 +117,15 @@ ConnOpener::start()
     switch (comm_connect_addr(solo->fd, solo->remote) ) {
 
     case COMM_INPROGRESS:
-        debugs(5, 5, HERE << "FD " << solo->fd << ": COMM_INPROGRESS");
-        commSetSelect(solo->fd, COMM_SELECT_WRITE, ConnOpener::ConnectRetry, this, 0);
+        // check for timeout FIRST.
+        if(squid_curtime - connstart > connect_timeout) {
+            debugs(5, 5, HERE << "FD " << solo->fd << ": * - ERR took too long already.");
+            callCallback(COMM_TIMEOUT, errno);
+            return;
+        } else {
+            debugs(5, 5, HERE << "FD " << solo->fd << ": COMM_INPROGRESS");
+            commSetSelect(solo->fd, COMM_SELECT_WRITE, ConnOpener::ConnectRetry, this, 0);
+        }
         break;
 
     case COMM_OK:
@@ -155,12 +181,6 @@ ConnOpener::EarlyAbort(int fd, void *data)
     ConnOpener *cs = static_cast<ConnOpener *>(data);
     debugs(5, 3, HERE << "FD " << fd);
     cs->callCallback(COMM_ERR_CLOSING, errno); // NP: is closing or shutdown better?
-
-    /* TODO split cases:
-     * remote end rejecting the connection is normal and one of the other paths may be taken.
-     * squid shutting down or forcing abort on the connection attempt(s) are the only real fatal cases.
-     * we may need separate error codes to send back for these two.
-     */
 }
 
 void
@@ -183,4 +203,3 @@ ConnOpener::ConnectTimeout(int fd, void *data)
     ConnOpener *cs = static_cast<ConnOpener *>(data);
     cs->start();
 }
-
index 9c4e2a6cc77873f833dd1949bd0316ee3ca2e442..b8632be161cf62777555e83d71774f62cabe67e3 100644 (file)
@@ -21,6 +21,7 @@ public:
     /** Actual start opening a TCP connection. */
     void start();
 
+    virtual bool doneAll() const;
 private:
     /* These objects may NOT be created without connections to act on. Do not define this operator. */
     ConnOpener(const ConnOpener &);
index 92f677c3c0c8ffc93e4a4d47b4b2ccb0d0e704b5..c7263fed18685939235dc58b5331441b481cd793 100644 (file)
@@ -751,7 +751,7 @@ idnsInitVC(int ns)
 
     ConnOpener *cs = new ConnOpener(conn, call);
     cs->setHost("DNS TCP Socket");
-    cs->start();
+    AsyncJob::AsyncStart(cs);
 }
 
 static void
index 7e531a420a0934aec2dccb68e63ffa4f1c0cf164..1cc2c240d8f3bdbc48aacae787780482106dccbe 100644 (file)
@@ -812,7 +812,7 @@ FwdState::connectStart()
     ConnOpener *cs = new ConnOpener(paths[0], call);
     cs->setHost(host);
     cs->connect_timeout = ctimeout;
-    cs->start();
+    AsyncJob::AsyncStart(cs);
 }
 
 void
index 7d500db11edcbaecc138d3ef9d8513bd5403f5fa..51559b2c023d2a373da33d4fe317ba4ed9951831 100644 (file)
@@ -2420,7 +2420,7 @@ ftpReadEPSV(FtpStateData* ftpState)
     AsyncCall::Pointer call = commCbCall(9,3, "FtpStateData::ftpPasvCallback", CommConnectCbPtrFun(FtpStateData::ftpPasvCallback, ftpState));
     ConnOpener *cs = new ConnOpener(conn, call);
     cs->setHost(ftpState->data.host);
-    cs->start();
+    AsyncJob::AsyncStart(cs);
 }
 
 /** \ingroup ServerProtocolFTPInternal
@@ -2705,7 +2705,7 @@ ftpReadPasv(FtpStateData * ftpState)
     ConnOpener *cs = new ConnOpener(conn, call);
     cs->setHost(ftpState->data.host);
     cs->connect_timeout = Config.Timeout.connect;
-    cs->start();
+    AsyncJob::AsyncStart(cs);
 }
 
 void
index e56476460d2fa0228a23243067b9334328eed406..15ed8e3cb15c830fb252afbb0652617bbd012b2b 100644 (file)
@@ -252,7 +252,7 @@ Ident::Start(Comm::ConnectionPointer &conn, IDCB * callback, void *data)
     AsyncCall::Pointer call = commCbCall(30,3, "Ident::ConnectDone", CommConnectCbPtrFun(Ident::ConnectDone, state));
     ConnOpener *cs = new ConnOpener(state->conn, call);
     cs->connect_timeout = Ident::TheConfig.timeout;
-    cs->start();
+    AsyncJob::AsyncStart(cs);
 }
 
 void
index 81859e30f17ff5706001cf860c4da84a34e77296..805d0524d72496d94a23a0faf1507271e1ebfc31 100644 (file)
@@ -1372,7 +1372,7 @@ peerProbeConnect(peer * p)
         ConnOpener *cs = new ConnOpener(conn, call);
         cs->connect_timeout = ctimeout;
         cs->setHost(p->host);
-        cs->start();
+        AsyncJob::AsyncStart(cs);
     }
 
     p->stats.last_connect_probe = squid_curtime;
index 88b714400663f96eaa2a0fdde905a84e1f2570b8..163f24e25a4134d2e89df2ce92447f4cae44bbeb 100644 (file)
@@ -550,7 +550,7 @@ tunnelConnectDone(Comm::ConnectionPointer &conn, comm_err_t status, int xerrno,
             ConnOpener *cs = new ConnOpener(tunnelState->paths[0], call);
             cs->setHost(tunnelState->url);
             cs->connect_timeout = Config.Timeout.connect;
-            cs->start();
+            AsyncJob::AsyncStart(cs);
         } else {
             err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE, request);
             *tunnelState->status_ptr = HTTP_SERVICE_UNAVAILABLE;
@@ -704,7 +704,7 @@ tunnelPeerSelectComplete(Comm::Paths *peer_paths, void *data)
     ConnOpener *cs = new ConnOpener(tunnelState->paths[0], call);
     cs->setHost(tunnelState->url);
     cs->connect_timeout = Config.Timeout.connect;
-    cs->start();
+    AsyncJob::AsyncStart(cs);
 }
 
 CBDATA_CLASS_INIT(TunnelStateData);