]> git.ipfire.org Git - thirdparty/squid.git/blame - src/HttpHdrSc.cc
Removed last traces remaining of -fhuge-objects compile flag
[thirdparty/squid.git] / src / HttpHdrSc.cc
CommitLineData
43ae1d95 1
2/*
262a0e14 3 * $Id$
43ae1d95 4 *
5 * DEBUG: section 90 HTTP Cache Control Header
6 * AUTHOR: Alex Rousskov
7 * Robert Collins (Surrogate-Control is derived from
8 * Cache-Control).
9 *
10 * SQUID Web Proxy Cache http://www.squid-cache.org/
11 * ----------------------------------------------------------
12 *
13 * Squid is the result of efforts by numerous individuals from
14 * the Internet community; see the CONTRIBUTORS file for full
15 * details. Many organizations have provided support for Squid's
16 * development; see the SPONSORS file for full details. Squid is
17 * Copyrighted (C) 2001 by the Regents of the University of
18 * California; see the COPYRIGHT file for full details. Squid
19 * incorporates software developed and/or copyrighted by other
20 * sources; see the CREDITS file for full details.
21 *
22 * This program is free software; you can redistribute it and/or modify
23 * it under the terms of the GNU General Public License as published by
24 * the Free Software Foundation; either version 2 of the License, or
25 * (at your option) any later version.
26ac0430 26 *
43ae1d95 27 * This program is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * GNU General Public License for more details.
26ac0430 31 *
43ae1d95 32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
35 *
36 */
37
38#include "squid.h"
39#include "Store.h"
40#include "HttpHeader.h"
25b6a907 41#include "HttpHdrSc.h"
43ae1d95 42
43/* this table is used for parsing surrogate control header */
26ac0430
AJ
44static const HttpHeaderFieldAttrs ScAttrs[SC_ENUM_END] = {
45 {"no-store", (http_hdr_type)SC_NO_STORE},
43ae1d95 46
26ac0430
AJ
47 {"no-store-remote", (http_hdr_type)SC_NO_STORE_REMOTE},
48 {"max-age", (http_hdr_type)SC_MAX_AGE},
49 {"content", (http_hdr_type)SC_CONTENT},
50 {"Other,", (http_hdr_type)SC_OTHER} /* ',' will protect from matches */
51};
43ae1d95 52
53HttpHeaderFieldInfo *ScFieldsInfo = NULL;
54
55http_hdr_sc_type &operator++ (http_hdr_sc_type &aHeader)
56{
892e7ba7 57 int tmp = (int)aHeader;
58 aHeader = (http_hdr_sc_type)(++tmp);
43ae1d95 59 return aHeader;
60}
61
62int operator - (http_hdr_sc_type const &anSc, http_hdr_sc_type const &anSc2)
63{
64 return (int)anSc - (int)anSc2;
65}
66
67
68/* local prototypes */
30abd221 69static int httpHdrScParseInit(HttpHdrSc * sc, const String * str);
43ae1d95 70
71/* module initialization */
72
73void
74httpHdrScInitModule(void)
75{
76 ScFieldsInfo = httpHeaderBuildFieldsInfo(ScAttrs, SC_ENUM_END);
77}
78
79void
80httpHdrScCleanModule(void)
81{
82 httpHeaderDestroyFieldsInfo(ScFieldsInfo, SC_ENUM_END);
83 ScFieldsInfo = NULL;
84}
85
86/* implementation */
87
88HttpHdrSc *
89httpHdrScCreate(void)
90{
25b6a907 91 return new HttpHdrSc();
43ae1d95 92}
93
94/* creates an sc object from a 0-terminating string */
95HttpHdrSc *
30abd221 96httpHdrScParseCreate(const String * str)
43ae1d95 97{
98 HttpHdrSc *sc = httpHdrScCreate();
99
100 if (!httpHdrScParseInit(sc, str)) {
101 httpHdrScDestroy(sc);
102 sc = NULL;
103 }
104
105 return sc;
106}
107
108/* parses a 0-terminating string and inits sc */
109static int
30abd221 110httpHdrScParseInit(HttpHdrSc * sc, const String * str)
43ae1d95 111{
112 const char *item;
113 const char *p; /* '=' parameter */
114 const char *pos = NULL;
115 const char *target = NULL; /* ;foo */
116 const char *temp = NULL; /* temp buffer */
117 int type;
34460e19 118 int ilen, vlen;
43ae1d95 119 int initiallen;
120 HttpHdrScTarget *sct;
121 assert(sc && str);
122
123 /* iterate through comma separated list */
124
125 while (strListGetItem(str, ',', &item, &ilen, &pos)) {
126 initiallen = ilen;
34460e19 127 vlen = 0;
43ae1d95 128 /* decrease ilen to still match the token for '=' statements */
129
34460e19 130 if ((p = strchr(item, '=')) && (p - item < ilen)) {
7c0f9f7e 131 vlen = ilen - (p + 1 - item);
34460e19 132 ilen = p - item;
7c0f9f7e 133 p++;
34460e19 134 }
43ae1d95 135
136 /* decrease ilen to still match the token for ';' qualified non '=' statments */
137 else if ((p = strchr(item, ';')) && (p - item < ilen))
138 ilen = p++ - item;
139
140 /* find type */
30abd221 141 type = httpHeaderIdByName(item, ilen,
142 ScFieldsInfo, SC_ENUM_END);
43ae1d95 143
144 if (type < 0) {
550cc09e 145 debugs(90, 2, "hdr sc: unknown control-directive: near '" << item << "' in '" << str << "'");
43ae1d95 146 type = SC_OTHER;
147 }
148
149 /* Is this a targeted directive? */
150 /* TODO sometime: implement a strnrchr that looks at a substring */
151 temp = xstrndup (item, initiallen + 1);
152
153 if (!((target = strrchr (temp, ';')) && !strchr (target, '"') && *(target + 1) != '\0'))
154 target = NULL;
155 else
156 ++target;
157
158 sct = httpHdrScFindTarget (sc, target);
159
160 if (!sct) {
161 sct = httpHdrScTargetCreate (target);
162 dlinkAdd(sct, &sct->node, &sc->targets);
163 }
164
165 safe_free (temp);
166
167 if (EBIT_TEST(sct->mask, type)) {
168 if (type != SC_OTHER)
550cc09e 169 debugs(90, 2, "hdr sc: ignoring duplicate control-directive: near '" << item << "' in '" << str << "'");
43ae1d95 170
171 ScFieldsInfo[type].stat.repCount++;
172
173 continue;
174 }
175
176 /* update mask */
177 EBIT_SET(sct->mask, type);
178
179 /* post-processing special cases */
180 switch (type) {
181
182 case SC_MAX_AGE:
183
184 if (!p || !httpHeaderParseInt(p, &sct->max_age)) {
bf8fe701 185 debugs(90, 2, "sc: invalid max-age specs near '" << item << "'");
43ae1d95 186 sct->max_age = -1;
187 EBIT_CLR(sct->mask, type);
188 }
189
190 if ((p = strchr (p, '+')))
191 if (!httpHeaderParseInt(++p, &sct->max_stale)) {
bf8fe701 192 debugs(90, 2, "sc: invalid max-stale specs near '" << item << "'");
43ae1d95 193 sct->max_stale = 0;
194 /* leave the max-age alone */
195 }
196
197 break;
198
199 case SC_CONTENT:
200
34460e19 201 if (!p || !httpHeaderParseQuotedString(p, vlen, &sct->content)) {
bf8fe701 202 debugs(90, 2, "sc: invalid content= quoted string near '" << item << "'");
30abd221 203 sct->content.clean();
43ae1d95 204 EBIT_CLR(sct->mask, type);
205 }
206
207 default:
208 break;
209 }
210 }
211
212 return sc->targets.head != NULL;
213}
214
215void
216httpHdrScDestroy(HttpHdrSc * sc)
217{
218 assert(sc);
219
220 if (sc->targets.head) {
221 dlink_node *sct = sc->targets.head;
222
223 while (sct) {
224 HttpHdrScTarget *t = (HttpHdrScTarget *)sct->data;
225 sct = sct->next;
226 dlinkDelete (&t->node, &sc->targets);
227 httpHdrScTargetDestroy (t);
228 }
229 }
230
25b6a907 231 delete sc;
43ae1d95 232}
233
234HttpHdrSc *
235httpHdrScDup(const HttpHdrSc * sc)
236{
237 HttpHdrSc *dup;
238 dlink_node *node;
239 assert(sc);
240 node = sc->targets.head;
241 dup = httpHdrScCreate();
242
243 while (node) {
244 HttpHdrScTarget *dupsct;
245 dupsct = httpHdrScTargetDup ((HttpHdrScTarget *)node->data);
246 dlinkAddTail (dupsct, &dupsct->node, &dup->targets);
247 node = node->next;
248 }
249
250 return dup;
251}
252
253void
254httpHdrScTargetPackInto(const HttpHdrScTarget * sc, Packer * p)
255{
256 http_hdr_sc_type flag;
257 int pcount = 0;
258 assert(sc && p);
259
260 for (flag = SC_NO_STORE; flag < SC_ENUM_END; ++flag) {
261 if (EBIT_TEST(sc->mask, flag) && flag != SC_OTHER) {
262
263 /* print option name */
826a1fed 264 packerPrintf(p, (pcount ? ", " SQUIDSTRINGPH : SQUIDSTRINGPH),
af6a12ee 265 SQUIDSTRINGPRINT(ScFieldsInfo[flag].name));
43ae1d95 266
267 /* handle options with values */
268
269 if (flag == SC_MAX_AGE)
270 packerPrintf(p, "=%d", (int) sc->max_age);
271
272 if (flag == SC_CONTENT)
826a1fed 273 packerPrintf(p, "=\"" SQUIDSTRINGPH "\"", SQUIDSTRINGPRINT(sc->content));
43ae1d95 274
275 pcount++;
276 }
277 }
278
279 if (sc->target.size())
826a1fed 280 packerPrintf (p, ";" SQUIDSTRINGPH, SQUIDSTRINGPRINT(sc->target));
43ae1d95 281}
282
283void
284httpHdrScPackInto(const HttpHdrSc * sc, Packer * p)
285{
286 dlink_node *node;
287 assert(sc && p);
288 node = sc->targets.head;
289
290 while (node) {
291 httpHdrScTargetPackInto((HttpHdrScTarget *)node->data, p);
292 node = node->next;
293 }
294}
295
296void
297httpHdrScJoinWith(HttpHdrSc * sc, const HttpHdrSc * new_sc)
298{
299 assert(sc && new_sc);
300#if 0
301 /* RC TODO: check that both have the same target */
302
303 if (sc->max_age < 0)
304 sc->max_age = new_sc->max_age;
305
306 /* RC TODO: copy unique missing stringlist entries */
307 cc->mask |= new_cc->mask;
308
309#endif
310}
311
312/* negative max_age will clean old max_Age setting */
313void
314httpHdrScSetMaxAge(HttpHdrSc * sc, char const *target, int max_age)
315{
316 HttpHdrScTarget *sct;
317 assert(sc);
318 sct = httpHdrScFindTarget (sc, target);
319
320 if (!sct) {
321 sct = httpHdrScTargetCreate (target);
322 dlinkAddTail (sct, &sct->node, &sc->targets);
323 }
324
325 httpHdrScTargetSetMaxAge(sct, max_age);
326}
327
328void
329httpHdrScUpdateStats(const HttpHdrSc * sc, StatHist * hist)
330{
331 dlink_node *sct;
332 assert(sc);
333 sct = sc->targets.head;
334
335 while (sct) {
336 httpHdrScTargetUpdateStats((HttpHdrScTarget *)sct->data, hist);
337 sct = sct->next;
338 }
339}
340
341void
342httpHdrScTargetStatDumper(StoreEntry * sentry, int idx, double val, double size, int count)
343{
344 extern const HttpHeaderStat *dump_stat; /* argh! */
345 const int id = (int) val;
346 const int valid_id = id >= 0 && id < SC_ENUM_END;
550cc09e 347 const char *name = valid_id ? ScFieldsInfo[id].name.termedBuf() : "INVALID";
43ae1d95 348
349 if (count || valid_id)
350 storeAppendPrintf(sentry, "%2d\t %-20s\t %5d\t %6.2f\n",
351 id, name, count, xdiv(count, dump_stat->scParsedCount));
352}
353
354void
355httpHdrScStatDumper(StoreEntry * sentry, int idx, double val, double size, int count)
356{
357 extern const HttpHeaderStat *dump_stat; /* argh! */
358 const int id = (int) val;
359 const int valid_id = id >= 0 && id < SC_ENUM_END;
550cc09e 360 const char *name = valid_id ? ScFieldsInfo[id].name.termedBuf() : "INVALID";
43ae1d95 361
362 if (count || valid_id)
363 storeAppendPrintf(sentry, "%2d\t %-20s\t %5d\t %6.2f\n",
364 id, name, count, xdiv(count, dump_stat->scParsedCount));
365}
366
367HttpHdrScTarget *
368httpHdrScFindTarget (HttpHdrSc *sc, const char *target)
369{
370 dlink_node *node;
371 assert (sc);
372 node = sc->targets.head;
373
374 while (node) {
375 HttpHdrScTarget *sct = (HttpHdrScTarget *)node->data;
376
550cc09e 377 if (target && sct->target.defined() && !strcmp (target, sct->target.termedBuf()))
43ae1d95 378 return sct;
550cc09e 379 else if (!target && sct->target.undefined())
43ae1d95 380 return sct;
381
382 node = node->next;
383 }
384
385 return NULL;
386}
387
388HttpHdrScTarget *
389httpHdrScGetMergedTarget (HttpHdrSc *sc, const char *ourtarget)
390{
391 HttpHdrScTarget *sctus = httpHdrScFindTarget (sc, ourtarget);
392 HttpHdrScTarget *sctgeneric = httpHdrScFindTarget (sc, NULL);
393
394 if (sctgeneric || sctus) {
395 HttpHdrScTarget *sctusable = httpHdrScTargetCreate (NULL);
396
397 if (sctgeneric)
398 httpHdrScTargetMergeWith (sctusable, sctgeneric);
399
400 if (sctus)
401 httpHdrScTargetMergeWith (sctusable, sctus);
402
403 return sctusable;
404 }
405
406 return NULL;
407}