else
cache.caddr.NtoA(buf, bufsz);
}
+
+AccessLogEntry::~AccessLogEntry()
+{
+ safe_free(headers.request);
+
+#if ICAP_CLIENT
+ safe_free(adapt.last_meta);
+#endif
+
+ safe_free(headers.reply);
+ safe_free(cache.authuser);
+
+ safe_free(headers.adapted_request);
+ HTTPMSGUNLOCK(adapted_request);
+
+ HTTPMSGUNLOCK(reply);
+ HTTPMSGUNLOCK(request);
+#if ICAP_CLIENT
+ HTTPMSGUNLOCK(icap.reply);
+ HTTPMSGUNLOCK(icap.request);
+#endif
+ cbdataReferenceDone(cache.port);
+}
#if ICAP_CLIENT
#include "adaptation/icap/Elements.h"
#endif
+#include "RefCount.h"
/* forward decls */
class HttpReply;
class HttpRequest;
-class AccessLogEntry
+class AccessLogEntry: public RefCountable
{
public:
+ typedef RefCount<AccessLogEntry> Pointer;
+
AccessLogEntry() : url(NULL), tcpClient(), reply(NULL), request(NULL),
adapted_request(NULL) {}
+ ~AccessLogEntry();
/// Fetch the client IP log string into the given buffer.
/// Knows about several alternate locations of the IP
msec(0),
rfc931 (NULL),
authuser (NULL),
- extuser(NULL)
+ extuser(NULL),
#if USE_SSL
- ,ssluser(NULL)
+ ssluser(NULL),
#endif
+ port(NULL)
{;
}
class StoreEntry;
/* Should be in 'AccessLog.h' as the driver */
-extern void accessLogLogTo(customlog* log, AccessLogEntry* al, ACLChecklist* checklist = NULL);
-extern void accessLogLog(AccessLogEntry *, ACLChecklist * checklist);
+extern void accessLogLogTo(customlog* log, AccessLogEntry::Pointer &al, ACLChecklist* checklist = NULL);
+extern void accessLogLog(AccessLogEntry::Pointer &, ACLChecklist * checklist);
extern void accessLogRotate(void);
extern void accessLogClose(void);
extern void accessLogInit(void);
-extern void accessLogFreeMemory(AccessLogEntry * aLogEntry);
extern const char *accessLogTime(time_t);
#endif /* SQUID_HTTPACCESSLOGENTRY_H */
Adaptation::Icap::Xaction::swanSong();
}
-void prepareLogWithRequestDetails(HttpRequest *, AccessLogEntry *);
+void prepareLogWithRequestDetails(HttpRequest *, AccessLogEntry::Pointer &);
void Adaptation::Icap::ModXact::finalizeLogInfo()
{
packerClean(&p);
mb.clean();
}
- prepareLogWithRequestDetails(request_, &al);
+ prepareLogWithRequestDetails(request_, alep);
Xaction::finalizeLogInfo();
}
isRetriable(true),
isRepeatable(true),
ignoreLastWrite(false),
- connector(NULL), reader(NULL), writer(NULL), closer(NULL)
+ connector(NULL), reader(NULL), writer(NULL), closer(NULL),
+ alep(new AccessLogEntry),
+ al(*alep)
{
debugs(93,3, typeName << " constructed, this=" << this <<
" [icapx" << id << ']'); // we should not call virtual status() here
ACLChecklist *checklist = new ACLFilledChecklist(::Config.accessList.icap, al.request, dash_str);
if (!::Config.accessList.icap || checklist->fastCheck() == ACCESS_ALLOWED) {
finalizeLogInfo();
- icapLogLog(&al, checklist);
+ icapLogLog(alep, checklist);
}
- accessLogFreeMemory(&al);
delete checklist;
}
}
AsyncCall::Pointer writer;
AsyncCall::Pointer closer;
- AccessLogEntry al;
+ AccessLogEntry::Pointer alep; ///< icap.log entry
+ AccessLogEntry &al; ///< short for *alep
timeval icap_tr_start; /*time when the ICAP transaction was created */
timeval icap_tio_start; /*time when the first ICAP request byte was scheduled for sending*/
}
}
-void icapLogLog(AccessLogEntry *al, ACLChecklist * checklist)
+void icapLogLog(AccessLogEntry::Pointer &al, ACLChecklist * checklist)
{
if (IcapLogfileStatus == LOG_ENABLE)
accessLogLogTo(Config.Log.icaplogs, al, checklist);
#ifndef ICAP_LOG_H_
#define ICAP_LOG_H_
+#include "RefCount.h"
+
+typedef RefCount<AccessLogEntry> AccessLogEntryPointer;
class AccessLogEntry;
class ACLChecklist;
void icapLogClose();
void icapLogOpen();
void icapLogRotate();
-void icapLogLog(AccessLogEntry *al, ACLChecklist * checklist);
+void icapLogLog(AccessLogEntryPointer &al, ACLChecklist * checklist);
extern int IcapLogfileStatus;
static void clientUpdateStatCounters(log_type logType);
static void clientUpdateHierCounters(HierarchyLogEntry *);
static bool clientPingHasFinished(ping_data const *aPing);
-void prepareLogWithRequestDetails(HttpRequest *, AccessLogEntry *);
+void prepareLogWithRequestDetails(HttpRequest *, AccessLogEntry::Pointer &);
#ifndef PURIFY
static bool connIsUsable(ConnStateData * conn);
#endif
}
void
-prepareLogWithRequestDetails(HttpRequest * request, AccessLogEntry * aLogEntry)
+prepareLogWithRequestDetails(HttpRequest * request, AccessLogEntry::Pointer &aLogEntry)
{
assert(request);
- assert(aLogEntry);
+ assert(aLogEntry != NULL);
if (Config.onoff.log_mime_hdrs) {
Packer p;
if (!out.size && !logType)
debugs(33, 5, HERE << "logging half-baked transaction: " << log_uri);
- al.icp.opcode = ICP_INVALID;
- al.url = log_uri;
- debugs(33, 9, "clientLogRequest: al.url='" << al.url << "'");
+ al->icp.opcode = ICP_INVALID;
+ al->url = log_uri;
+ debugs(33, 9, "clientLogRequest: al.url='" << al->url << "'");
- if (al.reply) {
- al.http.code = al.reply->sline.status;
- al.http.content_type = al.reply->content_type.termedBuf();
+ if (al->reply) {
+ al->http.code = al->reply->sline.status;
+ al->http.content_type = al->reply->content_type.termedBuf();
} else if (loggingEntry() && loggingEntry()->mem_obj) {
- al.http.code = loggingEntry()->mem_obj->getReply()->sline.status;
- al.http.content_type = loggingEntry()->mem_obj->getReply()->content_type.termedBuf();
+ al->http.code = loggingEntry()->mem_obj->getReply()->sline.status;
+ al->http.content_type = loggingEntry()->mem_obj->getReply()->content_type.termedBuf();
}
- debugs(33, 9, "clientLogRequest: http.code='" << al.http.code << "'");
+ debugs(33, 9, "clientLogRequest: http.code='" << al->http.code << "'");
if (loggingEntry() && loggingEntry()->mem_obj)
- al.cache.objectSize = loggingEntry()->contentLen();
+ al->cache.objectSize = loggingEntry()->contentLen();
- al.cache.caddr.SetNoAddr();
+ al->cache.caddr.SetNoAddr();
if (getConn() != NULL) {
- al.cache.caddr = getConn()->log_addr;
- al.cache.port = cbdataReference(getConn()->port);
+ al->cache.caddr = getConn()->log_addr;
+ al->cache.port = cbdataReference(getConn()->port);
}
- al.cache.requestSize = req_sz;
- al.cache.requestHeadersSize = req_sz;
+ al->cache.requestSize = req_sz;
+ al->cache.requestHeadersSize = req_sz;
- al.cache.replySize = out.size;
- al.cache.replyHeadersSize = out.headers_sz;
+ al->cache.replySize = out.size;
+ al->cache.replyHeadersSize = out.headers_sz;
- al.cache.highOffset = out.offset;
+ al->cache.highOffset = out.offset;
- al.cache.code = logType;
+ al->cache.code = logType;
- al.cache.msec = tvSubMsec(start_time, current_time);
+ al->cache.msec = tvSubMsec(start_time, current_time);
if (request)
- prepareLogWithRequestDetails(request, &al);
+ prepareLogWithRequestDetails(request, al);
if (getConn() != NULL && getConn()->clientConnection != NULL && getConn()->clientConnection->rfc931[0])
- al.cache.rfc931 = getConn()->clientConnection->rfc931;
+ al->cache.rfc931 = getConn()->clientConnection->rfc931;
#if USE_SSL && 0
* to snarf the ssl details some place earlier..
*/
if (getConn() != NULL)
- al.cache.ssluser = sslGetUserEmail(fd_table[getConn()->fd].ssl);
+ al->cache.ssluser = sslGetUserEmail(fd_table[getConn()->fd].ssl);
#endif
ACLFilledChecklist *checklist = clientAclChecklistCreate(Config.accessList.log, this);
- if (al.reply)
- checklist->reply = HTTPMSGLOCK(al.reply);
+ if (al->reply)
+ checklist->reply = HTTPMSGLOCK(al->reply);
if (!Config.accessList.log || checklist->fastCheck() == ACCESS_ALLOWED) {
if (request)
- al.adapted_request = HTTPMSGLOCK(request);
- accessLogLog(&al, checklist);
+ al->adapted_request = HTTPMSGLOCK(request);
+ accessLogLog(al, checklist);
updateCounters();
if (getConn() != NULL && getConn()->clientConnection != NULL)
}
delete checklist;
-
- accessLogFreeMemory(&al);
}
void
context->sendBody(rep, receivedData);
else {
assert(rep);
- http->al.reply = HTTPMSGLOCK(rep);
+ http->al->reply = HTTPMSGLOCK(rep);
context->sendStartOfMessage(rep, receivedData);
}
{
if (http) {
if (xerrno == ETIMEDOUT)
- http->al.http.timedout = true;
+ http->al->http.timedout = true;
else // even if xerrno is zero (which means read abort/eof)
- http->al.http.aborted = true;
+ http->al->http.aborted = true;
}
}
ClientHttpRequest *http = static_cast<ClientHttpRequest *>(io.data);
debugs(33, DBG_IMPORTANT, "WARNING: Closing client connection due to lifetime timeout");
debugs(33, DBG_IMPORTANT, "\t" << http->uri);
- http->al.http.timedout = true;
+ http->al->http.timedout = true;
if (Comm::IsConnOpen(io.conn))
io.conn->close();
}
/* prevent confusion over whether we default to persistent or not */
http->request->flags.proxy_keepalive = 0;
- http->al.http.code = errstate->httpStatus;
+ http->al->http.code = errstate->httpStatus;
createStoreEntry(method, request_flags());
#if USE_AUTH
/// Deny loops for accelerator and interceptor. TODO: deny in all modes?
if (r->flags.loopdetect &&
(http->flags.accel || http->flags.intercepted)) {
- http->al.http.code = HTTP_FORBIDDEN;
+ http->al->http.code = HTTP_FORBIDDEN;
err = clientBuildError(ERR_ACCESS_DENIED, HTTP_FORBIDDEN, NULL, http->getConn()->clientConnection->remote, http->request);
createStoreEntry(r->method, request_flags());
errorAppendEntry(http->storeEntry(), err);
{
debugs(88, 4, "clientProcessOnlyIfCachedMiss: '" <<
RequestMethodStr(http->request->method) << " " << http->uri << "'");
- http->al.http.code = HTTP_GATEWAY_TIMEOUT;
+ http->al->http.code = HTTP_GATEWAY_TIMEOUT;
ErrorState *err = clientBuildError(ERR_ONLY_IF_CACHED_MISS, HTTP_GATEWAY_TIMEOUT, NULL,
http->getConn()->clientConnection->remote, http->request);
removeClientStoreReference(&sc, http);
size_t k;
if ((k = headersEnd(buf, reqofs))) {
- safe_free(http->al.headers.reply);
- http->al.headers.reply = (char *)xcalloc(k + 1, 1);
- xstrncpy(http->al.headers.reply, buf, k);
+ safe_free(http->al->headers.reply);
+ http->al->headers.reply = (char *)xcalloc(k + 1, 1);
+ xstrncpy(http->al->headers.reply, buf, k);
}
}
{
start_time = current_time;
setConn(aConn);
- al.tcpClient = clientConnection = aConn->clientConnection;
+ al = new AccessLogEntry;
+ al->tcpClient = clientConnection = aConn->clientConnection;
dlinkAdd(this, &active, &ClientActiveRequests);
#if USE_ADAPTATION
request_satisfaction_mode = false;
loggingEntry(NULL);
if (request)
- checkFailureRatio(request->errType, al.hier.code);
+ checkFailureRatio(request->errType, al->hier.code);
freeResources();
#endif
logType = LOG_TCP_MISS;
getConn()->stopReading(); // tunnels read for themselves
- tunnelStart(this, &out.size, &al.http.code);
+ tunnelStart(this, &out.size, &al->http.code);
return;
}
assert(calloutContext);
/*Save the original request for logging purposes*/
- if (!calloutContext->http->al.request)
- calloutContext->http->al.request = HTTPMSGLOCK(request);
+ if (!calloutContext->http->al->request)
+ calloutContext->http->al->request = HTTPMSGLOCK(request);
// CVE-2009-0801: verify the Host: header is consistent with other known details.
if (!calloutContext->host_header_verify_done) {
log_type logType;
struct timeval start_time;
- AccessLogEntry al;
+ AccessLogEntry::Pointer al; ///< access.log entry
struct {
unsigned int accel:1;
}
void
-Format::Format::assemble(MemBuf &mb, AccessLogEntry *al, int logSequenceNumber) const
+Format::Format::assemble(MemBuf &mb, const AccessLogEntryPointer &al, int logSequenceNumber) const
{
char tmp[1024];
String sb;
#ifndef _SQUID_FORMAT_FORMAT_H
#define _SQUID_FORMAT_FORMAT_H
+#include "RefCount.h"
/*
* Squid configuration allows users to define custom formats in
* several components.
*/
class AccessLogEntry;
+typedef RefCount<AccessLogEntry> AccessLogEntryPointer;
class MemBuf;
class StoreEntry;
bool parse(char *def);
/// assemble the state information into a formatted line.
- void assemble(MemBuf &mb, AccessLogEntry *al, int logSequenceNumber) const;
+ void assemble(MemBuf &mb, const AccessLogEntryPointer &al, int logSequenceNumber) const;
/// dump this whole list of formats into the provided StoreEntry
void dump(StoreEntry * entry, const char *name);
static void
htcpLogHtcp(Ip::Address &caddr, int opcode, log_type logcode, const char *url)
{
- AccessLogEntry al;
+ AccessLogEntry::Pointer al = new AccessLogEntry;
if (LOG_TAG_NONE == logcode)
return;
if (!Config.onoff.log_udp)
return;
- al.htcp.opcode = htcpOpcodeStr[opcode];
- al.url = url;
- al.cache.caddr = caddr;
- al.cache.code = logcode;
- al.cache.msec = 0;
- accessLogLog(&al, NULL);
+ al->htcp.opcode = htcpOpcodeStr[opcode];
+ al->url = url;
+ al->cache.caddr = caddr;
+ al->cache.code = logcode;
+ al->cache.msec = 0;
+ accessLogLog(al, NULL);
}
static void
icpLogIcp(const Ip::Address &caddr, log_type logcode, int len, const char *url, int delay)
{
- AccessLogEntry al;
+ AccessLogEntry::Pointer al = new AccessLogEntry();
if (LOG_TAG_NONE == logcode)
return;
if (!Config.onoff.log_udp)
return;
- al.icp.opcode = ICP_QUERY;
+ al->icp.opcode = ICP_QUERY;
- al.url = url;
+ al->url = url;
- al.cache.caddr = caddr;
+ al->cache.caddr = caddr;
- al.cache.replySize = len;
+ al->cache.replySize = len;
- al.cache.code = logcode;
+ al->cache.code = logcode;
- al.cache.msec = delay;
+ al->cache.msec = delay;
- accessLogLog(&al, NULL);
+ accessLogLog(al, NULL);
}
/// \ingroup ServerProtocolICPInternal2
#include "SquidTime.h"
void
-Log::Format::HttpdCombined(AccessLogEntry * al, Logfile * logfile)
+Log::Format::HttpdCombined(const AccessLogEntry::Pointer &al, Logfile * logfile)
{
const char *user_ident = ::Format::QuoteUrlEncodeUsername(al->cache.rfc931);
const char *referer = NULL;
const char *agent = NULL;
- if (al && al->request) {
+ if (al->request) {
referer = al->request->header.getStr(HDR_REFERER);
agent = al->request->header.getStr(HDR_USER_AGENT);
}
#include "SquidTime.h"
void
-Log::Format::HttpdCommon(AccessLogEntry * al, Logfile * logfile)
+Log::Format::HttpdCommon(const AccessLogEntry::Pointer &al, Logfile * logfile)
{
const char *user_auth = ::Format::QuoteUrlEncodeUsername(al->cache.authuser);
const char *user_ident = ::Format::QuoteUrlEncodeUsername(al->cache.rfc931);
#include "MemBuf.h"
void
-Log::Format::SquidCustom(AccessLogEntry * al, customlog * log)
+Log::Format::SquidCustom(const AccessLogEntry::Pointer &al, customlog * log)
{
static MemBuf mb;
mb.reset();
#include "SquidTime.h"
void
-Log::Format::SquidIcap(AccessLogEntry * al, Logfile * logfile)
+Log::Format::SquidIcap(const AccessLogEntry::Pointer &al, Logfile * logfile)
{
const char *client = NULL;
const char *user = NULL;
#include "SquidTime.h"
void
-Log::Format::SquidNative(AccessLogEntry * al, Logfile * logfile)
+Log::Format::SquidNative(const AccessLogEntry::Pointer &al, Logfile * logfile)
{
char hierHost[MAX_IPSTRLEN];
#include "SquidTime.h"
void
-Log::Format::SquidReferer(AccessLogEntry *al, Logfile *logfile)
+Log::Format::SquidReferer(const AccessLogEntry::Pointer &al, Logfile *logfile)
{
const char *referer = NULL;
- if (al && al->request)
+ if (al->request)
referer = al->request->header.getStr(HDR_REFERER);
if (!referer || *referer == '\0')
#include "SquidTime.h"
void
-Log::Format::SquidUserAgent(AccessLogEntry * al, Logfile * logfile)
+Log::Format::SquidUserAgent(const AccessLogEntry::Pointer &al, Logfile * logfile)
{
const char *agent = NULL;
- if (al && al->request)
+ if (al->request)
agent = al->request->header.getStr(HDR_USER_AGENT);
if (!agent || *agent == '\0')
#ifndef _SQUID_LOG_FORMATS_H
#define _SQUID_LOG_FORMATS_H
+#include "RefCount.h"
+
+typedef RefCount<AccessLogEntry> AccessLogEntryPointer;
class AccessLogEntry;
class Logfile;
} log_type;
/// Native Squid Format Display
-void SquidNative(AccessLogEntry * al, Logfile * logfile);
+void SquidNative(const AccessLogEntryPointer &al, Logfile * logfile);
/// Display log details in Squid ICAP format.
-void SquidIcap(AccessLogEntry * al, Logfile * logfile);
+void SquidIcap(const AccessLogEntryPointer &al, Logfile * logfile);
/// Display log details in useragent format.
-void SquidUserAgent(AccessLogEntry * al, Logfile * logfile);
+void SquidUserAgent(const AccessLogEntryPointer &al, Logfile * logfile);
/// Display log details in Squid old refererlog format.
-void SquidReferer(AccessLogEntry * al, Logfile * logfile);
+void SquidReferer(const AccessLogEntryPointer &al, Logfile * logfile);
/// Log with a local custom format
-void SquidCustom(AccessLogEntry * al, customlog * log);
+void SquidCustom(const AccessLogEntryPointer &al, customlog * log);
/// Log with Apache httpd common format
-void HttpdCommon(AccessLogEntry * al, Logfile * logfile);
+void HttpdCommon(const AccessLogEntryPointer &al, Logfile * logfile);
/// Log with Apache httpd combined format
-void HttpdCombined(AccessLogEntry * al, Logfile * logfile);
+void HttpdCombined(const AccessLogEntryPointer &al, Logfile * logfile);
}; // namespace Format
}; // namespace Log
int LogfileStatus = LOG_DISABLE;
void
-accessLogLogTo(customlog* log, AccessLogEntry * al, ACLChecklist * checklist)
+accessLogLogTo(customlog* log, AccessLogEntry::Pointer &al, ACLChecklist * checklist)
{
if (al->url == NULL)
}
void
-accessLogLog(AccessLogEntry * al, ACLChecklist * checklist)
+accessLogLog(AccessLogEntry::Pointer &al, ACLChecklist * checklist)
{
if (LogfileStatus != LOG_ENABLE)
return;
#endif
-void
-accessLogFreeMemory(AccessLogEntry * aLogEntry)
-{
- safe_free(aLogEntry->headers.request);
-
-#if ICAP_CLIENT
- safe_free(aLogEntry->adapt.last_meta);
-#endif
-
- safe_free(aLogEntry->headers.reply);
- safe_free(aLogEntry->cache.authuser);
-
- safe_free(aLogEntry->headers.adapted_request);
- HTTPMSGUNLOCK(aLogEntry->adapted_request);
-
- HTTPMSGUNLOCK(aLogEntry->reply);
- HTTPMSGUNLOCK(aLogEntry->request);
-#if ICAP_CLIENT
- HTTPMSGUNLOCK(aLogEntry->icap.reply);
- HTTPMSGUNLOCK(aLogEntry->icap.request);
-#endif
- cbdataReferenceDone(aLogEntry->cache.port);
-}
-
int
logTypeIsATcpHit(log_type code)
{