]>
Commit | Line | Data |
---|---|---|
7faf2bdb | 1 | |
2 | /* | |
7e3ce7b9 | 3 | * $Id: HttpHdrCc.cc,v 1.19 1999/12/30 17:36:16 wessels Exp $ |
7faf2bdb | 4 | * |
5 | * DEBUG: section 65 HTTP Cache Control Header | |
6 | * AUTHOR: Alex Rousskov | |
7 | * | |
8 | * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ | |
e25c139f | 9 | * ---------------------------------------------------------- |
7faf2bdb | 10 | * |
11 | * Squid is the result of efforts by numerous individuals from the | |
12 | * Internet community. Development is led by Duane Wessels of the | |
e25c139f | 13 | * National Laboratory for Applied Network Research and funded by the |
14 | * National Science Foundation. Squid is Copyrighted (C) 1998 by | |
15 | * Duane Wessels and the University of California San Diego. Please | |
16 | * see the COPYRIGHT file for full details. Squid incorporates | |
17 | * software developed and/or copyrighted by other sources. Please see | |
18 | * 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" | |
37 | ||
de336bbe | 38 | /* this table is used for parsing cache control header */ |
39 | static const HttpHeaderFieldAttrs CcAttrs[CC_ENUM_END] = | |
7faf2bdb | 40 | { |
41 | {"public", CC_PUBLIC}, | |
42 | {"private", CC_PRIVATE}, | |
43 | {"no-cache", CC_NO_CACHE}, | |
44 | {"no-store", CC_NO_STORE}, | |
45 | {"no-transform", CC_NO_TRANSFORM}, | |
46 | {"must-revalidate", CC_MUST_REVALIDATE}, | |
47 | {"proxy-revalidate", CC_PROXY_REVALIDATE}, | |
d8b249ef | 48 | {"only-if-cached", CC_ONLY_IF_CACHED}, |
49 | {"max-age", CC_MAX_AGE}, | |
7e3ce7b9 | 50 | {"s-maxage", CC_S_MAXAGE}, |
8a21872b | 51 | {"Other,", CC_OTHER} /* ',' will protect from matches */ |
7faf2bdb | 52 | }; |
de336bbe | 53 | HttpHeaderFieldInfo *CcFieldsInfo = NULL; |
7faf2bdb | 54 | |
b5107edb | 55 | /* local prototypes */ |
5999b776 | 56 | static int httpHdrCcParseInit(HttpHdrCc * cc, const String * str); |
7faf2bdb | 57 | |
58 | ||
59 | /* module initialization */ | |
60 | ||
61 | void | |
9bc73deb | 62 | httpHdrCcInitModule(void) |
7faf2bdb | 63 | { |
de336bbe | 64 | CcFieldsInfo = httpHeaderBuildFieldsInfo(CcAttrs, CC_ENUM_END); |
65 | } | |
66 | ||
67 | void | |
9bc73deb | 68 | httpHdrCcCleanModule(void) |
de336bbe | 69 | { |
70 | httpHeaderDestroyFieldsInfo(CcFieldsInfo, CC_ENUM_END); | |
71 | CcFieldsInfo = NULL; | |
7faf2bdb | 72 | } |
73 | ||
74 | /* implementation */ | |
75 | ||
76 | HttpHdrCc * | |
9bc73deb | 77 | httpHdrCcCreate(void) |
7faf2bdb | 78 | { |
79 | HttpHdrCc *cc = memAllocate(MEM_HTTP_HDR_CC); | |
7e3ce7b9 | 80 | cc->max_age = cc->s_maxage = -1; |
7faf2bdb | 81 | return cc; |
82 | } | |
83 | ||
84 | /* creates an cc object from a 0-terminating string */ | |
85 | HttpHdrCc * | |
5999b776 | 86 | httpHdrCcParseCreate(const String * str) |
7faf2bdb | 87 | { |
88 | HttpHdrCc *cc = httpHdrCcCreate(); | |
b5107edb | 89 | if (!httpHdrCcParseInit(cc, str)) { |
90 | httpHdrCcDestroy(cc); | |
91 | cc = NULL; | |
92 | } | |
7faf2bdb | 93 | return cc; |
94 | } | |
95 | ||
96 | /* parses a 0-terminating string and inits cc */ | |
b5107edb | 97 | static int |
5999b776 | 98 | httpHdrCcParseInit(HttpHdrCc * cc, const String * str) |
7faf2bdb | 99 | { |
100 | const char *item; | |
101 | const char *p; /* '=' parameter */ | |
102 | const char *pos = NULL; | |
103 | int type; | |
104 | int ilen; | |
105 | assert(cc && str); | |
106 | ||
7faf2bdb | 107 | /* iterate through comma separated list */ |
108 | while (strListGetItem(str, ',', &item, &ilen, &pos)) { | |
109 | /* strip '=' statements @?@ */ | |
110 | if ((p = strchr(item, '=')) && (p - item < ilen)) | |
111 | ilen = p++ - item; | |
112 | /* find type */ | |
113 | type = httpHeaderIdByName(item, ilen, | |
d8b249ef | 114 | CcFieldsInfo, CC_ENUM_END); |
7faf2bdb | 115 | if (type < 0) { |
99edd1c3 | 116 | debug(65, 2) ("hdr cc: unknown cache-directive: near '%s' in '%s'\n", item, strBuf(*str)); |
d8b249ef | 117 | type = CC_OTHER; |
7faf2bdb | 118 | } |
119 | if (EBIT_TEST(cc->mask, type)) { | |
d8b249ef | 120 | if (type != CC_OTHER) |
99edd1c3 | 121 | debug(65, 2) ("hdr cc: ignoring duplicate cache-directive: near '%s' in '%s'\n", item, strBuf(*str)); |
de336bbe | 122 | CcFieldsInfo[type].stat.repCount++; |
7faf2bdb | 123 | continue; |
124 | } | |
125 | /* update mask */ | |
126 | EBIT_SET(cc->mask, type); | |
127 | /* post-processing special cases */ | |
128 | switch (type) { | |
129 | case CC_MAX_AGE: | |
d8b249ef | 130 | if (!p || !httpHeaderParseInt(p, &cc->max_age)) { |
20198c7a | 131 | debug(65, 2) ("cc: invalid max-age specs near '%s'\n", item); |
7faf2bdb | 132 | cc->max_age = -1; |
133 | EBIT_CLR(cc->mask, type); | |
134 | } | |
135 | break; | |
7e3ce7b9 | 136 | case CC_S_MAXAGE: |
137 | if (!p || !httpHeaderParseInt(p, &cc->s_maxage)) { | |
138 | debug(65, 2) ("cc: invalid s-maxage specs near '%s'\n", item); | |
139 | cc->s_maxage = -1; | |
140 | EBIT_CLR(cc->mask, type); | |
141 | } | |
142 | break; | |
7faf2bdb | 143 | default: |
d8b249ef | 144 | /* note that we ignore most of '=' specs */ |
7faf2bdb | 145 | break; |
146 | } | |
147 | } | |
b5107edb | 148 | return cc->mask != 0; |
7faf2bdb | 149 | } |
150 | ||
151 | void | |
152 | httpHdrCcDestroy(HttpHdrCc * cc) | |
153 | { | |
154 | assert(cc); | |
db1cd23c | 155 | memFree(cc, MEM_HTTP_HDR_CC); |
7faf2bdb | 156 | } |
157 | ||
158 | HttpHdrCc * | |
02922e76 | 159 | httpHdrCcDup(const HttpHdrCc * cc) |
7faf2bdb | 160 | { |
161 | HttpHdrCc *dup; | |
162 | assert(cc); | |
163 | dup = httpHdrCcCreate(); | |
164 | dup->mask = cc->mask; | |
165 | dup->max_age = cc->max_age; | |
7e3ce7b9 | 166 | dup->s_maxage = cc->s_maxage; |
7faf2bdb | 167 | return dup; |
168 | } | |
169 | ||
170 | void | |
d76fcfa7 | 171 | httpHdrCcPackInto(const HttpHdrCc * cc, Packer * p) |
7faf2bdb | 172 | { |
173 | http_hdr_cc_type flag; | |
174 | int pcount = 0; | |
175 | assert(cc && p); | |
7faf2bdb | 176 | for (flag = 0; flag < CC_ENUM_END; flag++) { |
91274dd0 | 177 | if (EBIT_TEST(cc->mask, flag) && flag != CC_OTHER) { |
178 | ||
179 | /* print option name */ | |
99edd1c3 | 180 | packerPrintf(p, (pcount ? ", %s" : "%s"), strBuf(CcFieldsInfo[flag].name)); |
91274dd0 | 181 | |
182 | /* handle options with values */ | |
183 | if (flag == CC_MAX_AGE) | |
184 | packerPrintf(p, "=%d", (int) cc->max_age); | |
185 | ||
7e3ce7b9 | 186 | if (flag == CC_S_MAXAGE) |
187 | packerPrintf(p, "=%d", (int) cc->s_maxage); | |
188 | ||
7faf2bdb | 189 | pcount++; |
190 | } | |
191 | } | |
192 | } | |
193 | ||
194 | void | |
02922e76 | 195 | httpHdrCcJoinWith(HttpHdrCc * cc, const HttpHdrCc * new_cc) |
7faf2bdb | 196 | { |
197 | assert(cc && new_cc); | |
198 | if (cc->max_age < 0) | |
199 | cc->max_age = new_cc->max_age; | |
7e3ce7b9 | 200 | if (cc->s_maxage < 0) |
201 | cc->s_maxage = new_cc->s_maxage; | |
7faf2bdb | 202 | cc->mask |= new_cc->mask; |
203 | } | |
204 | ||
99edd1c3 | 205 | /* negative max_age will clean old max_Age setting */ |
206 | void | |
207 | httpHdrCcSetMaxAge(HttpHdrCc * cc, int max_age) | |
208 | { | |
209 | assert(cc); | |
210 | cc->max_age = max_age; | |
211 | if (max_age >= 0) | |
212 | EBIT_SET(cc->mask, CC_MAX_AGE); | |
213 | else | |
214 | EBIT_CLR(cc->mask, CC_MAX_AGE); | |
215 | } | |
216 | ||
7e3ce7b9 | 217 | /* negative s_maxage will clean old s-maxage setting */ |
218 | void | |
219 | httpHdrCcSetSMaxAge(HttpHdrCc * cc, int s_maxage) | |
220 | { | |
221 | assert(cc); | |
222 | cc->s_maxage = s_maxage; | |
223 | if (s_maxage >= 0) | |
224 | EBIT_SET(cc->mask, CC_S_MAXAGE); | |
225 | else | |
226 | EBIT_CLR(cc->mask, CC_S_MAXAGE); | |
227 | } | |
228 | ||
7faf2bdb | 229 | void |
230 | httpHdrCcUpdateStats(const HttpHdrCc * cc, StatHist * hist) | |
231 | { | |
232 | http_hdr_cc_type c; | |
233 | assert(cc); | |
234 | for (c = 0; c < CC_ENUM_END; c++) | |
235 | if (EBIT_TEST(cc->mask, c)) | |
236 | statHistCount(hist, c); | |
237 | } | |
238 | ||
239 | void | |
240 | httpHdrCcStatDumper(StoreEntry * sentry, int idx, double val, double size, int count) | |
241 | { | |
0cdcddb9 | 242 | extern const HttpHeaderStat *dump_stat; /* argh! */ |
7faf2bdb | 243 | const int id = (int) val; |
244 | const int valid_id = id >= 0 && id < CC_ENUM_END; | |
de336bbe | 245 | const char *name = valid_id ? strBuf(CcFieldsInfo[id].name) : "INVALID"; |
7faf2bdb | 246 | if (count || valid_id) |
247 | storeAppendPrintf(sentry, "%2d\t %-20s\t %5d\t %6.2f\n", | |
fcd2d3ef | 248 | id, name, count, xdiv(count, dump_stat->ccParsedCount)); |
7faf2bdb | 249 | } |