]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
First implementation of do splice. Works only if the openSSL version of client and...
authorChristos Tsantilas <chtsanti@users.sourceforge.net>
Fri, 2 May 2014 15:15:18 +0000 (18:15 +0300)
committerChristos Tsantilas <chtsanti@users.sourceforge.net>
Fri, 2 May 2014 15:15:18 +0000 (18:15 +0300)
src/FwdState.cc
src/ssl/PeerConnector.cc
src/ssl/PeerConnector.h
src/tunnel.cc

index 3e492e37f68fa3832584f7e9c4115847f50d3115..8d11b75d6d4ab611927fc32e56f99eba3281597f 100644 (file)
@@ -703,7 +703,7 @@ FwdState::connectDone(const Comm::ConnectionPointer &conn, comm_err_t status, in
                 "FwdState::ConnectedToPeer",
                 FwdStatePeerAnswerDialer(&FwdState::connectedToPeer, this));
             Ssl::PeerConnector *connector =
-                new Ssl::PeerConnector(requestPointer, serverConnection(), callback);
+                new Ssl::PeerConnector(requestPointer, serverConnection(), clientConn, callback);
             AsyncJob::Start(connector); // will call our callback
             return;
         }
index 0682abdce0e8f8f9268ae82860f917ebc6e2568d..01e633240147831cf542d4fa47a3c2f2f45b9872 100644 (file)
@@ -29,10 +29,12 @@ CBDATA_NAMESPACED_CLASS_INIT(Ssl, PeerConnector);
 Ssl::PeerConnector::PeerConnector(
     HttpRequestPointer &aRequest,
     const Comm::ConnectionPointer &aServerConn,
+    const Comm::ConnectionPointer &aClientConn,
     AsyncCall::Pointer &aCallback):
     AsyncJob("Ssl::PeerConnector"),
     request(aRequest),
     serverConn(aServerConn),
+    clientConn(aClientConn),
     callback(aCallback)
 {
     // if this throws, the caller's cb dialer is not our CbDialer
@@ -262,6 +264,7 @@ Ssl::PeerConnector::negotiateSsl()
     callBack();
 }
 
+void switchToTunnel(HttpRequest *request, int *status_ptr, Comm::ConnectionPointer & clientConn, Comm::ConnectionPointer &srvConn);
 void
 Ssl::PeerConnector::checkForPeekAndSplice()
 {
@@ -269,13 +272,17 @@ Ssl::PeerConnector::checkForPeekAndSplice()
     BIO *b = SSL_get_rbio(ssl);
     Ssl::ServerBio *srvBio = static_cast<Ssl::ServerBio *>(b->ptr);
     debugs(83,5, "Will check for peek and splice on fd " << serverConn->fd);
-    const bool splice = false;
+    const bool splice = true;
     if (!splice) {
         //Allow write, proceed with the connection
         srvBio->holdWrite(false);
         srvBio->recordInput(false);
         Comm::SetSelect(serverConn->fd, COMM_SELECT_WRITE, &NegotiateSsl, this, 0);
         debugs(83,5, "Retry the fwdNegotiateSSL on fd " << serverConn->fd);
+    } else {
+        static int status_code = 0;
+        debugs(83,5, "Revert to tunnel fd " << clientConn->fd << " with fd " << serverConn->fd);
+        switchToTunnel(request.getRaw(), &status_code, clientConn, serverConn);
     }
 }
 
index 44c94eb51ef9aaaa4bd548c9a57f529e2836798c..8ab4b702ab44ac9790d8b300f9ee26c88d5432b7 100644 (file)
@@ -97,6 +97,7 @@ public:
 public:
     PeerConnector(HttpRequestPointer &aRequest,
                   const Comm::ConnectionPointer &aServerConn,
+                  const Comm::ConnectionPointer &aClientConn,
                   AsyncCall::Pointer &aCallback);
     virtual ~PeerConnector();
 
@@ -159,6 +160,7 @@ private:
 
     HttpRequestPointer request; ///< peer connection trigger or cause
     Comm::ConnectionPointer serverConn; ///< TCP connection to the peer
+    Comm::ConnectionPointer clientConn; ///< TCP connection to the client
     AsyncCall::Pointer callback; ///< we call this with the results
     AsyncCall::Pointer closeHandler; ///< we call this when the connection closed
 
index 7e491338b8b9a73fe3d85f4bab32947af20f3f81..d8a4d8f4e29455a92e586744aa745865603fa691 100644 (file)
@@ -43,6 +43,7 @@
 #include "comm/Write.h"
 #include "errorpage.h"
 #include "fde.h"
+#include "globals.h"
 #include "FwdState.h"
 #include "http.h"
 #include "HttpRequest.h"
@@ -53,6 +54,7 @@
 #include "SquidConfig.h"
 #include "StatCounters.h"
 #if USE_OPENSSL
+#include "ssl/bio.h"
 #include "ssl/PeerConnector.h"
 #endif
 #include "tools.h"
@@ -949,6 +951,7 @@ tunnelStart(ClientHttpRequest * http, int64_t * size_ptr, int *status_ptr, const
 void
 TunnelStateData::connectToPeer() {
     const Comm::ConnectionPointer &srv = server.conn;
+    const Comm::ConnectionPointer &cln = client.conn;
 
 #if USE_OPENSSL
     if (CachePeer *p = srv->getPeer()) {
@@ -957,7 +960,7 @@ TunnelStateData::connectToPeer() {
                 "TunnelStateData::ConnectedToPeer",
                 MyAnswerDialer(&TunnelStateData::connectedToPeer, this));
             Ssl::PeerConnector *connector =
-                new Ssl::PeerConnector(request, srv, callback);
+                new Ssl::PeerConnector(request, srv, cln, callback);
             AsyncJob::Start(connector); // will call our callback
             return;
         }
@@ -1087,3 +1090,76 @@ TunnelStateData::Connection::setDelayId(DelayId const &newDelay)
 }
 
 #endif
+
+int default_read_method(int, char *, int);
+int default_write_method(int, const char *, int);
+void
+switchToTunnel(HttpRequest *request, int *status_ptr, Comm::ConnectionPointer &clientConn, Comm::ConnectionPointer &srvConn)
+{
+    debugs(26, 3, HERE);
+    /* Create state structure. */
+    TunnelStateData *tunnelState = NULL;
+    const char *url = urlCanonical(request);
+
+    debugs(26, 3, HERE << "'" << request->method << " " << url << " " << request->http_ver << "'");
+    ++statCounter.server.all.requests;
+    ++statCounter.server.other.requests;
+
+    tunnelState = new TunnelStateData;
+#if USE_DELAY_POOLS
+    //tunnelState->server.setDelayId(DelayId::DelayClient(http));
+#endif
+    tunnelState->url = xstrdup(url);
+    tunnelState->request = request;
+    tunnelState->server.size_ptr = NULL;//????
+    tunnelState->status_ptr = status_ptr;
+    tunnelState->client.conn = clientConn;
+
+    comm_add_close_handler(tunnelState->client.conn->fd,
+                           tunnelClientClosed,
+                           tunnelState);
+
+    AsyncCall::Pointer timeoutCall = commCbCall(5, 4, "tunnelTimeout",
+                                     CommTimeoutCbPtrFun(tunnelTimeout, tunnelState));
+    commSetConnTimeout(tunnelState->client.conn, Config.Timeout.lifetime, timeoutCall);
+    fd_table[clientConn->fd].read_method = &default_read_method;
+    fd_table[clientConn->fd].write_method = &default_write_method;
+
+//Server connection
+#if USE_DELAY_POOLS
+    /* no point using the delayIsNoDelay stuff since tunnel is nice and simple */
+//    if (conn->getPeer() && conn->getPeer()->options.no_delay)
+//        tunnelState->server.setDelayId(DelayId());
+#endif
+
+    tunnelState->request->hier.note(srvConn, tunnelState->getHost());
+
+    tunnelState->server.conn = srvConn;
+    tunnelState->request->peer_host = srvConn->getPeer() ? srvConn->getPeer()->host : NULL;
+    comm_add_close_handler(srvConn->fd, tunnelServerClosed, tunnelState);
+
+    debugs(26, 4, HERE << "determine post-connect handling pathway.");
+    if (srvConn->getPeer()) {
+        tunnelState->request->peer_login = srvConn->getPeer()->login;
+        tunnelState->request->flags.proxying = !(srvConn->getPeer()->options.originserver);
+    } else {
+        tunnelState->request->peer_login = NULL;
+        tunnelState->request->flags.proxying = false;
+    }
+
+    timeoutCall = commCbCall(5, 4, "tunnelTimeout",
+                                     CommTimeoutCbPtrFun(tunnelTimeout, tunnelState));
+    commSetConnTimeout(srvConn, Config.Timeout.read, timeoutCall);
+    fd_table[srvConn->fd].read_method = &default_read_method;
+    fd_table[srvConn->fd].write_method = &default_write_method;
+
+    SSL *ssl = fd_table[srvConn->fd].ssl;
+    assert(ssl);
+    BIO *b = SSL_get_rbio(ssl);
+    Ssl::ServerBio *srvBio = static_cast<Ssl::ServerBio *>(b->ptr);
+    const MemBuf &buf = srvBio->rBufData();
+
+    AsyncCall::Pointer call = commCbCall(5,5, "tunnelConnectedWriteDone",
+                                         CommIoCbPtrFun(tunnelConnectedWriteDone, tunnelState));
+    Comm::Write(tunnelState->client.conn, buf.content(), buf.contentSize(), call, NULL);
+}