]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Add Master Transaction class
authorAmos Jeffries <squid3@treenet.co.nz>
Tue, 18 Jun 2013 23:26:17 +0000 (17:26 -0600)
committerAmos Jeffries <squid3@treenet.co.nz>
Tue, 18 Jun 2013 23:26:17 +0000 (17:26 -0600)
... 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.

src/CommCalls.cc
src/CommCalls.h
src/Makefile.am
src/MasterXaction.cc [new file with mode: 0644]
src/MasterXaction.h [new file with mode: 0644]
src/client_side.cc
src/client_side.h
src/comm/TcpAcceptor.cc

index 7c812a937b7afde97323617eb4c8509b2c89bf8e..e0f622cdbd3a94501dd76724392c1cac06e9d612 100644 (file)
@@ -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):
index fe8b735318f44b0a1a9c5b2bac86ff0dc3ced784..5003e78faa4e4b31cbb5b4097c62c5c7012c4667 100644 (file)
@@ -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
index 7e6b392df8f32ce85ff2e6604a27f44dc24ad5ca..07f8261c8ba0b96f6a5a74a04cc471835a85e281 100644 (file)
@@ -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 (file)
index 0000000..b380586
--- /dev/null
@@ -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 (file)
index 0000000..164a9d9
--- /dev/null
@@ -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<MasterXaction> Pointer;
+
+    /// transaction ID.
+    InstanceId<MasterXaction> 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 */
index a332617cebac463ddc61e7fc6d1e4dd14d932b21..3d2e653fc498d2e792d7312bfce0634709d4b8d3 100644 (file)
@@ -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<ConnStateData, CommCloseCbParams> 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 &params)
 {
-    AnyP::PortCfg *s = static_cast<AnyP::PortCfg *>(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 &params)
     ++ 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<ConnStateData, CommTimeoutCbParams> 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 &params)
 {
-    AnyP::PortCfg *s = static_cast<AnyP::PortCfg *>(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 &params)
     ++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
 {
index 79872cdefbafbdbb35099a59d7035a322336327a..a10e0b0caf63c56a6aeaf3c279bd97d86d865f69 100644 (file)
@@ -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;
index 7c8c7ec32005eb2182caa2f87cdebe6524196e60..33cf3fbd7fe01591453c01763a16cf0341736119 100644 (file)
@@ -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 &params = GetCommParams<CommAcceptCbParams>(call);
+        params.xaction = new MasterXaction;
+        params.xaction->squidPort = static_cast<AnyP::PortCfg*>(params.data);
         params.fd = conn->fd;
-        params.conn = newConnDetails;
+        params.conn = params.xaction->tcpClient = newConnDetails;
         params.flag = flag;
         params.xerrno = errcode;
         ScheduleCallHere(call);