--- /dev/null
+#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 */
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
{
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;
}
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 ¶ms)
{
- 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
++ 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,
/**
* 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
static void
httpsAccept(const CommAcceptCbParams ¶ms)
{
- 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
++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);
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
{