Server.h \
structs.h \
swap_log_op.h \
- SwapDir.cc \
- SwapDir.h \
+ SwapDir.cc MemStore.cc \
+ SwapDir.h MemStore.h \
time.cc \
+ TimeOrTag.h \
tools.cc \
tunnel.cc \
typedefs.h \
comm/libcomm.la \
icmp/libicmp.la icmp/libicmp-core.la \
log/liblog.la \
+ format/libformat.la \
$(REPL_OBJS) \
+ $(DISK_OS_LIBS) \
$(ADAPTATION_LIBS) \
$(ESI_LIBS) \
$(SSL_LIBS) \
tests/stub_HelperChildConfig.cc \
tests/stub_HttpRequest.cc \
tests/stub_http.cc \
+ tests/stub_icp.cc \
tests/stub_internal.cc \
+ tests/stub_ipc.cc \
+ tests/stub_ipcache.cc \
+ tests/stub_libicmp.cc \
+ tests/stub_MemStore.cc \
tests/stub_mime.cc \
+ tests/stub_pconn.cc \
tests/stub_Port.cc \
tests/stub_store_client.cc \
tests/stub_store_rebuild.cc \
acl/libstate.la \
$(AUTH_LIBS) \
libsquid.la \
- base/libbase.la \
+ comm/libcomm.la \
ip/libip.la \
fs/libfs.la \
+ ipc/libipc.la \
$(REPL_OBJS) \
$(DISK_LIBS) \
$(DISK_OS_LIBS) \
acl/libapi.la \
mgr/libmgr.la \
+ ipc/libipc.la \
+ base/libbase.la \
+ $(SSL_LIBS) \
$(top_builddir)/lib/libmisccontainers.la \
$(top_builddir)/lib/libmiscencoding.la \
$(top_builddir)/lib/libmiscutil.la \
tests/testMain.cc \
tests/testUfs.h \
tests/stub_cache_manager.cc \
+ tests/stub_client_db.cc \
tests/stub_HelperChildConfig.cc \
+ tests/stub_icp.cc \
+ tests/stub_ipc.cc \
+ tests/stub_MemStore.cc \
+ tests/stub_pconn.cc \
tests/stub_Port.cc \
- tests/stub_TypedMsgHdr.cc \
tests/stub_UdsOp.cc \
tests/stub_internal.cc \
- tests/stub_CommIO.cc \
tests/stub_store_rebuild.cc \
fd.cc \
disk.cc \
libsquid.la \
ip/libip.la \
fs/libfs.la \
- ipc/libipc.la \
mgr/libmgr.la \
$(REPL_OBJS) \
+ acl/libacls.la \
+ anyp/libanyp.la \
$(DISK_LIBS) \
$(DISK_OS_LIBS) \
+ acl/libapi.la \
+ ipc/libipc.la \
+ $(SSL_LIBS) \
+ comm/libcomm.la \
base/libbase.la \
+ ip/libip.la \
$(top_builddir)/lib/libmisccontainers.la \
$(top_builddir)/lib/libmiscencoding.la \
$(top_builddir)/lib/libmiscutil.la \
$(REPL_OBJS) \
$(DISK_LIBS) \
$(DISK_OS_LIBS) \
+ $(COMMON_LIBS) \
+ libsquid.la \
acl/libapi.la \
+ ipc/libipc.la \
+ base/libbase.la \
$(top_builddir)/lib/libmisccontainers.la \
$(top_builddir)/lib/libmiscencoding.la \
$(top_builddir)/lib/libmiscutil.la \
icmp/libicmp.la icmp/libicmp-core.la \
comm/libcomm.la \
log/liblog.la \
+ $(DISK_OS_LIBS) \
+ format/libformat.la \
$(REGEXLIB) \
$(REPL_OBJS) \
$(ADAPTATION_LIBS) \
}
// pools connection if it is reusable or closes it
- void Adaptation::Icap::ServiceRep::putConnection(int fd, bool isReusable, bool sendReset, const char *comment)
-void Adaptation::Icap::ServiceRep::putConnection(const Comm::ConnectionPointer &conn, bool isReusable, const char *comment)
++void Adaptation::Icap::ServiceRep::putConnection(const Comm::ConnectionPointer &conn, bool isReusable, bool sendReset, const char *comment)
{
- Must(fd >= 0);
+ Must(Comm::IsConnOpen(conn));
// do not pool an idle connection if we owe connections
if (isReusable && excessConnections() == 0) {
debugs(93, 3, HERE << "pushing pconn" << comment);
- commSetTimeout(fd, -1, NULL, NULL);
- Ip::Address anyAddr;
- theIdleConns.push(fd, cfg().host.termedBuf(), cfg().port, NULL, anyAddr);
+ commUnsetConnTimeout(conn);
+ theIdleConns->push(conn);
} else {
- debugs(93, 3, HERE << "closing pconn" << comment);
- // comm_close will clear timeout
- conn->close();
+ debugs(93, 3, HERE << (sendReset ? "RST" : "FIN") << "-closing " <<
+ comment);
- // comm_close will clear timeout
++ // comm_close called from Connection::close will clear timeout
++ // TODO: add "bool sendReset = false" to Connection::close()?
+ if (sendReset)
- comm_reset_close(fd);
++ comm_reset_close(conn);
+ else
- comm_close(fd);
++ conn->close();
}
Must(theBusyConns > 0);
bool wantsPreview(const String &urlPath, size_t &wantedSize) const;
bool allows204() const;
bool allows206() const;
- int getConnection(bool isRetriable, bool &isReused);
- void putConnection(int fd, bool isReusable, bool sendReset, const char *comment);
- void noteConnectionUse(int fd);
+ Comm::ConnectionPointer getConnection(bool isRetriable, bool &isReused);
- void putConnection(const Comm::ConnectionPointer &conn, bool isReusable, const char *comment);
++ void putConnection(const Comm::ConnectionPointer &conn, bool isReusable, bool sendReset, const char *comment);
+ void noteConnectionUse(const Comm::ConnectionPointer &conn);
+ void noteConnectionFailed(const char *comment);
void noteFailure(); // called by transactions to report service failure
}
void
- ClientSocketContext::writeComplete(int aFileDescriptor, char *bufnotused, size_t size, comm_err_t errflag)
+ ClientSocketContext::writeComplete(const Comm::ConnectionPointer &conn, char *bufnotused, size_t size, comm_err_t errflag)
{
- StoreEntry *entry = http->storeEntry();
+ const StoreEntry *entry = http->storeEntry();
http->out.size += size;
- assert(aFileDescriptor > -1);
- debugs(33, 5, "clientWriteComplete: FD " << aFileDescriptor << ", sz " << size <<
+ debugs(33, 5, HERE << conn << ", sz " << size <<
", err " << errflag << ", off " << http->out.size << ", len " <<
- entry ? entry->objectLen() : 0);
+ (entry ? entry->objectLen() : 0));
clientUpdateSocketStats(http->logType, size);
- assert (this->fd() == aFileDescriptor);
/* Bail out quickly on COMM_ERR_CLOSING - close handlers will tidy up */
* closed, TCP generates a RESET
*/
void
- comm_reset_close(int fd)
-comm_reset_close(Comm::ConnectionPointer &conn)
++comm_reset_close(const Comm::ConnectionPointer &conn)
{
+ struct linger L;
+ L.l_onoff = 1;
+ L.l_linger = 0;
+
+ if (setsockopt(conn->fd, SOL_SOCKET, SO_LINGER, (char *) &L, sizeof(L)) < 0)
+ debugs(50, DBG_CRITICAL, "ERROR: Closing " << conn << " with TCP RST: " << xstrerror());
+
+ conn->close();
+ }
+ // Legacy close function.
+ void
+ old_comm_reset_close(int fd)
+ {
struct linger L;
L.l_onoff = 1;
L.l_linger = 0;
SQUIDCEXTERN void commSetCloseOnExec(int fd);
SQUIDCEXTERN void commSetTcpKeepalive(int fd, int idle, int interval, int timeout);
extern void _comm_close(int fd, char const *file, int line);
- #define comm_close(fd) (_comm_close((fd), __FILE__, __LINE__))
- SQUIDCEXTERN void comm_reset_close(int fd);
+ #define comm_close(x) (_comm_close((x), __FILE__, __LINE__))
+ SQUIDCEXTERN void old_comm_reset_close(int fd);
-SQUIDCEXTERN void comm_reset_close(Comm::ConnectionPointer &conn);
++SQUIDCEXTERN void comm_reset_close(const Comm::ConnectionPointer &conn);
#if LINGERING_CLOSE
SQUIDCEXTERN void comm_lingering_close(int fd);
#endif
--- /dev/null
- if (fmt->width) {
+ #include "config.h"
+ #include "AccessLogEntry.h"
+ #include "comm/Connection.h"
+ #include "err_detail_type.h"
+ #include "errorpage.h"
+ #include "format/Format.h"
+ #include "format/Quoting.h"
+ #include "format/Tokens.h"
+ #include "HttpRequest.h"
+ #include "MemBuf.h"
+ #include "rfc1738.h"
+ #include "SquidTime.h"
+ #include "Store.h"
+
+
+ Format::Format::Format(const char *n) :
+ format(NULL),
+ next(NULL)
+ {
+ name = xstrdup(n);
+ }
+
+ Format::Format::~Format()
+ {
+ // erase the list without consuming stack space
+ while (next) {
+ // unlink the next entry for deletion
+ Format *temp = next;
+ next = temp->next;
+ temp->next = NULL;
+ delete temp;
+ }
+
+ // remove locals
+ xfree(name);
+ delete format;
+ }
+
+ bool
+ Format::Format::parse(char *def)
+ {
+ char *cur, *eos;
+ Token *new_lt, *last_lt;
+ enum Quoting quote = LOG_QUOTE_NONE;
+
+ debugs(46, 2, HERE << "got definition '" << def << "'");
+
+ if (format) {
+ debugs(46, DBG_IMPORTANT, "WARNING: existing format for '" << name << " " << def << "'");
+ return false;
+ }
+
+ /* very inefficent parser, but who cares, this needs to be simple */
+ /* First off, let's tokenize, we'll optimize in a second pass.
+ * A token can either be a %-prefixed sequence (usually a dynamic
+ * token but it can be an escaped sequence), or a string. */
+ cur = def;
+ eos = def + strlen(def);
+ format = new_lt = last_lt = new Token;
+ cur += new_lt->parse(cur, "e);
+
+ while (cur < eos) {
+ new_lt = new Token;
+ last_lt->next = new_lt;
+ last_lt = new_lt;
+ cur += new_lt->parse(cur, "e);
+ }
+
+ return true;
+ }
+
+ void
+ Format::Format::dump(StoreEntry * entry, const char *name)
+ {
+ debugs(46, 4, HERE);
+
+ // loop rather than recursing to conserve stack space.
+ for (Format *format = this; format; format = format->next) {
+ debugs(46, 3, HERE << "Dumping format definition for " << format->name);
+ storeAppendPrintf(entry, "format %s ", format->name);
+
+ for (Token *t = format->format; t; t = t->next) {
+ if (t->type == LFT_STRING)
+ storeAppendPrintf(entry, "%s", t->data.string);
+ else {
+ char argbuf[256];
+ char *arg = NULL;
+ ByteCode_t type = t->type;
+
+ switch (type) {
+ /* special cases */
+
+ case LFT_STRING:
+ break;
+ #if USE_ADAPTATION
+ case LFT_ADAPTATION_LAST_HEADER_ELEM:
+ #endif
+ #if ICAP_CLIENT
+ case LFT_ICAP_REQ_HEADER_ELEM:
+ case LFT_ICAP_REP_HEADER_ELEM:
+ #endif
+ case LFT_REQUEST_HEADER_ELEM:
+ case LFT_ADAPTED_REQUEST_HEADER_ELEM:
+ case LFT_REPLY_HEADER_ELEM:
+
+ if (t->data.header.separator != ',')
+ snprintf(argbuf, sizeof(argbuf), "%s:%c%s", t->data.header.header, t->data.header.separator, t->data.header.element);
+ else
+ snprintf(argbuf, sizeof(argbuf), "%s:%s", t->data.header.header, t->data.header.element);
+
+ arg = argbuf;
+
+ switch (type) {
+ case LFT_REQUEST_HEADER_ELEM:
+ type = LFT_REQUEST_HEADER_ELEM; // XXX: remove _ELEM?
+ break;
+ case LFT_ADAPTED_REQUEST_HEADER_ELEM:
+ type = LFT_ADAPTED_REQUEST_HEADER_ELEM; // XXX: remove _ELEM?
+ break;
+ case LFT_REPLY_HEADER_ELEM:
+ type = LFT_REPLY_HEADER_ELEM; // XXX: remove _ELEM?
+ break;
+ #if USE_ADAPTATION
+ case LFT_ADAPTATION_LAST_HEADER_ELEM:
+ type = LFT_ADAPTATION_LAST_HEADER;
+ break;
+ #endif
+ #if ICAP_CLIENT
+ case LFT_ICAP_REQ_HEADER_ELEM:
+ type = LFT_ICAP_REQ_HEADER;
+ break;
+ case LFT_ICAP_REP_HEADER_ELEM:
+ type = LFT_ICAP_REP_HEADER;
+ break;
+ #endif
+ default:
+ break;
+ }
+
+ break;
+
+ case LFT_REQUEST_ALL_HEADERS:
+ case LFT_ADAPTED_REQUEST_ALL_HEADERS:
+ case LFT_REPLY_ALL_HEADERS:
+
+ #if USE_ADAPTATION
+ case LFT_ADAPTATION_LAST_ALL_HEADERS:
+ #endif
+ #if ICAP_CLIENT
+ case LFT_ICAP_REQ_ALL_HEADERS:
+ case LFT_ICAP_REP_ALL_HEADERS:
+ #endif
+
+ switch (type) {
+ case LFT_REQUEST_ALL_HEADERS:
+ type = LFT_REQUEST_HEADER;
+ break;
+ case LFT_ADAPTED_REQUEST_ALL_HEADERS:
+ type = LFT_ADAPTED_REQUEST_HEADER;
+ break;
+ case LFT_REPLY_ALL_HEADERS:
+ type = LFT_REPLY_HEADER;
+ break;
+ #if USE_ADAPTATION
+ case LFT_ADAPTATION_LAST_ALL_HEADERS:
+ type = LFT_ADAPTATION_LAST_HEADER;
+ break;
+ #endif
+ #if ICAP_CLIENT
+ case LFT_ICAP_REQ_ALL_HEADERS:
+ type = LFT_ICAP_REQ_HEADER;
+ break;
+ case LFT_ICAP_REP_ALL_HEADERS:
+ type = LFT_ICAP_REP_HEADER;
+ break;
+ #endif
+ default:
+ break;
+ }
+
+ break;
+
+ default:
+ if (t->data.string)
+ arg = t->data.string;
+
+ break;
+ }
+
+ entry->append("%", 1);
+
+ switch (t->quote) {
+
+ case LOG_QUOTE_QUOTES:
+ entry->append("\"", 1);
+ break;
+
+ case LOG_QUOTE_MIMEBLOB:
+ entry->append("[", 1);
+ break;
+
+ case LOG_QUOTE_URL:
+ entry->append("#", 1);
+ break;
+
+ case LOG_QUOTE_RAW:
+ entry->append("'", 1);
+ break;
+
+ case LOG_QUOTE_NONE:
+ break;
+ }
+
+ if (t->left)
+ entry->append("-", 1);
+
+ if (t->zero)
+ entry->append("0", 1);
+
+ if (t->width)
+ storeAppendPrintf(entry, "%d", (int) t->width);
+
+ if (t->precision)
+ storeAppendPrintf(entry, ".%d", (int) t->precision);
+
+ if (arg)
+ storeAppendPrintf(entry, "{%s}", arg);
+
+ for (struct TokenTableEntry *te = TokenTable; te->config != NULL; te++) {
+ if (te->token_type == type) {
+ storeAppendPrintf(entry, "%s", te->config);
+ break;
+ }
+ }
+
+ if (t->space)
+ entry->append(" ", 1);
+ }
+ }
+
+ entry->append("\n", 1);
+ }
+
+ }
+
+ static void
+ log_quoted_string(const char *str, char *out)
+ {
+ char *p = out;
+
+ while (*str) {
+ int l = strcspn(str, "\"\\\r\n\t");
+ memcpy(p, str, l);
+ str += l;
+ p += l;
+
+ switch (*str) {
+
+ case '\0':
+ break;
+
+ case '\r':
+ *p++ = '\\';
+ *p++ = 'r';
+ str++;
+ break;
+
+ case '\n':
+ *p++ = '\\';
+ *p++ = 'n';
+ str++;
+ break;
+
+ case '\t':
+ *p++ = '\\';
+ *p++ = 't';
+ str++;
+ break;
+
+ default:
+ *p++ = '\\';
+ *p++ = *str;
+ str++;
+ break;
+ }
+ }
+
+ *p++ = '\0';
+ }
+
+ void
+ Format::Format::assemble(MemBuf &mb, AccessLogEntry *al, int logSequenceNumber) const
+ {
+ char tmp[1024];
+ String sb;
+
+ for (Token *fmt = format; fmt != NULL; fmt = fmt->next) { /* for each token */
+ const char *out = NULL;
+ int quote = 0;
+ long int outint = 0;
+ int doint = 0;
+ int dofree = 0;
+ int64_t outoff = 0;
+ int dooff = 0;
+
+ switch (fmt->type) {
+
+ case LFT_NONE:
+ out = "";
+ break;
+
+ case LFT_STRING:
+ out = fmt->data.string;
+ break;
+
+ case LFT_CLIENT_IP_ADDRESS:
+ if (al->cache.caddr.IsNoAddr()) // e.g., ICAP OPTIONS lack client
+ out = "-";
+ else
+ out = al->cache.caddr.NtoA(tmp,1024);
+ break;
+
+ case LFT_CLIENT_FQDN:
+ if (al->cache.caddr.IsAnyAddr()) // e.g., ICAP OPTIONS lack client
+ out = "-";
+ else
+ out = fqdncache_gethostbyaddr(al->cache.caddr, FQDN_LOOKUP_IF_MISS);
+ if (!out) {
+ out = al->cache.caddr.NtoA(tmp,1024);
+ }
+
+ break;
+
+ case LFT_CLIENT_PORT:
+ if (al->request) {
+ outint = al->request->client_addr.GetPort();
+ doint = 1;
+ }
+ break;
+
+ #if USE_SQUID_EUI
+ case LFT_CLIENT_EUI:
+ // TODO make the ACL checklist have a direct link to any TCP details.
+ if (al->request && al->request->clientConnectionManager.valid() && al->request->clientConnectionManager->clientConnection != NULL) {
+ if (al->request->clientConnectionManager->clientConnection->remote.IsIPv4())
+ al->request->clientConnectionManager->clientConnection->remoteEui48.encode(tmp, 1024);
+ else
+ al->request->clientConnectionManager->clientConnection->remoteEui64.encode(tmp, 1024);
+ out = tmp;
+ }
+ break;
+ #endif
+
+ /* case LFT_SERVER_IP_ADDRESS: */
+
+ case LFT_SERVER_IP_OR_PEER_NAME:
+ out = al->hier.host;
+
+ break;
+
+ /* case LFT_SERVER_PORT: */
+
+ case LFT_LOCAL_IP:
+ if (al->request) {
+ out = al->request->my_addr.NtoA(tmp,sizeof(tmp));
+ }
+
+ break;
+
+ case LFT_LOCAL_PORT:
+ if (al->request) {
+ outint = al->request->my_addr.GetPort();
+ doint = 1;
+ }
+
+ break;
+
+ // the fmt->type can not be LFT_PEER_LOCAL_IP_OLD_27
+ // but compiler complains if ommited
+ case LFT_PEER_LOCAL_IP_OLD_27:
+ case LFT_PEER_LOCAL_IP:
+ if (!al->hier.peer_local_addr.IsAnyAddr()) {
+ out = al->hier.peer_local_addr.NtoA(tmp,sizeof(tmp));
+ }
+ break;
+
+ case LFT_PEER_LOCAL_PORT:
+ if ((outint = al->hier.peer_local_addr.GetPort())) {
+ doint = 1;
+ }
+
+ break;
+
+ case LFT_TIME_SECONDS_SINCE_EPOCH:
+ // some platforms store time in 32-bit, some 64-bit...
+ outoff = static_cast<int64_t>(current_time.tv_sec);
+ dooff = 1;
+ break;
+
+ case LFT_TIME_SUBSECOND:
+ outint = current_time.tv_usec / fmt->divisor;
+ doint = 1;
+ break;
+
+
+ case LFT_TIME_LOCALTIME:
+
+ case LFT_TIME_GMT: {
+ const char *spec;
+
+ struct tm *t;
+ spec = fmt->data.timespec;
+
+ if (fmt->type == LFT_TIME_LOCALTIME) {
+ if (!spec)
+ spec = "%d/%b/%Y:%H:%M:%S %z";
+ t = localtime(&squid_curtime);
+ } else {
+ if (!spec)
+ spec = "%d/%b/%Y:%H:%M:%S";
+
+ t = gmtime(&squid_curtime);
+ }
+
+ strftime(tmp, sizeof(tmp), spec, t);
+
+ out = tmp;
+ }
+
+ break;
+
+ case LFT_TIME_TO_HANDLE_REQUEST:
+ outint = al->cache.msec;
+ doint = 1;
+ break;
+
+ case LFT_PEER_RESPONSE_TIME:
+ if (al->hier.peer_response_time < 0) {
+ out = "-";
+ } else {
+ outoff = al->hier.peer_response_time;
+ dooff = 1;
+ }
+ break;
+
+ case LFT_TOTAL_SERVER_SIDE_RESPONSE_TIME:
+ if (al->hier.total_response_time < 0) {
+ out = "-";
+ } else {
+ outoff = al->hier.total_response_time;
+ dooff = 1;
+ }
+ break;
+
+ case LFT_DNS_WAIT_TIME:
+ if (al->request && al->request->dnsWait >= 0) {
+ outint = al->request->dnsWait;
+ doint = 1;
+ }
+ break;
+
+ case LFT_REQUEST_HEADER:
+
+ if (al->request)
+ sb = al->request->header.getByName(fmt->data.header.header);
+
+ out = sb.termedBuf();
+
+ quote = 1;
+
+ break;
+
+ case LFT_ADAPTED_REQUEST_HEADER:
+
+ if (al->request)
+ sb = al->adapted_request->header.getByName(fmt->data.header.header);
+
+ out = sb.termedBuf();
+
+ quote = 1;
+
+ break;
+
+ case LFT_REPLY_HEADER:
+ if (al->reply)
+ sb = al->reply->header.getByName(fmt->data.header.header);
+
+ out = sb.termedBuf();
+
+ quote = 1;
+
+ break;
+
+ #if USE_ADAPTATION
+ case LTF_ADAPTATION_SUM_XACT_TIMES:
+ if (al->request) {
+ Adaptation::History::Pointer ah = al->request->adaptHistory();
+ if (ah != NULL)
+ ah->sumLogString(fmt->data.string, sb);
+ out = sb.termedBuf();
+ }
+ break;
+
+ case LTF_ADAPTATION_ALL_XACT_TIMES:
+ if (al->request) {
+ Adaptation::History::Pointer ah = al->request->adaptHistory();
+ if (ah != NULL)
+ ah->allLogString(fmt->data.string, sb);
+ out = sb.termedBuf();
+ }
+ break;
+
+ case LFT_ADAPTATION_LAST_HEADER:
+ if (al->request) {
+ const Adaptation::History::Pointer ah = al->request->adaptHistory();
+ if (ah != NULL) // XXX: add adapt::<all_h but use lastMeta here
+ sb = ah->allMeta.getByName(fmt->data.header.header);
+ }
+
+ // XXX: here and elsewhere: move such code inside the if guard
+ out = sb.termedBuf();
+
+ quote = 1;
+
+ break;
+
+ case LFT_ADAPTATION_LAST_HEADER_ELEM:
+ if (al->request) {
+ const Adaptation::History::Pointer ah = al->request->adaptHistory();
+ if (ah != NULL) // XXX: add adapt::<all_h but use lastMeta here
+ sb = ah->allMeta.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
+ }
+
+ out = sb.termedBuf();
+
+ quote = 1;
+
+ break;
+
+ case LFT_ADAPTATION_LAST_ALL_HEADERS:
+ out = al->adapt.last_meta;
+
+ quote = 1;
+
+ break;
+ #endif
+
+ #if ICAP_CLIENT
+ case LFT_ICAP_ADDR:
+ if (!out)
+ out = al->icap.hostAddr.NtoA(tmp,1024);
+ break;
+
+ case LFT_ICAP_SERV_NAME:
+ out = al->icap.serviceName.termedBuf();
+ break;
+
+ case LFT_ICAP_REQUEST_URI:
+ out = al->icap.reqUri.termedBuf();
+ break;
+
+ case LFT_ICAP_REQUEST_METHOD:
+ out = Adaptation::Icap::ICAP::methodStr(al->icap.reqMethod);
+ break;
+
+ case LFT_ICAP_BYTES_SENT:
+ outoff = al->icap.bytesSent;
+ dooff = 1;
+ break;
+
+ case LFT_ICAP_BYTES_READ:
+ outoff = al->icap.bytesRead;
+ dooff = 1;
+ break;
+
+ case LFT_ICAP_BODY_BYTES_READ:
+ if (al->icap.bodyBytesRead >= 0) {
+ outoff = al->icap.bodyBytesRead;
+ dooff = 1;
+ }
+ // else if icap.bodyBytesRead < 0, we do not have any http data,
+ // so just print a "-" (204 responses etc)
+ break;
+
+ case LFT_ICAP_REQ_HEADER:
+ if (NULL != al->icap.request) {
+ sb = al->icap.request->header.getByName(fmt->data.header.header);
+ out = sb.termedBuf();
+ quote = 1;
+ }
+ break;
+
+ case LFT_ICAP_REQ_HEADER_ELEM:
+ if (al->request)
+ sb = al->icap.request->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
+
+ out = sb.termedBuf();
+
+ quote = 1;
+
+ break;
+
+ case LFT_ICAP_REQ_ALL_HEADERS:
+ if (al->icap.request) {
+ HttpHeaderPos pos = HttpHeaderInitPos;
+ while (const HttpHeaderEntry *e = al->icap.request->header.getEntry(&pos)) {
+ sb.append(e->name);
+ sb.append(": ");
+ sb.append(e->value);
+ sb.append("\r\n");
+ }
+ out = sb.termedBuf();
+ quote = 1;
+ }
+ break;
+
+ case LFT_ICAP_REP_HEADER:
+ if (NULL != al->icap.reply) {
+ sb = al->icap.reply->header.getByName(fmt->data.header.header);
+ out = sb.termedBuf();
+ quote = 1;
+ }
+ break;
+
+ case LFT_ICAP_REP_HEADER_ELEM:
+ if (NULL != al->icap.reply)
+ sb = al->icap.reply->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
+
+ out = sb.termedBuf();
+
+ quote = 1;
+
+ break;
+
+ case LFT_ICAP_REP_ALL_HEADERS:
+ if (al->icap.reply) {
+ HttpHeaderPos pos = HttpHeaderInitPos;
+ while (const HttpHeaderEntry *e = al->icap.reply->header.getEntry(&pos)) {
+ sb.append(e->name);
+ sb.append(": ");
+ sb.append(e->value);
+ sb.append("\r\n");
+ }
+ out = sb.termedBuf();
+ quote = 1;
+ }
+ break;
+
+ case LFT_ICAP_TR_RESPONSE_TIME:
+ outint = al->icap.trTime;
+ doint = 1;
+ break;
+
+ case LFT_ICAP_IO_TIME:
+ outint = al->icap.ioTime;
+ doint = 1;
+ break;
+
+ case LFT_ICAP_STATUS_CODE:
+ outint = al->icap.resStatus;
+ doint = 1;
+ break;
+
+ case LFT_ICAP_OUTCOME:
+ out = al->icap.outcome;
+ break;
+
+ case LFT_ICAP_TOTAL_TIME:
+ outint = al->icap.processingTime;
+ doint = 1;
+ break;
+ #endif
+ case LFT_REQUEST_HEADER_ELEM:
+ if (al->request)
+ sb = al->request->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
+
+ out = sb.termedBuf();
+
+ quote = 1;
+
+ break;
+
+ case LFT_ADAPTED_REQUEST_HEADER_ELEM:
+ if (al->adapted_request)
+ sb = al->adapted_request->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
+
+ out = sb.termedBuf();
+
+ quote = 1;
+
+ break;
+
+ case LFT_REPLY_HEADER_ELEM:
+ if (al->reply)
+ sb = al->reply->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
+
+ out = sb.termedBuf();
+
+ quote = 1;
+
+ break;
+
+ case LFT_REQUEST_ALL_HEADERS:
+ out = al->headers.request;
+
+ quote = 1;
+
+ break;
+
+ case LFT_ADAPTED_REQUEST_ALL_HEADERS:
+ out = al->headers.adapted_request;
+
+ quote = 1;
+
+ break;
+
+ case LFT_REPLY_ALL_HEADERS:
+ out = al->headers.reply;
+
+ quote = 1;
+
+ break;
+
+ case LFT_USER_NAME:
+ out = QuoteUrlEncodeUsername(al->cache.authuser);
+
+ if (!out)
+ out = QuoteUrlEncodeUsername(al->cache.extuser);
+
+ #if USE_SSL
+
+ if (!out)
+ out = QuoteUrlEncodeUsername(al->cache.ssluser);
+
+ #endif
+
+ if (!out)
+ out = QuoteUrlEncodeUsername(al->cache.rfc931);
+
+ dofree = 1;
+
+ break;
+
+ case LFT_USER_LOGIN:
+ out = QuoteUrlEncodeUsername(al->cache.authuser);
+
+ dofree = 1;
+
+ break;
+
+ case LFT_USER_IDENT:
+ out = QuoteUrlEncodeUsername(al->cache.rfc931);
+
+ dofree = 1;
+
+ break;
+
+ case LFT_USER_EXTERNAL:
+ out = QuoteUrlEncodeUsername(al->cache.extuser);
+
+ dofree = 1;
+
+ break;
+
+ /* case LFT_USER_REALM: */
+ /* case LFT_USER_SCHEME: */
+
+ // the fmt->type can not be LFT_HTTP_SENT_STATUS_CODE_OLD_30
+ // but compiler complains if ommited
+ case LFT_HTTP_SENT_STATUS_CODE_OLD_30:
+ case LFT_HTTP_SENT_STATUS_CODE:
+ outint = al->http.code;
+
+ doint = 1;
+
+ break;
+
+ case LFT_HTTP_RECEIVED_STATUS_CODE:
+ if (al->hier.peer_reply_status == HTTP_STATUS_NONE) {
+ out = "-";
+ } else {
+ outint = al->hier.peer_reply_status;
+ doint = 1;
+ }
+ break;
+ /* case LFT_HTTP_STATUS:
+ * out = statusline->text;
+ * quote = 1;
+ * break;
+ */
+ case LFT_HTTP_BODY_BYTES_READ:
+ if (al->hier.bodyBytesRead >= 0) {
+ outoff = al->hier.bodyBytesRead;
+ dooff = 1;
+ }
+ // else if hier.bodyBytesRead < 0 we did not have any data exchange with
+ // a peer server so just print a "-" (eg requests served from cache,
+ // or internal error messages).
+ break;
+
+ case LFT_SQUID_STATUS:
+ if (al->http.timedout || al->http.aborted) {
+ snprintf(tmp, sizeof(tmp), "%s%s", log_tags[al->cache.code],
+ al->http.statusSfx());
+ out = tmp;
+ } else {
+ out = log_tags[al->cache.code];
+ }
+
+ break;
+
+ case LFT_SQUID_ERROR:
+ if (al->request && al->request->errType != ERR_NONE)
+ out = errorPageName(al->request->errType);
+ break;
+
+ case LFT_SQUID_ERROR_DETAIL:
+ if (al->request && al->request->errDetail != ERR_DETAIL_NONE) {
+ if (al->request->errDetail > ERR_DETAIL_START &&
+ al->request->errDetail < ERR_DETAIL_MAX)
+ out = errorDetailName(al->request->errDetail);
+ else {
+ if (al->request->errDetail >= ERR_DETAIL_EXCEPTION_START)
+ snprintf(tmp, sizeof(tmp), "%s=0x%X",
+ errorDetailName(al->request->errDetail), (uint32_t) al->request->errDetail);
+ else
+ snprintf(tmp, sizeof(tmp), "%s=%d",
+ errorDetailName(al->request->errDetail), al->request->errDetail);
+ out = tmp;
+ }
+ }
+ break;
+
+ case LFT_SQUID_HIERARCHY:
+ if (al->hier.ping.timedout)
+ mb.append("TIMEOUT_", 8);
+
+ out = hier_code_str[al->hier.code];
+
+ break;
+
+ case LFT_MIME_TYPE:
+ out = al->http.content_type;
+
+ break;
+
+ case LFT_CLIENT_REQ_METHOD:
+ if (al->request) {
+ out = al->request->method.image();
+ quote = 1;
+ }
+ break;
+
+ case LFT_CLIENT_REQ_URI:
+ // original client URI
+ if (al->request) {
+ out = urlCanonical(al->request);
+ quote = 1;
+ }
+ break;
+
+ case LFT_REQUEST_URLPATH_OLD_31:
+ case LFT_CLIENT_REQ_URLPATH:
+ if (al->request) {
+ out = al->request->urlpath.termedBuf();
+ quote = 1;
+ }
+ break;
+
+ case LFT_CLIENT_REQ_VERSION:
+ if (al->request) {
+ snprintf(tmp, sizeof(tmp), "%d.%d", (int) al->request->http_ver.major, (int) al->request->http_ver.minor);
+ out = tmp;
+ }
+ break;
+
+ case LFT_REQUEST_METHOD:
+ out = al->_private.method_str;
+ break;
+
+ case LFT_REQUEST_URI:
+ out = al->url;
+ break;
+
+ case LFT_REQUEST_VERSION_OLD_2X:
+ case LFT_REQUEST_VERSION:
+ snprintf(tmp, sizeof(tmp), "%d.%d", (int) al->http.version.major, (int) al->http.version.minor);
+ out = tmp;
+ break;
+
+ case LFT_SERVER_REQ_METHOD:
+ if (al->adapted_request) {
+ out = al->adapted_request->method.image();
+ quote = 1;
+ }
+ break;
+
+ case LFT_SERVER_REQ_URI:
+ // adapted request URI sent to server/peer
+ if (al->adapted_request) {
+ out = urlCanonical(al->adapted_request);
+ quote = 1;
+ }
+ break;
+
+ case LFT_SERVER_REQ_URLPATH:
+ if (al->adapted_request) {
+ out = al->adapted_request->urlpath.termedBuf();
+ quote = 1;
+ }
+ break;
+
+ case LFT_SERVER_REQ_VERSION:
+ if (al->adapted_request) {
+ snprintf(tmp, sizeof(tmp), "%d.%d",
+ (int) al->adapted_request->http_ver.major,
+ (int) al->adapted_request->http_ver.minor);
+ out = tmp;
+ }
+ break;
+
+ case LFT_REQUEST_SIZE_TOTAL:
+ outoff = al->cache.requestSize;
+ dooff = 1;
+ break;
+
+ /*case LFT_REQUEST_SIZE_LINE: */
+ case LFT_REQUEST_SIZE_HEADERS:
+ outoff = al->cache.requestHeadersSize;
+ dooff =1;
+ break;
+ /*case LFT_REQUEST_SIZE_BODY: */
+ /*case LFT_REQUEST_SIZE_BODY_NO_TE: */
+
+ case LFT_REPLY_SIZE_TOTAL:
+ outoff = al->cache.replySize;
+ dooff = 1;
+ break;
+
+ case LFT_REPLY_HIGHOFFSET:
+ outoff = al->cache.highOffset;
+
+ dooff = 1;
+
+ break;
+
+ case LFT_REPLY_OBJECTSIZE:
+ outoff = al->cache.objectSize;
+
+ dooff = 1;
+
+ break;
+
+ /*case LFT_REPLY_SIZE_LINE: */
+ case LFT_REPLY_SIZE_HEADERS:
+ outint = al->cache.replyHeadersSize;
+ doint = 1;
+ break;
+ /*case LFT_REPLY_SIZE_BODY: */
+ /*case LFT_REPLY_SIZE_BODY_NO_TE: */
+
+ case LFT_TAG:
+ if (al->request)
+ out = al->request->tag.termedBuf();
+
+ quote = 1;
+
+ break;
+
+ case LFT_IO_SIZE_TOTAL:
+ outint = al->cache.requestSize + al->cache.replySize;
+ doint = 1;
+ break;
+
+ case LFT_EXT_LOG:
+ if (al->request)
+ out = al->request->extacl_log.termedBuf();
+
+ quote = 1;
+
+ break;
+
+ case LFT_SEQUENCE_NUMBER:
+ outoff = logSequenceNumber;
+ dooff = 1;
+ break;
+
+ case LFT_PERCENT:
+ out = "%";
+
+ break;
+ }
+
+ if (dooff) {
+ snprintf(tmp, sizeof(tmp), "%0*" PRId64, fmt->zero ? (int) fmt->width : 0, outoff);
+ out = tmp;
+
+ } else if (doint) {
+ snprintf(tmp, sizeof(tmp), "%0*ld", fmt->zero ? (int) fmt->width : 0, outint);
+ out = tmp;
+ }
+
+ if (out && *out) {
+ if (quote || fmt->quote != LOG_QUOTE_NONE) {
+ char *newout = NULL;
+ int newfree = 0;
+
+ switch (fmt->quote) {
+
+ case LOG_QUOTE_NONE:
+ newout = rfc1738_escape_unescaped(out);
+ break;
+
+ case LOG_QUOTE_QUOTES: {
+ size_t out_len = static_cast<size_t>(strlen(out)) * 2 + 1;
+ if (out_len >= sizeof(tmp)) {
+ newout = (char *)xmalloc(out_len);
+ newfree = 1;
+ } else
+ newout = tmp;
+ log_quoted_string(out, newout);
+ }
+ break;
+
+ case LOG_QUOTE_MIMEBLOB:
+ newout = QuoteMimeBlob(out);
+ newfree = 1;
+ break;
+
+ case LOG_QUOTE_URL:
+ newout = rfc1738_escape(out);
+ break;
+
+ case LOG_QUOTE_RAW:
+ break;
+ }
+
+ if (newout) {
+ if (dofree)
+ safe_free(out);
+
+ out = newout;
+
+ dofree = newfree;
+ }
+ }
+
- mb.Printf("%-*s", (int) fmt->width, out);
++ // enforce width limits if configured
++ const bool haveMaxWidth = fmt->precision && !doint && !dooff;
++ if (haveMaxWidth || fmt->width) {
++ const int minWidth = fmt->width ?
++ static_cast<int>(fmt->width) : 0;
++ const int maxWidth = haveMaxWidth ?
++ static_cast<int>(fmt->precision) : strlen(out);
++
+ if (fmt->left)
- mb.Printf("%*s", (int) fmt->width, out);
++ mb.Printf("%-*.*s", minWidth, maxWidth, out);
+ else
++ mb.Printf("%*.*s", minWidth, maxWidth, out);
+ } else
+ mb.append(out, strlen(out));
+ } else {
+ mb.append("-", 1);
+ }
+
+ if (fmt->space)
+ mb.append(" ", 1);
+
+ sb.clean();
+
+ if (dofree)
+ safe_free(out);
+ }
+ }
} header;
char *timespec;
} data;
- unsigned char width;
- unsigned char precision;
+ unsigned int width;
+ unsigned int precision;
- enum log_quote quote;
+ enum Quoting quote;
unsigned int left:1;
unsigned int space:1;
unsigned int zero:1;
private:
StrandCoords strands_; ///< registered processes and threads
- typedef std::map<OpenListenerParams, Comm::ConnectionPointer> Listeners; ///< params:fd map
+ typedef std::list<StrandSearchRequest> Searchers; ///< search requests
+ Searchers searchers; ///< yet unanswered search requests in arrival order
+
- typedef std::map<OpenListenerParams, int> Listeners; ///< params:fd map
++ typedef std::map<OpenListenerParams, Comm::ConnectionPointer> Listeners; ///< params:connection map
Listeners listeners; ///< cached comm_open_listener() results
static Coordinator* TheInstance; ///< the only class instance in existence
Inquirer.cc \
Inquirer.h \
Request.h \
- Response.h
+ Response.h \
+ \
+ mem/Page.cc \
+ mem/Page.h \
+ mem/PagePool.cc \
+ mem/PagePool.h \
+ mem/Pages.cc \
+ mem/Pages.h \
+ mem/PageStack.cc \
+ mem/PageStack.h \
+ mem/Pointer.h \
+ mem/Segment.cc \
+ mem/Segment.h
- DEFS += -DDEFAULT_PREFIX=\"$(prefix)\"
+ DEFS += -DDEFAULT_STATEDIR=\"$(localstatedir)/run/squid\"
+
+ install-data-local:
+ $(mkinstalldirs) $(DESTDIR)$(localstatedir)/run/squid;
--- /dev/null
--- /dev/null
++/*
++ * $Id$
++ *
++ * DEBUG: section 46 Access Log - Squid Custom format
++ * AUTHOR: Duane Wessels
++ *
++ * SQUID Web Proxy Cache http://www.squid-cache.org/
++ * ----------------------------------------------------------
++ *
++ * Squid is the result of efforts by numerous individuals from
++ * the Internet community; see the CONTRIBUTORS file for full
++ * details. Many organizations have provided support for Squid's
++ * development; see the SPONSORS file for full details. Squid is
++ * Copyrighted (C) 2001 by the Regents of the University of
++ * California; see the COPYRIGHT file for full details. Squid
++ * incorporates software developed and/or copyrighted by other
++ * sources; see the CREDITS file for full details.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
++ *
++ */
++
++#include "config.h"
++#include "AccessLogEntry.h"
++#include "log/File.h"
++#include "log/Formats.h"
++#include "log/Gadgets.h"
++#include "log/Tokens.h"
++#include "SquidTime.h"
++
++#include "MemBuf.h"
++#include "HttpRequest.h"
++#include "rfc1738.h"
++#include "err_detail_type.h"
++#include "errorpage.h"
++
++static void
++log_quoted_string(const char *str, char *out)
++{
++ char *p = out;
++
++ while (*str) {
++ int l = strcspn(str, "\"\\\r\n\t");
++ memcpy(p, str, l);
++ str += l;
++ p += l;
++
++ switch (*str) {
++
++ case '\0':
++ break;
++
++ case '\r':
++ *p++ = '\\';
++ *p++ = 'r';
++ str++;
++ break;
++
++ case '\n':
++ *p++ = '\\';
++ *p++ = 'n';
++ str++;
++ break;
++
++ case '\t':
++ *p++ = '\\';
++ *p++ = 't';
++ str++;
++ break;
++
++ default:
++ *p++ = '\\';
++ *p++ = *str;
++ str++;
++ break;
++ }
++ }
++
++ *p++ = '\0';
++}
++
++void
++Log::Format::SquidCustom(AccessLogEntry * al, customlog * log)
++{
++ logformat *lf;
++ Logfile *logfile;
++ logformat_token *fmt;
++ static MemBuf mb;
++ char tmp[1024];
++ String sb;
++
++ mb.reset();
++
++ lf = log->logFormat;
++ logfile = log->logfile;
++
++ for (fmt = lf->format; fmt != NULL; fmt = fmt->next) { /* for each token */
++ const char *out = NULL;
++ int quote = 0;
++ long int outint = 0;
++ int doint = 0;
++ int dofree = 0;
++ int64_t outoff = 0;
++ int dooff = 0;
++
++ switch (fmt->type) {
++
++ case LFT_NONE:
++ out = "";
++ break;
++
++ case LFT_STRING:
++ out = fmt->data.string;
++ break;
++
++ case LFT_CLIENT_IP_ADDRESS:
++ if (al->cache.caddr.IsNoAddr()) // e.g., ICAP OPTIONS lack client
++ out = "-";
++ else
++ out = al->cache.caddr.NtoA(tmp,1024);
++ break;
++
++ case LFT_CLIENT_FQDN:
++ if (al->cache.caddr.IsAnyAddr()) // e.g., ICAP OPTIONS lack client
++ out = "-";
++ else
++ out = fqdncache_gethostbyaddr(al->cache.caddr, FQDN_LOOKUP_IF_MISS);
++ if (!out) {
++ out = al->cache.caddr.NtoA(tmp,1024);
++ }
++
++ break;
++
++ case LFT_CLIENT_PORT:
++ if (al->request) {
++ outint = al->request->client_addr.GetPort();
++ doint = 1;
++ }
++ break;
++
++#if USE_SQUID_EUI
++ case LFT_CLIENT_EUI:
++ if (al->request) {
++ if (al->cache.caddr.IsIPv4())
++ al->request->client_eui48.encode(tmp, 1024);
++ else
++ al->request->client_eui64.encode(tmp, 1024);
++ out = tmp;
++ }
++ break;
++#endif
++
++ /* case LFT_SERVER_IP_ADDRESS: */
++
++ case LFT_SERVER_IP_OR_PEER_NAME:
++ out = al->hier.host;
++
++ break;
++
++ /* case LFT_SERVER_PORT: */
++
++ case LFT_LOCAL_IP:
++ if (al->request) {
++ out = al->request->my_addr.NtoA(tmp,sizeof(tmp));
++ }
++
++ break;
++
++ case LFT_LOCAL_PORT:
++ if (al->request) {
++ outint = al->request->my_addr.GetPort();
++ doint = 1;
++ }
++
++ break;
++
++ // the fmt->type can not be LFT_PEER_LOCAL_IP_OLD_27
++ // but compiler complains if ommited
++ case LFT_PEER_LOCAL_IP_OLD_27:
++ case LFT_PEER_LOCAL_IP:
++ if (!al->hier.peer_local_addr.IsAnyAddr()) {
++ out = al->hier.peer_local_addr.NtoA(tmp,sizeof(tmp));
++ }
++ break;
++
++ case LFT_PEER_LOCAL_PORT:
++ if ((outint = al->hier.peer_local_addr.GetPort())) {
++ doint = 1;
++ }
++
++ break;
++
++ case LFT_TIME_SECONDS_SINCE_EPOCH:
++ // some platforms store time in 32-bit, some 64-bit...
++ outoff = static_cast<int64_t>(current_time.tv_sec);
++ dooff = 1;
++ break;
++
++ case LFT_TIME_SUBSECOND:
++ outint = current_time.tv_usec / fmt->divisor;
++ doint = 1;
++ break;
++
++
++ case LFT_TIME_LOCALTIME:
++
++ case LFT_TIME_GMT: {
++ const char *spec;
++
++ struct tm *t;
++ spec = fmt->data.timespec;
++
++ if (fmt->type == LFT_TIME_LOCALTIME) {
++ if (!spec)
++ spec = "%d/%b/%Y:%H:%M:%S %z";
++ t = localtime(&squid_curtime);
++ } else {
++ if (!spec)
++ spec = "%d/%b/%Y:%H:%M:%S";
++
++ t = gmtime(&squid_curtime);
++ }
++
++ strftime(tmp, sizeof(tmp), spec, t);
++
++ out = tmp;
++ }
++
++ break;
++
++ case LFT_TIME_TO_HANDLE_REQUEST:
++ outint = al->cache.msec;
++ doint = 1;
++ break;
++
++ case LFT_PEER_RESPONSE_TIME:
++ if (al->hier.peer_response_time < 0) {
++ out = "-";
++ } else {
++ outoff = al->hier.peer_response_time;
++ dooff = 1;
++ }
++ break;
++
++ case LFT_TOTAL_SERVER_SIDE_RESPONSE_TIME:
++ if (al->hier.total_response_time < 0) {
++ out = "-";
++ } else {
++ outoff = al->hier.total_response_time;
++ dooff = 1;
++ }
++ break;
++
++ case LFT_DNS_WAIT_TIME:
++ if (al->request && al->request->dnsWait >= 0) {
++ outint = al->request->dnsWait;
++ doint = 1;
++ }
++ break;
++
++ case LFT_REQUEST_HEADER:
++
++ if (al->request)
++ sb = al->request->header.getByName(fmt->data.header.header);
++
++ out = sb.termedBuf();
++
++ quote = 1;
++
++ break;
++
++ case LFT_ADAPTED_REQUEST_HEADER:
++
++ if (al->request)
++ sb = al->adapted_request->header.getByName(fmt->data.header.header);
++
++ out = sb.termedBuf();
++
++ quote = 1;
++
++ break;
++
++ case LFT_REPLY_HEADER:
++ if (al->reply)
++ sb = al->reply->header.getByName(fmt->data.header.header);
++
++ out = sb.termedBuf();
++
++ quote = 1;
++
++ break;
++
++#if USE_ADAPTATION
++ case LTF_ADAPTATION_SUM_XACT_TIMES:
++ if (al->request) {
++ Adaptation::History::Pointer ah = al->request->adaptHistory();
++ if (ah != NULL)
++ ah->sumLogString(fmt->data.string, sb);
++ out = sb.termedBuf();
++ }
++ break;
++
++ case LTF_ADAPTATION_ALL_XACT_TIMES:
++ if (al->request) {
++ Adaptation::History::Pointer ah = al->request->adaptHistory();
++ if (ah != NULL)
++ ah->allLogString(fmt->data.string, sb);
++ out = sb.termedBuf();
++ }
++ break;
++
++ case LFT_ADAPTATION_LAST_HEADER:
++ if (al->request) {
++ const Adaptation::History::Pointer ah = al->request->adaptHistory();
++ if (ah != NULL) // XXX: add adapt::<all_h but use lastMeta here
++ sb = ah->allMeta.getByName(fmt->data.header.header);
++ }
++
++ // XXX: here and elsewhere: move such code inside the if guard
++ out = sb.termedBuf();
++
++ quote = 1;
++
++ break;
++
++ case LFT_ADAPTATION_LAST_HEADER_ELEM:
++ if (al->request) {
++ const Adaptation::History::Pointer ah = al->request->adaptHistory();
++ if (ah != NULL) // XXX: add adapt::<all_h but use lastMeta here
++ sb = ah->allMeta.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
++ }
++
++ out = sb.termedBuf();
++
++ quote = 1;
++
++ break;
++
++ case LFT_ADAPTATION_LAST_ALL_HEADERS:
++ out = al->adapt.last_meta;
++
++ quote = 1;
++
++ break;
++#endif
++
++#if ICAP_CLIENT
++ case LFT_ICAP_ADDR:
++ if (!out)
++ out = al->icap.hostAddr.NtoA(tmp,1024);
++ break;
++
++ case LFT_ICAP_SERV_NAME:
++ out = al->icap.serviceName.termedBuf();
++ break;
++
++ case LFT_ICAP_REQUEST_URI:
++ out = al->icap.reqUri.termedBuf();
++ break;
++
++ case LFT_ICAP_REQUEST_METHOD:
++ out = Adaptation::Icap::ICAP::methodStr(al->icap.reqMethod);
++ break;
++
++ case LFT_ICAP_BYTES_SENT:
++ outoff = al->icap.bytesSent;
++ dooff = 1;
++ break;
++
++ case LFT_ICAP_BYTES_READ:
++ outoff = al->icap.bytesRead;
++ dooff = 1;
++ break;
++
++ case LFT_ICAP_BODY_BYTES_READ:
++ if (al->icap.bodyBytesRead >= 0) {
++ outoff = al->icap.bodyBytesRead;
++ dooff = 1;
++ }
++ // else if icap.bodyBytesRead < 0, we do not have any http data,
++ // so just print a "-" (204 responses etc)
++ break;
++
++ case LFT_ICAP_REQ_HEADER:
++ if (NULL != al->icap.request) {
++ sb = al->icap.request->header.getByName(fmt->data.header.header);
++ out = sb.termedBuf();
++ quote = 1;
++ }
++ break;
++
++ case LFT_ICAP_REQ_HEADER_ELEM:
++ if (al->request)
++ sb = al->icap.request->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
++
++ out = sb.termedBuf();
++
++ quote = 1;
++
++ break;
++
++ case LFT_ICAP_REQ_ALL_HEADERS:
++ if (al->icap.request) {
++ HttpHeaderPos pos = HttpHeaderInitPos;
++ while (const HttpHeaderEntry *e = al->icap.request->header.getEntry(&pos)) {
++ sb.append(e->name);
++ sb.append(": ");
++ sb.append(e->value);
++ sb.append("\r\n");
++ }
++ out = sb.termedBuf();
++ quote = 1;
++ }
++ break;
++
++ case LFT_ICAP_REP_HEADER:
++ if (NULL != al->icap.reply) {
++ sb = al->icap.reply->header.getByName(fmt->data.header.header);
++ out = sb.termedBuf();
++ quote = 1;
++ }
++ break;
++
++ case LFT_ICAP_REP_HEADER_ELEM:
++ if (NULL != al->icap.reply)
++ sb = al->icap.reply->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
++
++ out = sb.termedBuf();
++
++ quote = 1;
++
++ break;
++
++ case LFT_ICAP_REP_ALL_HEADERS:
++ if (al->icap.reply) {
++ HttpHeaderPos pos = HttpHeaderInitPos;
++ while (const HttpHeaderEntry *e = al->icap.reply->header.getEntry(&pos)) {
++ sb.append(e->name);
++ sb.append(": ");
++ sb.append(e->value);
++ sb.append("\r\n");
++ }
++ out = sb.termedBuf();
++ quote = 1;
++ }
++ break;
++
++ case LFT_ICAP_TR_RESPONSE_TIME:
++ outint = al->icap.trTime;
++ doint = 1;
++ break;
++
++ case LFT_ICAP_IO_TIME:
++ outint = al->icap.ioTime;
++ doint = 1;
++ break;
++
++ case LFT_ICAP_STATUS_CODE:
++ outint = al->icap.resStatus;
++ doint = 1;
++ break;
++
++ case LFT_ICAP_OUTCOME:
++ out = al->icap.outcome;
++ break;
++
++ case LFT_ICAP_TOTAL_TIME:
++ outint = al->icap.processingTime;
++ doint = 1;
++ break;
++#endif
++ case LFT_REQUEST_HEADER_ELEM:
++ if (al->request)
++ sb = al->request->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
++
++ out = sb.termedBuf();
++
++ quote = 1;
++
++ break;
++
++ case LFT_ADAPTED_REQUEST_HEADER_ELEM:
++ if (al->adapted_request)
++ sb = al->adapted_request->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
++
++ out = sb.termedBuf();
++
++ quote = 1;
++
++ break;
++
++ case LFT_REPLY_HEADER_ELEM:
++ if (al->reply)
++ sb = al->reply->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
++
++ out = sb.termedBuf();
++
++ quote = 1;
++
++ break;
++
++ case LFT_REQUEST_ALL_HEADERS:
++ out = al->headers.request;
++
++ quote = 1;
++
++ break;
++
++ case LFT_ADAPTED_REQUEST_ALL_HEADERS:
++ out = al->headers.adapted_request;
++
++ quote = 1;
++
++ break;
++
++ case LFT_REPLY_ALL_HEADERS:
++ out = al->headers.reply;
++
++ quote = 1;
++
++ break;
++
++ case LFT_USER_NAME:
++ out = Log::FormatName(al->cache.authuser);
++
++ if (!out)
++ out = Log::FormatName(al->cache.extuser);
++
++#if USE_SSL
++
++ if (!out)
++ out = Log::FormatName(al->cache.ssluser);
++
++#endif
++
++ if (!out)
++ out = Log::FormatName(al->cache.rfc931);
++
++ dofree = 1;
++
++ break;
++
++ case LFT_USER_LOGIN:
++ out = Log::FormatName(al->cache.authuser);
++
++ dofree = 1;
++
++ break;
++
++ case LFT_USER_IDENT:
++ out = Log::FormatName(al->cache.rfc931);
++
++ dofree = 1;
++
++ break;
++
++ case LFT_USER_EXTERNAL:
++ out = Log::FormatName(al->cache.extuser);
++
++ dofree = 1;
++
++ break;
++
++ /* case LFT_USER_REALM: */
++ /* case LFT_USER_SCHEME: */
++
++ // the fmt->type can not be LFT_HTTP_SENT_STATUS_CODE_OLD_30
++ // but compiler complains if ommited
++ case LFT_HTTP_SENT_STATUS_CODE_OLD_30:
++ case LFT_HTTP_SENT_STATUS_CODE:
++ outint = al->http.code;
++
++ doint = 1;
++
++ break;
++
++ case LFT_HTTP_RECEIVED_STATUS_CODE:
++ if (al->hier.peer_reply_status == HTTP_STATUS_NONE) {
++ out = "-";
++ } else {
++ outint = al->hier.peer_reply_status;
++ doint = 1;
++ }
++ break;
++ /* case LFT_HTTP_STATUS:
++ * out = statusline->text;
++ * quote = 1;
++ * break;
++ */
++ case LFT_HTTP_BODY_BYTES_READ:
++ if (al->hier.bodyBytesRead >= 0) {
++ outoff = al->hier.bodyBytesRead;
++ dooff = 1;
++ }
++ // else if hier.bodyBytesRead < 0 we did not have any data exchange with
++ // a peer server so just print a "-" (eg requests served from cache,
++ // or internal error messages).
++ break;
++
++ case LFT_SQUID_STATUS:
++ if (al->http.timedout || al->http.aborted) {
++ snprintf(tmp, sizeof(tmp), "%s%s", log_tags[al->cache.code],
++ al->http.statusSfx());
++ out = tmp;
++ } else {
++ out = log_tags[al->cache.code];
++ }
++
++ break;
++
++ case LFT_SQUID_ERROR:
++ if (al->request && al->request->errType != ERR_NONE)
++ out = errorPageName(al->request->errType);
++ break;
++
++ case LFT_SQUID_ERROR_DETAIL:
++ if (al->request && al->request->errDetail != ERR_DETAIL_NONE) {
++ if (al->request->errDetail > ERR_DETAIL_START &&
++ al->request->errDetail < ERR_DETAIL_MAX)
++ out = errorDetailName(al->request->errDetail);
++ else {
++ if (al->request->errDetail >= ERR_DETAIL_EXCEPTION_START)
++ snprintf(tmp, sizeof(tmp), "%s=0x%X",
++ errorDetailName(al->request->errDetail), (uint32_t) al->request->errDetail);
++ else
++ snprintf(tmp, sizeof(tmp), "%s=%d",
++ errorDetailName(al->request->errDetail), al->request->errDetail);
++ out = tmp;
++ }
++ }
++ break;
++
++ case LFT_SQUID_HIERARCHY:
++ if (al->hier.ping.timedout)
++ mb.append("TIMEOUT_", 8);
++
++ out = hier_code_str[al->hier.code];
++
++ break;
++
++ case LFT_MIME_TYPE:
++ out = al->http.content_type;
++
++ break;
++
++ case LFT_REQUEST_METHOD:
++ out = al->_private.method_str;
++
++ break;
++
++ case LFT_REQUEST_URI:
++ out = al->url;
++
++ break;
++
++ case LFT_REQUEST_URLPATH:
++ if (al->request) {
++ out = al->request->urlpath.termedBuf();
++ quote = 1;
++ }
++ break;
++
++ case LFT_REQUEST_VERSION:
++ snprintf(tmp, sizeof(tmp), "%d.%d", (int) al->http.version.major, (int) al->http.version.minor);
++ out = tmp;
++ break;
++
++ case LFT_REQUEST_SIZE_TOTAL:
++ outoff = al->cache.requestSize;
++ dooff = 1;
++ break;
++
++ /*case LFT_REQUEST_SIZE_LINE: */
++ case LFT_REQUEST_SIZE_HEADERS:
++ outoff = al->cache.requestHeadersSize;
++ dooff =1;
++ break;
++ /*case LFT_REQUEST_SIZE_BODY: */
++ /*case LFT_REQUEST_SIZE_BODY_NO_TE: */
++
++ case LFT_REPLY_SIZE_TOTAL:
++ outoff = al->cache.replySize;
++ dooff = 1;
++ break;
++
++ case LFT_REPLY_HIGHOFFSET:
++ outoff = al->cache.highOffset;
++
++ dooff = 1;
++
++ break;
++
++ case LFT_REPLY_OBJECTSIZE:
++ outoff = al->cache.objectSize;
++
++ dooff = 1;
++
++ break;
++
++ /*case LFT_REPLY_SIZE_LINE: */
++ case LFT_REPLY_SIZE_HEADERS:
++ outint = al->cache.replyHeadersSize;
++ doint = 1;
++ break;
++ /*case LFT_REPLY_SIZE_BODY: */
++ /*case LFT_REPLY_SIZE_BODY_NO_TE: */
++
++ case LFT_TAG:
++ if (al->request)
++ out = al->request->tag.termedBuf();
++
++ quote = 1;
++
++ break;
++
++ case LFT_IO_SIZE_TOTAL:
++ outint = al->cache.requestSize + al->cache.replySize;
++ doint = 1;
++ break;
++
++ case LFT_EXT_LOG:
++ if (al->request)
++ out = al->request->extacl_log.termedBuf();
++
++ quote = 1;
++
++ break;
++
++ case LFT_SEQUENCE_NUMBER:
++ outoff = logfile->sequence_number;
++ dooff = 1;
++ break;
++
++ case LFT_PERCENT:
++ out = "%";
++
++ break;
++ }
++
++ if (dooff) {
++ snprintf(tmp, sizeof(tmp), "%0*" PRId64, fmt->zero ? (int) fmt->width : 0, outoff);
++ out = tmp;
++
++ } else if (doint) {
++ snprintf(tmp, sizeof(tmp), "%0*ld", fmt->zero ? (int) fmt->width : 0, outint);
++ out = tmp;
++ }
++
++ if (out && *out) {
++ if (quote || fmt->quote != LOG_QUOTE_NONE) {
++ char *newout = NULL;
++ int newfree = 0;
++
++ switch (fmt->quote) {
++
++ case LOG_QUOTE_NONE:
++ newout = rfc1738_escape_unescaped(out);
++ break;
++
++ case LOG_QUOTE_QUOTES: {
++ size_t out_len = static_cast<size_t>(strlen(out)) * 2 + 1;
++ if (out_len >= sizeof(tmp)) {
++ newout = (char *)xmalloc(out_len);
++ newfree = 1;
++ } else
++ newout = tmp;
++ log_quoted_string(out, newout);
++ }
++ break;
++
++ case LOG_QUOTE_MIMEBLOB:
++ newout = Log::QuoteMimeBlob(out);
++ newfree = 1;
++ break;
++
++ case LOG_QUOTE_URL:
++ newout = rfc1738_escape(out);
++ break;
++
++ case LOG_QUOTE_RAW:
++ break;
++ }
++
++ if (newout) {
++ if (dofree)
++ safe_free(out);
++
++ out = newout;
++
++ dofree = newfree;
++ }
++ }
++
++ // enforce width limits if configured
++ const bool haveMaxWidth = fmt->precision && !doint && !dooff;
++ if (haveMaxWidth || fmt->width) {
++ const int minWidth = fmt->width ?
++ static_cast<int>(fmt->width) : 0;
++ const int maxWidth = haveMaxWidth ?
++ static_cast<int>(fmt->precision) : strlen(out);
++
++ if (fmt->left)
++ mb.Printf("%-*.*s", minWidth, maxWidth, out);
++ else
++ mb.Printf("%*.*s", minWidth, maxWidth, out);
++ } else
++ mb.append(out, strlen(out));
++ } else {
++ mb.append("-", 1);
++ }
++
++ if (fmt->space)
++ mb.append(" ", 1);
++
++ sb.clean();
++
++ if (dofree)
++ safe_free(out);
++ }
++
++ logfilePrintf(logfile, "%s\n", mb.buf);
++}
#if USE_AUTH
#include "auth/Gadgets.h"
#endif
+#include "base/RunnersRegistry.h"
+ #include "base/Subscription.h"
#include "base/TextException.h"
#if USE_DELAY_POOLS
#include "ClientDelayConfig.h"
}
- if (fd_table[fd].closing()) {
++ if (fd_table[conn->fd].closing()) {
+ // Readers must have closing callbacks if they want to be notified. No
+ // readers appeared to care around 2009/12/14 as they skipped reading
+ // for other reasons. Closing may already be true at the delyaAwareRead
+ // call time or may happen while we wait after delayRead() above.
- debugs(20, 3, HERE << "wont read from closing FD " << fd << " for " <<
++ debugs(20, 3, HERE << "wont read from closing " << conn << " for " <<
+ callback);
+ return; // the read callback will never be called
+ }
+
- comm_read(fd, buf, amountToRead, callback);
+ comm_read(conn, buf, amountToRead, callback);
}
size_t
return memset(dst, val, sz);
}
+bool
+IamWorkerProcess()
+{
+ fprintf(stderr, "Not implemented");
+ return true;
+}
+
+bool
+IamDiskProcess()
+{
+ fprintf(stderr, "Not implemented");
+ return false;
+}
+
+bool
+IamMasterProcess()
+{
+ fprintf(stderr, "Not implemented");
+ return false;
+}
+
+bool
+UsingSmp()
+{
+ fprintf(stderr, "Not implemented");
+ return false;
+}
++
+ void
+ logsFlush(void)
+ {
+ fatal("tools.cc required");
+ }
+
+ void
+ no_suid(void)
+ {
+ fatal("tools.cc required");
+ }