From: Amos Jeffries Date: Tue, 18 Jun 2013 23:26:17 +0000 (-0600) Subject: Add Master Transaction class X-Git-Tag: SQUID_3_4_0_1~46 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=94bfd31f0fabf4f7eee72bb8783e5a58e0e13ce6;p=thirdparty%2Fsquid.git Add Master Transaction class ... to store and propigate the shared state used end-to-end through Squid for logging or server-side component input. This excludes Job and Call pointers, but does include any 'factual' data regarding the traansaction. --- diff --git a/src/CommCalls.cc b/src/CommCalls.cc index 7c812a937b..e0f622cdbd 100644 --- a/src/CommCalls.cc +++ b/src/CommCalls.cc @@ -40,10 +40,19 @@ CommCommonCbParams::print(std::ostream &os) const /* CommAcceptCbParams */ CommAcceptCbParams::CommAcceptCbParams(void *aData): - CommCommonCbParams(aData) + CommCommonCbParams(aData), xaction() { } +void +CommAcceptCbParams::print(std::ostream &os) const +{ + CommCommonCbParams::print(os); + + if (xaction != NULL) + os << ", " << xaction->id; +} + /* CommConnectCbParams */ CommConnectCbParams::CommConnectCbParams(void *aData): diff --git a/src/CommCalls.h b/src/CommCalls.h index fe8b735318..5003e78faa 100644 --- a/src/CommCalls.h +++ b/src/CommCalls.h @@ -5,6 +5,7 @@ #include "base/AsyncJobCalls.h" #include "comm_err_t.h" #include "comm/forward.h" +#include "MasterXaction.h" /* CommCalls implement AsyncCall interface for comm_* callbacks. * The classes cover two call dialer kinds: @@ -89,6 +90,11 @@ class CommAcceptCbParams: public CommCommonCbParams { public: CommAcceptCbParams(void *aData); + + void print(std::ostream &os) const; + + /// Transaction which this call is part of. + MasterXaction::Pointer xaction; }; // connect parameters diff --git a/src/Makefile.am b/src/Makefile.am index 7e6b392df8..07f8261c8b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -422,6 +422,8 @@ squid_SOURCES = \ LogTags.h \ lookup_t.h \ main.cc \ + MasterXaction.cc \ + MasterXaction.h \ Mem.h \ mem.cc \ mem_node.cc \ @@ -1251,6 +1253,8 @@ tests_testACLMaxUserIP_SOURCES= \ HttpRequestMethod.cc \ int.h \ int.cc \ + MasterXaction.cc \ + MasterXaction.h \ SquidList.h \ SquidList.cc \ mem_node.cc \ @@ -1488,6 +1492,8 @@ tests_testCacheManager_SOURCES = \ internal.cc \ SquidList.h \ SquidList.cc \ + MasterXaction.cc \ + MasterXaction.h \ multicast.h \ multicast.cc \ mem_node.cc \ @@ -1668,6 +1674,8 @@ tests_testDiskIO_SOURCES = \ int.cc \ SquidList.h \ SquidList.cc \ + MasterXaction.cc \ + MasterXaction.h \ MemBuf.cc \ MemObject.cc \ mem_node.cc \ @@ -1904,6 +1912,8 @@ tests_testEvent_SOURCES = \ internal.cc \ SquidList.h \ SquidList.cc \ + MasterXaction.cc \ + MasterXaction.h \ Mem.h \ mem.cc \ mem_node.cc \ @@ -2152,6 +2162,8 @@ tests_testEventLoop_SOURCES = \ internal.cc \ SquidList.h \ SquidList.cc \ + MasterXaction.cc \ + MasterXaction.h \ MemBlob.cc \ MemBuf.cc \ MemObject.cc \ @@ -2397,6 +2409,8 @@ tests_test_http_range_SOURCES = \ ipcache.cc \ SquidList.h \ SquidList.cc \ + MasterXaction.cc \ + MasterXaction.h \ MemBlob.cc \ MemBuf.cc \ MemObject.cc \ @@ -2687,6 +2701,8 @@ tests_testHttpRequest_SOURCES = \ internal.cc \ SquidList.h \ SquidList.cc \ + MasterXaction.cc \ + MasterXaction.h \ multicast.h \ multicast.cc \ mem_node.cc \ @@ -2860,6 +2876,8 @@ tests_testStore_SOURCES= \ int.cc \ SquidList.h \ SquidList.cc \ + MasterXaction.cc \ + MasterXaction.h \ Mem.h \ mem.cc \ mem_node.cc \ @@ -3085,6 +3103,8 @@ tests_testUfs_SOURCES = \ RequestFlags.cc \ SquidList.h \ SquidList.cc \ + MasterXaction.cc \ + MasterXaction.h \ MemObject.cc \ StoreSwapLogData.cc \ StoreIOState.cc \ @@ -3271,6 +3291,8 @@ tests_testRock_SOURCES = \ int.cc \ SquidList.h \ SquidList.cc \ + MasterXaction.cc \ + MasterXaction.h \ Mem.h \ mem.cc \ MemBuf.cc \ @@ -3655,6 +3677,8 @@ tests_testURL_SOURCES = \ internal.cc \ SquidList.h \ SquidList.cc \ + MasterXaction.cc \ + MasterXaction.h \ multicast.h \ multicast.cc \ Mem.h \ diff --git a/src/MasterXaction.cc b/src/MasterXaction.cc new file mode 100644 index 0000000000..b380586d3d --- /dev/null +++ b/src/MasterXaction.cc @@ -0,0 +1,4 @@ +#include "squid.h" +#include "MasterXaction.h" + +InstanceIdDefinitions(MasterXaction, "MXID_"); diff --git a/src/MasterXaction.h b/src/MasterXaction.h new file mode 100644 index 0000000000..164a9d9f96 --- /dev/null +++ b/src/MasterXaction.h @@ -0,0 +1,46 @@ +#ifndef SQUID_SRC_MASTERXACTION_H +#define SQUID_SRC_MASTERXACTION_H + +#include "anyp/forward.h" +#include "base/CbcPointer.h" +#include "base/InstanceId.h" +#include "base/Lock.h" +#include "comm/forward.h" + +/** Master transaction details. + * + * Aggregates historical data from individual related protocol-specific + * transactions such as an HTTP client transaction and the corresponding + * HTTP or FTP server transaction. + * + * Individual transaction information worth sending or logging should be + * recorded here, ideally without exposing other master transaction users + * to internal details of individual transactions. For example, storing an + * HTTP client IP address is a good idea but storing a pointer to some + * client-side job which maintains that address is not. + * + * A master transaction is created by a newly accepted client connection, + * a new request on the existing client connection, or an internal request + * generated by Squid. All client-side protocols, including HTTP, HTCP, ICP, + * and SNMP will eventually create master transactions. + * + * A master transaction is auto-destroyed when its last user is gone. + */ +class MasterXaction : public RefCountable +{ +public: + typedef RefCount Pointer; + + /// transaction ID. + InstanceId id; + + /// the listening port which originated this transaction + AnyP::PortCfgPointer squidPort; + + /// the client TCP connection which originated this transaction + Comm::ConnectionPointer tcpClient; + + // TODO: add state from other Jobs in the transaction +}; + +#endif /* SQUID_SRC_MASTERXACTION_H */ diff --git a/src/client_side.cc b/src/client_side.cc index a332617ceb..3d2e653fc4 100644 --- a/src/client_side.cc +++ b/src/client_side.cc @@ -245,8 +245,6 @@ static void clientUpdateSocketStats(LogTags logType, size_t size); char *skipLeadingSpace(char *aString); static void connNoteUseOfBuffer(ConnStateData* conn, size_t byteCount); -static ConnStateData *connStateCreate(const Comm::ConnectionPointer &client, AnyP::PortCfg *port); - clientStreamNode * ClientSocketContext::getTail() const { @@ -3338,23 +3336,37 @@ clientLifetimeTimeout(const CommTimeoutCbParams &io) io.conn->close(); } -ConnStateData * -connStateCreate(const Comm::ConnectionPointer &client, AnyP::PortCfg *port) +ConnStateData::ConnStateData(const MasterXaction::Pointer &xact) : + AsyncJob("ConnStateData"), +#if USE_SSL + sslBumpMode(Ssl::bumpEnd), + switchedToHttps_(false), + sslServerBump(NULL), +#endif + stoppedSending_(NULL), + stoppedReceiving_(NULL) { - ConnStateData *result = new ConnStateData; + pinning.host = NULL; + pinning.port = -1; + pinning.pinned = false; + pinning.auth = false; + pinning.zeroReply = false; + pinning.peer = NULL; + + // store the details required for creating more MasterXaction objects as new requests come in + clientConnection = xact->tcpClient; + port = cbdataReference(xact->squidPort.get()); + log_addr = xact->tcpClient->remote; + log_addr.applyMask(Config.Addrs.client_netmask); - result->clientConnection = client; - result->log_addr = client->remote; - result->log_addr.applyMask(Config.Addrs.client_netmask); - result->in.buf = (char *)memAllocBuf(CLIENT_REQ_BUF_SZ, &result->in.allocatedSize); - result->port = cbdataReference(port); + in.buf = (char *)memAllocBuf(CLIENT_REQ_BUF_SZ, &in.allocatedSize); if (port->disable_pmtu_discovery != DISABLE_PMTU_OFF && - (result->transparent() || port->disable_pmtu_discovery == DISABLE_PMTU_ALWAYS)) { + (transparent() || port->disable_pmtu_discovery == DISABLE_PMTU_ALWAYS)) { #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) int i = IP_PMTUDISC_DONT; - if (setsockopt(client->fd, SOL_IP, IP_MTU_DISCOVER, &i, sizeof(i)) < 0) - debugs(33, 2, "WARNING: Path MTU discovery disabling failed on " << client << " : " << xstrerror()); + if (setsockopt(clientConnection->fd, SOL_IP, IP_MTU_DISCOVER, &i, sizeof(i)) < 0) + debugs(33, 2, "WARNING: Path MTU discovery disabling failed on " << clientConnection << " : " << xstrerror()); #else static bool reported = false; @@ -3366,33 +3378,39 @@ connStateCreate(const Comm::ConnectionPointer &client, AnyP::PortCfg *port) } typedef CommCbMemFunT Dialer; - AsyncCall::Pointer call = JobCallback(33, 5, Dialer, result, ConnStateData::connStateClosed); - comm_add_close_handler(client->fd, call); + AsyncCall::Pointer call = JobCallback(33, 5, Dialer, this, ConnStateData::connStateClosed); + comm_add_close_handler(clientConnection->fd, call); if (Config.onoff.log_fqdn) - fqdncache_gethostbyaddr(client->remote, FQDN_LOOKUP_IF_MISS); + fqdncache_gethostbyaddr(clientConnection->remote, FQDN_LOOKUP_IF_MISS); #if USE_IDENT if (Ident::TheConfig.identLookup) { ACLFilledChecklist identChecklist(Ident::TheConfig.identLookup, NULL, NULL); - identChecklist.src_addr = client->remote; - identChecklist.my_addr = client->local; + identChecklist.src_addr = xact->tcpClient->remote; + identChecklist.my_addr = xact->tcpClient->local; if (identChecklist.fastCheck() == ACCESS_ALLOWED) - Ident::Start(client, clientIdentDone, result); + Ident::Start(xact->tcpClient, clientIdentDone, this); } #endif - clientdbEstablished(client->remote, 1); + clientdbEstablished(clientConnection->remote, 1); - result->flags.readMore = true; - return result; + flags.readMore = true; } /** Handle a new connection on HTTP socket. */ void httpAccept(const CommAcceptCbParams ¶ms) { - AnyP::PortCfg *s = static_cast(params.data); + MasterXaction::Pointer xact = params.xaction; + AnyP::PortCfgPointer s = xact->squidPort; + + if (!s.valid()) { + // it is possible the call or accept() was still queued when the port was reconfigured + debugs(33, 2, "HTTP accept failure: port reconfigured."); + return; + } if (params.flag != COMM_OK) { // Its possible the call was still queued when the client disconnected @@ -3410,7 +3428,7 @@ httpAccept(const CommAcceptCbParams ¶ms) ++ incoming_sockets_accepted; // Socket is ready, setup the connection manager to start using it - ConnStateData *connState = connStateCreate(params.conn, s); + ConnStateData *connState = new ConnStateData(xact); typedef CommCbMemFunT TimeoutDialer; AsyncCall::Pointer timeoutCall = JobCallback(33, 5, @@ -3659,7 +3677,7 @@ httpsEstablish(ConnStateData *connState, SSL_CTX *sslContext, Ssl::BumpMode bum /** * A callback function to use with the ACLFilledChecklist callback. - * In the case of ACCES_ALLOWED answer initializes a bumped SSL connection, + * In the case of ACCESS_ALLOWED answer initializes a bumped SSL connection, * else reverts the connection to tunnel mode. */ static void @@ -3701,7 +3719,14 @@ httpsSslBumpAccessCheckDone(allow_t answer, void *data) static void httpsAccept(const CommAcceptCbParams ¶ms) { - AnyP::PortCfg *s = static_cast(params.data); + MasterXaction::Pointer xact = params.xaction; + const AnyP::PortCfgPointer s = xact->squidPort; + + if (!s.valid()) { + // it is possible the call or accept() was still queued when the port was reconfigured + debugs(33, 2, "HTTPS accept failure: port reconfigured."); + return; + } if (params.flag != COMM_OK) { // Its possible the call was still queued when the client disconnected @@ -3719,7 +3744,7 @@ httpsAccept(const CommAcceptCbParams ¶ms) ++incoming_sockets_accepted; // Socket is ready, setup the connection manager to start using it - ConnStateData *connState = connStateCreate(params.conn, s); + ConnStateData *connState = new ConnStateData(xact); if (s->flags.tunnelSslBumping) { debugs(33, 5, "httpsAccept: accept transparent connection: " << params.conn); @@ -4318,24 +4343,6 @@ clientAclChecklistCreate(const acl_access * acl, ClientHttpRequest * http) CBDATA_CLASS_INIT(ConnStateData); -ConnStateData::ConnStateData() : - AsyncJob("ConnStateData"), -#if USE_SSL - sslBumpMode(Ssl::bumpEnd), - switchedToHttps_(false), - sslServerBump(NULL), -#endif - stoppedSending_(NULL), - stoppedReceiving_(NULL) -{ - pinning.host = NULL; - pinning.port = -1; - pinning.pinned = false; - pinning.auth = false; - pinning.zeroReply = false; - pinning.peer = NULL; -} - bool ConnStateData::transparent() const { diff --git a/src/client_side.h b/src/client_side.h index 79872cdefb..a10e0b0caf 100644 --- a/src/client_side.h +++ b/src/client_side.h @@ -187,8 +187,7 @@ class ConnStateData : public BodyProducer, public HttpControlMsgSink { public: - - ConnStateData(); + explicit ConnStateData(const MasterXaction::Pointer &xact); ~ConnStateData(); void readSomeData(); @@ -273,6 +272,7 @@ public: AsyncCall::Pointer closeHandler; /*The close handler for pinned server side connection*/ } pinning; + /// Squid listening port details where this connection arrived. AnyP::PortCfg *port; bool transparent() const; diff --git a/src/comm/TcpAcceptor.cc b/src/comm/TcpAcceptor.cc index 7c8c7ec320..33cf3fbd7f 100644 --- a/src/comm/TcpAcceptor.cc +++ b/src/comm/TcpAcceptor.cc @@ -33,6 +33,7 @@ */ #include "squid.h" +#include "anyp/PortCfg.h" #include "base/TextException.h" #include "client_db.h" #include "comm/AcceptLimiter.h" @@ -46,6 +47,7 @@ #include "fde.h" #include "globals.h" #include "ip/Intercept.h" +#include "MasterXaction.h" #include "profiler/Profiler.h" #include "SquidConfig.h" #include "SquidTime.h" @@ -286,8 +288,10 @@ Comm::TcpAcceptor::notify(const comm_err_t flag, const Comm::ConnectionPointer & if (theCallSub != NULL) { AsyncCall::Pointer call = theCallSub->callback(); CommAcceptCbParams ¶ms = GetCommParams(call); + params.xaction = new MasterXaction; + params.xaction->squidPort = static_cast(params.data); params.fd = conn->fd; - params.conn = newConnDetails; + params.conn = params.xaction->tcpClient = newConnDetails; params.flag = flag; params.xerrno = errcode; ScheduleCallHere(call);