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
callBack();
}
+void switchToTunnel(HttpRequest *request, int *status_ptr, Comm::ConnectionPointer & clientConn, Comm::ConnectionPointer &srvConn);
void
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);
}
}
#include "comm/Write.h"
#include "errorpage.h"
#include "fde.h"
+#include "globals.h"
#include "FwdState.h"
#include "http.h"
#include "HttpRequest.h"
#include "SquidConfig.h"
#include "StatCounters.h"
#if USE_OPENSSL
+#include "ssl/bio.h"
#include "ssl/PeerConnector.h"
#endif
#include "tools.h"
void
TunnelStateData::connectToPeer() {
const Comm::ConnectionPointer &srv = server.conn;
+ const Comm::ConnectionPointer &cln = client.conn;
#if USE_OPENSSL
if (CachePeer *p = srv->getPeer()) {
"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;
}
}
#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);
+}