--- /dev/null
+
+/*
+ * $Id: HttpHdrCc.cc,v 1.1 1998/03/05 00:01:07 rousskov Exp $
+ *
+ * DEBUG: section 65 HTTP Cache Control Header
+ * AUTHOR: Alex Rousskov
+ *
+ * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
+ * --------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from the
+ * Internet community. Development is led by Duane Wessels of the
+ * National Laboratory for Applied Network Research and funded by
+ * the National Science Foundation.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include "squid.h"
+
+/* this table is used for parsing server cache control header */
+static field_attrs_t 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}
+};
+
+
+/* counters */
+static int CcPasredCount = 0;
+
+
+/* module initialization */
+
+void
+httpHdrCcInitModule()
+{
+ httpHeaderInitAttrTable((field_attrs_t *) CcAttrs, CC_ENUM_END);
+}
+
+/* implementation */
+
+HttpHdrCc *
+httpHdrCcCreate()
+{
+ HttpHdrCc *cc = memAllocate(MEM_HTTP_HDR_CC);
+ cc->max_age = -1;
+ return cc;
+}
+
+/* creates an cc object from a 0-terminating string */
+HttpHdrCc *
+httpHdrCcParseCreate(const char *str)
+{
+ HttpHdrCc *cc = httpHdrCcCreate();
+ httpHdrCcParseInit(cc, str);
+ return cc;
+}
+
+/* parses a 0-terminating string and inits cc */
+void
+httpHdrCcParseInit(HttpHdrCc * cc, const char *str)
+{
+ const char *item;
+ const char *p; /* '=' parameter */
+ const char *pos = NULL;
+ int type;
+ int ilen;
+ assert(cc && str);
+
+ CcPasredCount++;
+ /* iterate through comma separated list */
+ while (strListGetItem(str, ',', &item, &ilen, &pos)) {
+ /* strip '=' statements @?@ */
+ if ((p = strchr(item, '=')) && (p - item < ilen))
+ ilen = p++ - item;
+ /* find type */
+ type = httpHeaderIdByName(item, ilen,
+ CcAttrs, CC_ENUM_END, -1);
+ if (type < 0) {
+ debug(55, 0) ("hdr cc: unknown cache-directive: near '%s' in '%s'\n", item, str);
+ continue;
+ }
+ if (EBIT_TEST(cc->mask, type)) {
+ debug(55, 0) ("hdr cc: ignoring duplicate cache-directive: near '%s' in '%s'\n", item, str);
+ CcAttrs[type].stat.repCount++;
+ continue;
+ }
+ /* update mask */
+ EBIT_SET(cc->mask, type);
+ /* post-processing special cases */
+ switch (type) {
+ case CC_MAX_AGE:
+ if (p)
+ cc->max_age = (time_t) atoi(p);
+ if (cc->max_age < 0) {
+ debug(55, 0) ("cc: invalid max-age specs near '%s'\n", item);
+ cc->max_age = -1;
+ EBIT_CLR(cc->mask, type);
+ }
+ break;
+ default:
+ /* note that we ignore most of '=' specs @?@ */
+ break;
+ }
+ }
+ return;
+}
+
+void
+httpHdrCcDestroy(HttpHdrCc * cc)
+{
+ assert(cc);
+ memFree(MEM_HTTP_HDR_CC, cc);
+}
+
+HttpHdrCc *
+httpHdrCcDup(HttpHdrCc * cc)
+{
+ HttpHdrCc *dup;
+ assert(cc);
+ dup = httpHdrCcCreate();
+ dup->mask = cc->mask;
+ dup->max_age = cc->max_age;
+ return dup;
+}
+
+void
+httpHdrCcPackValueInto(HttpHdrCc * cc, Packer * p)
+{
+ http_hdr_cc_type flag;
+ int pcount = 0;
+ assert(cc && p);
+ if (cc->max_age >= 0) {
+ packerPrintf(p, "max-age=%d", cc->max_age);
+ pcount++;
+ }
+ for (flag = 0; flag < CC_ENUM_END; flag++) {
+ if (EBIT_TEST(cc->mask, flag)) {
+ packerPrintf(p, pcount ? ", %s" : "%s", CcAttrs[flag].name);
+ pcount++;
+ }
+ }
+}
+
+void
+httpHdrCcJoinWith(HttpHdrCc * cc, HttpHdrCc * new_cc)
+{
+ assert(cc && new_cc);
+ if (cc->max_age < 0)
+ cc->max_age = new_cc->max_age;
+ cc->mask |= new_cc->mask;
+}
+
+void
+httpHdrCcUpdateStats(const HttpHdrCc * cc, StatHist * hist)
+{
+ http_hdr_cc_type c;
+ assert(cc);
+ for (c = 0; c < CC_ENUM_END; c++)
+ if (EBIT_TEST(cc->mask, c))
+ statHistCount(hist, c);
+}
+
+void
+httpHdrCcStatDumper(StoreEntry * sentry, int idx, double val, double size, int count)
+{
+ const int id = (int) val;
+ const int valid_id = id >= 0 && id < CC_ENUM_END;
+ 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, CcPasredCount));
+}
/*
- * $Id: HttpHeader.cc,v 1.13 1998/03/04 05:39:28 rousskov Exp $
+ * $Id: HttpHeader.cc,v 1.14 1998/03/05 00:01:07 rousskov Exp $
*
* DEBUG: section 55 HTTP Header
* AUTHOR: Alex Rousskov
char *value; /* field-value from HTTP/1.1 */
};
-/* possible types for fields */
-typedef enum {
- ftInvalid = HDR_ENUM_END, /* to catch nasty errors with hdr_id<->fld_type clashes */
- ftInt,
- ftPChar,
- ftDate_1123,
- ftPSCC,
- ftPExtField
-} field_type;
-
/*
* HttpHeader entry
* ( the concrete type of entry.field is Headers[id].type )
};
-/* counters and size accumulators for stat objects */
-typedef int StatCount;
-typedef size_t StatSize;
-
-/* per field statistics */
-typedef struct {
- StatCount aliveCount; /* created but not destroyed (count) */
- StatCount parsCount; /* #parsing attempts */
- StatCount errCount; /* #pasring errors */
- StatCount repCount; /* #repetitons */
-} HttpHeaderFieldStat;
-
/* per header statistics */
typedef struct {
const char *label;
} HttpHeaderStat;
-/* constant attributes of fields */
-typedef struct {
- const char *name;
- http_hdr_type id;
- field_type type;
- int name_len;
- HttpHeaderFieldStat stat;
-} field_attrs_t;
-
/* use HttpHeaderPos as opaque type, do not interpret */
typedef ssize_t HttpHeaderPos;
/* use this and only this to initialize HttpHeaderPos */
{"Other:", HDR_OTHER, ftPExtField} /* ':' will not allow matches */
};
-/* this table is used for parsing server cache control header */
-static field_attrs_t SccAttrs[] =
-{
- {"public", SCC_PUBLIC},
- {"private", SCC_PRIVATE},
- {"no-cache", SCC_NO_CACHE},
- {"no-store", SCC_NO_STORE},
- {"no-transform", SCC_NO_TRANSFORM},
- {"must-revalidate", SCC_MUST_REVALIDATE},
- {"proxy-revalidate", SCC_PROXY_REVALIDATE},
- {"max-age", SCC_MAX_AGE}
-};
-
/*
* headers with field values defined as #(values) in HTTP/1.1
*
static int HttpHeaderStatCount = sizeof(HttpHeaderStats) / sizeof(*HttpHeaderStats);
/* global counters */
-static StatCount HeaderParsedCount = 0;
-static StatCount CcPasredCount = 0;
-static StatCount HeaderEntryParsedCount = 0;
+static int HeaderParsedCount = 0;
+static int HeaderEntryParsedCount = 0;
/* long strings accounting */
-static StatCount longStrAliveCount = 0;
-static StatCount longStrHighWaterCount = 0;
-static StatSize longStrAliveSize = 0;
-static StatSize longStrHighWaterSize = 0;
+static int longStrAliveCount = 0;
+static int longStrHighWaterCount = 0;
+static size_t longStrAliveSize = 0;
+static size_t longStrHighWaterSize = 0;
/*
#define assert_eid(id) assert((id) >= 0 && (id) < HDR_ENUM_END)
-static void httpHeaderInitAttrTable(field_attrs_t * table, int count);
-static int httpHeaderCalcMask(const int *enums, int count);
-static void httpHeaderStatInit(HttpHeaderStat * hs, const char *label);
-
static HttpHeaderEntry *httpHeaderGetEntry(const HttpHeader * hdr, HttpHeaderPos * pos);
static void httpHeaderDelAt(HttpHeader * hdr, HttpHeaderPos pos);
static void httpHeaderAddParsedEntry(HttpHeader * hdr, HttpHeaderEntry * e);
static field_store httpHeaderGet(const HttpHeader * hdr, http_hdr_type id);
static void httpHeaderSet(HttpHeader * hdr, http_hdr_type id, const field_store value);
static void httpHeaderSyncMasks(HttpHeader * hdr, const HttpHeaderEntry * e, int add);
-static int httpHeaderIdByName(const char *name, int name_len, const field_attrs_t * attrs, int end, int mask);
static void httpHeaderGrow(HttpHeader * hdr);
static void httpHeaderEntryInit(HttpHeaderEntry * e, http_hdr_type id, field_store field);
static field_store httpHeaderFieldDup(field_type type, field_store value);
static field_store httpHeaderFieldBadValue(field_type type);
+#if 0
static HttpScc *httpSccCreate();
static HttpScc *httpSccParseCreate(const char *str);
static void httpSccParseInit(HttpScc * scc, const char *str);
static void httpSccDestroy(HttpScc * scc);
static HttpScc *httpSccDup(HttpScc * scc);
static void httpSccUpdateStats(const HttpScc * scc, StatHist * hist);
-
static void httpSccPackValueInto(HttpScc * scc, Packer * p);
static void httpSccJoinWith(HttpScc * scc, HttpScc * new_scc);
+#endif
static HttpHeaderExtField *httpHeaderExtFieldCreate(const char *name, const char *value);
static HttpHeaderExtField *httpHeaderExtFieldParseCreate(const char *field_start, const char *field_end);
static void httpHeaderExtFieldDestroy(HttpHeaderExtField * f);
static HttpHeaderExtField *httpHeaderExtFieldDup(HttpHeaderExtField * f);
+static void httpHeaderStatInit(HttpHeaderStat * hs, const char *label);
static void httpHeaderStatDump(const HttpHeaderStat * hs, StoreEntry * e);
static void shortStringStatDump(StoreEntry * e);
static char *allocShortBuf(size_t size);
static void freeShortString(char *str);
+#if 0
static int strListGetItem(const char *str, char del, const char **item, int *ilen, const char **pos);
static const char *getStringPrefix(const char *str);
+#endif
-/* delete this when everybody remembers that ':' is not a part of a name */
-#define conversion_period_name_check(name) assert(!strchr((name), ':'))
-
/* handy to determine the #elements in a static array */
#define countof(arr) (sizeof(arr)/sizeof(*arr))
assert(sizeof(field_store) == sizeof(char *));
/* have to force removal of const here */
httpHeaderInitAttrTable((field_attrs_t *) Headers, countof(Headers));
- httpHeaderInitAttrTable((field_attrs_t *) SccAttrs, countof(SccAttrs));
/* create masks */
ListHeadersMask = httpHeaderCalcMask((const int *) ListHeaders, countof(ListHeaders));
ReplyHeadersMask = httpHeaderCalcMask((const int *) ReplyHeaders, countof(ReplyHeaders));
/* init header stats */
for (i = 0; i < HttpHeaderStatCount; i++)
httpHeaderStatInit(HttpHeaderStats + i, HttpHeaderStats[i].label);
+ httpHdrCcInitModule();
cachemgrRegister("http_headers",
"HTTP Header Statistics", httpHeaderStoreReport, 0);
}
}
}
-static void
-httpHeaderInitAttrTable(field_attrs_t * table, int count)
-{
- int i;
- assert(table);
- assert(count > 1); /* to protect from buggy "countof" implementations */
-
- /* reorder so that .id becomes an index */
- for (i = 0; i < count;) {
- const int id = table[i].id;
- assert(id >= 0 && id < count); /* sanity check */
- assert(id >= i); /* entries prior to i have been indexed already */
- if (id != i) { /* out of order */
- const field_attrs_t fa = table[id];
- assert(fa.id != id); /* avoid endless loops */
- table[id] = table[i]; /* swap */
- table[i] = fa;
- } else
- i++; /* make progress */
- }
-
- /* calculate name lengths and init stats */
- for (i = 0; i < count; ++i) {
- assert(table[i].name);
- table[i].name_len = strlen(table[i].name);
- debug(55, 5) ("hdr table entry[%d]: %s (%d)\n", i, table[i].name, table[i].name_len);
- assert(table[i].name_len);
- /* init stats */
- memset(&table[i].stat, 0, sizeof(table[i].stat));
- }
-}
-
static void
httpHeaderStatInit(HttpHeaderStat * hs, const char *label)
{
hs->label = label;
statHistEnumInit(&hs->hdrUCountDistr, 32); /* not a real enum */
statHistEnumInit(&hs->fieldTypeDistr, HDR_ENUM_END);
- statHistEnumInit(&hs->ccTypeDistr, SCC_ENUM_END);
-}
-
-/* calculates a bit mask of a given array (move this to lib/uitils) @?@ */
-static int
-httpHeaderCalcMask(const int *enums, int count)
-{
- int i;
- int mask = 0;
- assert(enums);
- assert(count < sizeof(int) * 8); /* check for overflow */
-
- for (i = 0; i < count; ++i) {
- assert(enums[i] < sizeof(int) * 8); /* check for overflow again */
- assert(!EBIT_TEST(mask, enums[i])); /* check for duplicates */
- EBIT_SET(mask, enums[i]);
- }
- return mask;
+ statHistEnumInit(&hs->ccTypeDistr, CC_ENUM_END);
}
-
/*
* HttpHeader Implementation
*/
/* fix this (for scc too) for req headers @?@ */
statHistCount(&HttpHeaderStats[0].fieldTypeDistr, e->id);
if (e->id == HDR_CACHE_CONTROL)
- httpSccUpdateStats(e->field.v_pscc, &HttpHeaderStats[0].ccTypeDistr);
+ httpHdrCcUpdateStats(e->field.v_pcc, &HttpHeaderStats[0].ccTypeDistr);
httpHeaderDelAt(hdr, pos);
}
xfree(hdr->entries);
return httpHeaderGet(hdr, id).v_time;
}
-HttpScc *
-httpHeaderGetScc(const HttpHeader * hdr)
+HttpHdrCc *
+httpHeaderGetCc(const HttpHeader * hdr)
{
- return httpHeaderGet(hdr, HDR_CACHE_CONTROL).v_pscc;
+ return httpHeaderGet(hdr, HDR_CACHE_CONTROL).v_pcc;
}
/* updates header masks */
add ? EBIT_SET(hdr->emask, e->id) : EBIT_CLR(hdr->emask, e->id);
}
-static int
-httpHeaderIdByName(const char *name, int name_len, const field_attrs_t * attrs, int end, int mask)
-{
- int i;
- for (i = 0; i < end; ++i) {
- if (mask < 0 || EBIT_TEST(mask, i)) {
- if (name_len >= 0 && name_len != attrs[i].name_len)
- continue;
- if (!strncasecmp(name, attrs[i].name,
- name_len < 0 ? attrs[i].name_len + 1 : name_len))
- return i;
- }
- }
- return -1;
-}
-
/* doubles the size of the fields index, starts with INIT_FIELDS_PER_HEADER */
static void
httpHeaderGrow(HttpHeader * hdr)
freeShortString(e->field.v_pchar);
break;
case ftPSCC:
- if (e->field.v_pscc)
- httpSccDestroy(e->field.v_pscc);
+ if (e->field.v_pcc)
+ httpHdrCcDestroy(e->field.v_pcc);
break;
case ftPExtField:
if (e->field.v_pefield)
break;
case ftPSCC:
- field.v_pscc = httpSccParseCreate(f->value);
- if (!field.v_pscc) {
+ field.v_pcc = httpHdrCcParseCreate(f->value);
+ if (!field.v_pcc) {
debug(55, 0) ("failed to parse scc hdr: id: %d, field: '%s: %s'\n",
id, f->name, f->value);
Headers[id].stat.errCount++;
packerPrintf(p, "%s", mkrfc1123(e->field.v_time));
break;
case ftPSCC:
- httpSccPackValueInto(e->field.v_pscc, p);
+ httpHdrCcPackValueInto(e->field.v_pcc, p);
break;
case ftPExtField:
packerPrintf(p, "%s", e->field.v_pefield->value);
e->field.v_pchar = appShortStr(e->field.v_pchar, newe->field.v_pchar);
break;
case ftPSCC:
- httpSccJoinWith(e->field.v_pscc, newe->field.v_pscc);
+ httpHdrCcJoinWith(e->field.v_pcc, newe->field.v_pcc);
break;
default:
debug(55, 0) ("join for invalid/unknown type: id: %d, type: %d\n", e->id, type);
case ftDate_1123:
return e->field.v_time >= 0;
case ftPSCC:
- return e->field.v_pscc != NULL;
+ return e->field.v_pcc != NULL;
case ftPExtField:
return e->field.v_pefield != NULL;
default:
case ftPChar:
return ptrField(dupShortStr(value.v_pchar));
case ftPSCC:
- return ptrField(httpSccDup(value.v_pscc));
+ return ptrField(httpHdrCcDup(value.v_pcc));
case ftPExtField:
return ptrField(httpHeaderExtFieldDup(value.v_pefield));
default:
return ptrField(NULL); /* not reached */
}
+#if 0 /* moved to HttpHdrCC.c */
+
/*
* HttpScc (server cache control)
*/
statHistCount(hist, c);
}
+#endif
+
/*
* HttpHeaderExtField
*/
id, name, count, xdiv(count, HeaderParsedCount));
}
+#if 0
static void
httpHeaderCCStatDumper(StoreEntry * sentry, int idx, double val, double size, int count)
{
storeAppendPrintf(sentry, "%2d\t %-20s\t %5d\t %6.2f\n",
id, name, count, xdiv(count, CcPasredCount));
}
-
+#endif
static void
httpHeaderFldsPerHdrDumper(StoreEntry * sentry, int idx, double val, double size, int count)
storeAppendPrintf(e, "<h3>Cache-control directives distribution</h3>\n");
storeAppendPrintf(e, "%2s\t %-20s\t %5s\t %6s\n",
"id", "name", "count", "#/cc_field");
- statHistDump(&hs->ccTypeDistr, e, httpHeaderCCStatDumper);
+ statHistDump(&hs->ccTypeDistr, e, httpHdrCcStatDumper);
storeAppendPrintf(e, "<h3>Number of fields per header distribution (init size: %d)</h3>\n",
INIT_FIELDS_PER_HEADER);
storeAppendPrintf(e, "%2s\t %-5s\t %5s\t %6s\n",
}
}
+#if 0
/*
* other routines (move these into lib if you need them somewhere else?)
*/
xstrncpy(buf, str, SHORT_PREFIX_SIZE);
return buf;
}
+#endif
--- /dev/null
+/*
+ * $Id: HttpHeaderTools.cc,v 1.1 1998/03/05 00:01:08 rousskov Exp $
+ *
+ * DEBUG: section 66 HTTP Header Tools
+ * AUTHOR: Alex Rousskov
+ *
+ * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
+ * --------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from the
+ * Internet community. Development is led by Duane Wessels of the
+ * National Laboratory for Applied Network Research and funded by
+ * the National Science Foundation.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include "squid.h"
+
+void
+httpHeaderInitAttrTable(field_attrs_t * table, int count)
+{
+ int i;
+ assert(table);
+ assert(count > 1); /* to protect from buggy "countof" implementations */
+
+ /* reorder so that .id becomes an index */
+ for (i = 0; i < count;) {
+ const int id = table[i].id;
+ assert(id >= 0 && id < count); /* sanity check */
+ assert(id >= i); /* entries prior to i have been indexed already */
+ if (id != i) { /* out of order */
+ const field_attrs_t fa = table[id];
+ assert(fa.id != id); /* avoid endless loops */
+ table[id] = table[i]; /* swap */
+ table[i] = fa;
+ } else
+ i++; /* make progress */
+ }
+
+ /* calculate name lengths and init stats */
+ for (i = 0; i < count; ++i) {
+ assert(table[i].name);
+ table[i].name_len = strlen(table[i].name);
+ debug(55, 5) ("hdr table entry[%d]: %s (%d)\n", i, table[i].name, table[i].name_len);
+ assert(table[i].name_len);
+ /* init stats */
+ memset(&table[i].stat, 0, sizeof(table[i].stat));
+ }
+}
+
+/* calculates a bit mask of a given array */
+int
+httpHeaderCalcMask(const int *enums, int count)
+{
+ int i;
+ int mask = 0;
+ assert(enums);
+ assert(count < sizeof(int) * 8); /* check for overflow */
+
+ for (i = 0; i < count; ++i) {
+ assert(enums[i] < sizeof(int) * 8); /* check for overflow again */
+ assert(!EBIT_TEST(mask, enums[i])); /* check for duplicates */
+ EBIT_SET(mask, enums[i]);
+ }
+ return mask;
+}
+
+
+int
+httpHeaderIdByName(const char *name, int name_len, const field_attrs_t * attrs, int end, int mask)
+{
+ int i;
+ for (i = 0; i < end; ++i) {
+ if (mask < 0 || EBIT_TEST(mask, i)) {
+ if (name_len >= 0 && name_len != attrs[i].name_len)
+ continue;
+ if (!strncasecmp(name, attrs[i].name,
+ name_len < 0 ? attrs[i].name_len + 1 : name_len))
+ return i;
+ }
+ }
+ return -1;
+}
+
+/*
+ * iterates through a 0-terminated string of items separated by 'del's.
+ * white space around 'del' is considered to be a part of 'del'
+ * like strtok, but preserves the source, and can iterate several strings at once
+ *
+ * returns true if next item is found.
+ * init pos with NULL to start iteration.
+ */
+int
+strListGetItem(const char *str, char del, const char **item, int *ilen, const char **pos)
+{
+ size_t len;
+ assert(str && item && pos);
+ if (*pos)
+ if (!**pos) /* end of string */
+ return 0;
+ else
+ (*pos)++;
+ else
+ *pos = str;
+
+ /* skip leading ws (ltrim) */
+ *pos += xcountws(*pos);
+ *item = *pos; /* remember item's start */
+ /* find next delimiter */
+ *pos = strchr(*item, del);
+ if (!*pos) /* last item */
+ *pos = *item + strlen(*item);
+ len = *pos - *item; /* *pos points to del or '\0' */
+ /* rtrim */
+ while (len > 0 && isspace((*item)[len - 1]))
+ len--;
+ if (ilen)
+ *ilen = len;
+ return len > 0;
+}
+
+/* handy to printf prefixes of potentially very long buffers */
+const char *
+getStringPrefix(const char *str)
+{
+#define SHORT_PREFIX_SIZE 256
+ LOCAL_ARRAY(char, buf, SHORT_PREFIX_SIZE);
+ xstrncpy(buf, str, SHORT_PREFIX_SIZE);
+ return buf;
+}
/*
- * $Id: HttpReply.cc,v 1.9 1998/03/04 05:39:27 rousskov Exp $
+ * $Id: HttpReply.cc,v 1.10 1998/03/05 00:01:08 rousskov Exp $
*
* DEBUG: section 58 HTTP Reply (Response)
* AUTHOR: Alex Rousskov
time_t
httpReplyExpires(const HttpReply * rep)
{
- HttpScc *scc;
+ HttpHdrCc *cc;
time_t exp = -1;
assert(rep);
/* The max-age directive takes priority over Expires, check it first */
- scc = httpHeaderGetScc(&rep->hdr);
- if (scc)
- exp = scc->max_age;
+ cc = httpHeaderGetCc(&rep->hdr);
+ if (cc)
+ exp = cc->max_age;
if (exp < 0)
exp = httpHeaderGetTime(&rep->hdr, HDR_EXPIRES);
return exp;
}
int
-httpReplyHasScc(const HttpReply * rep, http_scc_type type)
+httpReplyHasCc(const HttpReply * rep, http_hdr_cc_type type)
{
- HttpScc *scc;
+ HttpHdrCc *cc;
assert(rep);
- assert(type >= 0 && type < SCC_ENUM_END);
+ assert(type >= 0 && type < CC_ENUM_END);
- scc = httpHeaderGetScc(&rep->hdr);
- return scc && /* scc header is present */
- EBIT_TEST(scc->mask, type);
+ cc = httpHeaderGetCc(&rep->hdr);
+ return cc && /* scc header is present */
+ EBIT_TEST(cc->mask, type);
}
#
# Makefile for the Squid Object Cache server
#
-# $Id: Makefile.in,v 1.126 1998/03/03 00:31:00 rousskov Exp $
+# $Id: Makefile.in,v 1.127 1998/03/05 00:01:09 rousskov Exp $
#
# Uncomment and customize the following to suit your needs:
#
http.o \
http-anon.o \
HttpStatusLine.o \
+ HttpHdrCc.o \
HttpHeader.o \
+ HttpHeaderTools.o \
HttpBody.o \
HttpReply.o \
icmp.o \
/* were to look for errors if config path fails */
#define DEFAULT_SQUID_ERROR_DIR "/usr/local/squid/etc/errors"
+
+/* gb_type operations */
+#define gb_flush_limit (0x3FFFFFFF)
+#define gb_inc(gb, delta) { if ((gb)->bytes > gb_flush_limit || delta > gb_flush_limit) gb_flush(gb); (gb)->bytes += delta; (gb)->count++; }
/* server cache-control */
typedef enum {
- SCC_PUBLIC,
- SCC_PRIVATE,
- SCC_NO_CACHE,
- SCC_NO_STORE,
- SCC_NO_TRANSFORM,
- SCC_MUST_REVALIDATE,
- SCC_PROXY_REVALIDATE,
- SCC_MAX_AGE,
- SCC_ENUM_END
-} http_scc_type;
+ CC_PUBLIC,
+ CC_PRIVATE,
+ CC_NO_CACHE,
+ CC_NO_STORE,
+ CC_NO_TRANSFORM,
+ CC_MUST_REVALIDATE,
+ CC_PROXY_REVALIDATE,
+ CC_MAX_AGE,
+ CC_ENUM_END
+} http_hdr_cc_type;
+
+/* possible types for http header fields */
+typedef enum {
+ ftInvalid = HDR_ENUM_END, /* to catch nasty errors with hdr_id<->fld_type clashes */
+ ftInt,
+ ftPChar,
+ ftDate_1123,
+ ftPSCC,
+ ftPExtField
+} field_type;
typedef enum {
HIER_NONE,
#else
MEM_HTTPREPLY,
#endif
- MEM_HTTP_SCC,
+ MEM_HTTP_HDR_CC,
MEM_HTTPSTATEDATA,
MEM_ICPUDPDATA,
MEM_CLIENTHTTPREQUEST,
/*
- * $Id: http.cc,v 1.244 1998/03/04 23:52:40 wessels Exp $
+ * $Id: http.cc,v 1.245 1998/03/05 00:01:11 rousskov Exp $
*
* DEBUG: section 11 Hypertext Transfer Protocol (HTTP)
* AUTHOR: Harvest Derived
httpCachableReply(HttpStateData * httpState)
{
HttpHeader *hdr = &httpState->entry->mem_obj->reply->hdr;
- const HttpScc *scc = httpHeaderGetScc(hdr);
- const int scc_mask = (scc) ? scc->mask : 0;
- if (EBIT_TEST(scc_mask, SCC_PRIVATE))
+ const HttpHdrCc *cc = httpHeaderGetCc(hdr);
+ const int cc_mask = (cc) ? cc->mask : 0;
+ if (EBIT_TEST(cc_mask, CC_PRIVATE))
return 0;
- if (EBIT_TEST(scc_mask, SCC_NO_CACHE))
+ if (EBIT_TEST(cc_mask, CC_NO_CACHE))
return 0;
if (EBIT_TEST(httpState->request->flags, REQ_AUTH))
- if (!EBIT_TEST(scc_mask, SCC_PROXY_REVALIDATE))
+ if (!EBIT_TEST(cc_mask, CC_PROXY_REVALIDATE))
return 0;
/*
* Dealing with cookies is quite a bit more complicated
assert(0);
break;
}
- if (httpReplyHasScc(reply, SCC_PROXY_REVALIDATE))
+ if (httpReplyHasCc(reply, CC_PROXY_REVALIDATE))
EBIT_SET(entry->flag, ENTRY_REVALIDATE);
if (EBIT_TEST(httpState->flags, HTTP_KEEPALIVE))
if (httpState->peer)
storeAppendPrintf(entry, "%21.21s: %d\n",
HttpHdrMiscStr[j],
ReplyHeaderStats.misc[j]);
- for (i = SCC_PUBLIC; i < SCC_ENUM_END; i++)
+ for (i = CC_PUBLIC; i < CC_ENUM_END; i++)
storeAppendPrintf(entry, "Cache-Control %s: %d\n",
HttpServerCCStr[i],
ReplyHeaderStats.cc[i]);
/*
- * $Id: mem.cc,v 1.9 1998/03/03 22:17:54 rousskov Exp $
+ * $Id: mem.cc,v 1.10 1998/03/05 00:01:11 rousskov Exp $
*
* DEBUG: section 13 High Level Memory Pool Management
* AUTHOR: Harvest Derived
static MemPool *MemPools[MEM_MAX];
-/* all pools share common memory chunks so it is probably better to ignore max_pages */
+/* we have a limit on _total_ amount of idle memory so we ignore max_pages for now */
static void
memDataInit(mem_type type, const char *name, size_t size, int max_pages_notused)
{
sizeof(HierarchyLogEntry), 0);
memDataInit(MEM_HTTPSTATEDATA, "HttpStateData", sizeof(HttpStateData), 0);
memDataInit(MEM_HTTPREPLY, "http_reply", sizeof(http_reply), 0);
- memDataInit(MEM_HTTP_SCC, "HttpScc", sizeof(HttpScc), 0);
+ memDataInit(MEM_HTTP_HDR_CC, "HttpHdrCc", sizeof(HttpHdrCc), 0);
memDataInit(MEM_ICPUDPDATA, "icpUdpData", sizeof(icpUdpData), 0);
memDataInit(MEM_ICP_COMMON_T, "icp_common_t", sizeof(icp_common_t), 0);
memDataInit(MEM_ICP_PING_DATA, "icp_ping_data", sizeof(icp_ping_data), 0);
extern void httpBodyPackInto(const HttpBody * body, Packer * p);
+/* Http Cache Control Header Field */
+extern void httpHdrCcInitModule();
+extern HttpHdrCc *httpHdrCcCreate();
+extern HttpHdrCc *httpHdrCcParseCreate(const char *str);
+extern void httpHdrCcParseInit(HttpHdrCc * scc, const char *str);
+extern void httpHdrCcDestroy(HttpHdrCc * scc);
+extern HttpHdrCc *httpHdrCcDup(HttpHdrCc * scc);
+extern void httpHdrCcPackValueInto(HttpHdrCc * scc, Packer * p);
+extern void httpHdrCcJoinWith(HttpHdrCc * scc, HttpHdrCc * new_scc);
+extern void httpHdrCcUpdateStats(const HttpHdrCc * scc, StatHist * hist);
+extern void httpHdrCcStatDumper(StoreEntry * sentry, int idx, double val, double size, int count);
+
+/* Http Header Tools */
+extern int httpHeaderIdByName(const char *name, int name_len, const field_attrs_t * attrs, int end, int mask);
+extern void httpHeaderInitAttrTable(field_attrs_t * table, int count);
+extern int httpHeaderCalcMask(const int *enums, int count);
+extern int strListGetItem(const char *str, char del, const char **item, int *ilen, const char **pos);
+extern const char *getStringPrefix(const char *str);
+
/* Http Header */
extern void httpHeaderInitModule();
extern void httpHeaderCleanModule();
extern void httpHeaderAddExt(HttpHeader * hdr, const char *name, const char *value);
extern int httpHeaderGetInt(const HttpHeader * hdr, http_hdr_type id);
extern time_t httpHeaderGetTime(const HttpHeader * hdr, http_hdr_type id);
+extern HttpHdrCc *httpHeaderGetCc(const HttpHeader * hdr);
extern const char *httpHeaderGetStr(const HttpHeader * hdr, http_hdr_type id);
-extern HttpScc *httpHeaderGetScc(const HttpHeader * hdr);
int httpHeaderDelFields(HttpHeader * hdr, const char *name);
/* store report about current header usage and other stats */
extern void httpHeaderStoreReport(StoreEntry * e);
extern int httpReplyContentLen(const HttpReply * rep);
extern const char *httpReplyContentType(const HttpReply * rep);
extern time_t httpReplyExpires(const HttpReply * rep);
-extern int httpReplyHasScc(const HttpReply * rep, http_scc_type type);
+extern int httpReplyHasCc(const HttpReply * rep, http_hdr_cc_type type);
extern void icmpOpen(void);
extern void dlinkAdd(void *data, dlink_node *, dlink_list *);
extern void dlinkDelete(dlink_node * m, dlink_list * list);
extern void kb_incr(kb_t *, size_t);
+extern double gb_to_double(const gb_t *);
+extern const char *gb_to_str(const gb_t *);
+extern void gb_flush(gb_t *); /* internal, do not use this */
/*
* prototypes for system functions missing from system includes
};
-/* server cache control */
-struct _HttpScc {
+/* http cache control header field*/
+struct _HttpHdrCc {
int mask;
time_t max_age;
};
+
/* a storage for an entry of one of possible types (for lower level routines) */
union _field_store {
int v_int;
time_t v_time;
char *v_pchar;
const char *v_pcchar;
- HttpScc *v_pscc;
+ HttpHdrCc *v_pcc;
HttpHeaderExtField *v_pefield;
};
+/* per field statistics */
+struct _HttpHeaderFieldStat {
+ int aliveCount; /* created but not destroyed (count) */
+ int parsCount; /* #parsing attempts */
+ int errCount; /* #pasring errors */
+ int repCount; /* #repetitons */
+};
+
+
+/* constant attributes of http header fields */
+struct _field_attrs_t {
+ const char *name;
+ http_hdr_type id;
+ field_type type;
+ int name_len;
+ HttpHeaderFieldStat stat;
+};
+
struct _HttpHeader {
/* public, read only */
int emask; /* bits set for present entries */
size_t kb;
} kb_t;
+typedef struct {
+ size_t count;
+ size_t bytes;
+ size_t gb;
+} gb_t;
+
/*
* grep '^struct' structs.h \
* | perl -ne '($a,$b)=split;$c=$b;$c=~s/^_//; print "typedef struct $b $c;\n";'
typedef struct _fqdncache_entry fqdncache_entry;
typedef struct _hash_link hash_link;
typedef struct _hash_table hash_table;
-#if 0 /* use new interfaces */
-typedef struct _http_reply http_reply;
-#else
typedef struct _HttpReply http_reply;
typedef struct _HttpStatusLine HttpStatusLine;
+typedef struct _field_attrs_t field_attrs_t;
typedef struct _HttpHeader HttpHeader;
-typedef struct _HttpScc HttpScc;
+typedef struct _HttpHdrCc HttpHdrCc;
typedef struct _HttpHeaderExtField HttpHeaderExtField;
typedef struct _HttpHeaderEntry HttpHeaderEntry;
-typedef union _field_store field_store;
+typedef struct _HttpHeaderFieldStat HttpHeaderFieldStat;
+typedef union _field_store field_store;
typedef struct _HttpBody HttpBody;
typedef struct _HttpReply HttpReply;
-#endif
typedef struct _HttpStateData HttpStateData;
typedef struct _icpUdpData icpUdpData;
typedef struct _clientHttpRequest clientHttpRequest;