=== modified file 'src/HttpHdrCc.cc' --- src/HttpHdrCc.cc 2010-12-27 20:25:30 +0000 +++ src/HttpHdrCc.cc 2011-09-27 11:17:21 +0000 @@ -1,332 +1,274 @@ - /* - * $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) +void +HttpHdrCc::clear() { - HttpHdrCc *cc = (HttpHdrCc *)memAllocate(MEM_HTTP_HDR_CC); - cc->max_age = cc->s_maxage = cc->max_stale = cc->min_fresh = -1; - return cc; + *this=HttpHdrCc(); } -/* creates an cc object from a 0-terminating string */ -HttpHdrCc * -httpHdrCcParseCreate(const String * str) -{ - HttpHdrCc *cc = httpHdrCcCreate(); - - if (!httpHdrCcParseInit(cc, str)) { - httpHdrCcDestroy(cc); - cc = NULL; - } - - return cc; -} - -/* 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 StringArea tmpstr(item,nlen); + const CcNameToIdMap_t::const_iterator i=CcNameToIdMap.find(tmpstr); + 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); + set(type); } /* post-processing special cases */ 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); + setMaxAge(MAX_AGE_UNSET); + } else { + setMaxAge(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); + setSMaxAge(S_MAXAGE_UNSET); } 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; + setMaxStale(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); + setMinFresh(MIN_FRESH_UNSET); } 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); + setStaleIfError(STALE_IF_ERROR_UNSET); } break; case CC_OTHER: - if (cc->other.size()) - cc->other.append(", "); + if (other.size()) + other.append(", "); - cc->other.append(item, ilen); + other.append(item, ilen); break; default: /* note that we ignore most of '=' specs (RFCVIOLATION) */ break; } } - return cc->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; + return (mask != 0); } void httpHdrCcPackInto(const HttpHdrCc * cc, Packer * p) { http_hdr_cc_type flag; int pcount = 0; assert(cc && p); for (flag = CC_PUBLIC; flag < CC_ENUM_END; ++flag) { - if (EBIT_TEST(cc->mask, flag) && flag != CC_OTHER) { + if (cc->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) cc->getMaxAge()); if (flag == CC_S_MAXAGE) - packerPrintf(p, "=%d", (int) cc->s_maxage); + packerPrintf(p, "=%d", (int) cc->getSMaxAge()); - if (flag == CC_MAX_STALE && cc->max_stale >= 0) - packerPrintf(p, "=%d", (int) cc->max_stale); + if (flag == CC_MAX_STALE && cc->getMaxStale() >= 0) + packerPrintf(p, "=%d", (int) cc->getMaxStale()); if (flag == CC_MIN_FRESH) - packerPrintf(p, "=%d", (int) cc->min_fresh); + packerPrintf(p, "=%d", (int) cc->getMinFresh()); - pcount++; + ++pcount; } } if (cc->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); -} - 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 === modified file 'src/HttpHeader.cc' --- src/HttpHeader.cc 2011-08-29 03:47:54 +0000 +++ src/HttpHeader.cc 2011-09-27 11:17:21 +0000 @@ -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". * @@ -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; === modified file 'src/HttpReply.cc' --- src/HttpReply.cc 2011-07-16 15:21:48 +0000 +++ src/HttpReply.cc 2011-09-27 11:17:21 +0000 @@ -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->getSMaxAge() != HttpHdrCc::S_MAXAGE_UNSET) + return date + cache_control->getSMaxAge(); - if (cache_control->max_age >= 0) - return date + cache_control->max_age; + if (cache_control->getMaxAge() != HttpHdrCc::MAX_AGE_UNSET) + return date + cache_control->getMaxAge(); } 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->getSMaxAge() != HttpHdrCc::S_MAXAGE_UNSET) return squid_curtime; - if (cache_control->max_age >= 0) + if (cache_control->getMaxAge() != HttpHdrCc::MAX_AGE_UNSET) 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 { === modified file 'src/HttpRequest.cc' --- src/HttpRequest.cc 2011-08-04 03:21:06 +0000 +++ src/HttpRequest.cc 2011-09-27 11:17:21 +0000 @@ -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 === modified file 'src/Makefile.am' --- src/Makefile.am 2011-09-22 00:46:26 +0000 +++ src/Makefile.am 2011-09-27 11:17:21 +0000 @@ -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 \ === modified file 'src/base/Makefile.am' --- src/base/Makefile.am 2011-09-12 00:31:13 +0000 +++ src/base/Makefile.am 2011-09-27 11:17:22 +0000 @@ -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 === modified file 'src/client_side_request.cc' --- src/client_side_request.cc 2011-09-04 18:28:39 +0000 +++ src/client_side_request.cc 2011-09-27 11:17:22 +0000 @@ -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->isSet(CC_ONLY_IF_CACHED); } /* * 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->isSet(CC_NO_CACHE)) 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++; === modified file 'src/enums.h' --- src/enums.h 2011-07-16 04:00:55 +0000 +++ src/enums.h 2011-09-27 11:17:22 +0000 @@ -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, === modified file 'src/http.cc' --- src/http.cc 2011-08-30 15:04:30 +0000 +++ src/http.cc 2011-09-27 11:17:22 +0000 @@ -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->isSet(CC_NO_STORE) && !REFRESH_OVERRIDE(ignore_no_store)) return 0; if (!ignoreCacheControl) { - if (EBIT_TEST(cc_mask, CC_PRIVATE)) { + const HttpHdrCc* cc=request->cache_control; + if (cc->isSet(CC_PRIVATE)) { if (!REFRESH_OVERRIDE(ignore_private)) return 0; } - if (EBIT_TEST(cc_mask, CC_NO_CACHE)) { + if (cc->isSet(CC_NO_CACHE)) { if (!REFRESH_OVERRIDE(ignore_no_cache)) return 0; } - if (EBIT_TEST(cc_mask, CC_NO_STORE)) { + if (cc->isSet(CC_NO_STORE)) { 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->isSet(CC_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->isSet(CC_PROXY_REVALIDATE) || + rep->cache_control->isSet(CC_MUST_REVALIDATE) || + rep->cache_control->getSMaxAge() != HttpHdrCc::S_MAXAGE_UNSET + ) 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->getMaxAge()==HttpHdrCc::MAX_AGE_UNSET && !cc->isSet(CC_NO_CACHE)) { const char *url = entry ? entry->url() : urlCanonical(request); - httpHdrCcSetMaxAge(cc, getMaxAge(url)); + cc->setMaxAge(getMaxAge(url)); } /* Enforce sibling relations */ if (flags.only_if_cached) - EBIT_SET(cc->mask, CC_ONLY_IF_CACHED); + cc->set(CC_ONLY_IF_CACHED); 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. */ === modified file 'src/mem.cc' --- src/mem.cc 2011-08-10 15:54:51 +0000 +++ src/mem.cc 2011-09-27 11:17:22 +0000 @@ -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 */ === modified file 'src/mime.cc' --- src/mime.cc 2011-01-28 07:58:53 +0000 +++ src/mime.cc 2011-09-27 11:17:22 +0000 @@ -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->setMaxAge(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); === modified file 'src/protos.h' --- src/protos.h 2011-08-30 15:04:30 +0000 +++ src/protos.h 2011-09-27 11:17:22 +0000 @@ -220,47 +220,41 @@ 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; === modified file 'src/refresh.cc' --- src/refresh.cc 2011-09-12 00:31:13 +0000 +++ src/refresh.cc 2011-09-27 11:17:22 +0000 @@ -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->getMinFresh()!=HttpHdrCc::MIN_FRESH_UNSET) { + const int32_t minFresh=cc->getMinFresh(); 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->getStaleIfError() != HttpHdrCc::STALE_IF_ERROR_UNSET && + entry->mem_obj->getReply()->cache_control->getStaleIfError() < 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->getMaxAge() != HttpHdrCc::MAX_AGE_UNSET) { #if USE_HTTP_VIOLATIONS - if (R->flags.ignore_reload && cc->max_age == 0) { + if (R->flags.ignore_reload && cc->getMaxAge() == 0) { debugs(22, 3, "refreshCheck: MAYBE: client-max-age = 0 and ignore-reload"); } else #endif { - if (cc->max_age == 0) { + if (cc->getMaxAge() == 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->getMaxAge()) { 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->getMaxStale()>=0 && staleness > -1) { + if (cc->getMaxStale()==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->getMaxStale()) { 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; } === modified file 'src/structs.h' --- src/structs.h 2011-09-11 22:21:35 +0000 +++ src/structs.h 2011-09-27 11:17:22 +0000 @@ -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 {