--- trunk//src/base/Makefile.am 2011-09-27 13:17:48.885454000 +0200 +++ playground-patch//src/base/Makefile.am 2011-09-28 15:16:23.313575947 +0200 @@ -2,21 +2,22 @@ include $(top_srcdir)/src/Common.am include $(top_srcdir)/src/TestHeaders.am noinst_LTLIBRARIES = libbase.la libbase_la_SOURCES = \ AsyncCall.cc \ AsyncCall.h \ AsyncJob.h \ AsyncJob.cc \ AsyncJobCalls.h \ AsyncCallQueue.cc \ AsyncCallQueue.h \ TidyPointer.h \ CbcPointer.h \ InstanceId.h \ RunnersRegistry.cc \ RunnersRegistry.h \ Subscription.h \ TextException.cc \ - TextException.h + TextException.h \ + StringArea.h diff -Nr -U20 trunk//src/base/StringArea.h playground-patch//src/base/StringArea.h --- trunk//src/base/StringArea.h 1970-01-01 01:00:00.000000000 +0100 +++ playground-patch//src/base/StringArea.h 2011-09-28 15:16:23.313575947 +0200 @@ -0,0 +1,67 @@ +/* + * StringArea.h + * + * + * 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. + */ + +#ifndef SQUID_STRINGAREA_H +#define SQUID_STRINGAREA_H + +#if HAVE_CSTRING +#include +#endif + +/** A char* plus length combination. Useful for temporary storing + * and quickly looking up strings. + * + * The pointed-to string may not be null-terminated. + * The pointed-to string is not copied. + * + * Not meant for stand-alone storage. Validity of the + * pointed-to string is responsibility of the caller. + */ +class StringArea { + public: + /// build a StringArea by explicitly assigning pointed-to area and and length + StringArea(const char * ptr, size_t len): theStart(ptr), theLen(len) {} + bool operator==(const StringArea &s) const { return theLen==s.theLen && memcmp(theStart,s.theStart,theLen)==0; } + bool operator!=(const StringArea &s) const { return !operator==(s); } + bool operator< ( const StringArea &s) const { + return (theLen < s.theLen || (theLen == s.theLen && memcmp(theStart,s.theStart,theLen) < 0)) ; } + + private: + // default constructor is disabled + StringArea(); + + /// pointed to the externally-managed memory area + const char *theStart; + /// length of the string + size_t theLen; +}; + +#endif /* SQUID_STRINGAREA_H */ diff -Nr -U20 trunk//src/client_side_request.cc playground-patch//src/client_side_request.cc --- trunk//src/client_side_request.cc 2011-09-27 13:17:48.885454000 +0200 +++ playground-patch//src/client_side_request.cc 2011-09-28 15:16:23.313575947 +0200 @@ -50,40 +50,41 @@ #include "adaptation/Answer.h" #include "adaptation/Iterator.h" #include "adaptation/Service.h" #if ICAP_CLIENT #include "adaptation/icap/History.h" #endif #endif #if USE_AUTH #include "auth/UserRequest.h" #endif #include "clientStream.h" #include "client_side.h" #include "client_side_reply.h" #include "client_side_request.h" #include "ClientRequestContext.h" #include "comm/Connection.h" #include "comm/Write.h" #include "compat/inet_pton.h" #include "fde.h" #include "format/Tokens.h" +#include "HttpHdrCc.h" #include "HttpReply.h" #include "HttpRequest.h" #include "ip/QosConfig.h" #include "MemObject.h" #include "ProtoPort.h" #include "Store.h" #include "SquidTime.h" #include "wordlist.h" #include "err_detail_type.h" #if USE_SSL #include "ssl/support.h" #endif #if LINGERING_CLOSE #define comm_close comm_lingering_close #endif static const char *const crlf = "\r\n"; @@ -177,41 +178,41 @@ setConn(aConn); al.tcpClient = clientConnection = aConn->clientConnection; dlinkAdd(this, &active, &ClientActiveRequests); #if USE_ADAPTATION request_satisfaction_mode = false; #endif #if USE_SSL sslBumpNeed = needUnknown; #endif } /* * returns true if client specified that the object must come from the cache * without contacting origin server */ bool ClientHttpRequest::onlyIfCached()const { assert(request); return request->cache_control && - EBIT_TEST(request->cache_control->mask, CC_ONLY_IF_CACHED); + request->cache_control->onlyIfCached(); } /* * This function is designed to serve a fairly specific purpose. * Occasionally our vBNS-connected caches can talk to each other, but not * the rest of the world. Here we try to detect frequent failures which * make the cache unusable (e.g. DNS lookup and connect() failures). If * the failure:success ratio goes above 1.0 then we go into "hit only" * mode where we only return UDP_HIT or UDP_MISS_NOFETCH. Neighbors * will only fetch HITs from us if they are using the ICP protocol. We * stay in this mode for 5 minutes. * * Duane W., Sept 16, 1996 */ #define FAILURE_MODE_TIME 300 static void checkFailureRatio(err_type etype, hier_code hcode) { @@ -1002,41 +1003,41 @@ int no_cache = 0; const char *str; request->imslen = -1; request->ims = req_hdr->getTime(HDR_IF_MODIFIED_SINCE); if (request->ims > 0) request->flags.ims = 1; if (!request->flags.ignore_cc) { if (req_hdr->has(HDR_PRAGMA)) { String s = req_hdr->getList(HDR_PRAGMA); if (strListIsMember(&s, "no-cache", ',')) no_cache++; s.clean(); } if (request->cache_control) - if (EBIT_TEST(request->cache_control->mask, CC_NO_CACHE)) + if (request->cache_control->noCache()) no_cache++; /* * Work around for supporting the Reload button in IE browsers when Squid * is used as an accelerator or transparent proxy, by turning accelerated * IMS request to no-cache requests. Now knows about IE 5.5 fix (is * actually only fixed in SP1, but we can't tell whether we are talking to * SP1 or not so all 5.5 versions are treated 'normally'). */ if (Config.onoff.ie_refresh) { if (http->flags.accel && request->flags.ims) { if ((str = req_hdr->getStr(HDR_USER_AGENT))) { if (strstr(str, "MSIE 5.01") != NULL) no_cache++; else if (strstr(str, "MSIE 5.0") != NULL) no_cache++; else if (strstr(str, "MSIE 4.") != NULL) no_cache++; else if (strstr(str, "MSIE 3.") != NULL) no_cache++; diff -Nr -U20 trunk//src/enums.h playground-patch//src/enums.h --- trunk//src/enums.h 2011-09-27 13:17:48.885454000 +0200 +++ playground-patch//src/enums.h 2011-09-28 15:16:23.313575947 +0200 @@ -201,41 +201,40 @@ #endif typedef enum { MEM_NONE, MEM_2K_BUF, MEM_4K_BUF, MEM_8K_BUF, MEM_16K_BUF, MEM_32K_BUF, MEM_64K_BUF, MEM_ACL_DENY_INFO_LIST, MEM_ACL_NAME_LIST, #if USE_CACHE_DIGESTS MEM_CACHE_DIGEST, #endif MEM_CLIENT_INFO, MEM_LINK_LIST, MEM_DLINK_NODE, MEM_DREAD_CTRL, MEM_DWRITE_Q, - MEM_HTTP_HDR_CC, MEM_HTTP_HDR_CONTENT_RANGE, MEM_MD5_DIGEST, MEM_NETDBENTRY, MEM_NET_DB_NAME, MEM_RELIST, // IMPORTANT: leave this here. pools above are initialized early with memInit() MEM_DONTFREE, // following pools are initialized late by their component if needed (or never) MEM_FQDNCACHE_ENTRY, MEM_FWD_SERVER, #if !USE_DNSSERVERS MEM_IDNS_QUERY, #endif MEM_IPCACHE_ENTRY, MEM_MAX } mem_type; enum { STORE_LOG_CREATE, STORE_LOG_SWAPIN, diff -Nr -U20 trunk//src/http.cc playground-patch//src/http.cc --- trunk//src/http.cc 2011-09-27 13:17:48.885454000 +0200 +++ playground-patch//src/http.cc 2011-09-28 15:16:23.313575947 +0200 @@ -41,40 +41,41 @@ #include "squid.h" #include "acl/FilledChecklist.h" #if USE_AUTH #include "auth/UserRequest.h" #endif #include "base/AsyncJobCalls.h" #include "base/TextException.h" #include "base64.h" #include "comm/Connection.h" #include "comm/Write.h" #if USE_DELAY_POOLS #include "DelayPools.h" #endif #include "err_detail_type.h" #include "errorpage.h" #include "fde.h" #include "http.h" #include "HttpControlMsg.h" #include "HttpHdrContRange.h" +#include "HttpHdrCc.h" #include "HttpHdrSc.h" #include "HttpHdrScTarget.h" #include "HttpReply.h" #include "HttpRequest.h" #include "MemBuf.h" #include "MemObject.h" #include "protos.h" #include "rfc1738.h" #include "SquidTime.h" #include "Store.h" #define SQUID_ENTER_THROWING_CODE() try { #define SQUID_EXIT_THROWING_CODE(status) \ status = true; \ } \ catch (const std::exception &e) { \ debugs (11, 1, "Exception error:" << e.what()); \ status = false; \ } @@ -313,92 +314,92 @@ else reply->expires = reply->date + sctusable->max_stale; /* And update the timestamps */ entry->timestampsSet(); } /* We ignore cache-control directives as per the Surrogate specification */ ignoreCacheControl = true; httpHdrScTargetDestroy(sctusable); } } } int HttpStateData::cacheableReply() { HttpReply const *rep = finalReply(); HttpHeader const *hdr = &rep->header; - const int cc_mask = (rep->cache_control) ? rep->cache_control->mask : 0; const char *v; #if USE_HTTP_VIOLATIONS const refresh_t *R = NULL; /* This strange looking define first looks up the refresh pattern * and then checks if the specified flag is set. The main purpose * of this is to simplify the refresh pattern lookup and USE_HTTP_VIOLATIONS * condition */ #define REFRESH_OVERRIDE(flag) \ ((R = (R ? R : refreshLimits(entry->mem_obj->url))) , \ (R && R->flags.flag)) #else #define REFRESH_OVERRIDE(flag) 0 #endif if (surrogateNoStore) return 0; // RFC 2616: do not cache replies to responses with no-store CC directive if (request && request->cache_control && - EBIT_TEST(request->cache_control->mask, CC_NO_STORE) && + request->cache_control->noStore() && !REFRESH_OVERRIDE(ignore_no_store)) return 0; - if (!ignoreCacheControl) { - if (EBIT_TEST(cc_mask, CC_PRIVATE)) { + if (!ignoreCacheControl && request->cache_control != NULL) { + const HttpHdrCc* cc=request->cache_control; + if (cc->Private()) { if (!REFRESH_OVERRIDE(ignore_private)) return 0; } - if (EBIT_TEST(cc_mask, CC_NO_CACHE)) { + if (cc->noCache()) { if (!REFRESH_OVERRIDE(ignore_no_cache)) return 0; } - if (EBIT_TEST(cc_mask, CC_NO_STORE)) { + if (cc->noStore()) { if (!REFRESH_OVERRIDE(ignore_no_store)) return 0; } } if (request->flags.auth || request->flags.auth_sent) { /* * Responses to requests with authorization may be cached * only if a Cache-Control: public reply header is present. * RFC 2068, sec 14.9.4 */ - if (!EBIT_TEST(cc_mask, CC_PUBLIC)) { + if (!request->cache_control->Public()) { if (!REFRESH_OVERRIDE(ignore_auth)) return 0; } } /* Pragma: no-cache in _replies_ is not documented in HTTP, * but servers like "Active Imaging Webcast/2.0" sure do use it */ if (hdr->has(HDR_PRAGMA)) { String s = hdr->getList(HDR_PRAGMA); const int no_cache = strListIsMember(&s, "no-cache", ','); s.clean(); if (no_cache) { if (!REFRESH_OVERRIDE(ignore_no_cache)) return 0; } } /* * The "multipart/x-mixed-replace" content type is used for @@ -908,43 +909,44 @@ case -1: #if USE_HTTP_VIOLATIONS if (Config.negativeTtl > 0) entry->cacheNegatively(); else #endif entry->makePrivate(); break; default: assert(0); break; } no_cache: if (!ignoreCacheControl && rep->cache_control) { - if (EBIT_TEST(rep->cache_control->mask, CC_PROXY_REVALIDATE) || - EBIT_TEST(rep->cache_control->mask, CC_MUST_REVALIDATE) || - EBIT_TEST(rep->cache_control->mask, CC_S_MAXAGE)) + if (rep->cache_control->proxyRevalidate() || + rep->cache_control->mustRevalidate() || + rep->cache_control->haveSMaxAge() + ) EBIT_SET(entry->flags, ENTRY_REVALIDATE); } #if HEADERS_LOG headersLog(1, 0, request->method, rep); #endif ctx_exit(ctx); } HttpStateData::ConnectionStatus HttpStateData::statusIfComplete() const { const HttpReply *rep = virginReply(); /** \par * If the reply wants to close the connection, it takes precedence */ if (httpHeaderHasConnDir(&rep->header, "close")) return COMPLETE_NONPERSISTENT_MSG; @@ -1743,63 +1745,63 @@ (int) request->port); } } /* append Authorization if known in URL, not in header and going direct */ if (!hdr_out->has(HDR_AUTHORIZATION)) { if (!request->flags.proxying && request->login && *request->login) { httpHeaderPutStrf(hdr_out, HDR_AUTHORIZATION, "Basic %s", old_base64_encode(request->login)); } } /* Fixup (Proxy-)Authorization special cases. Plain relaying dealt with above */ httpFixupAuthentication(request, hdr_in, hdr_out, flags); /* append Cache-Control, add max-age if not there already */ { HttpHdrCc *cc = hdr_in->getCc(); if (!cc) - cc = httpHdrCcCreate(); + cc = new HttpHdrCc(); #if 0 /* see bug 2330 */ /* Set no-cache if determined needed but not found */ if (request->flags.nocache) EBIT_SET(cc->mask, CC_NO_CACHE); #endif /* Add max-age only without no-cache */ - if (!EBIT_TEST(cc->mask, CC_MAX_AGE) && !EBIT_TEST(cc->mask, CC_NO_CACHE)) { + if (cc->haveMaxAge() && !cc->noCache()) { const char *url = entry ? entry->url() : urlCanonical(request); - httpHdrCcSetMaxAge(cc, getMaxAge(url)); + cc->maxAge(getMaxAge(url)); } /* Enforce sibling relations */ if (flags.only_if_cached) - EBIT_SET(cc->mask, CC_ONLY_IF_CACHED); + cc->onlyIfCached(true); hdr_out->putCc(cc); - httpHdrCcDestroy(cc); + delete cc; } /* maybe append Connection: keep-alive */ if (flags.keepalive) { hdr_out->putStr(HDR_CONNECTION, "keep-alive"); } /* append Front-End-Https */ if (flags.front_end_https) { if (flags.front_end_https == 1 || request->protocol == AnyP::PROTO_HTTPS) hdr_out->putStr(HDR_FRONT_END_HTTPS, "On"); } if (flags.chunked_request) { // Do not just copy the original value so that if the client-side // starts decode other encodings, this code may remain valid. hdr_out->putStr(HDR_TRANSFER_ENCODING, "chunked"); } /* Now mangle the headers. */ diff -Nr -U20 trunk//src/HttpHdrCc.cc playground-patch//src/HttpHdrCc.cc --- trunk//src/HttpHdrCc.cc 2011-09-27 13:17:48.885454000 +0200 +++ playground-patch//src/HttpHdrCc.cc 2011-09-28 15:16:23.293575947 +0200 @@ -1,332 +1,271 @@ - /* - * $Id$ * * DEBUG: section 65 HTTP Cache Control Header - * AUTHOR: Alex Rousskov * * 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 "squid.h" +#include "base/StringArea.h" #include "Store.h" #include "HttpHeader.h" +#include "HttpHdrCc.h" -/* this table is used for parsing cache control header */ -static const HttpHeaderFieldAttrs CcAttrs[CC_ENUM_END] = { - {"public", (http_hdr_type)CC_PUBLIC}, - - {"private", (http_hdr_type)CC_PRIVATE}, - {"no-cache", (http_hdr_type)CC_NO_CACHE}, - {"no-store", (http_hdr_type)CC_NO_STORE}, - {"no-transform", (http_hdr_type)CC_NO_TRANSFORM}, - {"must-revalidate", (http_hdr_type)CC_MUST_REVALIDATE}, - {"proxy-revalidate", (http_hdr_type)CC_PROXY_REVALIDATE}, - {"only-if-cached", (http_hdr_type)CC_ONLY_IF_CACHED}, - {"max-age", (http_hdr_type)CC_MAX_AGE}, - {"s-maxage", (http_hdr_type)CC_S_MAXAGE}, - {"max-stale", (http_hdr_type)CC_MAX_STALE}, - {"stale-if-error", (http_hdr_type)CC_STALE_IF_ERROR}, - {"min-fresh", (http_hdr_type)CC_MIN_FRESH}, - {"Other,", (http_hdr_type)CC_OTHER} /* ',' will protect from matches */ +#if HAVE_MAP +#include +#endif + +/* a row in the table used for parsing cache control header and statistics */ +typedef struct { + const char *name; + http_hdr_cc_type id; + HttpHeaderFieldStat stat; +} HttpHeaderCcFields; + +/* order must match that of enum http_hdr_cc_type. The constraint is verified at initialization time */ +static HttpHeaderCcFields CcAttrs[CC_ENUM_END] = { + {"public", CC_PUBLIC}, + {"private", CC_PRIVATE}, + {"no-cache", CC_NO_CACHE}, + {"no-store", CC_NO_STORE}, + {"no-transform", CC_NO_TRANSFORM}, + {"must-revalidate", CC_MUST_REVALIDATE}, + {"proxy-revalidate", CC_PROXY_REVALIDATE}, + {"max-age", CC_MAX_AGE}, + {"s-maxage", CC_S_MAXAGE}, + {"max-stale", CC_MAX_STALE}, + {"min-fresh", CC_MIN_FRESH}, + {"only-if-cached", CC_ONLY_IF_CACHED}, + {"stale-if-error", CC_STALE_IF_ERROR}, + {"Other,", CC_OTHER} /* ',' will protect from matches */ }; -HttpHeaderFieldInfo *CcFieldsInfo = NULL; +/// Map an header name to its type, to expedite parsing +typedef std::map CcNameToIdMap_t; +static CcNameToIdMap_t CcNameToIdMap; +/// iterate over a table of http_header_cc_type structs http_hdr_cc_type &operator++ (http_hdr_cc_type &aHeader) { int tmp = (int)aHeader; aHeader = (http_hdr_cc_type)(++tmp); return aHeader; } -/* local prototypes */ -static int httpHdrCcParseInit(HttpHdrCc * cc, const String * str); - - -/* module initialization */ - +/// Module initialization hook void httpHdrCcInitModule(void) { - CcFieldsInfo = httpHeaderBuildFieldsInfo(CcAttrs, CC_ENUM_END); + /* build lookup and accounting structures */ + for (int32_t i = 0;i < CC_ENUM_END; ++i) { + const HttpHeaderCcFields &f=CcAttrs[i]; + assert(i == f.id); /* verify assumption: the id is the key into the array */ + const StringArea k(f.name,strlen(f.name)); + CcNameToIdMap[k]=f.id; + } } +/// Module cleanup hook. void httpHdrCcCleanModule(void) { - httpHeaderDestroyFieldsInfo(CcFieldsInfo, CC_ENUM_END); - CcFieldsInfo = NULL; + // HdrCcNameToIdMap is self-cleaning } -/* implementation */ - -HttpHdrCc * -httpHdrCcCreate(void) -{ - HttpHdrCc *cc = (HttpHdrCc *)memAllocate(MEM_HTTP_HDR_CC); - cc->max_age = cc->s_maxage = cc->max_stale = cc->min_fresh = -1; - return cc; -} - -/* creates an cc object from a 0-terminating string */ -HttpHdrCc * -httpHdrCcParseCreate(const String * str) +void +HttpHdrCc::clear() { - HttpHdrCc *cc = httpHdrCcCreate(); - - if (!httpHdrCcParseInit(cc, str)) { - httpHdrCcDestroy(cc); - cc = NULL; - } - - return cc; + *this=HttpHdrCc(); } -/* parses a 0-terminating string and inits cc */ -static int -httpHdrCcParseInit(HttpHdrCc * cc, const String * str) +bool +HttpHdrCc::parse(const String & str) { const char *item; const char *p; /* '=' parameter */ const char *pos = NULL; http_hdr_cc_type type; int ilen; int nlen; - assert(cc && str); /* iterate through comma separated list */ - while (strListGetItem(str, ',', &item, &ilen, &pos)) { + while (strListGetItem(&str, ',', &item, &ilen, &pos)) { /* isolate directive name */ if ((p = (const char *)memchr(item, '=', ilen)) && (p - item < ilen)) nlen = p++ - item; else nlen = ilen; /* find type */ - type = (http_hdr_cc_type ) httpHeaderIdByName(item, nlen, - CcFieldsInfo, CC_ENUM_END); - - if (type < 0) { - debugs(65, 2, "hdr cc: unknown cache-directive: near '" << item << "' in '" << str << "'"); - type = CC_OTHER; - } + const CcNameToIdMap_t::const_iterator i=CcNameToIdMap.find(StringArea(item,nlen)); + if (i==CcNameToIdMap.end()) + type=CC_OTHER; + else + type=i->second; // ignore known duplicate directives - if (EBIT_TEST(cc->mask, type)) { + if (isSet(type)) { if (type != CC_OTHER) { debugs(65, 2, "hdr cc: ignoring duplicate cache-directive: near '" << item << "' in '" << str << "'"); - CcFieldsInfo[type].stat.repCount++; + ++CcAttrs[type].stat.repCount; continue; } - } else { - EBIT_SET(cc->mask, type); } - /* post-processing special cases */ + /* special-case-parsing and attribute-setting */ switch (type) { case CC_MAX_AGE: - - if (!p || !httpHeaderParseInt(p, &cc->max_age)) { + int32_t ma; + if (!p || !httpHeaderParseInt(p, &ma)) { debugs(65, 2, "cc: invalid max-age specs near '" << item << "'"); - cc->max_age = -1; - EBIT_CLR(cc->mask, type); + clearMaxAge(); + } else { + maxAge(ma); } - break; case CC_S_MAXAGE: - - if (!p || !httpHeaderParseInt(p, &cc->s_maxage)) { + if (!p || !httpHeaderParseInt(p, &s_maxage)) { debugs(65, 2, "cc: invalid s-maxage specs near '" << item << "'"); - cc->s_maxage = -1; - EBIT_CLR(cc->mask, type); + clearSMaxAge(); } - break; case CC_MAX_STALE: - - if (!p || !httpHeaderParseInt(p, &cc->max_stale)) { + if (!p || !httpHeaderParseInt(p, &max_stale)) { debugs(65, 2, "cc: max-stale directive is valid without value"); - cc->max_stale = -1; + maxStale(MAX_STALE_ALWAYS); } - break; case CC_MIN_FRESH: - - if (!p || !httpHeaderParseInt(p, &cc->min_fresh)) { + if (!p || !httpHeaderParseInt(p, &min_fresh)) { debugs(65, 2, "cc: invalid min-fresh specs near '" << item << "'"); - cc->min_fresh = -1; - EBIT_CLR(cc->mask, type); + clearMinFresh(); } - break; case CC_STALE_IF_ERROR: - if (!p || !httpHeaderParseInt(p, &cc->stale_if_error)) { + if (!p || !httpHeaderParseInt(p, &stale_if_error)) { debugs(65, 2, "cc: invalid stale-if-error specs near '" << item << "'"); - cc->stale_if_error = -1; - EBIT_CLR(cc->mask, type); + clearStaleIfError(); } break; - case CC_OTHER: - - if (cc->other.size()) - cc->other.append(", "); + case CC_PUBLIC: Public(true); break; + case CC_PRIVATE: Private(true); break; + case CC_NO_CACHE: noCache(true); break; + case CC_NO_STORE: noStore(true); break; + case CC_NO_TRANSFORM: noTransform(true); break; + case CC_MUST_REVALIDATE: mustRevalidate(true); break; + case CC_PROXY_REVALIDATE: proxyRevalidate(true); break; + case CC_ONLY_IF_CACHED: onlyIfCached(true); break; - cc->other.append(item, ilen); + case CC_OTHER: + if (other.size()) + other.append(", "); + other.append(item, ilen); break; default: /* note that we ignore most of '=' specs (RFCVIOLATION) */ break; } } - return cc->mask != 0; + return (mask != 0); } void -httpHdrCcDestroy(HttpHdrCc * cc) -{ - assert(cc); - - if (cc->other.defined()) - cc->other.clean(); - - memFree(cc, MEM_HTTP_HDR_CC); -} - -HttpHdrCc * -httpHdrCcDup(const HttpHdrCc * cc) -{ - HttpHdrCc *dup; - assert(cc); - dup = httpHdrCcCreate(); - dup->mask = cc->mask; - dup->max_age = cc->max_age; - dup->s_maxage = cc->s_maxage; - dup->max_stale = cc->max_stale; - dup->min_fresh = cc->min_fresh; - return dup; -} - -void -httpHdrCcPackInto(const HttpHdrCc * cc, Packer * p) +HttpHdrCc::packInto(Packer * p) const { http_hdr_cc_type flag; int pcount = 0; - assert(cc && p); + assert(p); for (flag = CC_PUBLIC; flag < CC_ENUM_END; ++flag) { - if (EBIT_TEST(cc->mask, flag) && flag != CC_OTHER) { + if (isSet(flag) && flag != CC_OTHER) { /* print option name */ - packerPrintf(p, (pcount ? ", " SQUIDSTRINGPH : SQUIDSTRINGPH), - SQUIDSTRINGPRINT(CcFieldsInfo[flag].name)); + packerPrintf(p, (pcount ? ", %s": "%s") , CcAttrs[flag].name); /* handle options with values */ if (flag == CC_MAX_AGE) - packerPrintf(p, "=%d", (int) cc->max_age); + packerPrintf(p, "=%d", (int) maxAge()); if (flag == CC_S_MAXAGE) - packerPrintf(p, "=%d", (int) cc->s_maxage); + packerPrintf(p, "=%d", (int) sMaxAge()); - if (flag == CC_MAX_STALE && cc->max_stale >= 0) - packerPrintf(p, "=%d", (int) cc->max_stale); + if (flag == CC_MAX_STALE && maxStale()!=MAX_STALE_ALWAYS) + packerPrintf(p, "=%d", (int) maxStale()); if (flag == CC_MIN_FRESH) - packerPrintf(p, "=%d", (int) cc->min_fresh); + packerPrintf(p, "=%d", (int) minFresh()); - pcount++; + ++pcount; } } - if (cc->other.size() != 0) + if (other.size() != 0) packerPrintf(p, (pcount ? ", " SQUIDSTRINGPH : SQUIDSTRINGPH), - SQUIDSTRINGPRINT(cc->other)); -} - -/* negative max_age will clean old max_Age setting */ -void -httpHdrCcSetMaxAge(HttpHdrCc * cc, int max_age) -{ - assert(cc); - cc->max_age = max_age; - - if (max_age >= 0) - EBIT_SET(cc->mask, CC_MAX_AGE); - else - EBIT_CLR(cc->mask, CC_MAX_AGE); -} - -/* negative s_maxage will clean old s-maxage setting */ -void -httpHdrCcSetSMaxAge(HttpHdrCc * cc, int s_maxage) -{ - assert(cc); - cc->s_maxage = s_maxage; - - if (s_maxage >= 0) - EBIT_SET(cc->mask, CC_S_MAXAGE); - else - EBIT_CLR(cc->mask, CC_S_MAXAGE); + SQUIDSTRINGPRINT(other)); } void httpHdrCcUpdateStats(const HttpHdrCc * cc, StatHist * hist) { http_hdr_cc_type c; assert(cc); for (c = CC_PUBLIC; c < CC_ENUM_END; ++c) - if (EBIT_TEST(cc->mask, c)) + if (cc->isSet(c)) statHistCount(hist, c); } void httpHdrCcStatDumper(StoreEntry * sentry, int idx, double val, double size, int count) { extern const HttpHeaderStat *dump_stat; /* argh! */ const int id = (int) val; const int valid_id = id >= 0 && id < CC_ENUM_END; - const char *name = valid_id ? CcFieldsInfo[id].name.termedBuf() : "INVALID"; + const char *name = valid_id ? CcAttrs[id].name : "INVALID"; if (count || valid_id) storeAppendPrintf(sentry, "%2d\t %-20s\t %5d\t %6.2f\n", id, name, count, xdiv(count, dump_stat->ccParsedCount)); } + +#if !_USE_INLINE_ +#include "HttpHdrCc.cci" +#endif diff -Nr -U20 trunk//src/HttpHdrCc.cci playground-patch//src/HttpHdrCc.cci --- trunk//src/HttpHdrCc.cci 1970-01-01 01:00:00.000000000 +0100 +++ playground-patch//src/HttpHdrCc.cci 2011-09-28 15:16:23.293575947 +0200 @@ -0,0 +1,46 @@ +/* + * + * DEBUG: section 65 HTTP Cache Control Header + * + * 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. + * + */ +bool +HttpHdrCc::isSet(http_hdr_cc_type id) const +{ + assert(id>=CC_PUBLIC && id < CC_ENUM_END); + return EBIT_TEST(mask,id); +} + +void +HttpHdrCc::setMask(http_hdr_cc_type id, bool newval) +{ + if (newval) + EBIT_SET(mask,id); + else + EBIT_CLR(mask,id); +} diff -Nr -U20 trunk//src/HttpHdrCc.h playground-patch//src/HttpHdrCc.h --- trunk//src/HttpHdrCc.h 1970-01-01 01:00:00.000000000 +0100 +++ playground-patch//src/HttpHdrCc.h 2011-09-28 15:16:23.303575947 +0200 @@ -0,0 +1,183 @@ +/* + * HttpHdrCc.h + * + * + * 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. + */ + +#ifndef SQUID_HTTPHDRCC_H +#define SQUID_HTTPHDRCC_H + +#include "config.h" +#include "MemPool.h" +#include "SquidString.h" + +/** Http Cache-Control header representation + * + * Store and parse the Cache-Control HTTP header. + */ +class HttpHdrCc +{ + +public: + static const int32_t MAX_AGE_UNKNOWN=-1; //max-age is unset + static const int32_t S_MAXAGE_UNKNOWN=-1; //s-maxage is unset + static const int32_t MAX_STALE_UNKNOWN=-1; //max-stale is unset + static const int32_t MAX_STALE_ALWAYS=-2; //max-stale is set to no value + static const int32_t STALE_IF_ERROR_UNKNOWN=-1; //stale_if_error is unset + static const int32_t MIN_FRESH_UNKNOWN=-1; //min_fresh is unset + + HttpHdrCc() : + mask(0), max_age(MAX_AGE_UNKNOWN), s_maxage(S_MAXAGE_UNKNOWN), + max_stale(MAX_STALE_UNKNOWN), stale_if_error(STALE_IF_ERROR_UNKNOWN), + min_fresh(MIN_FRESH_UNKNOWN) {} + + /// reset data-members to default state + void clear(); + + /// parse a header-string and fill in appropriate values. + bool parse(const String & s); + + //manipulation for Cache-Control: public header + inline bool havePublic() const {return isSet(CC_PUBLIC);} + inline bool Public() const {return isSet(CC_PUBLIC);} + inline void Public(bool newval) {setMask(CC_PUBLIC,newval);} + inline void clearPublic() {setMask(CC_PUBLIC,false);} + + //manipulation for Cache-Control: private header + inline bool havePrivate() const {return isSet(CC_PRIVATE);} + inline bool Private() const {return isSet(CC_PRIVATE);} + inline void Private(bool newval) {setMask(CC_PRIVATE,newval);} + inline void clearPrivate() {setMask(CC_PRIVATE,false);} + + //manipulation for Cache-Control: no-cache header + inline bool haveNoCache() const {return isSet(CC_NO_CACHE);} + inline bool noCache() const {return isSet(CC_NO_CACHE);} + inline void noCache(bool newval) {setMask(CC_NO_CACHE,newval);} + inline void clearNoCache() {setMask(CC_NO_CACHE,false);} + + //manipulation for Cache-Control: no-store header + inline bool haveNoStore() const {return isSet(CC_NO_STORE);} + inline bool noStore() const {return isSet(CC_NO_STORE);} + inline void noStore(bool newval) {setMask(CC_NO_STORE,newval);} + inline void clearNoStore() {setMask(CC_NO_STORE,false);} + + //manipulation for Cache-Control: no-transform header + inline bool haveNoTransform() const {return isSet(CC_NO_TRANSFORM);} + inline bool noTransform() const {return isSet(CC_NO_TRANSFORM);} + inline void noTransform(bool newval) {setMask(CC_NO_TRANSFORM,newval);} + inline void clearNoTransform() {setMask(CC_NO_TRANSFORM,false);} + + //manipulation for Cache-Control: must-revalidate header + inline bool haveMustRevalidate() const {return isSet(CC_MUST_REVALIDATE);} + inline bool mustRevalidate() const {return isSet(CC_MUST_REVALIDATE);} + inline void mustRevalidate(bool newval) {setMask(CC_MUST_REVALIDATE,newval);} + inline void clearMustRevalidate() {setMask(CC_MUST_REVALIDATE,false);} + + //manipulation for Cache-Control: proxy-revalidate header + inline bool haveProxyRevalidate() const {return isSet(CC_PROXY_REVALIDATE);} + inline bool proxyRevalidate() const {return isSet(CC_PROXY_REVALIDATE);} + inline void proxyRevalidate(bool newval) {setMask(CC_PROXY_REVALIDATE,newval);} + inline void clearProxyRevalidate() {setMask(CC_PROXY_REVALIDATE,false);} + + //manipulation for Cache-Control: max-age header + inline bool haveMaxAge() const {return isSet(CC_MAX_AGE);} + inline int32_t maxAge() const { return max_age;} + inline void maxAge(int32_t newval) {if (newval < 0) return; max_age = newval; setMask(CC_MAX_AGE); } + inline void clearMaxAge() {max_age=MAX_AGE_UNKNOWN; setMask(CC_MAX_AGE,false);} + + //manipulation for Cache-Control: s-maxage header + inline bool haveSMaxAge() const {return isSet(CC_S_MAXAGE);} + inline int32_t sMaxAge() const { return s_maxage;} + inline void sMaxAge(int32_t newval) {if (newval < 0) return; s_maxage = newval; setMask(CC_S_MAXAGE); } + inline void clearSMaxAge() {s_maxage=MAX_AGE_UNKNOWN; setMask(CC_S_MAXAGE,false);} + + //manipulation for Cache-Control: max-stale header + inline bool haveMaxStale() const {return isSet(CC_MAX_STALE);} + inline int32_t maxStale() const { return max_stale;} + // max-stale has a special value (MAX_STALE_ALWAYS) which correspond to having + // the directive without a numeric specification, and directs to consider the object + // as always-expired. + inline void maxStale(int32_t newval) { + if (newval < 0 && newval != CC_MAX_STALE) return; + max_stale = newval; setMask(CC_MAX_STALE); } + inline void clearMaxStale() {max_stale=MAX_STALE_UNKNOWN; setMask(CC_MAX_STALE,false);} + + //manipulation for Cache-Control:min-fresh header + inline bool haveMinFresh() const {return isSet(CC_MIN_FRESH);} + inline int32_t minFresh() const { return min_fresh;} + inline void minFresh(int32_t newval) {if (newval < 0) return; min_fresh = newval; setMask(CC_MIN_FRESH); } + inline void clearMinFresh() {min_fresh=MIN_FRESH_UNKNOWN; setMask(CC_MIN_FRESH,false);} + + //manipulation for Cache-Control: only-if-cached header + inline bool haveOnlyIfCached() const {return isSet(CC_ONLY_IF_CACHED);} + inline bool onlyIfCached() const {return isSet(CC_ONLY_IF_CACHED);} + inline void onlyIfCached(bool newval) {setMask(CC_ONLY_IF_CACHED,newval);} + inline void clearOnlyIfCached() {setMask(CC_ONLY_IF_CACHED,false);} + + //manipulation for Cache-Control: stale-if-error header + inline bool haveStaleIfError() const {return isSet(CC_STALE_IF_ERROR);} + inline int32_t staleIfError() const { return stale_if_error;} + inline void staleIfError(int32_t newval) {if (newval < 0) return; stale_if_error = newval; setMask(CC_STALE_IF_ERROR); } + inline void clearStaleIfError() {stale_if_error=STALE_IF_ERROR_UNKNOWN; setMask(CC_STALE_IF_ERROR,false);} + + /// check whether the attribute value supplied by id is set + _SQUID_INLINE_ bool isSet(http_hdr_cc_type id) const; + + void packInto(Packer * p) const; + + MEMPROXY_CLASS(HttpHdrCc); + + /** bit-mask representing what header values are set among those + * recognized by squid. + * + * managed via EBIT_SET/TEST/CLR + */ +private: + int32_t mask; + int32_t max_age; + int32_t s_maxage; + int32_t max_stale; + int32_t stale_if_error; + int32_t min_fresh; + /// low-level part of the public set method, performs no checks + _SQUID_INLINE_ void setMask(http_hdr_cc_type id, bool newval=true); + +public: + /**comma-separated representation of the header values which were + * received but are not recognized. + */ + String other; +}; + +MEMPROXY_CLASS_INLINE(HttpHdrCc); + +#if _USE_INLINE_ +#include "HttpHdrCc.cci" +#endif + +#endif /* SQUID_HTTPHDRCC_H */ diff -Nr -U20 trunk//src/HttpHeader.cc playground-patch//src/HttpHeader.cc --- trunk//src/HttpHeader.cc 2011-09-27 13:17:48.885454000 +0200 +++ playground-patch//src/HttpHeader.cc 2011-09-28 15:16:23.303575947 +0200 @@ -19,40 +19,41 @@ * * 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 "squid.h" #include "base64.h" #include "HttpHdrContRange.h" +#include "HttpHdrCc.h" #include "HttpHdrSc.h" #include "HttpHeader.h" #include "MemBuf.h" #include "mgr/Registration.h" #include "rfc1123.h" #include "Store.h" #include "TimeOrTag.h" /* * On naming conventions: * * HTTP/1.1 defines message-header as * * message-header = field-name ":" [ field-value ] CRLF * field-name = token * field-value = *( field-content | LWS ) * * HTTP/1.1 does not give a name name a group of all message-headers in a message. * Squid 1.1 seems to refer to that group _plus_ start-line as "headers". * @@ -1134,41 +1135,41 @@ } void HttpHeader::putAuth(const char *auth_scheme, const char *realm) { assert(auth_scheme && realm); httpHeaderPutStrf(this, HDR_WWW_AUTHENTICATE, "%s realm=\"%s\"", auth_scheme, realm); } void HttpHeader::putCc(const HttpHdrCc * cc) { MemBuf mb; Packer p; assert(cc); /* remove old directives if any */ delById(HDR_CACHE_CONTROL); /* pack into mb */ mb.init(); packerToMemInit(&p, &mb); - httpHdrCcPackInto(cc, &p); + cc->packInto(&p); /* put */ addEntry(new HttpHeaderEntry(HDR_CACHE_CONTROL, NULL, mb.buf)); /* cleanup */ packerClean(&p); mb.clean(); } void HttpHeader::putContRange(const HttpHdrContRange * cr) { MemBuf mb; Packer p; assert(cr); /* remove old directives if any */ delById(HDR_CONTENT_RANGE); /* pack into mb */ mb.init(); packerToMemInit(&p, &mb); httpHdrContRangePackInto(cr, &p); /* put */ @@ -1293,50 +1294,53 @@ /* unusual */ const char * HttpHeader::getLastStr(http_hdr_type id) const { HttpHeaderEntry *e; assert_eid(id); assert(Headers[id].type == ftStr); /* must be of an appropriate type */ if ((e = findLastEntry(id))) { httpHeaderNoteParsedEntry(e->id, e->value, 0); /* no errors are possible */ return e->value.termedBuf(); } return NULL; } HttpHdrCc * HttpHeader::getCc() const { - HttpHdrCc *cc; - String s; - if (!CBIT_TEST(mask, HDR_CACHE_CONTROL)) return NULL; PROF_start(HttpHeader_getCc); + String s; getList(HDR_CACHE_CONTROL, &s); - cc = httpHdrCcParseCreate(&s); + HttpHdrCc *cc=new HttpHdrCc(); + + if (!cc->parse(s)) { + delete cc; + cc = NULL; + } HttpHeaderStats[owner].ccParsedCount++; if (cc) httpHdrCcUpdateStats(cc, &HttpHeaderStats[owner].ccTypeDistr); httpHeaderNoteParsedEntry(HDR_CACHE_CONTROL, s, !cc); PROF_stop(HttpHeader_getCc); return cc; } HttpHdrRange * HttpHeader::getRange() const { HttpHdrRange *r = NULL; HttpHeaderEntry *e; /* some clients will send "Request-Range" _and_ *matching* "Range" * who knows, some clients might send Request-Range only; diff -Nr -U20 trunk//src/HttpReply.cc playground-patch//src/HttpReply.cc --- trunk//src/HttpReply.cc 2011-09-27 13:17:48.885454000 +0200 +++ playground-patch//src/HttpReply.cc 2011-09-28 15:16:23.303575947 +0200 @@ -21,40 +21,41 @@ * 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 "squid.h" #include "SquidTime.h" #include "Store.h" #include "HttpReply.h" #include "HttpHdrContRange.h" +#include "HttpHdrCc.h" #include "HttpHdrSc.h" #include "acl/FilledChecklist.h" #include "HttpRequest.h" #include "MemBuf.h" /* local constants */ /* If we receive a 304 from the origin during a cache revalidation, we must * update the headers of the existing entry. Specifically, we need to update all * end-to-end headers and not any hop-by-hop headers (rfc2616 13.5.3). * * This is not the whole story though: since it is possible for a faulty/malicious * origin server to set headers it should not in a 304, we must explicitly ignore * these too. Specifically all entity-headers except those permitted in a 304 * (rfc2616 10.3.5) must be ignored. * * The list of headers we don't update is made up of: * all hop-by-hop headers * all entity-headers except Expires and Content-Location */ @@ -313,55 +314,55 @@ /* clean cache */ hdrCacheClean(); /* update raw headers */ header.update(&freshRep->header, (const HttpHeaderMask *) &Denied304HeadersMask); header.compact(); /* init cache */ hdrCacheInit(); } /* internal routines */ time_t HttpReply::hdrExpirationTime() { /* The s-maxage and max-age directive takes priority over Expires */ if (cache_control) { if (date >= 0) { - if (cache_control->s_maxage >= 0) - return date + cache_control->s_maxage; + if (cache_control->haveSMaxAge()) + return date + cache_control->sMaxAge(); - if (cache_control->max_age >= 0) - return date + cache_control->max_age; + if (cache_control->haveMaxAge()) + return date + cache_control->maxAge(); } else { /* * Conservatively handle the case when we have a max-age * header, but no Date for reference? */ - if (cache_control->s_maxage >= 0) + if (cache_control->haveSMaxAge()) return squid_curtime; - if (cache_control->max_age >= 0) + if (cache_control->haveMaxAge()) return squid_curtime; } } if (Config.onoff.vary_ignore_expire && header.has(HDR_VARY)) { const time_t d = header.getTime(HDR_DATE); const time_t e = header.getTime(HDR_EXPIRES); if (d == e) return -1; } if (header.has(HDR_EXPIRES)) { const time_t e = header.getTime(HDR_EXPIRES); /* * HTTP/1.0 says that robust implementations should consider * bad or malformed Expires header as equivalent to "expires * immediately." */ @@ -385,41 +386,41 @@ content_range = header.getContRange(); keep_alive = persistent() ? 1 : 0; const char *str = header.getStr(HDR_CONTENT_TYPE); if (str) content_type.limitInit(str, strcspn(str, ";\t ")); else content_type = String(); /* be sure to set expires after date and cache-control */ expires = hdrExpirationTime(); } /* sync this routine when you update HttpReply struct */ void HttpReply::hdrCacheClean() { content_type.clean(); if (cache_control) { - httpHdrCcDestroy(cache_control); + delete cache_control; cache_control = NULL; } if (surrogate_control) { httpHdrScDestroy(surrogate_control); surrogate_control = NULL; } if (content_range) { httpHdrContRangeDestroy(content_range); content_range = NULL; } } /* * Returns the body size of a HTTP response */ int64_t HttpReply::bodySize(const HttpRequestMethod& method) const { diff -Nr -U20 trunk//src/HttpRequest.cc playground-patch//src/HttpRequest.cc --- trunk//src/HttpRequest.cc 2011-09-27 13:17:48.885454000 +0200 +++ playground-patch//src/HttpRequest.cc 2011-09-28 15:16:23.303575947 +0200 @@ -20,40 +20,41 @@ * 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. * * Copyright (c) 2003, Robert Collins */ #include "squid.h" #include "DnsLookupDetails.h" #include "HttpRequest.h" +#include "HttpHdrCc.h" #if USE_AUTH #include "auth/UserRequest.h" #endif #include "HttpHeaderRange.h" #include "log/Config.h" #include "MemBuf.h" #include "Store.h" #if ICAP_CLIENT #include "adaptation/icap/icap_log.h" #endif #include "acl/FilledChecklist.h" #include "err_detail_type.h" HttpRequest::HttpRequest() : HttpMsg(hoRequest) { init(); } HttpRequest::HttpRequest(const HttpRequestMethod& aMethod, AnyP::ProtocolType aProtocol, const char *aUrlpath) : HttpMsg(hoRequest) { @@ -128,41 +129,41 @@ } void HttpRequest::clean() { // we used to assert that the pipe is NULL, but now the request only // points to a pipe that is owned and initiated by another object. body_pipe = NULL; #if USE_AUTH auth_user_request = NULL; #endif safe_free(canonical); safe_free(vary_headers); urlpath.clean(); header.clean(); if (cache_control) { - httpHdrCcDestroy(cache_control); + delete cache_control; cache_control = NULL; } if (range) { delete range; range = NULL; } myportname.clean(); tag.clean(); #if USE_AUTH extacl_user.clean(); extacl_passwd.clean(); #endif extacl_log.clean(); extacl_message.clean(); #if USE_ADAPTATION diff -Nr -U20 trunk//src/Makefile.am playground-patch//src/Makefile.am --- trunk//src/Makefile.am 2011-09-27 13:17:48.885454000 +0200 +++ playground-patch//src/Makefile.am 2011-09-28 15:16:23.313575947 +0200 @@ -325,41 +325,43 @@ filemap.cc \ forward.cc \ forward.h \ fqdncache.cc \ ftp.cc \ Generic.h \ globals.h \ gopher.cc \ helper.cc \ helper.h \ HelperChildConfig.h \ HelperChildConfig.cc \ hier_code.h \ HierarchyLogEntry.h \ $(HTCPSOURCE) \ http.cc \ http.h \ HttpStatusCode.h \ HttpStatusLine.cc \ HttpStatusLine.h \ + HttpHdrCc.h \ HttpHdrCc.cc \ + HttpHdrCc.cci \ HttpHdrRange.cc \ HttpHdrSc.cc \ HttpHdrSc.h \ HttpHdrScTarget.cc \ HttpHdrScTarget.h \ HttpHdrContRange.cc \ HttpHdrContRange.h \ HttpHeader.cc \ HttpHeader.h \ HttpHeaderMask.h \ HttpHeaderRange.h \ HttpHeaderTools.cc \ HttpBody.cc \ HttpControlMsg.h \ HttpMsg.cc \ HttpMsg.h \ HttpParser.cc \ HttpParser.h \ HttpReply.cc \ HttpReply.h \ @@ -1016,41 +1018,43 @@ # tests/testX.cc \ # tests/testMain.cc \ # X.h \ # X.cc #nodist_tests_testX_SOURCES=\ # $(TESTSOURCES) #tests_testX_LDFLAGS = $(LIBADD_DL) #tests_testX_LDADD=\ # $(SQUID_CPPUNIT_LIBS) \ # $(SQUID_CPPUNIT_LA) \ # $(COMPAT_LIB) \ #tests_testX_DEPENDENCIES= $(SQUID_CPPUNIT_LA) # - add other component .(h|cc) files needed to link and run tests tests_testHttpReply_SOURCES=\ cbdata.cc \ cbdata.h \ ETag.cc \ HttpBody.cc \ + HttpHdrCc.h \ HttpHdrCc.cc \ + HttpHdrCc.cci \ HttpHdrContRange.cc \ HttpHdrContRange.h \ HttpHdrRange.cc \ HttpHdrSc.cc \ HttpHdrSc.h \ HttpHdrScTarget.cc \ HttpHdrScTarget.h \ HttpHeader.cc \ HttpHeader.h \ HttpHeaderMask.h \ HttpHeaderTools.cc \ HttpControlMsg.h \ HttpMsg.cc \ HttpMsg.h \ HttpReply.cc \ HttpReply.h \ HttpStatusCode.h \ HttpStatusLine.cc \ HttpStatusLine.h \ mem.cc \ @@ -1111,41 +1115,43 @@ ## String.cc \ ## ## disk.cc \ ## fs/libfs.la \ tests_testACLMaxUserIP_SOURCES= \ cbdata.cc \ ClientInfo.h \ ConfigOption.cc \ ConfigParser.cc \ DiskIO/ReadRequest.cc \ DiskIO/WriteRequest.cc \ ETag.cc \ event.cc \ filemap.cc \ HelperChildConfig.h \ HelperChildConfig.cc \ HttpHeader.cc \ HttpHeaderTools.cc \ HttpHdrContRange.cc \ HttpHdrRange.cc \ + HttpHdrCc.h \ HttpHdrCc.cc \ + HttpHdrCc.cci \ HttpHdrSc.cc \ HttpHdrScTarget.cc \ HttpMsg.cc \ HttpRequestMethod.cc \ int.cc \ list.cc \ mem_node.cc \ Packer.cc \ Parsing.cc \ SquidMath.cc \ StatHist.cc \ stmem.cc \ String.cc \ store_dir.cc \ StoreIOState.cc \ StoreMeta.cc \ StoreMetaMD5.cc \ StoreMetaSTD.cc \ StoreMetaSTDLFS.cc \ StoreMetaUnpacker.cc \ @@ -1276,41 +1282,43 @@ ETag.cc \ event.cc \ external_acl.cc \ ExternalACLEntry.cc \ fd.cc \ fde.cc \ filemap.cc \ forward.cc \ fqdncache.cc \ ftp.cc \ gopher.cc \ hier_code.h \ helper.cc \ HelperChildConfig.h \ HelperChildConfig.cc \ $(HTCPSOURCE) \ http.cc \ HttpBody.cc \ HttpHeader.cc \ HttpHeaderTools.cc \ + HttpHdrCc.h \ HttpHdrCc.cc \ + HttpHdrCc.cci \ HttpHdrContRange.cc \ HttpHdrRange.cc \ HttpHdrSc.cc \ HttpHdrScTarget.cc \ HttpMsg.cc \ HttpReply.cc \ HttpStatusLine.cc \ icp_v2.cc \ icp_v3.cc \ $(IPC_SOURCE) \ ipcache.cc \ int.cc \ internal.cc \ list.cc \ multicast.cc \ mem_node.cc \ MemBuf.cc \ MemObject.cc \ mime.cc \ mime_header.cc \ @@ -1412,41 +1420,43 @@ $(REPL_OBJS) \ $(SQUID_CPPUNIT_LA) # tests/stub_CommIO.cc \ # tests/stub_comm.cc tests_testDiskIO_SOURCES = \ CacheDigest.cc \ cbdata.cc \ ClientInfo.h \ ConfigOption.cc \ ConfigParser.cc \ $(DELAY_POOL_SOURCE) \ $(DISKIO_SOURCE) \ disk.cc \ ETag.cc \ EventLoop.cc \ event.cc \ fd.cc \ filemap.cc \ HttpBody.cc \ + HttpHdrCc.h \ HttpHdrCc.cc \ + HttpHdrCc.cci \ HttpHdrContRange.cc \ HttpHdrSc.cc \ HttpHdrScTarget.cc \ HttpHdrRange.cc \ HttpHeaderTools.cc \ HttpHeader.cc \ HttpMsg.cc \ HttpReply.cc \ HttpRequestMethod.cc \ HttpStatusLine.cc \ int.cc \ list.cc \ MemBuf.cc \ MemObject.cc \ mem_node.cc \ mem.cc \ Packer.cc \ Parsing.cc \ refresh.cc \ RemovalPolicy.cc \ @@ -1587,41 +1597,43 @@ EventLoop.cc \ external_acl.cc \ ExternalACLEntry.cc \ FadingCounter.cc \ fd.cc \ fde.cc \ filemap.cc \ forward.cc \ fqdncache.cc \ ftp.cc \ gopher.cc \ helper.cc \ HelperChildConfig.h \ HelperChildConfig.cc \ hier_code.h \ $(HTCPSOURCE) \ http.cc \ HttpBody.cc \ HttpHeader.cc \ HttpHeaderTools.cc \ + HttpHdrCc.h \ HttpHdrCc.cc \ + HttpHdrCc.cci \ HttpHdrContRange.cc \ HttpHdrRange.cc \ HttpHdrSc.cc \ HttpHdrScTarget.cc \ HttpMsg.cc \ HttpParser.cc \ HttpParser.h \ HttpReply.cc \ HttpRequest.cc \ HttpRequestMethod.cc \ HttpStatusLine.cc \ icp_v2.cc \ icp_v3.cc \ $(IPC_SOURCE) \ ipcache.cc \ int.cc \ internal.cc \ list.cc \ mem.cc \ mem_node.cc \ @@ -1772,41 +1784,43 @@ event.cc \ external_acl.cc \ ExternalACLEntry.cc \ FadingCounter.cc \ fd.cc \ fde.cc \ filemap.cc \ forward.cc \ fqdncache.cc \ ftp.cc \ gopher.cc \ helper.cc \ HelperChildConfig.h \ HelperChildConfig.cc \ hier_code.h \ $(HTCPSOURCE) \ http.cc \ HttpBody.cc \ HttpHeader.cc \ HttpHeaderTools.cc \ + HttpHdrCc.h \ HttpHdrCc.cc \ + HttpHdrCc.cci \ HttpHdrContRange.cc \ HttpHdrRange.cc \ HttpHdrSc.cc \ HttpHdrScTarget.cc \ HttpMsg.cc \ HttpParser.cc \ HttpParser.h \ HttpReply.cc \ HttpRequest.cc \ HttpRequestMethod.cc \ HttpStatusLine.cc \ icp_v2.cc \ icp_v3.cc \ $(IPC_SOURCE) \ ipcache.cc \ int.cc \ internal.cc \ list.cc \ MemBuf.cc \ MemObject.cc \ @@ -1953,41 +1967,43 @@ errorpage.cc \ ETag.cc \ event.cc \ external_acl.cc \ ExternalACLEntry.cc \ FadingCounter.cc \ fd.cc \ fde.cc \ filemap.cc \ forward.cc \ fqdncache.cc \ ftp.cc \ gopher.cc \ helper.cc \ HelperChildConfig.h \ HelperChildConfig.cc \ hier_code.h \ $(HTCPSOURCE) \ http.cc \ HttpBody.cc \ + HttpHdrCc.h \ HttpHdrCc.cc \ + HttpHdrCc.cci \ HttpHdrContRange.cc \ HttpHdrRange.cc \ HttpHdrSc.cc \ HttpHdrScTarget.cc \ HttpHeader.cc \ HttpHeaderTools.cc \ HttpMsg.cc \ HttpParser.cc \ HttpParser.h \ HttpReply.cc \ HttpRequest.cc \ HttpRequestMethod.cc \ HttpStatusLine.cc \ icp_v2.cc \ icp_v3.cc \ int.cc \ internal.cc \ $(IPC_SOURCE) \ ipcache.cc \ list.cc \ @@ -2178,41 +2194,43 @@ $(DNSSOURCE) \ errorpage.cc \ ETag.cc \ external_acl.cc \ ExternalACLEntry.cc \ fd.cc \ fde.cc \ forward.cc \ fqdncache.cc \ ftp.cc \ gopher.cc \ helper.cc \ HelperChildConfig.h \ HelperChildConfig.cc \ hier_code.h \ $(HTCPSOURCE) \ http.cc \ HttpBody.cc \ HttpHeader.cc \ HttpHeaderTools.cc \ + HttpHdrCc.h \ HttpHdrCc.cc \ + HttpHdrCc.cci \ HttpHdrContRange.cc \ HttpHdrRange.cc \ HttpHdrSc.cc \ HttpHdrScTarget.cc \ HttpMsg.cc \ HttpReply.cc \ HttpStatusLine.cc \ icp_v2.cc \ icp_v3.cc \ $(IPC_SOURCE) \ ipcache.cc \ int.cc \ internal.cc \ list.cc \ multicast.cc \ mem_node.cc \ MemBuf.cc \ MemObject.cc \ mime.cc \ mime_header.cc \ @@ -2310,41 +2328,43 @@ tests_testHttpRequest_DEPENDENCIES = \ $(REPL_OBJS) \ $(SQUID_CPPUNIT_LA) ## why so many sources? well httpHeaderTools requites ACLChecklist & friends. ## first line - what we are testing. tests_testStore_SOURCES= \ CacheDigest.cc \ cbdata.cc \ ClientInfo.h \ ConfigOption.cc \ ConfigParser.cc \ $(DELAY_POOL_SOURCE) \ disk.cc \ DiskIO/ReadRequest.cc \ DiskIO/WriteRequest.cc \ ETag.cc \ event.cc \ EventLoop.cc \ filemap.cc \ + HttpHdrCc.h \ HttpHdrCc.cc \ + HttpHdrCc.cci \ HttpHdrContRange.cc \ HttpHdrRange.cc \ HttpHdrSc.cc \ HttpHdrScTarget.cc \ HttpHeaderTools.cc \ HttpHeader.cc \ HttpMsg.cc \ HttpRequestMethod.cc \ int.cc \ list.cc \ mem.cc \ mem_node.cc \ MemBuf.cc \ Packer.cc \ Parsing.cc \ RemovalPolicy.cc \ refresh.cc \ StatHist.cc \ stmem.cc \ store.cc \ @@ -2548,41 +2568,43 @@ ConfigOption.cc \ SwapDir.cc \ tests/stub_acl.cc \ tests/stub_cache_cf.cc \ tests/stub_helper.cc \ cbdata.cc \ String.cc \ tests/stub_debug.cc \ tests/stub_client_side_request.cc \ tests/stub_http.cc \ mem_node.cc \ stmem.cc \ tests/stub_mime.cc \ HttpHeaderTools.cc \ HttpHeader.cc \ mem.cc \ ClientInfo.h \ MemBuf.cc \ HttpHdrContRange.cc \ Packer.cc \ + HttpHdrCc.h \ HttpHdrCc.cc \ + HttpHdrCc.cci \ HttpHdrSc.cc \ HttpHdrScTarget.cc \ url.cc \ StatHist.cc \ HttpHdrRange.cc \ ETag.cc \ tests/stub_errorpage.cc \ tests/stub_HttpRequest.cc \ tests/stub_access_log.cc \ refresh.cc \ tests/stub_store_client.cc \ tests/stub_tools.cc \ tests/testStoreSupport.cc \ tests/testStoreSupport.h \ time.cc \ URLScheme.cc \ wordlist.cc \ $(DISKIO_SOURCE) nodist_tests_testUfs_SOURCES = \ @@ -2678,41 +2700,43 @@ Parsing.cc \ ConfigOption.cc \ SwapDir.cc \ tests/stub_acl.cc \ tests/stub_cache_cf.cc \ tests/stub_helper.cc \ cbdata.cc \ String.cc \ tests/stub_client_side_request.cc \ tests/stub_http.cc \ mem_node.cc \ stmem.cc \ tests/stub_mime.cc \ HttpHeaderTools.cc \ HttpHeader.cc \ mem.cc \ ClientInfo.h \ MemBuf.cc \ HttpHdrContRange.cc \ Packer.cc \ + HttpHdrCc.h \ HttpHdrCc.cc \ + HttpHdrCc.cci \ HttpHdrSc.cc \ HttpHdrScTarget.cc \ url.cc \ StatHist.cc \ HttpHdrRange.cc \ ETag.cc \ tests/stub_errorpage.cc \ tests/stub_HttpRequest.cc \ tests/stub_access_log.cc \ refresh.cc \ tests/stub_MemStore.cc \ tests/stub_Port.cc \ tests/stub_store_client.cc \ tests/stub_tools.cc \ tests/stub_UdsOp.cc \ tests/testStoreSupport.cc \ tests/testStoreSupport.h \ time.cc \ URLScheme.cc \ wordlist.cc \ @@ -2807,41 +2831,43 @@ SwapDir.cc \ tests/stub_acl.cc \ tests/stub_cache_cf.cc \ tests/stub_helper.cc \ cbdata.cc \ String.cc \ tests/stub_comm.cc \ tests/stub_debug.cc \ tests/stub_client_side_request.cc \ tests/stub_http.cc \ mem_node.cc \ stmem.cc \ tests/stub_mime.cc \ HttpHeaderTools.cc \ HttpHeader.cc \ mem.cc \ ClientInfo.h \ MemBuf.cc \ HttpHdrContRange.cc \ Packer.cc \ + HttpHdrCc.h \ HttpHdrCc.cc \ + HttpHdrCc.cci \ HttpHdrSc.cc \ HttpHdrScTarget.cc \ url.cc \ StatHist.cc \ HttpHdrRange.cc \ ETag.cc \ tests/stub_errorpage.cc \ tests/stub_HttpRequest.cc \ tests/stub_access_log.cc \ refresh.cc \ tests/stub_store_client.cc \ tests/stub_tools.cc \ tests/testStoreSupport.cc \ tests/testStoreSupport.h \ time.cc \ URLScheme.cc \ wordlist.cc \ $(DISKIO_SOURCE) nodist_tests_testNull_SOURCES = \ @@ -2909,41 +2935,43 @@ $(DNSSOURCE) \ errorpage.cc \ ETag.cc \ event.cc \ external_acl.cc \ ExternalACLEntry.cc \ fd.cc \ fde.cc \ filemap.cc \ forward.cc \ fqdncache.cc \ ftp.cc \ gopher.cc \ helper.cc \ HelperChildConfig.h \ HelperChildConfig.cc \ hier_code.h \ $(HTCPSOURCE) \ http.cc \ HttpBody.cc \ + HttpHdrCc.h \ HttpHdrCc.cc \ + HttpHdrCc.cci \ HttpHdrContRange.cc \ HttpHdrRange.cc \ HttpHdrSc.cc \ HttpHdrScTarget.cc \ HttpHeader.cc \ HttpHeaderTools.cc \ HttpMsg.cc \ HttpParser.cc \ HttpParser.h \ HttpReply.cc \ HttpRequest.cc \ HttpRequestMethod.cc \ HttpStatusLine.cc \ icp_v2.cc \ icp_v3.cc \ $(IPC_SOURCE) \ ipcache.cc \ int.cc \ internal.cc \ list.cc \ diff -Nr -U20 trunk//src/Makefile.am.orig playground-patch//src/Makefile.am.orig --- trunk//src/mem.cc 2011-09-27 13:17:48.885454000 +0200 +++ playground-patch//src/mem.cc 2011-09-28 15:16:23.323575947 +0200 @@ -436,41 +436,40 @@ * malloc() for those? @?@ */ memDataInit(MEM_2K_BUF, "2K Buffer", 2048, 10, false); memDataInit(MEM_4K_BUF, "4K Buffer", 4096, 10, false); memDataInit(MEM_8K_BUF, "8K Buffer", 8192, 10, false); memDataInit(MEM_16K_BUF, "16K Buffer", 16384, 10, false); memDataInit(MEM_32K_BUF, "32K Buffer", 32768, 10, false); memDataInit(MEM_64K_BUF, "64K Buffer", 65536, 10, false); memDataInit(MEM_ACL_DENY_INFO_LIST, "acl_deny_info_list", sizeof(acl_deny_info_list), 0); memDataInit(MEM_ACL_NAME_LIST, "acl_name_list", sizeof(acl_name_list), 0); #if USE_CACHE_DIGESTS memDataInit(MEM_CACHE_DIGEST, "CacheDigest", sizeof(CacheDigest), 0); #endif memDataInit(MEM_LINK_LIST, "link_list", sizeof(link_list), 10); memDataInit(MEM_DLINK_NODE, "dlink_node", sizeof(dlink_node), 10); memDataInit(MEM_DREAD_CTRL, "dread_ctrl", sizeof(dread_ctrl), 0); memDataInit(MEM_DWRITE_Q, "dwrite_q", sizeof(dwrite_q), 0); - memDataInit(MEM_HTTP_HDR_CC, "HttpHdrCc", sizeof(HttpHdrCc), 0); memDataInit(MEM_HTTP_HDR_CONTENT_RANGE, "HttpHdrContRange", sizeof(HttpHdrContRange), 0); memDataInit(MEM_NETDBENTRY, "netdbEntry", sizeof(netdbEntry), 0); memDataInit(MEM_NET_DB_NAME, "net_db_name", sizeof(net_db_name), 0); memDataInit(MEM_RELIST, "relist", sizeof(relist), 0); memDataInit(MEM_CLIENT_INFO, "ClientInfo", sizeof(ClientInfo), 0); memDataInit(MEM_MD5_DIGEST, "MD5 digest", SQUID_MD5_DIGEST_LENGTH, 0); MemPools[MEM_MD5_DIGEST]->setChunkSize(512 * 1024); /** Lastly init the string pools. */ for (i = 0; i < mem_str_pool_count; ++i) { StrPools[i].pool = memPoolCreate(StrPoolsAttrs[i].name, StrPoolsAttrs[i].obj_size); StrPools[i].pool->zeroOnPush(false); if (StrPools[i].pool->objectSize() != StrPoolsAttrs[i].obj_size) debugs(13, 1, "Notice: " << StrPoolsAttrs[i].name << " is " << StrPools[i].pool->objectSize() << " bytes instead of requested " << StrPoolsAttrs[i].obj_size << " bytes"); } MemIsInitialized = true; /** \par * finally register with the cache manager */ diff -Nr -U20 trunk//src/mime.cc playground-patch//src/mime.cc --- trunk//src/mime.cc 2011-09-27 13:17:48.885454000 +0200 +++ playground-patch//src/mime.cc 2011-09-28 15:16:23.323575947 +0200 @@ -17,40 +17,41 @@ * 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 "squid.h" +#include "HttpHdrCc.h" #include "Store.h" #include "StoreClient.h" #include "HttpReply.h" #include "HttpRequest.h" #include "MemObject.h" #include "fde.h" #include "MemBuf.h" #define GET_HDR_SZ 1024 class MimeIcon : public StoreClient { public: MimeIcon (); ~MimeIcon (); void setName (char const *); char const * getName () const; void _free(); void load(); @@ -445,43 +446,43 @@ flags.cachable = 1; StoreEntry *e = storeCreateEntry(url, url, flags, METHOD_GET); assert(e != NULL); EBIT_SET(e->flags, ENTRY_SPECIAL); e->setPublicKey(); e->buffer(); HttpRequest *r = HttpRequest::CreateFromUrl(url); if (NULL == r) fatal("mimeLoadIcon: cannot parse internal URL"); e->mem_obj->request = HTTPMSGLOCK(r); HttpReply *reply = new HttpReply; reply->setHeaders(HTTP_OK, NULL, mimeGetContentType(icon), sb.st_size, sb.st_mtime, -1); - reply->cache_control = httpHdrCcCreate(); + reply->cache_control = new HttpHdrCc(); - httpHdrCcSetMaxAge(reply->cache_control, 86400); + reply->cache_control->maxAge(86400); reply->header.putCc(reply->cache_control); e->replaceHttpReply(reply); /* read the file into the buffer and append it to store */ buf = (char *)memAllocate(MEM_4K_BUF); while ((n = FD_READ_METHOD(fd, buf, 4096)) > 0) e->append(buf, n); file_close(fd); e->flush(); e->complete(); e->timestampsSet(); debugs(25, 3, "Loaded icon " << url); diff -Nr -U20 trunk//src/protos.h playground-patch//src/protos.h --- trunk//src/protos.h 2011-09-27 13:17:48.885454000 +0200 +++ playground-patch//src/protos.h 2011-09-28 15:16:23.323575947 +0200 @@ -220,47 +220,40 @@ SQUIDCEXTERN const char *httpMakeVaryMark(HttpRequest * request, HttpReply const * reply); #include "HttpStatusCode.h" SQUIDCEXTERN const char *httpStatusString(http_status status); /* Http Body */ /* init/clean */ SQUIDCEXTERN void httpBodyInit(HttpBody * body); SQUIDCEXTERN void httpBodyClean(HttpBody * body); /* get body ptr (always use this) */ SQUIDCEXTERN const char *httpBodyPtr(const HttpBody * body); /* set body, does not clone mb so you should not reuse it */ SQUIDCEXTERN void httpBodySet(HttpBody * body, MemBuf * mb); /* pack */ SQUIDCEXTERN void httpBodyPackInto(const HttpBody * body, Packer * p); /* Http Cache Control Header Field */ SQUIDCEXTERN void httpHdrCcInitModule(void); SQUIDCEXTERN void httpHdrCcCleanModule(void); -SQUIDCEXTERN HttpHdrCc *httpHdrCcCreate(void); -SQUIDCEXTERN HttpHdrCc *httpHdrCcParseCreate(const String * str); -SQUIDCEXTERN void httpHdrCcDestroy(HttpHdrCc * cc); -SQUIDCEXTERN HttpHdrCc *httpHdrCcDup(const HttpHdrCc * cc); -SQUIDCEXTERN void httpHdrCcPackInto(const HttpHdrCc * cc, Packer * p); -SQUIDCEXTERN void httpHdrCcSetMaxAge(HttpHdrCc * cc, int max_age); -SQUIDCEXTERN void httpHdrCcSetSMaxAge(HttpHdrCc * cc, int s_maxage); SQUIDCEXTERN void httpHdrCcUpdateStats(const HttpHdrCc * cc, StatHist * hist); void httpHdrCcStatDumper(StoreEntry * sentry, int idx, double val, double size, int count); /* Http Header Tools */ class HttpHeaderFieldInfo; SQUIDCEXTERN HttpHeaderFieldInfo *httpHeaderBuildFieldsInfo(const HttpHeaderFieldAttrs * attrs, int count); SQUIDCEXTERN void httpHeaderDestroyFieldsInfo(HttpHeaderFieldInfo * info, int count); SQUIDCEXTERN http_hdr_type httpHeaderIdByName(const char *name, size_t name_len, const HttpHeaderFieldInfo * attrs, int end); SQUIDCEXTERN http_hdr_type httpHeaderIdByNameDef(const char *name, int name_len); SQUIDCEXTERN const char *httpHeaderNameById(int id); SQUIDCEXTERN int httpHeaderHasConnDir(const HttpHeader * hdr, const char *directive); SQUIDCEXTERN void strListAdd(String * str, const char *item, char del); SQUIDCEXTERN int strListIsMember(const String * str, const char *item, char del); SQUIDCEXTERN int strListIsSubstr(const String * list, const char *s, char del); SQUIDCEXTERN int strListGetItem(const String * str, char del, const char **item, int *ilen, const char **pos); SQUIDCEXTERN const char *getStringPrefix(const char *str, const char *end); SQUIDCEXTERN int httpHeaderParseInt(const char *start, int *val); SQUIDCEXTERN int httpHeaderParseOffset(const char *start, int64_t * off); SQUIDCEXTERN void httpHeaderPutStrf(HttpHeader * hdr, http_hdr_type id, const char *fmt,...) PRINTF_FORMAT_ARG3; diff -Nr -U20 trunk//src/refresh.cc playground-patch//src/refresh.cc --- trunk//src/refresh.cc 2011-09-27 13:17:48.885454000 +0200 +++ playground-patch//src/refresh.cc 2011-09-28 15:16:23.333575947 +0200 @@ -21,40 +21,41 @@ * 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. * */ #ifndef USE_POSIX_REGEX #define USE_POSIX_REGEX /* put before includes; always use POSIX */ #endif #include "squid.h" +#include "HttpHdrCc.h" #include "mgr/Registration.h" #include "Store.h" #include "MemObject.h" #include "HttpRequest.h" #include "HttpReply.h" #include "SquidTime.h" typedef enum { rcHTTP, rcICP, #if USE_HTCP rcHTCP, #endif #if USE_CACHE_DIGESTS rcCDigest, #endif rcStore, rcCount } refreshCountsEnum; @@ -250,61 +251,62 @@ // FIXME: what to do when age < 0 or counter overflow? assert(age >= 0); R = uri ? refreshLimits(uri) : refreshUncompiledPattern("."); if (NULL == R) R = &DefaultRefresh; debugs(22, 3, "refreshCheck: Matched '" << R->pattern << " " << (int) R->min << " " << (int) (100.0 * R->pct) << "%% " << (int) R->max << "'"); debugs(22, 3, "\tage:\t" << age); debugs(22, 3, "\tcheck_time:\t" << mkrfc1123(check_time)); debugs(22, 3, "\tentry->timestamp:\t" << mkrfc1123(entry->timestamp)); if (request && !request->flags.ignore_cc) { const HttpHdrCc *const cc = request->cache_control; - if (cc && cc->min_fresh > 0) { + if (cc && cc->haveMinFresh()) { + const int32_t minFresh=cc->minFresh(); debugs(22, 3, "\tage + min-fresh:\t" << age << " + " << - cc->min_fresh << " = " << age + cc->min_fresh); + minFresh << " = " << age + minFresh); debugs(22, 3, "\tcheck_time + min-fresh:\t" << check_time << " + " - << cc->min_fresh << " = " << - mkrfc1123(check_time + cc->min_fresh)); - age += cc->min_fresh; - check_time += cc->min_fresh; + << minFresh << " = " << + mkrfc1123(check_time + minFresh)); + age += minFresh; + check_time += minFresh; } } memset(&sf, '\0', sizeof(sf)); staleness = refreshStaleness(entry, check_time, age, R, &sf); debugs(22, 3, "Staleness = " << staleness); // stale-if-error requires any failure be passed thru when its period is over. if (request && entry->mem_obj && entry->mem_obj->getReply() && entry->mem_obj->getReply()->cache_control && - EBIT_TEST(entry->mem_obj->getReply()->cache_control->mask, CC_STALE_IF_ERROR) && - entry->mem_obj->getReply()->cache_control->stale_if_error < staleness) { + entry->mem_obj->getReply()->cache_control->haveStaleIfError() && + entry->mem_obj->getReply()->cache_control->staleIfError() < staleness) { debugs(22, 3, "refreshCheck: stale-if-error period expired."); request->flags.fail_on_validation_err = 1; } if (EBIT_TEST(entry->flags, ENTRY_REVALIDATE) && staleness > -1 #if USE_HTTP_VIOLATIONS && !R->flags.ignore_must_revalidate #endif ) { debugs(22, 3, "refreshCheck: YES: Must revalidate stale response"); if (request) request->flags.fail_on_validation_err = 1; return STALE_MUST_REVALIDATE; } /* request-specific checks */ if (request && !request->flags.ignore_cc) { HttpHdrCc *cc = request->cache_control; @@ -317,65 +319,65 @@ #if USE_HTTP_VIOLATIONS if (!request->flags.nocache_hack) { (void) 0; } else if (R->flags.ignore_reload) { /* The clients no-cache header is ignored */ debugs(22, 3, "refreshCheck: MAYBE: ignore-reload"); } else if (R->flags.reload_into_ims || Config.onoff.reload_into_ims) { /* The clients no-cache header is changed into a IMS query */ debugs(22, 3, "refreshCheck: YES: reload-into-ims"); return STALE_RELOAD_INTO_IMS; } else { /* The clients no-cache header is not overridden on this request */ debugs(22, 3, "refreshCheck: YES: client reload"); request->flags.nocache = 1; return STALE_FORCED_RELOAD; } #endif if (NULL != cc) { - if (cc->max_age > -1) { + if (cc->haveMaxAge()) { #if USE_HTTP_VIOLATIONS - if (R->flags.ignore_reload && cc->max_age == 0) { + if (R->flags.ignore_reload && cc->maxAge() == 0) { debugs(22, 3, "refreshCheck: MAYBE: client-max-age = 0 and ignore-reload"); } else #endif { - if (cc->max_age == 0) { + if (cc->maxAge() == 0) { debugs(22, 3, "refreshCheck: YES: client-max-age = 0"); return STALE_EXCEEDS_REQUEST_MAX_AGE_VALUE; } - if (age > cc->max_age) { + if (age > cc->maxAge()) { debugs(22, 3, "refreshCheck: YES: age > client-max-age"); return STALE_EXCEEDS_REQUEST_MAX_AGE_VALUE; } } } - if (EBIT_TEST(cc->mask, CC_MAX_STALE) && staleness > -1) { - if (cc->max_stale < 0) { + if (cc->haveMaxStale() && staleness > -1) { + if (cc->maxStale()==HttpHdrCc::MAX_STALE_ALWAYS) { /* max-stale directive without a value */ debugs(22, 3, "refreshCheck: NO: max-stale wildcard"); return FRESH_REQUEST_MAX_STALE_ALL; - } else if (staleness < cc->max_stale) { + } else if (staleness < cc->maxStale()) { debugs(22, 3, "refreshCheck: NO: staleness < max-stale"); return FRESH_REQUEST_MAX_STALE_VALUE; } } } } if (-1 == staleness) { debugs(22, 3, "refreshCheck: object isn't stale.."); if (sf.expires) { debugs(22, 3, "refreshCheck: returning FRESH_EXPIRES"); return FRESH_EXPIRES; } assert(!sf.max); if (sf.lmfactor) { debugs(22, 3, "refreshCheck: returning FRESH_LMFACTOR_RULE"); return FRESH_LMFACTOR_RULE; } diff -Nr -U20 trunk//src/structs.h playground-patch//src/structs.h --- trunk//src/structs.h 2011-09-27 13:17:48.885454000 +0200 +++ playground-patch//src/structs.h 2011-09-28 15:16:23.333575947 +0200 @@ -706,55 +706,40 @@ * Note: HttpBody is used only for messages with a small content that is * known a priory (e.g., error messages). */ class MemBuf; struct _HttpBody { /* private */ MemBuf *mb; }; #include "SquidString.h" /* http header extention field */ class HttpHdrExtField { String name; /* field-name from HTTP/1.1 (no column after name) */ String value; /* field-value from HTTP/1.1 */ }; -/* http cache control header field */ - -class HttpHdrCc -{ - -public: - int mask; - int max_age; - int s_maxage; - int max_stale; - int stale_if_error; - int min_fresh; - String other; -}; - /* per field statistics */ class HttpHeaderFieldStat { public: HttpHeaderFieldStat() : aliveCount(0), seenCount(0), parsCount(0), errCount(0), repCount(0) {} int aliveCount; /* created but not destroyed (count) */ int seenCount; /* #fields we've seen */ int parsCount; /* #parsing attempts */ int errCount; /* #pasring errors */ int repCount; /* #repetitons */ }; /* compiled version of HttpHeaderFieldAttrs plus stats */ class HttpHeaderFieldInfo {