]> git.ipfire.org Git - thirdparty/squid.git/blame - src/HttpHdrCc.cc
Removed statHistCopy, started using operator= instead.
[thirdparty/squid.git] / src / HttpHdrCc.cc
CommitLineData
7faf2bdb 1/*
7faf2bdb 2 *
3 * DEBUG: section 65 HTTP Cache Control Header
7faf2bdb 4 *
2b6662ba 5 * SQUID Web Proxy Cache http://www.squid-cache.org/
e25c139f 6 * ----------------------------------------------------------
7faf2bdb 7 *
2b6662ba 8 * Squid is the result of efforts by numerous individuals from
9 * the Internet community; see the CONTRIBUTORS file for full
10 * details. Many organizations have provided support for Squid's
11 * development; see the SPONSORS file for full details. Squid is
12 * Copyrighted (C) 2001 by the Regents of the University of
13 * California; see the COPYRIGHT file for full details. Squid
14 * incorporates software developed and/or copyrighted by other
15 * sources; see the CREDITS file for full details.
7faf2bdb 16 *
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version.
26ac0430 21 *
7faf2bdb 22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26ac0430 26 *
7faf2bdb 27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
cbdec147 29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
7faf2bdb 30 *
31 */
32
33#include "squid.h"
46cba5d3 34#include "base/StringArea.h"
e6ccf245 35#include "HttpHeader.h"
ce394734 36#include "HttpHdrCc.h"
00a7574e
FC
37#include "StatHist.h"
38#include "Store.h"
ce394734
FC
39
40#if HAVE_MAP
41#include <map>
42#endif
43
d4cb5913 44/* a row in the table used for parsing cache control header and statistics */
ce394734
FC
45typedef struct {
46 const char *name;
47 http_hdr_cc_type id;
48 HttpHeaderFieldStat stat;
49} HttpHeaderCcFields;
50
51/* order must match that of enum http_hdr_cc_type. The constraint is verified at initialization time */
52static HttpHeaderCcFields CcAttrs[CC_ENUM_END] = {
77da1817
A
53 {"public", CC_PUBLIC},
54 {"private", CC_PRIVATE},
55 {"no-cache", CC_NO_CACHE},
56 {"no-store", CC_NO_STORE},
57 {"no-transform", CC_NO_TRANSFORM},
58 {"must-revalidate", CC_MUST_REVALIDATE},
59 {"proxy-revalidate", CC_PROXY_REVALIDATE},
60 {"max-age", CC_MAX_AGE},
61 {"s-maxage", CC_S_MAXAGE},
62 {"max-stale", CC_MAX_STALE},
63 {"min-fresh", CC_MIN_FRESH},
64 {"only-if-cached", CC_ONLY_IF_CACHED},
65 {"stale-if-error", CC_STALE_IF_ERROR},
66 {"Other,", CC_OTHER} /* ',' will protect from matches */
26ac0430 67};
62e76326 68
ce394734 69/// Map an header name to its type, to expedite parsing
46cba5d3 70typedef std::map<const StringArea,http_hdr_cc_type> CcNameToIdMap_t;
7ebe76de 71static CcNameToIdMap_t CcNameToIdMap;
7faf2bdb 72
d74ad83f 73/// used to walk a table of http_header_cc_type structs
e6ccf245 74http_hdr_cc_type &operator++ (http_hdr_cc_type &aHeader)
75{
1f1ae50a 76 int tmp = (int)aHeader;
77 aHeader = (http_hdr_cc_type)(++tmp);
e6ccf245 78 return aHeader;
79}
80
81
c23f7c32 82/// Module initialization hook
7faf2bdb 83void
9bc73deb 84httpHdrCcInitModule(void)
7faf2bdb 85{
ce394734 86 /* build lookup and accounting structures */
77da1817 87 for (int32_t i = 0; i < CC_ENUM_END; ++i) {
46cba5d3
FC
88 const HttpHeaderCcFields &f=CcAttrs[i];
89 assert(i == f.id); /* verify assumption: the id is the key into the array */
90 const StringArea k(f.name,strlen(f.name));
91 CcNameToIdMap[k]=f.id;
ce394734 92 }
de336bbe 93}
94
c23f7c32 95/// Module cleanup hook.
de336bbe 96void
9bc73deb 97httpHdrCcCleanModule(void)
de336bbe 98{
ce394734 99 // HdrCcNameToIdMap is self-cleaning
7faf2bdb 100}
101
ce394734
FC
102void
103HttpHdrCc::clear()
7faf2bdb 104{
7ebe76de 105 *this=HttpHdrCc();
7faf2bdb 106}
107
ce394734 108bool
7ebe76de 109HttpHdrCc::parse(const String & str)
7faf2bdb 110{
111 const char *item;
112 const char *p; /* '=' parameter */
113 const char *pos = NULL;
e6ccf245 114 http_hdr_cc_type type;
7faf2bdb 115 int ilen;
1b2e9616 116 int nlen;
7faf2bdb 117
7faf2bdb 118 /* iterate through comma separated list */
62e76326 119
ce394734 120 while (strListGetItem(&str, ',', &item, &ilen, &pos)) {
1b2e9616 121 /* isolate directive name */
62e76326 122
1b2e9616 123 if ((p = (const char *)memchr(item, '=', ilen)) && (p - item < ilen))
124 nlen = p++ - item;
125 else
126 nlen = ilen;
62e76326 127
128 /* find type */
cf7c2e94 129 const CcNameToIdMap_t::const_iterator i=CcNameToIdMap.find(StringArea(item,nlen));
7ebe76de 130 if (i==CcNameToIdMap.end())
ce394734
FC
131 type=CC_OTHER;
132 else
133 type=i->second;
62e76326 134
aa62670a 135 // ignore known duplicate directives
f9517ad8 136 if (isSet(type)) {
aa62670a 137 if (type != CC_OTHER) {
e8466ea9 138 debugs(65, 2, "hdr cc: ignoring duplicate cache-directive: near '" << item << "' in '" << str << "'");
7ebe76de 139 ++CcAttrs[type].stat.repCount;
aa62670a
AR
140 continue;
141 }
62e76326 142 }
143
4ce6e3b5 144 /* special-case-parsing and attribute-setting */
62e76326 145 switch (type) {
146
147 case CC_MAX_AGE:
d74ad83f 148 if (!p || !httpHeaderParseInt(p, &max_age) || max_age < 0) {
bf8fe701 149 debugs(65, 2, "cc: invalid max-age specs near '" << item << "'");
4ce6e3b5 150 clearMaxAge();
1ba0611a 151 } else {
d74ad83f 152 setMask(type,true);
62e76326 153 }
62e76326 154 break;
155
156 case CC_S_MAXAGE:
d74ad83f 157 if (!p || !httpHeaderParseInt(p, &s_maxage) || s_maxage < 0) {
bf8fe701 158 debugs(65, 2, "cc: invalid s-maxage specs near '" << item << "'");
4ce6e3b5 159 clearSMaxAge();
d74ad83f
FC
160 } else {
161 setMask(type,true);
62e76326 162 }
62e76326 163 break;
164
165 case CC_MAX_STALE:
d74ad83f 166 if (!p || !httpHeaderParseInt(p, &max_stale) || max_stale < 0) {
bf8fe701 167 debugs(65, 2, "cc: max-stale directive is valid without value");
d74ad83f
FC
168 maxStale(MAX_STALE_ANY);
169 } else {
170 setMask(type,true);
62e76326 171 }
62e76326 172 break;
173
64f8c2cb 174 case CC_MIN_FRESH:
d74ad83f 175 if (!p || !httpHeaderParseInt(p, &min_fresh) || min_fresh < 0) {
64f8c2cb 176 debugs(65, 2, "cc: invalid min-fresh specs near '" << item << "'");
4ce6e3b5 177 clearMinFresh();
d74ad83f
FC
178 } else {
179 setMask(type,true);
64f8c2cb 180 }
64f8c2cb
AR
181 break;
182
65fd3895 183 case CC_STALE_IF_ERROR:
d74ad83f 184 if (!p || !httpHeaderParseInt(p, &stale_if_error) || stale_if_error < 0) {
65fd3895 185 debugs(65, 2, "cc: invalid stale-if-error specs near '" << item << "'");
4ce6e3b5 186 clearStaleIfError();
d74ad83f
FC
187 } else {
188 setMask(type,true);
65fd3895
AJ
189 }
190 break;
191
77da1817
A
192 case CC_PUBLIC:
193 Public(true);
194 break;
195 case CC_PRIVATE:
196 Private(true);
197 break;
198 case CC_NO_CACHE:
199 noCache(true);
200 break;
201 case CC_NO_STORE:
202 noStore(true);
203 break;
204 case CC_NO_TRANSFORM:
205 noTransform(true);
206 break;
207 case CC_MUST_REVALIDATE:
208 mustRevalidate(true);
209 break;
210 case CC_PROXY_REVALIDATE:
211 proxyRevalidate(true);
212 break;
213 case CC_ONLY_IF_CACHED:
214 onlyIfCached(true);
215 break;
1b2e9616 216
4ce6e3b5 217 case CC_OTHER:
f9517ad8
FC
218 if (other.size())
219 other.append(", ");
1b2e9616 220
f9517ad8 221 other.append(item, ilen);
1b2e9616 222 break;
223
62e76326 224 default:
1b2e9616 225 /* note that we ignore most of '=' specs (RFCVIOLATION) */
62e76326 226 break;
227 }
7faf2bdb 228 }
62e76326 229
f9517ad8 230 return (mask != 0);
7faf2bdb 231}
232
7faf2bdb 233void
4ce6e3b5 234HttpHdrCc::packInto(Packer * p) const
7faf2bdb 235{
2c8c98ad
FC
236 // optimization: if the mask is empty do nothing
237 if (mask==0)
238 return;
239
7faf2bdb 240 http_hdr_cc_type flag;
241 int pcount = 0;
4ce6e3b5 242 assert(p);
62e76326 243
e6ccf245 244 for (flag = CC_PUBLIC; flag < CC_ENUM_END; ++flag) {
4ce6e3b5 245 if (isSet(flag) && flag != CC_OTHER) {
62e76326 246
c397963f 247 /* print option name for all options */
ce394734 248 packerPrintf(p, (pcount ? ", %s": "%s") , CcAttrs[flag].name);
91274dd0 249
c397963f
FC
250 /* for all options having values, "=value" after the name */
251 switch (flag) {
252 case CC_MAX_AGE:
4ce6e3b5 253 packerPrintf(p, "=%d", (int) maxAge());
c397963f
FC
254 break;
255 case CC_S_MAXAGE:
4ce6e3b5 256 packerPrintf(p, "=%d", (int) sMaxAge());
c397963f
FC
257 break;
258 case CC_MAX_STALE:
259 /* max-stale's value is optional.
260 If we didn't receive it, don't send it */
261 if (maxStale()!=MAX_STALE_ANY)
262 packerPrintf(p, "=%d", (int) maxStale());
263 break;
264 case CC_MIN_FRESH:
4ce6e3b5 265 packerPrintf(p, "=%d", (int) minFresh());
c397963f
FC
266 break;
267 default:
268 /* do nothing, directive was already printed */
269 break;
270 }
64f8c2cb 271
7ebe76de 272 ++pcount;
62e76326 273 }
7faf2bdb 274 }
1b2e9616 275
4ce6e3b5 276 if (other.size() != 0)
826a1fed 277 packerPrintf(p, (pcount ? ", " SQUIDSTRINGPH : SQUIDSTRINGPH),
4ce6e3b5 278 SQUIDSTRINGPRINT(other));
7faf2bdb 279}
280
7faf2bdb 281void
282httpHdrCcUpdateStats(const HttpHdrCc * cc, StatHist * hist)
283{
284 http_hdr_cc_type c;
285 assert(cc);
62e76326 286
e6ccf245 287 for (c = CC_PUBLIC; c < CC_ENUM_END; ++c)
f9517ad8 288 if (cc->isSet(c))
62e76326 289 statHistCount(hist, c);
7faf2bdb 290}
291
292void
293httpHdrCcStatDumper(StoreEntry * sentry, int idx, double val, double size, int count)
294{
0cdcddb9 295 extern const HttpHeaderStat *dump_stat; /* argh! */
7faf2bdb 296 const int id = (int) val;
297 const int valid_id = id >= 0 && id < CC_ENUM_END;
ce394734 298 const char *name = valid_id ? CcAttrs[id].name : "INVALID";
62e76326 299
7faf2bdb 300 if (count || valid_id)
62e76326 301 storeAppendPrintf(sentry, "%2d\t %-20s\t %5d\t %6.2f\n",
302 id, name, count, xdiv(count, dump_stat->ccParsedCount));
7faf2bdb 303}
1ba0611a 304
9774b48e
FC
305#if !_USE_INLINE_
306#include "HttpHdrCc.cci"
307#endif