]>
Commit | Line | Data |
---|---|---|
7faf2bdb | 1 | |
2 | /* | |
62e76326 | 3 | * $Id: HttpHdrCc.cc,v 1.25 2003/02/21 22:50:05 robertc Exp $ |
7faf2bdb | 4 | * |
5 | * DEBUG: section 65 HTTP Cache Control Header | |
6 | * AUTHOR: Alex Rousskov | |
7 | * | |
2b6662ba | 8 | * SQUID Web Proxy Cache http://www.squid-cache.org/ |
e25c139f | 9 | * ---------------------------------------------------------- |
7faf2bdb | 10 | * |
2b6662ba | 11 | * Squid is the result of efforts by numerous individuals from |
12 | * the Internet community; see the CONTRIBUTORS file for full | |
13 | * details. Many organizations have provided support for Squid's | |
14 | * development; see the SPONSORS file for full details. Squid is | |
15 | * Copyrighted (C) 2001 by the Regents of the University of | |
16 | * California; see the COPYRIGHT file for full details. Squid | |
17 | * incorporates software developed and/or copyrighted by other | |
18 | * sources; see the CREDITS file for full details. | |
7faf2bdb | 19 | * |
20 | * This program is free software; you can redistribute it and/or modify | |
21 | * it under the terms of the GNU General Public License as published by | |
22 | * the Free Software Foundation; either version 2 of the License, or | |
23 | * (at your option) any later version. | |
e25c139f | 24 | * |
7faf2bdb | 25 | * This program is distributed in the hope that it will be useful, |
26 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
27 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
28 | * GNU General Public License for more details. | |
e25c139f | 29 | * |
7faf2bdb | 30 | * You should have received a copy of the GNU General Public License |
31 | * along with this program; if not, write to the Free Software | |
cbdec147 | 32 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. |
7faf2bdb | 33 | * |
34 | */ | |
35 | ||
36 | #include "squid.h" | |
e6ccf245 | 37 | #include "Store.h" |
38 | #include "HttpHeader.h" | |
7faf2bdb | 39 | |
de336bbe | 40 | /* this table is used for parsing cache control header */ |
41 | static const HttpHeaderFieldAttrs CcAttrs[CC_ENUM_END] = | |
62e76326 | 42 | { |
43 | {"public", (http_hdr_type)CC_PUBLIC}, | |
44 | ||
45 | {"private", (http_hdr_type)CC_PRIVATE}, | |
46 | {"no-cache", (http_hdr_type)CC_NO_CACHE}, | |
47 | {"no-store", (http_hdr_type)CC_NO_STORE}, | |
48 | {"no-transform", (http_hdr_type)CC_NO_TRANSFORM}, | |
49 | {"must-revalidate", (http_hdr_type)CC_MUST_REVALIDATE}, | |
50 | {"proxy-revalidate", (http_hdr_type)CC_PROXY_REVALIDATE}, | |
51 | {"only-if-cached", (http_hdr_type)CC_ONLY_IF_CACHED}, | |
52 | {"max-age", (http_hdr_type)CC_MAX_AGE}, | |
53 | {"s-maxage", (http_hdr_type)CC_S_MAXAGE}, | |
54 | {"max-stale", (http_hdr_type)CC_MAX_STALE}, | |
55 | {"Other,", (http_hdr_type)CC_OTHER} /* ',' will protect from matches */ | |
56 | }; | |
57 | ||
de336bbe | 58 | HttpHeaderFieldInfo *CcFieldsInfo = NULL; |
7faf2bdb | 59 | |
e6ccf245 | 60 | http_hdr_cc_type &operator++ (http_hdr_cc_type &aHeader) |
61 | { | |
62 | aHeader = (http_hdr_cc_type)(++(int)aHeader); | |
63 | return aHeader; | |
64 | } | |
65 | ||
66 | ||
b5107edb | 67 | /* local prototypes */ |
5999b776 | 68 | static int httpHdrCcParseInit(HttpHdrCc * cc, const String * str); |
7faf2bdb | 69 | |
70 | ||
71 | /* module initialization */ | |
72 | ||
73 | void | |
9bc73deb | 74 | httpHdrCcInitModule(void) |
7faf2bdb | 75 | { |
de336bbe | 76 | CcFieldsInfo = httpHeaderBuildFieldsInfo(CcAttrs, CC_ENUM_END); |
77 | } | |
78 | ||
79 | void | |
9bc73deb | 80 | httpHdrCcCleanModule(void) |
de336bbe | 81 | { |
82 | httpHeaderDestroyFieldsInfo(CcFieldsInfo, CC_ENUM_END); | |
83 | CcFieldsInfo = NULL; | |
7faf2bdb | 84 | } |
85 | ||
86 | /* implementation */ | |
87 | ||
88 | HttpHdrCc * | |
9bc73deb | 89 | httpHdrCcCreate(void) |
7faf2bdb | 90 | { |
e6ccf245 | 91 | HttpHdrCc *cc = (HttpHdrCc *)memAllocate(MEM_HTTP_HDR_CC); |
49ff0930 | 92 | cc->max_age = cc->s_maxage = cc->max_stale = -1; |
7faf2bdb | 93 | return cc; |
94 | } | |
95 | ||
96 | /* creates an cc object from a 0-terminating string */ | |
97 | HttpHdrCc * | |
5999b776 | 98 | httpHdrCcParseCreate(const String * str) |
7faf2bdb | 99 | { |
100 | HttpHdrCc *cc = httpHdrCcCreate(); | |
62e76326 | 101 | |
b5107edb | 102 | if (!httpHdrCcParseInit(cc, str)) { |
62e76326 | 103 | httpHdrCcDestroy(cc); |
104 | cc = NULL; | |
b5107edb | 105 | } |
62e76326 | 106 | |
7faf2bdb | 107 | return cc; |
108 | } | |
109 | ||
110 | /* parses a 0-terminating string and inits cc */ | |
b5107edb | 111 | static int |
5999b776 | 112 | httpHdrCcParseInit(HttpHdrCc * cc, const String * str) |
7faf2bdb | 113 | { |
114 | const char *item; | |
115 | const char *p; /* '=' parameter */ | |
116 | const char *pos = NULL; | |
e6ccf245 | 117 | http_hdr_cc_type type; |
7faf2bdb | 118 | int ilen; |
119 | assert(cc && str); | |
120 | ||
7faf2bdb | 121 | /* iterate through comma separated list */ |
62e76326 | 122 | |
7faf2bdb | 123 | while (strListGetItem(str, ',', &item, &ilen, &pos)) { |
62e76326 | 124 | /* strip '=' statements @?@ */ |
125 | ||
126 | if ((p = strchr(item, '=')) && (p - item < ilen)) | |
127 | ilen = p++ - item; | |
128 | ||
129 | /* find type */ | |
130 | type = (http_hdr_cc_type ) httpHeaderIdByName(item, ilen, | |
131 | CcFieldsInfo, CC_ENUM_END); | |
132 | ||
133 | if (type < 0) { | |
134 | debug(65, 2) ("hdr cc: unknown cache-directive: near '%s' in '%s'\n", item, str->buf()); | |
135 | type = CC_OTHER; | |
136 | } | |
137 | ||
138 | if (EBIT_TEST(cc->mask, type)) { | |
139 | if (type != CC_OTHER) | |
140 | debug(65, 2) ("hdr cc: ignoring duplicate cache-directive: near '%s' in '%s'\n", item, str->buf()); | |
141 | ||
142 | CcFieldsInfo[type].stat.repCount++; | |
143 | ||
144 | continue; | |
145 | } | |
146 | ||
147 | /* update mask */ | |
148 | EBIT_SET(cc->mask, type); | |
149 | ||
150 | /* post-processing special cases */ | |
151 | switch (type) { | |
152 | ||
153 | case CC_MAX_AGE: | |
154 | ||
155 | if (!p || !httpHeaderParseInt(p, &cc->max_age)) { | |
156 | debug(65, 2) ("cc: invalid max-age specs near '%s'\n", item); | |
157 | cc->max_age = -1; | |
158 | EBIT_CLR(cc->mask, type); | |
159 | } | |
160 | ||
161 | break; | |
162 | ||
163 | case CC_S_MAXAGE: | |
164 | ||
165 | if (!p || !httpHeaderParseInt(p, &cc->s_maxage)) { | |
166 | debug(65, 2) ("cc: invalid s-maxage specs near '%s'\n", item); | |
167 | cc->s_maxage = -1; | |
168 | EBIT_CLR(cc->mask, type); | |
169 | } | |
170 | ||
171 | break; | |
172 | ||
173 | case CC_MAX_STALE: | |
174 | ||
175 | if (!p || !httpHeaderParseInt(p, &cc->max_stale)) { | |
176 | debug(65, 2) ("cc: max-stale directive is valid without value\n"); | |
177 | cc->max_stale = -1; | |
178 | } | |
179 | ||
180 | break; | |
181 | ||
182 | default: | |
183 | /* note that we ignore most of '=' specs */ | |
184 | break; | |
185 | } | |
7faf2bdb | 186 | } |
62e76326 | 187 | |
b5107edb | 188 | return cc->mask != 0; |
7faf2bdb | 189 | } |
190 | ||
191 | void | |
192 | httpHdrCcDestroy(HttpHdrCc * cc) | |
193 | { | |
194 | assert(cc); | |
db1cd23c | 195 | memFree(cc, MEM_HTTP_HDR_CC); |
7faf2bdb | 196 | } |
197 | ||
198 | HttpHdrCc * | |
02922e76 | 199 | httpHdrCcDup(const HttpHdrCc * cc) |
7faf2bdb | 200 | { |
201 | HttpHdrCc *dup; | |
202 | assert(cc); | |
203 | dup = httpHdrCcCreate(); | |
204 | dup->mask = cc->mask; | |
205 | dup->max_age = cc->max_age; | |
7e3ce7b9 | 206 | dup->s_maxage = cc->s_maxage; |
49ff0930 | 207 | dup->max_stale = cc->max_stale; |
7faf2bdb | 208 | return dup; |
209 | } | |
210 | ||
211 | void | |
d76fcfa7 | 212 | httpHdrCcPackInto(const HttpHdrCc * cc, Packer * p) |
7faf2bdb | 213 | { |
214 | http_hdr_cc_type flag; | |
215 | int pcount = 0; | |
216 | assert(cc && p); | |
62e76326 | 217 | |
e6ccf245 | 218 | for (flag = CC_PUBLIC; flag < CC_ENUM_END; ++flag) { |
62e76326 | 219 | if (EBIT_TEST(cc->mask, flag) && flag != CC_OTHER) { |
220 | ||
221 | /* print option name */ | |
222 | packerPrintf(p, (pcount ? ", %s" : "%s"), CcFieldsInfo[flag].name.buf()); | |
91274dd0 | 223 | |
62e76326 | 224 | /* handle options with values */ |
91274dd0 | 225 | |
62e76326 | 226 | if (flag == CC_MAX_AGE) |
227 | packerPrintf(p, "=%d", (int) cc->max_age); | |
91274dd0 | 228 | |
62e76326 | 229 | if (flag == CC_S_MAXAGE) |
230 | packerPrintf(p, "=%d", (int) cc->s_maxage); | |
7e3ce7b9 | 231 | |
62e76326 | 232 | if (flag == CC_MAX_STALE) |
233 | packerPrintf(p, "=%d", (int) cc->max_stale); | |
49ff0930 | 234 | |
62e76326 | 235 | pcount++; |
236 | } | |
7faf2bdb | 237 | } |
238 | } | |
239 | ||
240 | void | |
02922e76 | 241 | httpHdrCcJoinWith(HttpHdrCc * cc, const HttpHdrCc * new_cc) |
7faf2bdb | 242 | { |
243 | assert(cc && new_cc); | |
62e76326 | 244 | |
7faf2bdb | 245 | if (cc->max_age < 0) |
62e76326 | 246 | cc->max_age = new_cc->max_age; |
247 | ||
7e3ce7b9 | 248 | if (cc->s_maxage < 0) |
62e76326 | 249 | cc->s_maxage = new_cc->s_maxage; |
250 | ||
49ff0930 | 251 | if (cc->max_stale < 0) |
62e76326 | 252 | cc->max_stale = new_cc->max_stale; |
253 | ||
7faf2bdb | 254 | cc->mask |= new_cc->mask; |
255 | } | |
256 | ||
99edd1c3 | 257 | /* negative max_age will clean old max_Age setting */ |
258 | void | |
259 | httpHdrCcSetMaxAge(HttpHdrCc * cc, int max_age) | |
260 | { | |
261 | assert(cc); | |
262 | cc->max_age = max_age; | |
62e76326 | 263 | |
99edd1c3 | 264 | if (max_age >= 0) |
62e76326 | 265 | EBIT_SET(cc->mask, CC_MAX_AGE); |
99edd1c3 | 266 | else |
62e76326 | 267 | EBIT_CLR(cc->mask, CC_MAX_AGE); |
99edd1c3 | 268 | } |
269 | ||
7e3ce7b9 | 270 | /* negative s_maxage will clean old s-maxage setting */ |
271 | void | |
272 | httpHdrCcSetSMaxAge(HttpHdrCc * cc, int s_maxage) | |
273 | { | |
274 | assert(cc); | |
275 | cc->s_maxage = s_maxage; | |
62e76326 | 276 | |
7e3ce7b9 | 277 | if (s_maxage >= 0) |
62e76326 | 278 | EBIT_SET(cc->mask, CC_S_MAXAGE); |
7e3ce7b9 | 279 | else |
62e76326 | 280 | EBIT_CLR(cc->mask, CC_S_MAXAGE); |
7e3ce7b9 | 281 | } |
282 | ||
7faf2bdb | 283 | void |
284 | httpHdrCcUpdateStats(const HttpHdrCc * cc, StatHist * hist) | |
285 | { | |
286 | http_hdr_cc_type c; | |
287 | assert(cc); | |
62e76326 | 288 | |
e6ccf245 | 289 | for (c = CC_PUBLIC; c < CC_ENUM_END; ++c) |
62e76326 | 290 | if (EBIT_TEST(cc->mask, c)) |
291 | statHistCount(hist, c); | |
7faf2bdb | 292 | } |
293 | ||
294 | void | |
295 | httpHdrCcStatDumper(StoreEntry * sentry, int idx, double val, double size, int count) | |
296 | { | |
0cdcddb9 | 297 | extern const HttpHeaderStat *dump_stat; /* argh! */ |
7faf2bdb | 298 | const int id = (int) val; |
299 | const int valid_id = id >= 0 && id < CC_ENUM_END; | |
528b2c61 | 300 | const char *name = valid_id ? CcFieldsInfo[id].name.buf() : "INVALID"; |
62e76326 | 301 | |
7faf2bdb | 302 | if (count || valid_id) |
62e76326 | 303 | storeAppendPrintf(sentry, "%2d\t %-20s\t %5d\t %6.2f\n", |
304 | id, name, count, xdiv(count, dump_stat->ccParsedCount)); | |
7faf2bdb | 305 | } |