--------------------- PatchSet 10371 Date: 2008/01/06 09:19:51 Author: adri Branch: s27_adri Tag: (none) Log: Begin the long road to a replacement buf_t based header parser. * shuffle around the mem_type enum into lib/ so it can be used from the libhttp code. I hate calling mem* functions from there as they still live in src/ but I'll resolve that mess later. * Move around some of the http header and http header entry related code, in preparation for generating/destroying http header entries in libhttp/. * Port over an incremental HTTP header parser from a private branch. Its not used incrementally here but the logic will work fine if/when that needs to change. * Use the new buf_t based http reply parsing routine in src/http.c for testing. Now, all this parser does it dump what its doing to debug() but doesn't (yet) create any http header entries. I still need to shuffle around a whole lot of code before I can properly create the entries in my new parser. Members: doc/debug-sections.txt:1.10.58.1->1.10.58.2 libhttp/HttpHeader.c:1.1.2.1->1.1.2.2 libhttp/HttpHeader.h:1.1.2.1->1.1.2.2 libhttp/HttpHeaderEntry.c:1.1->1.1.2.1 libhttp/HttpHeaderEntry.h:1.1->1.1.2.1 libhttp/HttpHeaderInfo.h:1.1->1.1.2.1 libhttp/Makefile.am:1.1.2.2->1.1.2.3 libmem/mem.h:1.1.2.1->1.1.2.2 src/HttpHeader.c:1.28.6.1.4.24->1.28.6.1.4.25 src/HttpReply.c:1.23.6.1.4.2->1.23.6.1.4.3 src/enums.h:1.62.2.1.4.2->1.62.2.1.4.3 src/http.c:1.63.2.3.4.31->1.63.2.3.4.32 src/protos.h:1.146.2.4.4.34->1.146.2.4.4.35 src/squid.h:1.36.24.12->1.36.24.13 src/structs.h:1.158.2.5.4.14->1.158.2.5.4.15 src/typedefs.h:1.43.2.3.4.8->1.43.2.3.4.9 tools/cossdump.c:1.5.28.1->1.5.28.2 Index: squid/doc/debug-sections.txt =================================================================== RCS file: /cvsroot/squid-sf//squid/doc/debug-sections.txt,v retrieving revision 1.10.58.1 retrieving revision 1.10.58.2 diff -u -r1.10.58.1 -r1.10.58.2 --- squid/doc/debug-sections.txt 2 Dec 2007 09:34:15 -0000 1.10.58.1 +++ squid/doc/debug-sections.txt 6 Jan 2008 09:19:51 -0000 1.10.58.2 @@ -89,3 +89,4 @@ section 83 SSL accelerator support section 84 Helper process maintenance section 85 libbuf - buffer, string, iobuf +section 86 libhttp - parse headers Index: squid/libhttp/HttpHeader.c =================================================================== RCS file: /cvsroot/squid-sf//squid/libhttp/Attic/HttpHeader.c,v retrieving revision 1.1.2.1 retrieving revision 1.1.2.2 diff -u -r1.1.2.1 -r1.1.2.2 --- squid/libhttp/HttpHeader.c 5 Jan 2008 11:46:56 -0000 1.1.2.1 +++ squid/libhttp/HttpHeader.c 6 Jan 2008 09:19:52 -0000 1.1.2.2 @@ -1,6 +1,6 @@ /* - * $Id: HttpHeader.c,v 1.1.2.1 2008/01/05 11:46:56 adri Exp $ + * $Id: HttpHeader.c,v 1.1.2.2 2008/01/06 09:19:52 adri Exp $ */ #include @@ -21,5 +21,169 @@ #include "../libbuf/String.h" #include "HttpStrList.h" +#include "HttpHeaderInfo.h" +#include "HttpHeaderEntry.h" #include "HttpHeader.h" +HttpHeaderFieldInfo *Headers = NULL; + +static int +hdr_add(HttpHeader *hdr, buf_t *b, int fs, int fe, int vs, int ve) +{ + /* Look up the field name - is it a field we know? */ + + /* No, then allocate a string for that field name */ + + /* Content-Length header? Sanity-check it */ + + /* White-space in field name? Bad bad! */ + + /* At this point; add and return successful */ + + return 1; +} + + +/* + * Parse a buf_t referencing a http header block. + * + * This function (for now) doesn't try to incrementally parse the headers + * although that is an end-goal (as its pretty simple to implement.) + * + * It returns 0 if more data is needed, -1 on error and >0 if headers + * were parsed. Even blank headers require at least one \n and thus + * the return value will be +ve. + */ +int +httpHeaderParseBuf(HttpHeader *hdr, buf_t *buf, int offset) +{ + int n = offset; + int fs, fe, vs, ve; + char *b = buf_buf(buf); + int retcode = 0; /* 0 - exit, more data plz; -1 = exit, error plz; 1 = exit, completed! */ + + /* + * We'll loop through until we find: + * + a blank line - that means we've completed our parsing run + * + overflow whatever we've specified the maximum request size is - error + * + reach end of buffer without reaching end of parsing run - note it, ask for more data + */ + while (n < buf_len(buf)) { + /* + * We'll look for complete lines here. + * If we parse a complete line then update bofs and mark that data as "taken" + * so the buffer contents aren't changed from underneath us. + * If we get a non-complete line then we'll leave bofs where it is and not mark + * the data as taken; hopefully the buffer will be filled with more data! + */ + /* blank line? End of headers, woo */ + if (b[n] == '\n') { + debug(86, 5) ("parse_hdrs: %p: found blank line; end of headers!\n", hdr); + retcode = 1; + //ph->bofs = n + 1; + break; + } + if (b[n] == '\r' && n < buf_len(buf) - 1 && b[n+1] == '\n') { + debug(86, 5) ("parse_hdrs: %p: found blank line; end of headers!\n", hdr); + retcode = 1; + //ph->bofs = n + 1; + break; + } + /* find first non-whitespace: that'll be field start (even though it shouldn't be!) */ + for (; n < buf_len(buf) && isspace(b[n]); n++); + if (n >= buf_len(buf)) { + retcode = 0; + break; + } + fs = n; + + /* find whitespace/: ; end of field */ + for (; n < buf_len(buf) && (! isspace(b[n])) && (b[n] != ':'); n++); + if (n >= buf_len(buf)) { + retcode = 0; + break; + } + /* if we receive a \r\n or here then we're stuffed */ + if (b[n] == '\r' || b[n] == '\n') { + debug(86, 5) ("parse_hdrs: %p: received CR or LF during parsing field name\n", hdr); + retcode = -1; + break; + } + /* whitespace is badness; ignore it (and log maybe?) - end of field ; skip to after : */ + if (b[n] != ':') { + debug(86, 5) ("parse_hdrs: %p: received whitespace whilst parsing field name\n", hdr); + retcode = -1; + break; + } + fe = n - 1; + n++; + + /* find first non-whitespace; that'll be value start */ + for (; n < buf_len(buf) && isspace(b[n]); n++); + if (n >= buf_len(buf)) { + retcode = 0; + break; + } + vs = n; + +value_start: + /* find CRLF (\n, \r\n) */ + for (; n < buf_len(buf) && b[n] != '\r' && b[n] != '\n'; n++); + if (n >= buf_len(buf)) { + retcode = 0; + break; + } + ve = n - 1; + /* if b[n] is \r then check if the next char is \n */ + if (b[n] == '\r') { + n++; + if (n >= buf_len(buf)) { + retcode = 0; + break; + } + if (b[n] != '\n') { + debug(86, 5) ("parse_hdrs: %p: end of value found a \\r but no subsequent \\n!\n", hdr); + retcode = -1; + break; + } + } + /* + * Now, strictly speaking we can't actually count this as being the value-end for now. + * We need to be able to read the next byte and see whether its whitespace or not. + * For now we'll ignore continuation lines purely for testing purposes but we'll _need_ + * to add in support for it later! + */ + + /* + * So in order to have successfully parsed a header we need to be able to see a character past it. + * This'll tell us whether its a continuation or not. + */ + n++; + if (n >= buf_len(buf)) { + debug(86, 5) ("parse_hdrs: %p: can't tell whether continuation or not, need more data\n", hdr); + retcode = 0; + break; + } + if (b[n] == ' ' || b[n] == '\t') { + debug(86, 5) ("parse_hdrs: %p: continuation\n", hdr); + /* continuation; go back to parsing the field */ + /* XXX should really fix this.. */ + goto value_start; + } + + /* not a continuation! */ + + /* Add header! */ + debug(86, 5) ("parse_hdrs: header field '%.*s', value '%.*s'\n", fe - fs + 1, b + fs, ve - vs + 1, b + vs); + if (! hdr_add(hdr, buf, fs, fe, vs, ve)) { + debug(86, 5) ("parse_hdrs: %p: hdr_add failed for some reason!\n", hdr); + retcode = -1; + break; + } + /* update bofs and buffer offset */ + //ph->bofs = n; + /* next line! */ + } + return retcode; +} + Index: squid/libhttp/HttpHeader.h =================================================================== RCS file: /cvsroot/squid-sf//squid/libhttp/Attic/HttpHeader.h,v retrieving revision 1.1.2.1 retrieving revision 1.1.2.2 diff -u -r1.1.2.1 -r1.1.2.2 --- squid/libhttp/HttpHeader.h 5 Jan 2008 11:46:57 -0000 1.1.2.1 +++ squid/libhttp/HttpHeader.h 6 Jan 2008 09:19:52 -0000 1.1.2.2 @@ -1,84 +1,6 @@ #ifndef __LIBHTTP_HEADER_H__ #define __LIBHTTP_HEADER_H__ -/* recognized or "known" header fields; @?@ add more! */ -typedef enum { - HDR_UNKNOWN = -1, - HDR_ACCEPT = 0, - HDR_ACCEPT_CHARSET, - HDR_ACCEPT_ENCODING, - HDR_ACCEPT_LANGUAGE, - HDR_ACCEPT_RANGES, - HDR_AGE, - HDR_ALLOW, - HDR_AUTHORIZATION, - HDR_CACHE_CONTROL, - HDR_CONNECTION, - HDR_CONTENT_BASE, - HDR_CONTENT_DISPOSITION, - HDR_CONTENT_ENCODING, - HDR_CONTENT_LANGUAGE, - HDR_CONTENT_LENGTH, - HDR_CONTENT_LOCATION, - HDR_CONTENT_MD5, - HDR_CONTENT_RANGE, - HDR_CONTENT_TYPE, - HDR_TE, - HDR_TRANSFER_ENCODING, - HDR_TRAILER, - HDR_COOKIE, - HDR_DATE, - HDR_ETAG, - HDR_EXPIRES, - HDR_FROM, - HDR_HOST, - HDR_IF_MATCH, - HDR_IF_MODIFIED_SINCE, - HDR_IF_NONE_MATCH, - HDR_IF_RANGE, - HDR_LAST_MODIFIED, - HDR_LINK, - HDR_LOCATION, - HDR_MAX_FORWARDS, - HDR_MIME_VERSION, - HDR_PRAGMA, - HDR_PROXY_AUTHENTICATE, - HDR_PROXY_AUTHENTICATION_INFO, - HDR_PROXY_AUTHORIZATION, - HDR_PROXY_CONNECTION, - HDR_PUBLIC, - HDR_RANGE, - HDR_REQUEST_RANGE, /* some clients use this, sigh */ - HDR_REFERER, - HDR_RETRY_AFTER, - HDR_SERVER, - HDR_SET_COOKIE, - HDR_UPGRADE, - HDR_USER_AGENT, - HDR_VARY, - HDR_VIA, - HDR_EXPECT, - HDR_WARNING, - HDR_WWW_AUTHENTICATE, - HDR_AUTHENTICATION_INFO, - HDR_X_CACHE, - HDR_X_CACHE_LOOKUP, /* tmp hack, remove later */ - HDR_X_FORWARDED_FOR, - HDR_X_REQUEST_URI, /* appended if ADD_X_REQUEST_URI is #defined */ - HDR_X_SQUID_ERROR, - HDR_NEGOTIATE, -#if X_ACCELERATOR_VARY - HDR_X_ACCELERATOR_VARY, -#endif - HDR_X_ERROR_URL, /* errormap, requested URL */ - HDR_X_ERROR_STATUS, /* errormap, received HTTP status line */ - HDR_FRONT_END_HTTPS, - HDR_PROXY_SUPPORT, - HDR_KEEP_ALIVE, - HDR_OTHER, - HDR_ENUM_END -} http_hdr_type; - typedef char HttpHeaderMask[(HDR_ENUM_END + 7) / 8]; /* possible owners of http header */ @@ -91,13 +13,6 @@ hoReply } http_hdr_owner_type; -struct _HttpHeaderEntry { - http_hdr_type id; - int active; - String name; - String value; -}; - struct _HttpHeader { /* protected, do not use these, use interface functions instead */ Array entries; /* parsed entries in raw format */ @@ -105,9 +20,9 @@ http_hdr_owner_type owner; /* request or reply */ int len; /* length when packed, not counting terminating '\0' */ }; - typedef struct _HttpHeader HttpHeader; -typedef struct _HttpHeaderEntry HttpHeaderEntry; + +extern int httpHeaderParseBuf(HttpHeader *hdr, buf_t *buf, int offset); #endif --- /dev/null Mon Jan 7 01:22:42 2008 +++ squid/libhttp/HttpHeaderEntry.c Mon Jan 7 01:22:42 2008 @@ -0,0 +1,170 @@ + +/* + * $Id: HttpHeaderEntry.c,v 1.1.2.1 2008/01/06 09:19:52 adri Exp $ + */ + +#include +#include +#include +#include +#include +#include + +#include "../include/util.h" +#include "../include/Array.h" +#include "../include/Stack.h" + +#include "../libcore/varargs.h" +#include "../libcore/debug.h" +#include "../libcore/tools.h" +#include "../libmem/mem.h" +#include "../libmem/MemPool.h" + +#include "../libbuf/buf.h" +#include "../libbuf/String.h" + +#include "HttpStrList.h" +#include "HttpHeaderInfo.h" +#include "HttpHeaderEntry.h" +#include "HttpHeader.h" + +int HeaderEntryParsedCount = 0; + +int +httpHeaderIdByName(const char *name, int name_len, const HttpHeaderFieldInfo * info, int end) +{ + int i; + for (i = 0; i < end; ++i) { + if (name_len >= 0 && name_len != strLen(info[i].name)) + continue; + if (!strNCaseCmp(info[i].name, name, name_len < 0 ? strLen2(info[i].name) + 1 : name_len)) + return i; + } + return -1; +} + +HttpHeaderEntry * +httpHeaderEntryCreate(http_hdr_type id, const char *name, const char *value) +{ + HttpHeaderEntry *e; + assert_eid(id); + e = memAllocate(MEM_HTTP_HDR_ENTRY); + e->id = id; + if (id != HDR_OTHER) + e->name = Headers[id].name; + else + stringInit(&e->name, name); + stringInit(&e->value, value); + Headers[id].stat.aliveCount++; + debug(55, 9) ("created entry %p: '%.*s: %.*s'\n", e, strLen2(e->name), strBuf2(e->name), strLen2(e->value), strBuf2(e->value)); + return e; +} + +HttpHeaderEntry * +httpHeaderEntryCreate2(http_hdr_type id, String name, String value) +{ + HttpHeaderEntry *e; + assert_eid(id); + e = memAllocate(MEM_HTTP_HDR_ENTRY); + e->id = id; + if (id != HDR_OTHER) + e->name = Headers[id].name; + else + e->name = stringDup(&name); + e->value = stringDup(&value); + Headers[id].stat.aliveCount++; + debug(55, 9) ("created entry %p: '%.*s: %.*s'\n", e, strLen2(e->name), strBuf2(e->name), strLen2(e->value), strBuf2(e->value)); + return e; +} + +void +httpHeaderEntryDestroy(HttpHeaderEntry * e) +{ + assert(e); + assert_eid(e->id); + debug(55, 9) ("destroying entry %p: '%.*s: %.*s'\n", e, strLen2(e->name), strBuf2(e->name), strLen2(e->value), strBuf2(e->value)); + /* clean name if needed */ + if (e->id == HDR_OTHER) + stringClean(&e->name); + stringClean(&e->value); + assert(Headers[e->id].stat.aliveCount); + Headers[e->id].stat.aliveCount--; + e->id = -1; + memFree(e, MEM_HTTP_HDR_ENTRY); +} + +HttpHeaderEntry * +httpHeaderEntryClone(const HttpHeaderEntry * e) +{ + return httpHeaderEntryCreate2(e->id, e->name, e->value); +} + +/* parses and inits header entry, returns new entry on success */ +HttpHeaderEntry * +httpHeaderEntryParseCreate(const char *field_start, const char *field_end) +{ + HttpHeaderEntry *e; + int id; + /* note: name_start == field_start */ + const char *name_end = memchr(field_start, ':', field_end - field_start); + int name_len = name_end ? name_end - field_start : 0; + const char *value_start = field_start + name_len + 1; /* skip ':' */ + /* note: value_end == field_end */ + + HeaderEntryParsedCount++; + + /* do we have a valid field name within this field? */ + if (!name_len || name_end > field_end) + return NULL; + if (name_len > 65534) { + /* String must be LESS THAN 64K and it adds a terminating NULL */ + debug(55, 1) ("WARNING: ignoring header name of %d bytes\n", name_len); + return NULL; + } + /* XXX [ahc] disable this for now until configuration can be handled saner.. */ +#if 0 + if (Config.onoff.relaxed_header_parser && xisspace(field_start[name_len - 1])) { + debug(55, Config.onoff.relaxed_header_parser <= 0 ? 1 : 2) + ("NOTICE: Whitespace after header name in '%s'\n", getStringPrefix(field_start, field_end)); + while (name_len > 0 && xisspace(field_start[name_len - 1])) + name_len--; + if (!name_len) + return NULL; + } +#endif + /* now we know we can parse it */ + e = memAllocate(MEM_HTTP_HDR_ENTRY); + debug(55, 9) ("creating entry %p: near '%.*s'\n", e, field_end - field_start, field_start); + /* is it a "known" field? */ + id = httpHeaderIdByName(field_start, name_len, Headers, HDR_ENUM_END); + if (id < 0) + id = HDR_OTHER; + assert_eid(id); + e->id = id; + /* set field name */ + if (id == HDR_OTHER) + stringLimitInit(&e->name, field_start, name_len); + else + e->name = Headers[id].name; + /* trim field value */ + while (value_start < field_end && xisspace(*value_start)) + value_start++; + while (value_start < field_end && xisspace(field_end[-1])) + field_end--; + if (field_end - value_start > 65534) { + /* String must be LESS THAN 64K and it adds a terminating NULL */ + debug(55, 1) ("WARNING: ignoring '%.*s' header of %d bytes\n", + strLen2(e->name), strBuf2(e->name), (int) (field_end - value_start)); + if (e->id == HDR_OTHER) + stringClean(&e->name); + memFree(e, MEM_HTTP_HDR_ENTRY); + return NULL; + } + /* set field value */ + stringLimitInit(&e->value, value_start, field_end - value_start); + Headers[id].stat.seenCount++; + Headers[id].stat.aliveCount++; + debug(55, 9) ("created entry %p: '%.*s: %.*s'\n", e, strLen2(e->name), strBuf2(e->name), strLen2(e->value), strBuf2(e->value)); + return e; +} + --- /dev/null Mon Jan 7 01:22:42 2008 +++ squid/libhttp/HttpHeaderEntry.h Mon Jan 7 01:22:42 2008 @@ -0,0 +1,25 @@ +#ifndef __LIBHTTP_HTTPHEADERENTRY_H__ +#define __LIBHTTP_HTTPHEADERENTRY_H__ + +struct _HttpHeaderEntry { + http_hdr_type id; + int active; + String name; + String value; +}; + +#define assert_eid(id) assert((id) < HDR_ENUM_END) + +typedef struct _HttpHeaderEntry HttpHeaderEntry; + +extern int HeaderEntryParsedCount; + +extern HttpHeaderEntry *httpHeaderEntryCreate(http_hdr_type id, const char *name, const char *value); +extern HttpHeaderEntry *httpHeaderEntryCreate2(http_hdr_type id, String name, String value); +extern void httpHeaderEntryDestroy(HttpHeaderEntry * e); +extern HttpHeaderEntry *httpHeaderEntryParseCreate(const char *field_start, const char *field_end); +extern HttpHeaderEntry * httpHeaderEntryClone(const HttpHeaderEntry * e); +extern int httpHeaderIdByName(const char *name, int name_len, const HttpHeaderFieldInfo * info, int end); + + +#endif --- /dev/null Mon Jan 7 01:22:42 2008 +++ squid/libhttp/HttpHeaderInfo.h Mon Jan 7 01:22:42 2008 @@ -0,0 +1,116 @@ +#ifndef __LIBHTTP_HTTPHEADERINFO_H__ +#define __LIBHTTP_HTTPHEADERINFO_H__ + +typedef enum { + HDR_UNKNOWN = -1, + HDR_ACCEPT = 0, + HDR_ACCEPT_CHARSET, + HDR_ACCEPT_ENCODING, + HDR_ACCEPT_LANGUAGE, + HDR_ACCEPT_RANGES, + HDR_AGE, + HDR_ALLOW, + HDR_AUTHORIZATION, + HDR_CACHE_CONTROL, + HDR_CONNECTION, + HDR_CONTENT_BASE, + HDR_CONTENT_DISPOSITION, + HDR_CONTENT_ENCODING, + HDR_CONTENT_LANGUAGE, + HDR_CONTENT_LENGTH, + HDR_CONTENT_LOCATION, + HDR_CONTENT_MD5, + HDR_CONTENT_RANGE, + HDR_CONTENT_TYPE, + HDR_TE, + HDR_TRANSFER_ENCODING, + HDR_TRAILER, + HDR_COOKIE, + HDR_DATE, + HDR_ETAG, + HDR_EXPIRES, + HDR_FROM, + HDR_HOST, + HDR_IF_MATCH, + HDR_IF_MODIFIED_SINCE, + HDR_IF_NONE_MATCH, + HDR_IF_RANGE, + HDR_LAST_MODIFIED, + HDR_LINK, + HDR_LOCATION, + HDR_MAX_FORWARDS, + HDR_MIME_VERSION, + HDR_PRAGMA, + HDR_PROXY_AUTHENTICATE, + HDR_PROXY_AUTHENTICATION_INFO, + HDR_PROXY_AUTHORIZATION, + HDR_PROXY_CONNECTION, + HDR_PUBLIC, + HDR_RANGE, + HDR_REQUEST_RANGE, /* some clients use this, sigh */ + HDR_REFERER, + HDR_RETRY_AFTER, + HDR_SERVER, + HDR_SET_COOKIE, + HDR_UPGRADE, + HDR_USER_AGENT, + HDR_VARY, + HDR_VIA, + HDR_EXPECT, + HDR_WARNING, + HDR_WWW_AUTHENTICATE, + HDR_AUTHENTICATION_INFO, + HDR_X_CACHE, + HDR_X_CACHE_LOOKUP, /* tmp hack, remove later */ + HDR_X_FORWARDED_FOR, + HDR_X_REQUEST_URI, /* appended if ADD_X_REQUEST_URI is #defined */ + HDR_X_SQUID_ERROR, + HDR_NEGOTIATE, +#if X_ACCELERATOR_VARY + HDR_X_ACCELERATOR_VARY, +#endif + HDR_X_ERROR_URL, /* errormap, requested URL */ + HDR_X_ERROR_STATUS, /* errormap, received HTTP status line */ + HDR_FRONT_END_HTTPS, + HDR_PROXY_SUPPORT, + HDR_KEEP_ALIVE, + HDR_OTHER, + HDR_ENUM_END +} http_hdr_type; + +/* possible types for http header fields */ +typedef enum { + ftInvalid = HDR_ENUM_END, /* to catch nasty errors with hdr_id<->fld_type clashes */ + ftInt, + ftStr, + ftDate_1123, + ftETag, + ftPCc, + ftPContRange, + ftPRange, + ftDate_1123_or_ETag, + ftSize +} field_type; + +/* per field statistics */ +struct _HttpHeaderFieldStat { + int aliveCount; /* created but not destroyed (count) */ + int seenCount; /* #fields we've seen */ + int parsCount; /* #parsing attempts */ + int errCount; /* #pasring errors */ + int repCount; /* #repetitons */ +}; +typedef struct _HttpHeaderFieldStat HttpHeaderFieldStat; + +/* compiled version of HttpHeaderFieldAttrs plus stats */ +struct _HttpHeaderFieldInfo { + http_hdr_type id; + String name; + field_type type; + HttpHeaderFieldStat stat; +}; +typedef struct _HttpHeaderFieldInfo HttpHeaderFieldInfo; + +extern HttpHeaderFieldInfo *Headers; + +#endif Index: squid/libhttp/Makefile.am =================================================================== RCS file: /cvsroot/squid-sf//squid/libhttp/Attic/Makefile.am,v retrieving revision 1.1.2.2 retrieving revision 1.1.2.3 diff -u -r1.1.2.2 -r1.1.2.3 --- squid/libhttp/Makefile.am 5 Jan 2008 11:46:57 -0000 1.1.2.2 +++ squid/libhttp/Makefile.am 6 Jan 2008 09:19:52 -0000 1.1.2.3 @@ -1,15 +1,17 @@ ## Process this file with automake to produce Makefile.in # -# $Id: Makefile.am,v 1.1.2.2 2008/01/05 11:46:57 adri Exp $ +# $Id: Makefile.am,v 1.1.2.3 2008/01/06 09:19:52 adri Exp $ # libhttp_a_SOURCES = \ HttpStrList.c \ - HttpHeader.c + HttpHeader.c \ + HttpHeaderEntry.c libhttp_a_LIBADD = \ HttpStrList.o \ - HttpHeader.o + HttpHeader.o \ + HttpHeaderEntry.o noinst_LIBRARIES = \ libhttp.a Index: squid/libmem/mem.h =================================================================== RCS file: /cvsroot/squid-sf//squid/libmem/Attic/mem.h,v retrieving revision 1.1.2.1 retrieving revision 1.1.2.2 diff -u -r1.1.2.1 -r1.1.2.2 --- squid/libmem/mem.h 6 Dec 2007 06:34:38 -0000 1.1.2.1 +++ squid/libmem/mem.h 6 Jan 2008 09:19:52 -0000 1.1.2.2 @@ -1,6 +1,72 @@ #ifndef __LIBCORE_MEM_H__ #define __LIBCORE_MEM_H__ +typedef enum { + MEM_NONE, + MEM_2K_BUF, + MEM_4K_BUF, + MEM_8K_BUF, + MEM_16K_BUF, + MEM_32K_BUF, + MEM_64K_BUF, + MEM_ACL, + MEM_ACL_DENY_INFO_LIST, + MEM_ACL_IP_DATA, + MEM_ACL_LIST, + MEM_ACL_NAME_LIST, + MEM_ACL_REQUEST_TYPE, + MEM_AUTH_USER_T, + MEM_AUTH_USER_HASH, + MEM_ACL_PROXY_AUTH_MATCH, + MEM_ACL_USER_DATA, + MEM_ACL_TIME_DATA, +#if USE_CACHE_DIGESTS + MEM_CACHE_DIGEST, +#endif + MEM_CLIENT_INFO, + MEM_STORE_CLIENT_BUF, + MEM_LINK_LIST, + MEM_DLINK_NODE, + MEM_DONTFREE, + MEM_DREAD_CTRL, + MEM_DWRITE_Q, + MEM_FQDNCACHE_ENTRY, + MEM_FWD_SERVER, + MEM_HELPER_REQUEST, + MEM_HELPER_STATEFUL_REQUEST, + MEM_HTTP_HDR_CC, + MEM_HTTP_HDR_CONTENT_RANGE, + MEM_HTTP_HDR_ENTRY, + MEM_HTTP_HDR_RANGE, + MEM_HTTP_HDR_RANGE_SPEC, + MEM_HTTP_REPLY, + MEM_INTLIST, + MEM_IPCACHE_ENTRY, + MEM_MD5_DIGEST, + MEM_MEMOBJECT, + MEM_MEM_NODE, + MEM_NETDBENTRY, + MEM_NET_DB_NAME, + MEM_RELIST, + MEM_REQUEST_T, + MEM_STOREENTRY, + MEM_WORDLIST, +#if !USE_DNSSERVERS + MEM_IDNS_QUERY, +#endif + MEM_EVENT, + MEM_TLV, + MEM_SWAP_LOG_DATA, +#if USE_SSL + MEM_ACL_CERT_DATA, +#endif + MEM_MAX +} mem_type; + +/* XXX this is sitting in src/mem.c rather than here for now .. */ +extern void * memAllocate(mem_type); +extern void memFree(void *, int); + #endif Index: squid/src/HttpHeader.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/HttpHeader.c,v retrieving revision 1.28.6.1.4.24 retrieving revision 1.28.6.1.4.25 diff -u -r1.28.6.1.4.24 -r1.28.6.1.4.25 --- squid/src/HttpHeader.c 22 Dec 2007 14:32:11 -0000 1.28.6.1.4.24 +++ squid/src/HttpHeader.c 6 Jan 2008 09:19:53 -0000 1.28.6.1.4.25 @@ -1,6 +1,6 @@ /* - * $Id: HttpHeader.c,v 1.28.6.1.4.24 2007/12/22 14:32:11 adri Exp $ + * $Id: HttpHeader.c,v 1.28.6.1.4.25 2008/01/06 09:19:53 adri Exp $ * * DEBUG: section 55 HTTP Header * AUTHOR: Alex Rousskov @@ -139,7 +139,6 @@ {"Keep-Alive", HDR_KEEP_ALIVE, ftStr}, {"Other:", HDR_OTHER, ftStr} /* ':' will not allow matches */ }; -static HttpHeaderFieldInfo *Headers = NULL; /* * headers with field values defined as #(values) in HTTP/1.1 @@ -235,18 +234,10 @@ }; static int HttpHeaderStatCount = countof(HttpHeaderStats); -static int HeaderEntryParsedCount = 0; - /* * local routines */ -#define assert_eid(id) assert((id) < HDR_ENUM_END) - -static HttpHeaderEntry *httpHeaderEntryCreate(http_hdr_type id, const char *name, const char *value); -static HttpHeaderEntry *httpHeaderEntryCreate2(http_hdr_type id, String name, String value); -static void httpHeaderEntryDestroy(HttpHeaderEntry * e); -static HttpHeaderEntry *httpHeaderEntryParseCreate(const char *field_start, const char *field_end); static void httpHeaderNoteParsedEntry(http_hdr_type id, String value, int error); static void httpHeaderStatInit(HttpHeaderStat * hs, const char *label); @@ -328,6 +319,18 @@ arrayInit(&hdr->entries); } +/* just handy in parsing: resets and returns false */ +int +httpHeaderReset(HttpHeader * hdr) +{ + http_hdr_owner_type ho = hdr->owner; + assert(hdr); + ho = hdr->owner; + httpHeaderClean(hdr); + httpHeaderInit(hdr, ho); + return 0; +} + void httpHeaderClean(HttpHeader * hdr) { @@ -435,18 +438,6 @@ httpHeaderRepack(old); } -/* just handy in parsing: resets and returns false */ -int -httpHeaderReset(HttpHeader * hdr) -{ - http_hdr_owner_type ho = hdr->owner; - assert(hdr); - ho = hdr->owner; - httpHeaderClean(hdr); - httpHeaderInit(hdr, ho); - return 0; -} - int httpHeaderParse(HttpHeader * hdr, const char *header_start, const char *header_end) { @@ -1217,132 +1208,6 @@ return tot; } -/* - * HttpHeaderEntry - */ - -static HttpHeaderEntry * -httpHeaderEntryCreate(http_hdr_type id, const char *name, const char *value) -{ - HttpHeaderEntry *e; - assert_eid(id); - e = memAllocate(MEM_HTTP_HDR_ENTRY); - e->id = id; - if (id != HDR_OTHER) - e->name = Headers[id].name; - else - stringInit(&e->name, name); - stringInit(&e->value, value); - Headers[id].stat.aliveCount++; - debug(55, 9) ("created entry %p: '%.*s: %.*s'\n", e, strLen2(e->name), strBuf2(e->name), strLen2(e->value), strBuf2(e->value)); - return e; -} - -static HttpHeaderEntry * -httpHeaderEntryCreate2(http_hdr_type id, String name, String value) -{ - HttpHeaderEntry *e; - assert_eid(id); - e = memAllocate(MEM_HTTP_HDR_ENTRY); - e->id = id; - if (id != HDR_OTHER) - e->name = Headers[id].name; - else - e->name = stringDup(&name); - e->value = stringDup(&value); - Headers[id].stat.aliveCount++; - debug(55, 9) ("created entry %p: '%.*s: %.*s'\n", e, strLen2(e->name), strBuf2(e->name), strLen2(e->value), strBuf2(e->value)); - return e; -} - -static void -httpHeaderEntryDestroy(HttpHeaderEntry * e) -{ - assert(e); - assert_eid(e->id); - debug(55, 9) ("destroying entry %p: '%.*s: %.*s'\n", e, strLen2(e->name), strBuf2(e->name), strLen2(e->value), strBuf2(e->value)); - /* clean name if needed */ - if (e->id == HDR_OTHER) - stringClean(&e->name); - stringClean(&e->value); - assert(Headers[e->id].stat.aliveCount); - Headers[e->id].stat.aliveCount--; - e->id = -1; - memFree(e, MEM_HTTP_HDR_ENTRY); -} - -/* parses and inits header entry, returns new entry on success */ -static HttpHeaderEntry * -httpHeaderEntryParseCreate(const char *field_start, const char *field_end) -{ - HttpHeaderEntry *e; - int id; - /* note: name_start == field_start */ - const char *name_end = memchr(field_start, ':', field_end - field_start); - int name_len = name_end ? name_end - field_start : 0; - const char *value_start = field_start + name_len + 1; /* skip ':' */ - /* note: value_end == field_end */ - - HeaderEntryParsedCount++; - - /* do we have a valid field name within this field? */ - if (!name_len || name_end > field_end) - return NULL; - if (name_len > 65534) { - /* String must be LESS THAN 64K and it adds a terminating NULL */ - debug(55, 1) ("WARNING: ignoring header name of %d bytes\n", name_len); - return NULL; - } - if (Config.onoff.relaxed_header_parser && xisspace(field_start[name_len - 1])) { - debug(55, Config.onoff.relaxed_header_parser <= 0 ? 1 : 2) - ("NOTICE: Whitespace after header name in '%s'\n", getStringPrefix(field_start, field_end)); - while (name_len > 0 && xisspace(field_start[name_len - 1])) - name_len--; - if (!name_len) - return NULL; - } - /* now we know we can parse it */ - e = memAllocate(MEM_HTTP_HDR_ENTRY); - debug(55, 9) ("creating entry %p: near '%s'\n", e, getStringPrefix(field_start, field_end)); - /* is it a "known" field? */ - id = httpHeaderIdByName(field_start, name_len, Headers, HDR_ENUM_END); - if (id < 0) - id = HDR_OTHER; - assert_eid(id); - e->id = id; - /* set field name */ - if (id == HDR_OTHER) - stringLimitInit(&e->name, field_start, name_len); - else - e->name = Headers[id].name; - /* trim field value */ - while (value_start < field_end && xisspace(*value_start)) - value_start++; - while (value_start < field_end && xisspace(field_end[-1])) - field_end--; - if (field_end - value_start > 65534) { - /* String must be LESS THAN 64K and it adds a terminating NULL */ - debug(55, 1) ("WARNING: ignoring '%.*s' header of %d bytes\n", - strLen2(e->name), strBuf2(e->name), (int) (field_end - value_start)); - if (e->id == HDR_OTHER) - stringClean(&e->name); - memFree(e, MEM_HTTP_HDR_ENTRY); - return NULL; - } - /* set field value */ - stringLimitInit(&e->value, value_start, field_end - value_start); - Headers[id].stat.seenCount++; - Headers[id].stat.aliveCount++; - debug(55, 9) ("created entry %p: '%.*s: %.*s'\n", e, strLen2(e->name), strBuf2(e->name), strLen2(e->value), strBuf2(e->value)); - return e; -} - -HttpHeaderEntry * -httpHeaderEntryClone(const HttpHeaderEntry * e) -{ - return httpHeaderEntryCreate2(e->id, e->name, e->value); -} - void httpHeaderAddClone(HttpHeader * hdr, const HttpHeaderEntry * e) { @@ -1466,19 +1331,6 @@ } int -httpHeaderIdByName(const char *name, int name_len, const HttpHeaderFieldInfo * info, int end) -{ - int i; - for (i = 0; i < end; ++i) { - if (name_len >= 0 && name_len != strLen(info[i].name)) - continue; - if (!strNCaseCmp(info[i].name, name, name_len < 0 ? strLen2(info[i].name) + 1 : name_len)) - return i; - } - return -1; -} - -int httpHeaderIdByNameDef(const char *name, int name_len) { if (!Headers) Index: squid/src/HttpReply.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/HttpReply.c,v retrieving revision 1.23.6.1.4.2 retrieving revision 1.23.6.1.4.3 diff -u -r1.23.6.1.4.2 -r1.23.6.1.4.3 --- squid/src/HttpReply.c 22 Dec 2007 14:32:11 -0000 1.23.6.1.4.2 +++ squid/src/HttpReply.c 6 Jan 2008 09:19:53 -0000 1.23.6.1.4.3 @@ -1,6 +1,6 @@ /* - * $Id: HttpReply.c,v 1.23.6.1.4.2 2007/12/22 14:32:11 adri Exp $ + * $Id: HttpReply.c,v 1.23.6.1.4.3 2008/01/06 09:19:53 adri Exp $ * * DEBUG: section 58 HTTP Reply (Response) * AUTHOR: Alex Rousskov @@ -404,6 +404,60 @@ } /* + * parses a buf_t into HttpReply. + * Returns: + * +1 -- success + * 0 -- need more data (partial parse) + * -1 -- parse error + */ +int +httpReplyParseBuf(HttpReply *rep, buf_t *b, int offset) +{ + int i, ret; + int len = buf_len(b) - offset; + const char *buf = buf_buf(b) + offset; + const char *re; + + assert(rep); + assert(rep->pstate < psParsed); + + /* For now we'll assume we need to parse the whole lot */ + + /* Find end of start line */ + re = memchr(buf, '\n', len); + if (!re) + return httpReplyParseError(rep); + + /* Skip \n */ + re++; + i = re - buf; + if (i >= len) + return httpReplyParseError(rep); + + /* Pass that to the existing Squid status line parsing routine */ + if (!httpStatusLineParse(&rep->sline, buf, re - 1)) + return httpReplyParseError(rep); + rep->pstate++; + + /* All good? parse headers */ + ret = httpHeaderParseBuf(&rep->header, b, i); + if (ret <= 0) { + return httpReplyParseError(rep); + httpHeaderReset(&rep->header); + } + + /* Update rep */ + httpReplyHdrCacheInit(rep); + /* the previous code had hdr_sz including the status line + headers and final \r\n */ + rep->hdr_sz = ret - offset; + rep->pstate++; + + /* Done */ + return 1; + +} + +/* * parses a 0-terminating buffer into HttpReply. * Returns: * +1 -- success Index: squid/src/enums.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/enums.h,v retrieving revision 1.62.2.1.4.2 retrieving revision 1.62.2.1.4.3 diff -u -r1.62.2.1.4.2 -r1.62.2.1.4.3 --- squid/src/enums.h 5 Jan 2008 11:46:57 -0000 1.62.2.1.4.2 +++ squid/src/enums.h 6 Jan 2008 09:19:53 -0000 1.62.2.1.4.3 @@ -1,6 +1,6 @@ /* - * $Id: enums.h,v 1.62.2.1.4.2 2008/01/05 11:46:57 adri Exp $ + * $Id: enums.h,v 1.62.2.1.4.3 2008/01/06 09:19:53 adri Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -207,20 +207,6 @@ 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, - ftStr, - ftDate_1123, - ftETag, - ftPCc, - ftPContRange, - ftPRange, - ftDate_1123_or_ETag, - ftSize -} field_type; - typedef enum { HIER_NONE, HIER_DIRECT, @@ -494,68 +480,6 @@ #endif -typedef enum { - MEM_NONE, - MEM_2K_BUF, - MEM_4K_BUF, - MEM_8K_BUF, - MEM_16K_BUF, - MEM_32K_BUF, - MEM_64K_BUF, - MEM_ACL, - MEM_ACL_DENY_INFO_LIST, - MEM_ACL_IP_DATA, - MEM_ACL_LIST, - MEM_ACL_NAME_LIST, - MEM_ACL_REQUEST_TYPE, - MEM_AUTH_USER_T, - MEM_AUTH_USER_HASH, - MEM_ACL_PROXY_AUTH_MATCH, - MEM_ACL_USER_DATA, - MEM_ACL_TIME_DATA, -#if USE_CACHE_DIGESTS - MEM_CACHE_DIGEST, -#endif - MEM_CLIENT_INFO, - MEM_STORE_CLIENT_BUF, - MEM_LINK_LIST, - MEM_DLINK_NODE, - MEM_DONTFREE, - MEM_DREAD_CTRL, - MEM_DWRITE_Q, - MEM_FQDNCACHE_ENTRY, - MEM_FWD_SERVER, - MEM_HELPER_REQUEST, - MEM_HELPER_STATEFUL_REQUEST, - MEM_HTTP_HDR_CC, - MEM_HTTP_HDR_CONTENT_RANGE, - MEM_HTTP_HDR_ENTRY, - MEM_HTTP_HDR_RANGE, - MEM_HTTP_HDR_RANGE_SPEC, - MEM_HTTP_REPLY, - MEM_INTLIST, - MEM_IPCACHE_ENTRY, - MEM_MD5_DIGEST, - MEM_MEMOBJECT, - MEM_MEM_NODE, - MEM_NETDBENTRY, - MEM_NET_DB_NAME, - MEM_RELIST, - MEM_REQUEST_T, - MEM_STOREENTRY, - MEM_WORDLIST, -#if !USE_DNSSERVERS - MEM_IDNS_QUERY, -#endif - MEM_EVENT, - MEM_TLV, - MEM_SWAP_LOG_DATA, -#if USE_SSL - MEM_ACL_CERT_DATA, -#endif - MEM_MAX -} mem_type; - /* * NOTE! We must preserve the order of this list! */ Index: squid/src/http.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/http.c,v retrieving revision 1.63.2.3.4.31 retrieving revision 1.63.2.3.4.32 diff -u -r1.63.2.3.4.31 -r1.63.2.3.4.32 --- squid/src/http.c 3 Jan 2008 16:38:01 -0000 1.63.2.3.4.31 +++ squid/src/http.c 6 Jan 2008 09:19:53 -0000 1.63.2.3.4.32 @@ -1,6 +1,6 @@ /* - * $Id: http.c,v 1.63.2.3.4.31 2008/01/03 16:38:01 adri Exp $ + * $Id: http.c,v 1.63.2.3.4.32 2008/01/06 09:19:53 adri Exp $ * * DEBUG: section 11 Hypertext Transfer Protocol (HTTP) * AUTHOR: Harvest Derived @@ -480,7 +480,7 @@ (int) hdr_size, buf_buf(b) + parse_start); /* Parse headers into reply structure */ /* what happens if we fail to parse here? */ - httpReplyParse(reply, buf_buf(b) + parse_start, hdr_size); + httpReplyParseBuf(reply, b, parse_start); /* Skip 1xx messages for now. Advertised in Via as an internal 1.0 hop */ if (reply->sline.status >= 100 && reply->sline.status < 200) { Index: squid/src/protos.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/protos.h,v retrieving revision 1.146.2.4.4.34 retrieving revision 1.146.2.4.4.35 diff -u -r1.146.2.4.4.34 -r1.146.2.4.4.35 --- squid/src/protos.h 5 Jan 2008 09:42:40 -0000 1.146.2.4.4.34 +++ squid/src/protos.h 6 Jan 2008 09:19:53 -0000 1.146.2.4.4.35 @@ -1,6 +1,6 @@ /* - * $Id: protos.h,v 1.146.2.4.4.34 2008/01/05 09:42:40 adri Exp $ + * $Id: protos.h,v 1.146.2.4.4.35 2008/01/06 09:19:53 adri Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -395,7 +395,6 @@ /* Http Header Tools */ extern HttpHeaderFieldInfo *httpHeaderBuildFieldsInfo(const HttpHeaderFieldAttrs * attrs, int count); extern void httpHeaderDestroyFieldsInfo(HttpHeaderFieldInfo * info, int count); -extern int httpHeaderIdByName(const char *name, int name_len, const HttpHeaderFieldInfo * attrs, int end); extern int httpHeaderIdByNameDef(const char *name, int name_len); extern String httpHeaderNameById(int id); extern void httpHeaderMaskInit(HttpHeaderMask * mask, int value); @@ -485,6 +484,7 @@ extern void httpReplyReset(HttpReply * rep); /* parse returns -1,0,+1 on error,need-more-data,success */ extern int httpReplyParse(HttpReply * rep, const char *buf, size_t); +extern int httpReplyParseBuf(HttpReply *rep, buf_t *b, int offset); extern void httpReplyPackInto(const HttpReply * rep, Packer * p); /* ez-routines */ /* mem-pack: returns a ready to use mem buffer with a packed reply */ Index: squid/src/squid.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/squid.h,v retrieving revision 1.36.24.12 retrieving revision 1.36.24.13 diff -u -r1.36.24.12 -r1.36.24.13 --- squid/src/squid.h 5 Jan 2008 11:46:57 -0000 1.36.24.12 +++ squid/src/squid.h 6 Jan 2008 09:19:54 -0000 1.36.24.13 @@ -1,6 +1,6 @@ /* - * $Id: squid.h,v 1.36.24.12 2008/01/05 11:46:57 adri Exp $ + * $Id: squid.h,v 1.36.24.13 2008/01/06 09:19:54 adri Exp $ * * AUTHOR: Duane Wessels * @@ -393,6 +393,8 @@ /* libhttp */ #include "../libhttp/HttpStrList.h" +#include "../libhttp/HttpHeaderInfo.h" +#include "../libhttp/HttpHeaderEntry.h" #include "../libhttp/HttpHeader.h" /* Needed for poll() on Linux at least */ Index: squid/src/structs.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/structs.h,v retrieving revision 1.158.2.5.4.14 retrieving revision 1.158.2.5.4.15 diff -u -r1.158.2.5.4.14 -r1.158.2.5.4.15 --- squid/src/structs.h 5 Jan 2008 11:46:57 -0000 1.158.2.5.4.14 +++ squid/src/structs.h 6 Jan 2008 09:19:54 -0000 1.158.2.5.4.15 @@ -1,6 +1,6 @@ /* - * $Id: structs.h,v 1.158.2.5.4.14 2008/01/05 11:46:57 adri Exp $ + * $Id: structs.h,v 1.158.2.5.4.15 2008/01/06 09:19:54 adri Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -1036,23 +1036,6 @@ field_type type; }; -/* per field statistics */ -struct _HttpHeaderFieldStat { - int aliveCount; /* created but not destroyed (count) */ - int seenCount; /* #fields we've seen */ - int parsCount; /* #parsing attempts */ - int errCount; /* #pasring errors */ - int repCount; /* #repetitons */ -}; - -/* compiled version of HttpHeaderFieldAttrs plus stats */ -struct _HttpHeaderFieldInfo { - http_hdr_type id; - String name; - field_type type; - HttpHeaderFieldStat stat; -}; - struct _HttpReply { /* unsupported, writable, may disappear/change in the future */ int hdr_sz; /* sums _stored_ status-line, headers, and */ Index: squid/src/typedefs.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/typedefs.h,v retrieving revision 1.43.2.3.4.8 retrieving revision 1.43.2.3.4.9 diff -u -r1.43.2.3.4.8 -r1.43.2.3.4.9 --- squid/src/typedefs.h 5 Jan 2008 11:46:57 -0000 1.43.2.3.4.8 +++ squid/src/typedefs.h 6 Jan 2008 09:19:54 -0000 1.43.2.3.4.9 @@ -1,6 +1,6 @@ /* - * $Id: typedefs.h,v 1.43.2.3.4.8 2008/01/05 11:46:57 adri Exp $ + * $Id: typedefs.h,v 1.43.2.3.4.9 2008/01/06 09:19:54 adri Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -126,14 +126,12 @@ typedef struct _HttpReply http_reply; typedef struct _HttpStatusLine HttpStatusLine; typedef struct _HttpHeaderFieldAttrs HttpHeaderFieldAttrs; -typedef struct _HttpHeaderFieldInfo HttpHeaderFieldInfo; typedef struct _HttpHdrCc HttpHdrCc; typedef struct _HttpHdrRangeSpec HttpHdrRangeSpec; typedef struct _HttpHdrRange HttpHdrRange; typedef struct _HttpHdrRangeIter HttpHdrRangeIter; typedef struct _HttpHdrContRange HttpHdrContRange; typedef struct _TimeOrTag TimeOrTag; -typedef struct _HttpHeaderFieldStat HttpHeaderFieldStat; typedef struct _HttpHeaderStat HttpHeaderStat; typedef struct _HttpBody HttpBody; typedef struct _HttpReply HttpReply; Index: squid/tools/cossdump.c =================================================================== RCS file: /cvsroot/squid-sf//squid/tools/cossdump.c,v retrieving revision 1.5.28.1 retrieving revision 1.5.28.2 diff -u -r1.5.28.1 -r1.5.28.2 --- squid/tools/cossdump.c 5 Jan 2008 11:46:57 -0000 1.5.28.1 +++ squid/tools/cossdump.c 6 Jan 2008 09:19:55 -0000 1.5.28.2 @@ -33,6 +33,7 @@ #include "../libbuf/String.h" #include "../libhttp/HttpStrList.h" +#include "../libhttp/HttpHeaderInfo.h" #include "../libhttp/HttpHeader.h"