]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
- gb_t additions to .h monsters
authorrousskov <>
Thu, 5 Mar 1998 07:01:07 +0000 (07:01 +0000)
committerrousskov <>
Thu, 5 Mar 1998 07:01:07 +0000 (07:01 +0000)
- Renamed HttpScc object into HttpHdrCc
- Moved HttpHdrCc from HttpHeader.c to HttpHdrCc.c
- Moved "commonly used" routines from HttpHeader.c to HttpHeaderTools.c.
All this was done to prepare for addition of HttpHdrRange.

12 files changed:
src/HttpHdrCc.cc [new file with mode: 0644]
src/HttpHeader.cc
src/HttpHeaderTools.cc [new file with mode: 0644]
src/HttpReply.cc
src/Makefile.in
src/defines.h
src/enums.h
src/http.cc
src/mem.cc
src/protos.h
src/structs.h
src/typedefs.h

diff --git a/src/HttpHdrCc.cc b/src/HttpHdrCc.cc
new file mode 100644 (file)
index 0000000..7bb44ce
--- /dev/null
@@ -0,0 +1,193 @@
+
+/*
+ * $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));
+}
index b9468f997e798d6349c24a53ec7653d79dc870bf..90b3545cc2b01624a3bcda702cf753c8439a1215 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $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
@@ -62,16 +62,6 @@ struct _HttpHeaderExtField {
     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 )
@@ -82,18 +72,6 @@ struct _HttpHeaderEntry {
 };
 
 
-/* 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;
@@ -103,15 +81,6 @@ typedef struct {
 } 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 */
@@ -157,19 +126,6 @@ static field_attrs_t Headers[] =
     {"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
  *
@@ -227,15 +183,14 @@ static HttpHeaderStat HttpHeaderStats[] =
 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;
 
 
 /*
@@ -244,10 +199,6 @@ static StatSize 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);
@@ -255,7 +206,6 @@ static void httpHeaderAddNewEntry(HttpHeader * hdr, const 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);
@@ -274,21 +224,23 @@ static void httpHeaderFieldInit(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);
 
@@ -298,13 +250,12 @@ static char *appShortStr(char *str, const char *app_str);
 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))
 
@@ -328,7 +279,6 @@ httpHeaderInitModule()
     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));
@@ -338,6 +288,7 @@ httpHeaderInitModule()
     /* init header stats */
     for (i = 0; i < HttpHeaderStatCount; i++)
        httpHeaderStatInit(HttpHeaderStats + i, HttpHeaderStats[i].label);
+    httpHdrCcInitModule();
     cachemgrRegister("http_headers",
        "HTTP Header Statistics", httpHeaderStoreReport, 0);
 }
@@ -351,38 +302,6 @@ httpHeaderCleanModule()
     }
 }
 
-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)
 {
@@ -391,27 +310,9 @@ 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
  */
@@ -448,7 +349,7 @@ httpHeaderClean(HttpHeader * hdr)
        /* 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);
@@ -883,10 +784,10 @@ httpHeaderGetTime(const HttpHeader * hdr, http_hdr_type id)
     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 */
@@ -906,22 +807,6 @@ httpHeaderSyncMasks(HttpHeader * hdr, const HttpHeaderEntry * e, int add)
     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)
@@ -971,8 +856,8 @@ httpHeaderEntryClean(HttpHeaderEntry * e)
        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)
@@ -1101,8 +986,8 @@ httpHeaderEntryParseByTypeInit(HttpHeaderEntry * e, int id, const HttpHeaderExtF
        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++;
@@ -1174,7 +1059,7 @@ httpHeaderEntryPackByType(const HttpHeaderEntry * e, Packer * p)
        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);
@@ -1200,7 +1085,7 @@ httpHeaderEntryJoinWith(HttpHeaderEntry * e, const HttpHeaderEntry * newe)
        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);
@@ -1227,7 +1112,7 @@ httpHeaderEntryIsValid(const HttpHeaderEntry * e)
     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:
@@ -1268,7 +1153,7 @@ httpHeaderFieldDup(field_type type, field_store value)
     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:
@@ -1300,6 +1185,8 @@ httpHeaderFieldBadValue(field_type type)
     return ptrField(NULL);     /* not reached */
 }
 
+#if 0 /* moved to HttpHdrCC.c */
+
 /*
  * HttpScc (server cache control)
  */
@@ -1426,6 +1313,8 @@ httpSccUpdateStats(const HttpScc * scc, StatHist * hist)
            statHistCount(hist, c);
 }
 
+#endif
+
 /*
  * HttpHeaderExtField
  */
@@ -1501,6 +1390,7 @@ httpHeaderFieldStatDumper(StoreEntry * sentry, int idx, double val, double size,
            id, name, count, xdiv(count, HeaderParsedCount));
 }
 
+#if 0
 static void
 httpHeaderCCStatDumper(StoreEntry * sentry, int idx, double val, double size, int count)
 {
@@ -1511,7 +1401,7 @@ httpHeaderCCStatDumper(StoreEntry * sentry, int idx, double val, double size, in
        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)
@@ -1535,7 +1425,7 @@ httpHeaderStatDump(const HttpHeaderStat * hs, StoreEntry * e)
     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",
@@ -1655,6 +1545,7 @@ freeShortString(char *str)
     }
 }
 
+#if 0
 /*
  * other routines (move these into lib if you need them somewhere else?)
  */
@@ -1705,3 +1596,4 @@ getStringPrefix(const char *str)
     xstrncpy(buf, str, SHORT_PREFIX_SIZE);
     return buf;
 }
+#endif
diff --git a/src/HttpHeaderTools.cc b/src/HttpHeaderTools.cc
new file mode 100644 (file)
index 0000000..7cf32c0
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * $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;
+}
index 6efd533a1bc660045e96d7539cb2fa51d21f8ca1..5a0d9b87e735820181ee1644072fd513f4097074 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $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
@@ -295,28 +295,28 @@ httpReplyContentType(const HttpReply * rep)
 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);
 }
 
 
index 52fcbf9e8f09703d09ac1557eba3ae1fadea5e8f..8ef7e82231619e528b9e86c850063f31be92f769 100644 (file)
@@ -1,7 +1,7 @@
 #
 #  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:
 #
@@ -90,7 +90,9 @@ OBJS          = \
                http.o \
                http-anon.o \
                HttpStatusLine.o \
+               HttpHdrCc.o \
                HttpHeader.o \
+               HttpHeaderTools.o \
                HttpBody.o \
                HttpReply.o \
                icmp.o \
index 9f7c3dfc14c76161a559acb441e8ad795f695505..9595fe3f6955f264f1c1676a1291ed1da7e6daa1 100644 (file)
 
 /* 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++; }
index fce7dd65e9afac410bf325ddf00fcb011caee2f4..e94974b4e3440d5cfb18ce1864512f94f7bb0fa1 100644 (file)
@@ -194,16 +194,26 @@ typedef enum {
 
 /* 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,
@@ -464,7 +474,7 @@ typedef enum {
 #else
     MEM_HTTPREPLY,
 #endif
-    MEM_HTTP_SCC,
+    MEM_HTTP_HDR_CC,
     MEM_HTTPSTATEDATA,
     MEM_ICPUDPDATA,
     MEM_CLIENTHTTPREQUEST,
index 3be3fefe5068c00fe6c896044fc817e72bde7409..cb2f07655a4ba37ae5b3b0a98da9c9de8ce8da74 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $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
@@ -435,14 +435,14 @@ static int
 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
@@ -572,7 +572,7 @@ httpProcessReplyHeader(HttpStateData * httpState, const char *buf, int size)
            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)
@@ -1159,7 +1159,7 @@ httpReplyHeaderStats(StoreEntry * entry)
        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]);
index d13d394e26db068e0d68cf54c44cf4aff6ca1f07..4c7fee3866397138bb2043547f0cecaca288bced 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $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
@@ -35,7 +35,7 @@
 
 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)
 {
@@ -126,7 +126,7 @@ memInit(void)
        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);
index d218e065448ca37961bea5d79729a6c031a1d856..19fb42a2627f43be1e61f61b4743beb243af32f7 100644 (file)
@@ -257,6 +257,25 @@ extern void httpBodySet(HttpBody * body, const char *content, int size,
 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();
@@ -280,8 +299,8 @@ extern void httpHeaderSetAuth(HttpHeader * hdr, const char *authScheme, const ch
 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);
@@ -317,7 +336,7 @@ extern void httpReplyUpdateOnNotModified(HttpReply * rep, HttpReply * freshRep);
 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);
@@ -787,6 +806,9 @@ extern void asnFreeMemory(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
index 16141dd4d6174a940b0d1d81aadb523d140ae508..23cfc73755b1668dd6eba19ad1ba4ffc4ac09f54 100644 (file)
@@ -465,22 +465,41 @@ struct _HttpBody {
 };
 
 
-/* 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 */
index 3fdf0158c8688910ae1c6ffd9e5e839a78c109f7..e4db68fb8895335b17987309702e539f51e78e49 100644 (file)
@@ -9,6 +9,12 @@ typedef struct {
     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";'
@@ -42,19 +48,17 @@ typedef struct _fileMap fileMap;
 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;