--------------------- PatchSet 91 Date: 2002/10/31 22:57:18 Author: rbcollins Branch: esi Tag: (none) Log: really create the squid 3 esi branch Members: configure.in:1.4->1.4.2.1 doc/debug-sections.txt:1.1->1.1.6.1 doc/Programming-Guide/prog-guide.sgml:1.1->1.1.6.1 include/profiling.h:1.1->1.1.6.1 src/ESI.cc:1.1->1.1.2.1 src/ESI.h:1.1->1.1.2.1 src/ESIExpression.cc:1.1->1.1.2.1 src/HttpHdrSc.cc:1.1->1.1.2.1 src/HttpHdrScTarget.cc:1.1->1.1.2.1 src/HttpHeader.cc:1.1->1.1.6.1 src/HttpHeader.h:1.1->1.1.6.1 src/HttpHeaderTools.cc:1.1->1.1.6.1 src/HttpReply.cc:1.1->1.1.6.1 src/Makefile.am:1.4->1.4.2.1 src/ProfStats.cc:1.1->1.1.6.1 src/cf.data.pre:1.1->1.1.6.1 src/clientStream.cc:1.1->1.1.6.1 src/clientStream.h:1.1->1.1.6.1 src/client_side.cc:1.6->1.6.2.1 src/client_side_reply.cc:1.6->1.6.2.1 src/client_side_request.cc:1.2->1.2.2.1 src/comm.cc:1.8->1.8.2.1 src/comm.h:1.4->1.4.2.1 src/enums.h:1.1->1.1.6.1 src/errorpage.cc:1.3->1.3.2.1 src/forward.cc:1.1->1.1.6.1 src/http.cc:1.5->1.5.2.1 src/mem.cc:1.1->1.1.6.1 src/pinger.cc:1.1->1.1.6.1 src/protos.h:1.4->1.4.2.1 src/structs.h:1.4->1.4.2.1 Index: squid3/configure.in =================================================================== RCS file: /cvsroot/squid-sf//squid3/configure.in,v retrieving revision 1.4 retrieving revision 1.4.2.1 diff -u -r1.4 -r1.4.2.1 --- squid3/configure.in 22 Oct 2002 08:29:02 -0000 1.4 +++ squid3/configure.in 31 Oct 2002 22:57:18 -0000 1.4.2.1 @@ -3,7 +3,7 @@ dnl dnl Duane Wessels, wessels@nlanr.net, February 1996 (autoconf v2.9) dnl -dnl $Id: configure.in,v 1.4 2002/10/22 08:29:02 squidadm Exp $ +dnl $Id: configure.in,v 1.4.2.1 2002/10/31 22:57:18 rbcollins Exp $ dnl dnl dnl @@ -13,7 +13,7 @@ AC_CONFIG_AUX_DIR(cfgaux) AM_INIT_AUTOMAKE(squid, 3.0-DEVEL) AM_CONFIG_HEADER(include/autoconf.h) -AC_REVISION($Revision: 1.4 $)dnl +AC_REVISION($Revision: 1.4.2.1 $)dnl AC_PREFIX_DEFAULT(/usr/local/squid) AM_MAINTAINER_MODE @@ -454,6 +454,17 @@ fi ]) +AM_CONDITIONAL(USE_ESI, false) +AC_ARG_ENABLE(esi, + AC_HELP_STRING([--enable-esi],[Enable ESI for accelerators. Requires libexpat. Enabling ESI will cause squid to follow the Edge Acceleration Specification (www.esi.org). This causes squid to IGNORE client Cache-Control headers. DO NOT use this in a squid configured as a web proxy, ONLY use it in a squid configured for webserver acceleration.]), + ac_cv_use_esi=$enableval, ac_cv_use_esi=no) +AC_CACHE_CHECK(whether to enable ESI,ac_cv_use_esi, ac_cv_use_esi=no) +if test "$ac_cv_use_esi" = "yes" ; then + AC_DEFINE(ESI,1,[Compile the ESI processor and Surrogate header support]) + AM_CONDITIONAL(USE_ESI, true) + XTRA_LIBS="$XTRA_LIBS -lexpat" +fi + dnl This is a developer only option. Developers know how to set defines dnl dnl AC_ARG_ENABLE(mem-gen-trace, Index: squid3/doc/debug-sections.txt =================================================================== RCS file: /cvsroot/squid-sf//squid3/doc/debug-sections.txt,v retrieving revision 1.1 retrieving revision 1.1.6.1 diff -u -r1.1 -r1.1.6.1 --- squid3/doc/debug-sections.txt 14 Oct 2002 00:18:06 -0000 1.1 +++ squid3/doc/debug-sections.txt 31 Oct 2002 22:57:18 -0000 1.1.6.1 @@ -89,6 +89,8 @@ section 83 SSL accelerator support section 84 Helper process maintenance section 85 Client side request management - after parsing, before caching +section 86 ESI processing section 87 client side stream management section 88 Client side reply management - from store to stream section 89 NAT / IP Interception +section 90 Http Surrogate-Control Header Index: squid3/doc/Programming-Guide/prog-guide.sgml =================================================================== RCS file: /cvsroot/squid-sf//squid3/doc/Programming-Guide/prog-guide.sgml,v retrieving revision 1.1 retrieving revision 1.1.6.1 diff -u -r1.1 -r1.1.6.1 --- squid3/doc/Programming-Guide/prog-guide.sgml 14 Oct 2002 00:18:07 -0000 1.1 +++ squid3/doc/Programming-Guide/prog-guide.sgml 31 Oct 2002 22:57:18 -0000 1.1.6.1 @@ -2,7 +2,7 @@
Squid Programmers Guide Squid Developers -$Id: prog-guide.sgml,v 1.1 2002/10/14 00:18:07 squidadm Exp $ +$Id: prog-guide.sgml,v 1.1.6.1 2002/10/31 22:57:18 rbcollins Exp $ Squid is a WWW Cache application developed by the National Laboratory @@ -450,6 +450,12 @@ see . +ESI +

+ ESI is an implementation of Edge Side Includes (.) + ESI is implemented as a client side stream and a small + modification to client_side_reply.c to check whether + ESI should be inserted into the reply stream or not. External Programs Index: squid3/include/profiling.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/include/profiling.h,v retrieving revision 1.1 retrieving revision 1.1.6.1 diff -u -r1.1 -r1.1.6.1 --- squid3/include/profiling.h 14 Oct 2002 00:18:18 -0000 1.1 +++ squid3/include/profiling.h 31 Oct 2002 22:57:19 -0000 1.1.6.1 @@ -83,6 +83,11 @@ XPROF_file_read, XPROF_file_write, XPROF_file_close, +#ifdef ESI + XPROF_esiExpressionEval, + XPROF_esiProcessing, + XPROF_esiParsing, +#endif XPROF_LAST } xprof_type; Index: squid3/src/ESI.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/ESI.cc,v retrieving revision 1.1 retrieving revision 1.1.2.1 diff -u -r1.1 -r1.1.2.1 --- squid3/src/ESI.cc 31 Oct 2002 08:12:52 -0000 1.1 +++ squid3/src/ESI.cc 31 Oct 2002 22:57:23 -0000 1.1.2.1 @@ -1,6 +1,6 @@ /* - * $Id: ESI.cc,v 1.1 2002/10/31 08:12:52 rbcollins Exp $ + * $Id: ESI.cc,v 1.1.2.1 2002/10/31 22:57:23 rbcollins Exp $ * * DEBUG: section 86 ESI processing * AUTHOR: Robert Collins @@ -61,7 +61,6 @@ typedef struct _esiStreamContext esiStreamContext; typedef struct _esiContext esiContext; -typedef struct _esiInclude esiInclude; /* TODO: split thisNode out into separate files ? */ /* Parsing: quick and dirty. ESI files are not valid XML, so a generic @@ -85,9 +84,7 @@ * FAILED - processing failed, return an error to the client. */ -/* TODO: remove invalid markup (silently swallow markup in invalid locations - * - * +/* * NOT TODO: esi:inline - out of scope. */ @@ -162,21 +159,23 @@ } esiKick_t; typedef struct _esiElementType esiElementType; -typedef struct _esiElement esiElement; typedef void esiRender (void *, esiSegment *); /* render into the segment list */ -#define RENDER(foo, bar) foo->vptr->render(foo, bar) +class esiElement; +#define RENDER(foo, bar) foo->Vptr->render(foo, bar) typedef int esiAddElement (void *, esiElement *); /* add a child to an element */ -#define ADDELEMENT(foo, bar) foo->vptr->add(foo,bar) +#define ADDELEMENT(foo, bar) foo->Vptr->add(foo,bar) typedef esiProcessResult_t esiProcessSelf (void *, int); /* process thisNode element */ -#define PROCESS(foo, bar) foo->vptr->process(foo, bar) +#define PROCESS(foo, bar) foo->Vptr->process(foo, bar) struct _esiElementType { esiRender *render; esiAddElement *add; esiProcessSelf *process; }; -struct _esiElement { - esiElementType *vptr; +struct esiElement { + virtual void render (esiSegment *) = 0; + virtual void deleteSelf() = 0; + esiElementType *Vptr; }; /* some core operators */ @@ -196,6 +195,7 @@ static esiRender esiIncludeRender; static esiProcessSelf esiIncludeProcess; +struct esiInclude; static void esiIncludeSubRequestDone (esiInclude *, esiStreamContext *, int); static esiRender esiRemoveRender; @@ -240,30 +240,42 @@ /* esiComment */ -typedef struct { - esiElementType *vptr; -} esiComment; +struct esiComment : public esiElement { + void *operator new (size_t byteCount); + void operator delete (void *address); + void deleteSelf(); + + esiComment(); + void render(esiSegment *); + +}; CBDATA_TYPE (esiComment); static FREE esiCommentFree; static esiElement * esiCommentNew(void); /* esiLiteral */ -typedef struct { - esiElementType *vptr; +struct esiLiteral : public esiElement{ + void deleteSelf(); /* optimise copies away later */ esiSegment *buffer; struct { int donevars:1; } flags; esiVarState *varState; -} esiLiteral; +}; CBDATA_TYPE (esiLiteral); static FREE esiLiteralFree; static esiElement * esiLiteralNew(esiContext *, const XML_Char *s, int len); /* esiSequence */ -typedef struct { - esiElementType *vptr; +class esiSequence : public esiElement{ +public: + void *operator new (size_t byteCount); + void operator delete (void *address); + void deleteSelf(); + + esiSequence(); + void render(esiSegment *); esiElement ** elements; /* unprocessed or rendered nodes */ int allocedcount; size_t allocedsize; @@ -273,14 +285,13 @@ int dovars:1; /* for esiVar */ int testtrue:1; /* for esiWhen */ } flags; -} esiSequence; +}; CBDATA_TYPE (esiSequence); static FREE esiSequenceFree; static esiElement * esiSequenceNew(void); /* esiInclude */ -struct _esiInclude { - esiElementType *vptr; +struct esiInclude : public esiElement{ struct { int onerrorcontinue:1; /* on error return zero data */ int failed:1; /* Failed to process completely */ @@ -298,9 +309,8 @@ static esiElement * esiIncludeNew (int attributes, const char **attr, esiContext *); /* esiRemove */ -typedef struct { - esiElementType *vptr; -} esiRemove; +struct esiRemove : public esiElement{ +}; CBDATA_TYPE (esiRemove); static FREE esiRemoveFree; static esiElement * esiRemoveNew(void); @@ -314,8 +324,7 @@ static esiElement *esiExceptNew(void); /* esiTry */ -typedef struct { - esiElementType *vptr; +struct esiTry : public esiElement{ esiElement *attempt; esiElement *except; struct { @@ -324,7 +333,7 @@ int attemptfailed:1; /* The attempt branch failed */ int exceptfailed:1; /* the except branch failed */ } flags; -} esiTry; +}; CBDATA_TYPE (esiTry); static FREE esiTryFree; static esiElement *esiTryNew(void); @@ -334,15 +343,14 @@ static esiElement *esiVarNew(void); /* esiChoose */ -typedef struct { - esiElementType *vptr; +struct esiChoose : public esiElement { esiElement ** elements; /* unprocessed nodes */ int allocedcount; size_t allocedsize; int elementcount; int chosenelement; esiElement *otherwise; -} esiChoose; +}; CBDATA_TYPE (esiChoose); static FREE esiChooseFree; static esiElement *esiChooseNew(void); @@ -767,7 +775,7 @@ clientStreamCallback (thisNode, http, rep, recievedData); return; } - debug (86, 3)("esiProcessStream: Processing thisNode %p context %p\n",thisNode, context); + debug (86, 3)("esiProcessStream: Processing thisNode %p context %p offset %d length %u\n",thisNode, context, (int) recievedData.offset, (unsigned int)recievedData.length); /* once we finish the template, we *cannot* return here */ assert (!context->flags.finishedtemplate); @@ -1217,6 +1225,7 @@ XML_SetDefaultHandler(context->parserState.p, esiExpatDefault); XML_SetCommentHandler(context->parserState.p, esiExpatComment); XML_UseParserAsHandlerArg(context->parserState.p); + context->flags.parserinited = 1; } /* we have data */ @@ -1396,6 +1405,7 @@ cbdataFree (context->tree); if (context->flags.parserinited) { XML_ParserFree (context->parserState.p); + context->flags.parserinited = 0; } esiSegmentFreeList (&context->buffered); esiSegmentFreeList (&context->outbound); @@ -1660,22 +1670,57 @@ esiElement * esiCommentNew () { - esiComment *rv; + return new esiComment; +} + +void * +esiComment::operator new(size_t byteCount) +{ + assert (byteCount == sizeof (esiComment)); + void *rv; CBDATA_INIT_TYPE_FREECB(esiComment, esiCommentFree); - rv = cbdataAlloc (esiComment); - rv->vptr = &_esiComment; - return (esiElement *) rv; + rv = (void *)cbdataAlloc (esiComment); + return rv; +} + +void +esiComment::operator delete (void *address) +{ + cbdataFree ((esiComment *)address); +} + +void +esiComment::deleteSelf() +{ + delete this; +} + +esiComment::esiComment() +{ + Vptr = &_esiComment; } void esiCommentRender (void *data, esiSegment *output) { + ((esiComment *)data)->render(output); +} + +void +esiComment::render(esiSegment *output) +{ /* Comments do nothing dude */ - debug (86, 5)("esiCommentRender: Rendering comment %p\n", data); + debug (86, 5)("esiCommentRender: Rendering comment %p\n", output); } /* esiLiteral */ void +esiLiteral::deleteSelf() +{ + delete this; +} + +void esiLiteralFree (void *data) { esiLiteral *thisNode = (esiLiteral *)data; @@ -1694,7 +1739,7 @@ off_t start; CBDATA_INIT_TYPE_FREECB(esiLiteral, esiLiteralFree); rv = cbdataAlloc (esiLiteral); - rv->vptr = &_esiLiteral; + rv->Vptr = &_esiLiteral; assert (s); rv->buffer = cbdataAlloc (esiSegment); local = rv->buffer; @@ -1751,6 +1796,12 @@ /* esiSequence */ void +esiSequence::deleteSelf() +{ + delete this; +} + +void esiSequenceFree (void *data) { esiSequence *thisNode = (esiSequence *)data; @@ -1763,37 +1814,62 @@ memFreeBuf (thisNode->allocedsize, thisNode->elements); } +void * +esiSequence::operator new(size_t byteCount) +{ + assert (byteCount == sizeof (esiSequence)); + void *rv; + CBDATA_INIT_TYPE_FREECB(esiSequence, esiSequenceFree); + rv = (void *)cbdataAlloc (esiSequence); + return rv; +} + +void +esiSequence::operator delete (void *address) +{ + cbdataFree ((esiSequence *)address); +} + + esiElement * esiSequenceNew () { - esiSequence *rv; - CBDATA_INIT_TYPE_FREECB(esiSequence, esiSequenceFree); - rv = cbdataAlloc (esiSequence); - rv->vptr = &_esiSequence; - rv->elements = NULL; - return (esiElement *)rv; + return new esiSequence; +} + +esiSequence::esiSequence() +{ + Vptr = &_esiSequence; + elements = NULL; } void esiSequenceRender (void *data, esiSegment *output) { - /* append all processed elements, and trim processed and rendered elements */ - esiSequence *thisNode = (esiSequence *)data; + ((esiSequence *)data)->render(output); +} + +void +esiSequence::render(esiSegment *output) +{ + /* append all processed elements, and trim processed + * and rendered elements + */ int i; assert (output->next == NULL); - debug (86,5)("esiSequenceRender: rendering %d elements\n", thisNode->processedcount); - for (i = 0; i < thisNode->processedcount; ++i) { - RENDER (thisNode->elements[i], output); + debug (86,5)("esiSequenceRender: rendering %d elements\n", processedcount); + for (i = 0; i < processedcount; ++i) { + RENDER (elements[i], output); /* FIXME: pass a esiSegment ** ? */ while (output->next) output = output->next; - cbdataFree (thisNode->elements[i]); + cbdataFree (elements[i]); } - if (thisNode->processedcount) { - xmemmove (thisNode->elements, &thisNode->elements[thisNode->processedcount], (thisNode->elementcount - thisNode->processedcount) * sizeof (esiElement *)); + if (processedcount) { + xmemmove (elements, &elements[processedcount], (elementcount - processedcount) * sizeof (esiElement *)); } - thisNode->elementcount -= thisNode->processedcount; - thisNode->processedcount = 0; + elementcount -= processedcount; + processedcount = 0; assert (output->next == NULL); } @@ -1803,14 +1879,14 @@ /* add an element to the output list */ esiSequence *thisNode = (esiSequence *)data; /* Some elements require specific parents */ - if (element->vptr == &_esiAttempt || - element->vptr == &_esiExcept) { + if (element->Vptr == &_esiAttempt || + element->Vptr == &_esiExcept) { debug (86,0)("esiSequenceAdd: misparented Attempt or Except element (section 3.4)\n"); return -1; } /* Tie literals together for efficiency */ - if (thisNode->elementcount && element->vptr == &_esiLiteral && - thisNode->elements[thisNode->elementcount - 1]->vptr == &_esiLiteral) { + if (thisNode->elementcount && element->Vptr == &_esiLiteral && + thisNode->elements[thisNode->elementcount - 1]->Vptr == &_esiLiteral) { debug (86,5)("esiSequenceAdd: tying Literals %p and %p together\n", thisNode->elements[thisNode->elementcount - 1], element); esiSegmentTransferList (&((esiLiteral *)element)->buffer, @@ -1911,7 +1987,7 @@ assert (context); CBDATA_INIT_TYPE_FREECB(esiInclude, esiIncludeFree); rv = cbdataAlloc (esiInclude); - rv->vptr = &_esiInclude; + rv->Vptr = &_esiInclude; for (i = 0; attr[i] && i < attrcount; i += 2) { if (!strcmp(attr[i],"src")) { @@ -2083,7 +2159,7 @@ esiRemove *rv; CBDATA_INIT_TYPE_FREECB(esiRemove, esiRemoveFree); rv = cbdataAlloc (esiRemove); - rv->vptr = &_esiRemove; + rv->Vptr = &_esiRemove; return (esiElement *) rv; } @@ -2098,7 +2174,7 @@ int esiRemoveAdd (void *data, esiElement *element) { - if (element->vptr != & _esiLiteral) { + if (element->Vptr != & _esiLiteral) { debug (86,5)("esiRemoveAdd: Failed for %p\n",data); return -1; } @@ -2122,7 +2198,7 @@ esiTry *rv; CBDATA_INIT_TYPE_FREECB(esiTry, esiTryFree); rv = cbdataAlloc (esiTry); - rv->vptr = &_esiTry; + rv->Vptr = &_esiTry; return (esiElement *) rv; } @@ -2149,13 +2225,13 @@ { esiTry *thisNode = (esiTry *)data; debug (86,5)("esiTryAdd: Try %p adding element %p\n",thisNode, element); - if (element->vptr == &_esiLiteral) { + if (element->Vptr == &_esiLiteral) { /* Swallow whitespace */ debug (86,5)("esiTryAdd: Try %p skipping whitespace %p\n",thisNode, element); cbdataFree (element); return 0; } - if (element->vptr == &_esiAttempt) { + if (element->Vptr == &_esiAttempt) { if (thisNode->attempt) { debug (86,1)("esiTryAdd: Failed for %p - try allready has an attempt node (section 3.4)\n",data); return -1; @@ -2163,7 +2239,7 @@ thisNode->attempt = element; return 0; } - if (element->vptr == &_esiExcept) { + if (element->Vptr == &_esiExcept) { if (thisNode->except) { debug (86,1)("esiTryAdd: Failed for %p - try already has an except node (section 3.4)\n",data); return -1; @@ -2245,7 +2321,7 @@ esiAttemptNew () { esiElement *rv = esiSequenceNew(); - rv->vptr = &_esiAttempt; + rv->Vptr = &_esiAttempt; return rv; } @@ -2254,7 +2330,7 @@ esiExceptNew () { esiElement *rv = esiSequenceNew(); - rv->vptr = &_esiExcept; + rv->Vptr = &_esiExcept; return rv; } @@ -2263,7 +2339,7 @@ esiVarNew () { esiSequence *rv = (esiSequence *)esiSequenceNew(); - rv->vptr = &_esiVar; + rv->Vptr = &_esiVar; rv->flags.dovars = 1; return (esiElement *)rv; } @@ -2839,7 +2915,7 @@ esiChoose *rv; CBDATA_INIT_TYPE_FREECB(esiChoose, esiChooseFree); rv = cbdataAlloc (esiChoose); - rv->vptr = &_esiChoose; + rv->Vptr = &_esiChoose; rv->elements = NULL; rv->chosenelement = -1; return (esiElement *)rv; @@ -2865,7 +2941,7 @@ { /* add an element to the output list */ esiChoose *thisNode = (esiChoose *)data; - if (element->vptr == &_esiLiteral) { + if (element->Vptr == &_esiLiteral) { /* Swallow whitespace */ debug (86,5)("esiChooseAdd: Choose %p skipping whitespace %p\n",thisNode, element); cbdataFree (element); @@ -2873,11 +2949,11 @@ } /* Some elements require specific parents */ - if (!(element->vptr == &_esiWhen || element->vptr == &_esiOtherwise)) { + if (!(element->Vptr == &_esiWhen || element->Vptr == &_esiOtherwise)) { debug (86,0)("esiChooseAdd: invalid child node for esi:choose (section 3.3)\n"); return -1; } - if (element->vptr == &_esiOtherwise) { + if (element->Vptr == &_esiOtherwise) { if (thisNode->otherwise) { debug (86,0)("esiChooseAdd: only one otherwise node allowed for esi:choose (section 3.3)\n"); return -1; @@ -2925,7 +3001,7 @@ esiSequence *rv = (esiSequence *)esiSequenceNew(); char const *expression = NULL; int i; - rv->vptr = &_esiWhen; + rv->Vptr = &_esiWhen; for (i = 0; attr[i] && i < attrcount; i += 2) { if (!strcmp(attr[i],"test")) { @@ -2957,7 +3033,7 @@ esiOtherwiseNew () { esiSequence *rv = (esiSequence *)esiSequenceNew(); - rv->vptr = &_esiOtherwise; + rv->Vptr = &_esiOtherwise; return (esiElement *)rv; } @@ -2969,7 +3045,7 @@ int rv = 0; if (httpHeaderHas(&rep->header, HDR_SURROGATE_CONTROL)) { HttpHdrScTarget *sctusable = httpHdrScGetMergedTarget (rep->surrogate_control, - Config.Accel.surrogate_id); + Config.Accel.surrogate_id); if (!sctusable || strLen (sctusable->content) == 0) /* Nothing generic or targeted at us, or no * content processing requested Index: squid3/src/ESI.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/ESI.h,v retrieving revision 1.1 retrieving revision 1.1.2.1 diff -u -r1.1 -r1.1.2.1 --- squid3/src/ESI.h 31 Oct 2002 08:12:55 -0000 1.1 +++ squid3/src/ESI.h 31 Oct 2002 22:57:28 -0000 1.1.2.1 @@ -1,6 +1,6 @@ /* - * $Id: ESI.h,v 1.1 2002/10/31 08:12:55 rbcollins Exp $ + * $Id: ESI.h,v 1.1.2.1 2002/10/31 22:57:28 rbcollins Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ Index: squid3/src/ESIExpression.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/ESIExpression.cc,v retrieving revision 1.1 retrieving revision 1.1.2.1 diff -u -r1.1 -r1.1.2.1 --- squid3/src/ESIExpression.cc 31 Oct 2002 08:12:55 -0000 1.1 +++ squid3/src/ESIExpression.cc 31 Oct 2002 22:57:29 -0000 1.1.2.1 @@ -1,6 +1,6 @@ /* - * $Id: ESIExpression.cc,v 1.1 2002/10/31 08:12:55 rbcollins Exp $ + * $Id: ESIExpression.cc,v 1.1.2.1 2002/10/31 22:57:29 rbcollins Exp $ * * DEBUG: section 86 ESI processing * AUTHOR: Robert Collins Index: squid3/src/HttpHdrSc.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/HttpHdrSc.cc,v retrieving revision 1.1 retrieving revision 1.1.2.1 diff -u -r1.1 -r1.1.2.1 --- squid3/src/HttpHdrSc.cc 31 Oct 2002 08:12:57 -0000 1.1 +++ squid3/src/HttpHdrSc.cc 31 Oct 2002 22:57:29 -0000 1.1.2.1 @@ -1,6 +1,6 @@ /* - * $Id: HttpHdrSc.cc,v 1.1 2002/10/31 08:12:57 rbcollins Exp $ + * $Id: HttpHdrSc.cc,v 1.1.2.1 2002/10/31 22:57:29 rbcollins Exp $ * * DEBUG: section 90 HTTP Cache Control Header * AUTHOR: Alex Rousskov Index: squid3/src/HttpHdrScTarget.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/HttpHdrScTarget.cc,v retrieving revision 1.1 retrieving revision 1.1.2.1 diff -u -r1.1 -r1.1.2.1 --- squid3/src/HttpHdrScTarget.cc 31 Oct 2002 08:12:58 -0000 1.1 +++ squid3/src/HttpHdrScTarget.cc 31 Oct 2002 22:57:29 -0000 1.1.2.1 @@ -1,6 +1,6 @@ /* - * $Id: HttpHdrScTarget.cc,v 1.1 2002/10/31 08:12:58 rbcollins Exp $ + * $Id: HttpHdrScTarget.cc,v 1.1.2.1 2002/10/31 22:57:29 rbcollins Exp $ * * DEBUG: section 90 HTTP Cache Control Header * AUTHOR: Alex Rousskov Index: squid3/src/HttpHeader.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/HttpHeader.cc,v retrieving revision 1.1 retrieving revision 1.1.6.1 diff -u -r1.1 -r1.1.6.1 --- squid3/src/HttpHeader.cc 14 Oct 2002 00:18:19 -0000 1.1 +++ squid3/src/HttpHeader.cc 31 Oct 2002 22:57:30 -0000 1.1.6.1 @@ -1,6 +1,6 @@ /* - * $Id: HttpHeader.cc,v 1.1 2002/10/14 00:18:19 squidadm Exp $ + * $Id: HttpHeader.cc,v 1.1.6.1 2002/10/31 22:57:30 rbcollins Exp $ * * DEBUG: section 55 HTTP Header * AUTHOR: Alex Rousskov @@ -131,6 +131,8 @@ #if X_ACCELERATOR_VARY {"X-Accelerator-Vary", HDR_X_ACCELERATOR_VARY, ftStr}, #endif + {"Surrogate-Capability", HDR_SURROGATE_CAPABILITY, ftStr}, + {"Surrogate-Control", HDR_SURROGATE_CONTROL, ftPSc}, {"Other:", HDR_OTHER, ftStr} /* ':' will not allow matches */ }; static HttpHeaderFieldInfo *Headers = NULL; @@ -171,6 +173,8 @@ #if X_ACCELERATOR_VARY HDR_X_ACCELERATOR_VARY, #endif + HDR_SURROGATE_CAPABILITY, + HDR_SURROGATE_CONTROL, HDR_X_FORWARDED_FOR }; @@ -179,9 +183,9 @@ { HDR_CACHE_CONTROL, HDR_CONNECTION, HDR_DATE, HDR_PRAGMA, HDR_TRANSFER_ENCODING, - HDR_UPGRADE, + HDR_UPGRADE, /* HDR_TRAILER, */ - HDR_VIA + HDR_VIA, }; /* entity-headers */ @@ -207,7 +211,8 @@ #if X_ACCELERATOR_VARY HDR_X_ACCELERATOR_VARY, #endif - HDR_X_SQUID_ERROR + HDR_X_SQUID_ERROR, + HDR_SURROGATE_CONTROL }; static HttpHeaderMask RequestHeadersMask; /* set run-time using RequestHeaders */ @@ -217,7 +222,7 @@ HDR_IF_MATCH, HDR_IF_MODIFIED_SINCE, HDR_IF_NONE_MATCH, HDR_IF_RANGE, HDR_MAX_FORWARDS, HDR_PROXY_CONNECTION, HDR_PROXY_AUTHORIZATION, HDR_RANGE, HDR_REFERER, HDR_REQUEST_RANGE, - HDR_USER_AGENT, HDR_X_FORWARDED_FOR + HDR_USER_AGENT, HDR_X_FORWARDED_FOR, HDR_SURROGATE_CAPABILITY }; /* header accounting */ @@ -284,6 +289,7 @@ #endif /* init dependent modules */ httpHdrCcInitModule(); + httpHdrScInitModule(); /* register with cache manager */ cachemgrRegister("http_headers", "HTTP Header Statistics", httpHeaderStoreReport, 0, 1); @@ -295,6 +301,7 @@ httpHeaderDestroyFieldsInfo(Headers, HDR_ENUM_END); Headers = NULL; httpHdrCcCleanModule(); + httpHdrScCleanModule(); } static void @@ -307,6 +314,7 @@ statHistEnumInit(&hs->hdrUCountDistr, 32); /* not a real enum */ statHistEnumInit(&hs->fieldTypeDistr, HDR_ENUM_END); statHistEnumInit(&hs->ccTypeDistr, CC_ENUM_END); + statHistEnumInit(&hs->scTypeDistr, SC_ENUM_END); } /* @@ -828,6 +836,25 @@ memBufClean(&mb); } +void +httpHeaderPutSc(HttpHeader *hdr, const HttpHdrSc *sc) +{ + MemBuf mb; + Packer p; + assert(hdr && sc); + /* remove old directives if any */ + httpHeaderDelById(hdr, HDR_RANGE); + /* pack into mb */ + memBufDefInit(&mb); + packerToMemInit(&p, &mb); + httpHdrScPackInto(sc, &p); + /* put */ + httpHeaderAddEntry(hdr, httpHeaderEntryCreate(HDR_SURROGATE_CONTROL, NULL, mb.buf)); + /* cleanup */ + packerClean(&p); + memBufClean(&mb); +} + /* add extension header (these fields are not parsed/analyzed/joined, etc.) */ void httpHeaderPutExt(HttpHeader * hdr, const char *name, const char *value) @@ -928,6 +955,23 @@ return r; } +HttpHdrSc * +httpHeaderGetSc(const HttpHeader *hdr) +{ + HttpHdrSc *sc; + String s; + if (!CBIT_TEST(hdr->mask, HDR_SURROGATE_CONTROL)) + return NULL; + s = httpHeaderGetList(hdr, HDR_SURROGATE_CONTROL); + sc = httpHdrScParseCreate(&s); + HttpHeaderStats[hdr->owner].ccParsedCount++; + if (sc) + httpHdrScUpdateStats(sc, &HttpHeaderStats[hdr->owner].scTypeDistr); + httpHeaderNoteParsedEntry(HDR_SURROGATE_CONTROL, s, !sc); + stringClean(&s); + return sc; +} + HttpHdrContRange * httpHeaderGetContRange(const HttpHeader * hdr) { @@ -1166,6 +1210,10 @@ storeAppendPrintf(e, "%2s\t %-20s\t %5s\t %6s\n", "id", "name", "count", "#/cc_field"); statHistDump(&hs->ccTypeDistr, e, httpHdrCcStatDumper); + storeAppendPrintf(e, "\nSurrogate-control directives distribution\n"); + storeAppendPrintf(e, "%2s\t %-20s\t %5s\t %6s\n", + "id", "name", "count", "#/sc_field"); + statHistDump(&hs->scTypeDistr, e, httpHdrScStatDumper); storeAppendPrintf(e, "\nNumber of fields per header distribution\n"); storeAppendPrintf(e, "%2s\t %-5s\t %5s\t %6s\n", "id", "#flds", "count", "%total"); Index: squid3/src/HttpHeader.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/HttpHeader.h,v retrieving revision 1.1 retrieving revision 1.1.6.1 diff -u -r1.1 -r1.1.6.1 --- squid3/src/HttpHeader.h 14 Oct 2002 00:18:19 -0000 1.1 +++ squid3/src/HttpHeader.h 31 Oct 2002 22:57:30 -0000 1.1.6.1 @@ -1,6 +1,6 @@ /* - * $Id: HttpHeader.h,v 1.1 2002/10/14 00:18:19 squidadm Exp $ + * $Id: HttpHeader.h,v 1.1.6.1 2002/10/31 22:57:30 rbcollins Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -44,4 +44,7 @@ field_type type; }; +extern int httpHeaderParseQuotedString (const char *start, String *val); +extern void httpHeaderPutSc(HttpHeader *hdr, const HttpHdrSc *sc); +extern HttpHdrSc *httpHeaderGetSc(const HttpHeader *hdr); #endif /* SQUID_HTTPHEADER_H */ Index: squid3/src/HttpHeaderTools.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/HttpHeaderTools.cc,v retrieving revision 1.1 retrieving revision 1.1.6.1 diff -u -r1.1 -r1.1.6.1 --- squid3/src/HttpHeaderTools.cc 14 Oct 2002 00:18:19 -0000 1.1 +++ squid3/src/HttpHeaderTools.cc 31 Oct 2002 22:57:30 -0000 1.1.6.1 @@ -1,6 +1,6 @@ /* - * $Id: HttpHeaderTools.cc,v 1.1 2002/10/14 00:18:19 squidadm Exp $ + * $Id: HttpHeaderTools.cc,v 1.1.6.1 2002/10/31 22:57:30 rbcollins Exp $ * * DEBUG: section 66 HTTP Header Tools * AUTHOR: Alex Rousskov @@ -311,6 +311,35 @@ } +/* Parses a quoted-string field (RFC 2616 section 2.2), complains if + * something went wrong, returns non-zero on success. + * start should point at the first ". + * RC TODO: This is too looose. We should honour the BNF and exclude CTL's + */ +int +httpHeaderParseQuotedString (const char *start, String *val) +{ + const char *end, *pos; + stringClean (val); + *val = StringNull; + assert (*start == '"'); + pos = start + 1; + while (1) { + if (!(end = index (pos,'"'))) { + debug (66, 2) ("failed to parse a quoted-string header field near '%s'\n", start); + return 0; + } + /* check for quoted-chars */ + if (*(end - 1) != '\\') { + /* done */ + stringAppend(val, start + 1, end-start-1); + return 1; + } + /* try for the end again */ + pos = end + 1; + } +} + /* * parses a given string then packs compiled headers and compares the result * with the original, reports discrepancies Index: squid3/src/HttpReply.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/HttpReply.cc,v retrieving revision 1.1 retrieving revision 1.1.6.1 diff -u -r1.1 -r1.1.6.1 --- squid3/src/HttpReply.cc 14 Oct 2002 00:18:19 -0000 1.1 +++ squid3/src/HttpReply.cc 31 Oct 2002 22:57:30 -0000 1.1.6.1 @@ -1,6 +1,6 @@ /* - * $Id: HttpReply.cc,v 1.1 2002/10/14 00:18:19 squidadm Exp $ + * $Id: HttpReply.cc,v 1.1.6.1 2002/10/31 22:57:30 rbcollins Exp $ * * DEBUG: section 58 HTTP Reply (Response) * AUTHOR: Alex Rousskov @@ -34,6 +34,7 @@ */ #include "squid.h" +#include "HttpHeader.h" /* local constants */ @@ -358,6 +359,7 @@ else rep->content_type = StringNull; rep->cache_control = httpHeaderGetCc(hdr); + rep->surrogate_control = httpHeaderGetSc(hdr); rep->content_range = httpHeaderGetContRange(hdr); rep->keep_alive = httpMsgIsPersistent(rep->sline.version, &rep->header); /* be sure to set expires after date and cache-control */ @@ -371,6 +373,8 @@ stringClean(&rep->content_type); if (rep->cache_control) httpHdrCcDestroy(rep->cache_control); + if (rep->surrogate_control) + httpHdrScDestroy(rep->surrogate_control); if (rep->content_range) httpHdrContRangeDestroy(rep->content_range); } Index: squid3/src/Makefile.am =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Makefile.am,v retrieving revision 1.4 retrieving revision 1.4.2.1 diff -u -r1.4 -r1.4.2.1 --- squid3/src/Makefile.am 25 Oct 2002 21:45:57 -0000 1.4 +++ squid3/src/Makefile.am 31 Oct 2002 22:57:32 -0000 1.4.2.1 @@ -1,7 +1,7 @@ # # Makefile for the Squid Object Cache server # -# $Id: Makefile.am,v 1.4 2002/10/25 21:45:57 squidadm Exp $ +# $Id: Makefile.am,v 1.4.2.1 2002/10/31 22:57:32 rbcollins Exp $ # # Uncomment and customize the following to suit your needs: # @@ -26,6 +26,12 @@ DELAY_POOL_SOURCE = endif +if USE_ESI + ESI_SOURCE = ESI.cc ESI.h ESIExpression.cc +else + ESI_SOURCE = +endif + if ENABLE_XPROF_STATS XPROF_STATS_SOURCE = ProfStats.cc else @@ -68,8 +74,8 @@ WIN32SOURCE = endif -AM_CFLAGS = -Werror -Wall -AM_CXXFLAGS = -Werror -Wall +AM_CFLAGS = -Werror -Wall -Wpointer-arith -Wwrite-strings -Wmissing-prototypes -Wmissing-declarations -Wcomments +AM_CXXFLAGS = -Werror -Wall -Wpointer-arith -Wwrite-strings -Wmissing-prototypes -Wmissing-declarations -Wcomments SUBDIRS = fs repl auth @@ -108,6 +114,9 @@ dnsserver.cc \ dns_internal.cc \ htcp.cc \ + ESI.cc \ + ESI.h \ + ESIExpression.cc \ leakfinder.cc \ snmp_core.cc \ snmp_agent.cc \ @@ -146,6 +155,7 @@ $(DNSSOURCE) \ enums.h \ errorpage.cc \ + $(ESI_SOURCE) \ ETag.cc \ event.cc \ external_acl.cc \ @@ -164,6 +174,8 @@ HttpStatusLine.cc \ HttpHdrCc.cc \ HttpHdrRange.cc \ + HttpHdrSc.cc \ + HttpHdrScTarget.cc \ HttpHdrContRange.cc \ HttpHeader.cc \ HttpHeader.h \ Index: squid3/src/ProfStats.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/ProfStats.cc,v retrieving revision 1.1 retrieving revision 1.1.6.1 diff -u -r1.1 -r1.1.6.1 --- squid3/src/ProfStats.cc 14 Oct 2002 00:18:19 -0000 1.1 +++ squid3/src/ProfStats.cc 31 Oct 2002 22:57:32 -0000 1.1.6.1 @@ -1,6 +1,6 @@ /* - * $Id: ProfStats.cc,v 1.1 2002/10/14 00:18:19 squidadm Exp $ + * $Id: ProfStats.cc,v 1.1.6.1 2002/10/31 22:57:32 rbcollins Exp $ * * DEBUG: section 81 CPU Profiling Routines * AUTHOR: Andres Kroonmaa @@ -61,6 +61,7 @@ static TimersArray *xprof_stats_avg24hour = NULL; static xprof_stats_node *sortlist[XPROF_LAST + 2]; +static void xprof_summary(StoreEntry * sentry); static void xprof_reset(xprof_stats_data * head) @@ -120,7 +121,7 @@ } static void -xprof_summary_item(StoreEntry * sentry, char *descr, TimersArray * list) +xprof_summary_item(StoreEntry * sentry, char const *descr, TimersArray * list) { int i; xprof_stats_node **hist; Index: squid3/src/cf.data.pre =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/cf.data.pre,v retrieving revision 1.1 retrieving revision 1.1.6.1 diff -u -r1.1 -r1.1.6.1 --- squid3/src/cf.data.pre 14 Oct 2002 00:18:19 -0000 1.1 +++ squid3/src/cf.data.pre 31 Oct 2002 22:57:32 -0000 1.1.6.1 @@ -1,6 +1,6 @@ # -# $Id: cf.data.pre,v 1.1 2002/10/14 00:18:19 squidadm Exp $ +# $Id: cf.data.pre,v 1.1.6.1 2002/10/31 22:57:32 rbcollins Exp $ # # # SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -2573,6 +2573,29 @@ require the Host: header will not be properly cached. DOC_END +NAME: httpd_accel_surrogate_id +IFDEF: ESI +TYPE: string +LOC: Config.Accel.surrogate_id +DEFAULT: none +DOC_START + Surrogates (http://www.esi.org/architecture_spec_1.0.html) + need an identification token to allow control targeting. Because + a farm of surrogates may all perform the same tasks, they may share + an identification token. +DOC_END + +NAME: http_accel_surrogate_remote +IFDEF: ESI +COMMENT: on|off +TYPE: onoff +DEFAULT: off +LOC: Config.onoff.surrogate_is_remote +DOC_START + Remote surrogates (such as those in a CDN) honour Surrogate-Control: no-store-remote. + Set this to on to have squid behave as a remote surrogate. +DOC_END + COMMENT_START MISCELLANEOUS ----------------------------------------------------------------------------- Index: squid3/src/clientStream.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/clientStream.cc,v retrieving revision 1.1 retrieving revision 1.1.6.1 diff -u -r1.1 -r1.1.6.1 --- squid3/src/clientStream.cc 14 Oct 2002 00:18:19 -0000 1.1 +++ squid3/src/clientStream.cc 31 Oct 2002 22:57:32 -0000 1.1.6.1 @@ -1,6 +1,6 @@ /* - * $Id: clientStream.cc,v 1.1 2002/10/14 00:18:19 squidadm Exp $ + * $Id: clientStream.cc,v 1.1.6.1 2002/10/31 22:57:32 rbcollins Exp $ * * DEBUG: section 87 Client-side Stream routines. * AUTHOR: Robert Collins @@ -269,6 +269,7 @@ if (thisObject->node.next || thisObject->node.prev) { dlinkDelete(&thisObject->node, thisObject->head); } + } _clientStreamNode * Index: squid3/src/clientStream.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/clientStream.h,v retrieving revision 1.1 retrieving revision 1.1.6.1 diff -u -r1.1 -r1.1.6.1 --- squid3/src/clientStream.h 14 Oct 2002 00:18:19 -0000 1.1 +++ squid3/src/clientStream.h 31 Oct 2002 22:57:32 -0000 1.1.6.1 @@ -1,6 +1,6 @@ /* - * $Id: clientStream.h,v 1.1 2002/10/14 00:18:19 squidadm Exp $ + * $Id: clientStream.h,v 1.1.6.1 2002/10/31 22:57:32 rbcollins Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -47,11 +47,9 @@ struct _clientStreamNode { -#ifdef __cplusplus public: _clientStreamNode *prev() const; _clientStreamNode *next() const; -#endif dlink_node node; dlink_list *head; /* sucks I know, but hey, the interface is limited */ CSR *readfunc; Index: squid3/src/client_side.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/client_side.cc,v retrieving revision 1.6 retrieving revision 1.6.2.1 diff -u -r1.6 -r1.6.2.1 --- squid3/src/client_side.cc 25 Oct 2002 21:45:57 -0000 1.6 +++ squid3/src/client_side.cc 31 Oct 2002 22:57:32 -0000 1.6.2.1 @@ -1,6 +1,6 @@ /* - * $Id: client_side.cc,v 1.6 2002/10/25 21:45:57 squidadm Exp $ + * $Id: client_side.cc,v 1.6.2.1 2002/10/31 22:57:32 rbcollins Exp $ * * DEBUG: section 33 Client-side Routines * AUTHOR: Duane Wessels @@ -1680,7 +1680,7 @@ callback(buf, -1, cbdata); /* Signal abort to clientReadBody caller */ requestUnlink(request); } - clientReadBodyAbortHandler(NULL, -1, conn); /* Install abort handler */ + clientReadBodyAbortHandler(NULL, -1, conn); /* Install abort handler */ /* clientProcessBody() */ return 1; /* Aborted */ } @@ -1873,7 +1873,8 @@ clientReadSomeData(conn); } -struct _https_port_data { +struct _https_port_data +{ SSL_CTX *sslContext; }; typedef struct _https_port_data https_port_data; Index: squid3/src/client_side_reply.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/client_side_reply.cc,v retrieving revision 1.6 retrieving revision 1.6.2.1 diff -u -r1.6 -r1.6.2.1 --- squid3/src/client_side_reply.cc 26 Oct 2002 21:45:35 -0000 1.6 +++ squid3/src/client_side_reply.cc 31 Oct 2002 22:57:33 -0000 1.6.2.1 @@ -1,6 +1,6 @@ /* - * $Id: client_side_reply.cc,v 1.6 2002/10/26 21:45:35 squidadm Exp $ + * $Id: client_side_reply.cc,v 1.6.2.1 2002/10/31 22:57:33 rbcollins Exp $ * * DEBUG: section 88 Client-side Reply Routines * AUTHOR: Robert Collins (Originally Duane Wessels in client_side.c) @@ -39,6 +39,9 @@ #include "clientStream.h" #include "authenticate.h" +#if ESI +#include "ESI.h" +#endif class clientReplyContext : public StoreClient { public: @@ -150,7 +153,7 @@ { clientReplyContext *context = (clientReplyContext *)data; ErrorState *errstate = - clientBuildError(err, status, uri, addr, failedrequest); + clientBuildError(err, status, uri, addr, failedrequest); if (unparsedrequest) errstate->request_hdrs = xstrdup(unparsedrequest); @@ -1559,6 +1562,7 @@ xmemcpy(buf + context->reqofs, result.data, result.length); body_buf = buf; } + /* We've got the final data to start pushing... */ context->flags.storelogiccomplete = 1; @@ -1601,7 +1605,7 @@ if (result.length == 0) context->flags.complete = 1; /* REMOVE ME: Only useful for two node streams */ - assert(result.offset - context->headers_sz == ((clientStreamNode *) http->client_stream.tail->data)->readBuffer.offset); + assert(result.offset - context->headers_sz == next->readBuffer.offset); tempBuffer.offset = result.offset - context->headers_sz; tempBuffer.length = result.length; tempBuffer.data = buf; @@ -1625,7 +1629,7 @@ httpReplyBodyBuildSize(http->request, rep, &Config.ReplyBodySize); if (clientReplyBodyTooLarge(rep, rep->content_length)) { ErrorState *err = - clientBuildError(ERR_TOO_BIG, HTTP_FORBIDDEN, NULL, + clientBuildError(ERR_TOO_BIG, HTTP_FORBIDDEN, NULL, http->conn ? &http->conn->peer.sin_addr : &no_addr, http->request); clientRemoveStoreReference(context, &context->sc, &http->entry); @@ -1665,6 +1669,15 @@ httpReplyDestroy(rep); return; } +#if ESI + if (http->flags.accel && rep->sline.status != HTTP_FORBIDDEN && + !clientAlwaysAllowResponse(rep->sline.status) && + esiEnableProcessing(rep)) { + debug(88, 2) ("Enabling ESI processing for %s\n", http->uri); + clientStreamInsertHead(&http->client_stream, esiStreamRead, + esiProcessStream, esiStreamDetach, esiStreamStatus, NULL); + } +#endif } else if (size < HTTP_REQBUF_SZ && entry->store_status == STORE_PENDING) { StoreIOBuffer tempBuffer = EMPTYIOBUFFER; /* wait for more to arrive */ @@ -1764,7 +1777,7 @@ * buffers have been set up */ // storeClientCopy(h->sc, e, 0, HTTP_REQBUF_SZ, h->reqbuf, - // clientSendMoreData, context); +// clientSendMoreData, context); /* So, we mark the store logic as complete */ context->flags.storelogiccomplete = 1; /* and get the caller to request a read, from whereever they are */ Index: squid3/src/client_side_request.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/client_side_request.cc,v retrieving revision 1.2 retrieving revision 1.2.2.1 diff -u -r1.2 -r1.2.2.1 --- squid3/src/client_side_request.cc 22 Oct 2002 21:46:41 -0000 1.2 +++ squid3/src/client_side_request.cc 31 Oct 2002 22:57:33 -0000 1.2.2.1 @@ -1,6 +1,6 @@ /* - * $Id: client_side_request.cc,v 1.2 2002/10/22 21:46:41 squidadm Exp $ + * $Id: client_side_request.cc,v 1.2.2.1 2002/10/31 22:57:33 rbcollins Exp $ * * DEBUG: section 85 Client-side Request Routines * AUTHOR: Robert Collins (Originally Duane Wessels in client_side.c) @@ -52,12 +52,13 @@ static const char *const crlf = "\r\n"; -typedef struct _clientRequestContext { +typedef struct _clientRequestContext +{ aclCheck_t *acl_checklist; /* need ptr back so we can unreg if needed */ int redirect_state; clientHttpRequest *http; -} clientRequestContext; - +} +clientRequestContext; CBDATA_TYPE(clientRequestContext); /* Local functions */ @@ -109,8 +110,7 @@ char *tailbuf, size_t taillen) { size_t url_sz; - http_version_t http_ver = - {1, 0}; + http_version_t http_ver = { 1, 0 }; clientHttpRequest *http = cbdataAlloc(clientHttpRequest); request_t *request; StoreIOBuffer tempBuffer = EMPTYIOBUFFER; Index: squid3/src/comm.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/comm.cc,v retrieving revision 1.8 retrieving revision 1.8.2.1 diff -u -r1.8 -r1.8.2.1 --- squid3/src/comm.cc 28 Oct 2002 22:45:37 -0000 1.8 +++ squid3/src/comm.cc 31 Oct 2002 22:57:33 -0000 1.8.2.1 @@ -1,6 +1,6 @@ /* - * $Id: comm.cc,v 1.8 2002/10/28 22:45:37 squidadm Exp $ + * $Id: comm.cc,v 1.8.2.1 2002/10/31 22:57:33 rbcollins Exp $ * * DEBUG: section 5 Socket Functions * AUTHOR: Harvest Derived @@ -151,7 +151,7 @@ typedef struct _CommCallbackData CommCallbackData; struct _fd_debug_t { - char *close_file; + char const *close_file; int close_line; }; typedef struct _fd_debug_t fd_debug_t; @@ -600,7 +600,7 @@ * + accept() poll time is 250ms */ void -fdc_open(int fd, unsigned int type, char *desc) +fdc_open(int fd, unsigned int type, char const *desc) { assert(fdc_table[fd].active == 0); @@ -1320,7 +1320,7 @@ * + call closing handlers */ void -_comm_close(int fd, char *file, int line) +_comm_close(int fd, char const *file, int line) { fde *F = NULL; dlink_node *node; Index: squid3/src/comm.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/comm.h,v retrieving revision 1.4 retrieving revision 1.4.2.1 diff -u -r1.4 -r1.4.2.1 --- squid3/src/comm.h 28 Oct 2002 22:45:37 -0000 1.4 +++ squid3/src/comm.h 31 Oct 2002 22:57:34 -0000 1.4.2.1 @@ -11,7 +11,7 @@ extern int comm_has_pending_read_callback(int fd); extern int comm_has_pending_read(int fd); extern void comm_read_cancel(int fd, IOCB *callback, void *data); -extern void fdc_open(int fd, unsigned int type, char *desc); +extern void fdc_open(int fd, unsigned int type, char const *desc); extern int comm_udp_recvfrom(int fd, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen); extern int comm_udp_recv(int fd, void *buf, size_t len, int flags); Index: squid3/src/enums.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/enums.h,v retrieving revision 1.1 retrieving revision 1.1.6.1 diff -u -r1.1 -r1.1.6.1 --- squid3/src/enums.h 14 Oct 2002 00:18:19 -0000 1.1 +++ squid3/src/enums.h 31 Oct 2002 22:57:34 -0000 1.1.6.1 @@ -1,6 +1,6 @@ /* - * $Id: enums.h,v 1.1 2002/10/14 00:18:19 squidadm Exp $ + * $Id: enums.h,v 1.1.6.1 2002/10/31 22:57:34 rbcollins Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -93,6 +93,7 @@ ERR_ONLY_IF_CACHED_MISS, /* failure to satisfy only-if-cached request */ ERR_TOO_BIG, TCP_RESET, + ERR_ESI, /* Failure to perform ESI processing */ ERR_MAX } err_type; @@ -247,6 +248,8 @@ #if X_ACCELERATOR_VARY HDR_X_ACCELERATOR_VARY, #endif + HDR_SURROGATE_CAPABILITY, + HDR_SURROGATE_CONTROL, HDR_OTHER, HDR_ENUM_END } http_hdr_type; @@ -268,6 +271,15 @@ CC_ENUM_END } http_hdr_cc_type; +typedef enum { + SC_NO_STORE, + SC_NO_STORE_REMOTE, + SC_MAX_AGE, + SC_CONTENT, + SC_OTHER, + SC_ENUM_END +} http_hdr_sc_type; + /* possible types for http header fields */ typedef enum { ftInvalid = HDR_ENUM_END, /* to catch nasty errors with hdr_id<->fld_type clashes */ @@ -278,6 +290,7 @@ ftPCc, ftPContRange, ftPRange, + ftPSc, ftDate_1123_or_ETag } field_type; @@ -612,6 +625,8 @@ MEM_HTTP_HDR_ENTRY, MEM_HTTP_HDR_RANGE, MEM_HTTP_HDR_RANGE_SPEC, + MEM_HTTP_HDR_SC, + MEM_HTTP_HDR_SCTARGET, MEM_HTTP_REPLY, MEM_INTLIST, MEM_IPCACHE_ENTRY, Index: squid3/src/errorpage.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/errorpage.cc,v retrieving revision 1.3 retrieving revision 1.3.2.1 diff -u -r1.3 -r1.3.2.1 --- squid3/src/errorpage.cc 25 Oct 2002 21:45:57 -0000 1.3 +++ squid3/src/errorpage.cc 31 Oct 2002 22:57:34 -0000 1.3.2.1 @@ -1,6 +1,6 @@ /* - * $Id: errorpage.cc,v 1.3 2002/10/25 21:45:57 squidadm Exp $ + * $Id: errorpage.cc,v 1.3.2.1 2002/10/31 22:57:34 rbcollins Exp $ * * DEBUG: section 4 Error Generation * AUTHOR: Duane Wessels @@ -414,6 +414,7 @@ if (err->auth_user_request) authenticateAuthUserRequestUnlock(err->auth_user_request); err->auth_user_request = NULL; + safe_free(err->err_msg); cbdataFree(err); } @@ -512,6 +513,7 @@ * w - cachemgr email address x * W - error data (to be included in the mailto links) * z - dns server error message x + * Z - Preformatted error message x */ static const char * @@ -658,6 +660,12 @@ else p = "[unknown]"; break; + case 'Z': + if (err->err_msg) + p = err->err_msg; + else + p = "[unknown]"; + break; case '%': p = "%"; break; Index: squid3/src/forward.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/forward.cc,v retrieving revision 1.1 retrieving revision 1.1.6.1 diff -u -r1.1 -r1.1.6.1 --- squid3/src/forward.cc 14 Oct 2002 00:18:19 -0000 1.1 +++ squid3/src/forward.cc 31 Oct 2002 22:57:35 -0000 1.1.6.1 @@ -1,6 +1,6 @@ /* - * $Id: forward.cc,v 1.1 2002/10/14 00:18:19 squidadm Exp $ + * $Id: forward.cc,v 1.1.6.1 2002/10/31 22:57:35 rbcollins Exp $ * * DEBUG: section 17 Request Forwarding * AUTHOR: Duane Wessels @@ -341,6 +341,7 @@ ctimeout = fs->_peer->connect_timeout > 0 ? fs->_peer->connect_timeout : Config.Timeout.peer_connect; } else if (fwdState->request->flags.accelerated && + !fwdState->request->flags.internalclient && Config.Accel.single_host && Config.Accel.host) { host = Config.Accel.host; port = Config.Accel.port; Index: squid3/src/http.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/http.cc,v retrieving revision 1.5 retrieving revision 1.5.2.1 diff -u -r1.5 -r1.5.2.1 --- squid3/src/http.cc 21 Oct 2002 21:45:43 -0000 1.5 +++ squid3/src/http.cc 31 Oct 2002 22:57:35 -0000 1.5.2.1 @@ -1,6 +1,6 @@ /* - * $Id: http.cc,v 1.5 2002/10/21 21:45:43 squidadm Exp $ + * $Id: http.cc,v 1.5.2.1 2002/10/31 22:57:35 rbcollins Exp $ * * DEBUG: section 11 Hypertext Transfer Protocol (HTTP) * AUTHOR: Harvest Derived @@ -343,8 +343,7 @@ const char *item; const char *value; int ilen; - static String vstr = - {0, 0, NULL}; + static String vstr = { 0, 0, NULL }; stringClean(&vstr); vary = httpHeaderGetList(&reply->header, HDR_VARY); @@ -396,6 +395,7 @@ char *t = NULL; int room; size_t hdr_len; + int ignore_cc = 0; HttpReply *reply = entry->mem_obj->reply; Ctx ctx; debug(11, 3) ("httpProcessReplyHeader: key '%s'\n", @@ -444,7 +444,8 @@ httpReplyParse(reply, reply_hdr, hdr_len); storeTimestampsSet(entry); /* Check if object is cacheable or not based on reply code */ - debug(11, 3) ("httpProcessReplyHeader: HTTP CODE: %d\n", reply->sline.status); + debug(11, 3) ("httpProcessReplyHeader: HTTP CODE: %d\n", + reply->sline.status); if (neighbors_do_private_keys) httpMaybeRemovePublic(entry, reply->sline.status); @@ -477,7 +478,35 @@ assert(0); break; } - if (reply->cache_control) { +#if ESI + if (request->flags.accelerated && reply->surrogate_control) { + HttpHdrScTarget *sctusable = + httpHdrScGetMergedTarget(reply->surrogate_control, + Config.Accel.surrogate_id); + if (sctusable) { + if (EBIT_TEST(sctusable->mask, SC_NO_STORE) || + (Config.onoff.surrogate_is_remote + && EBIT_TEST(sctusable->mask, SC_NO_STORE_REMOTE))) + httpMakePrivate(entry); + /* The HttpHeader logic cannot tell if the header it's parsing is a reply to an + * accelerated request or not... + * Still, this is an abtraction breach. - RC + */ + if (sctusable->max_age != -1) { + if (sctusable->max_age < sctusable->max_stale) + reply->expires = reply->date + sctusable->max_age; + else + reply->expires = reply->date + sctusable->max_stale; + /* And update the timestamps */ + storeTimestampsSet(entry); + } + /* We ignore cache-control directives as per the Surrogate specification */ + ignore_cc = 1; + httpHdrScTargetDestroy(sctusable); + } + } +#endif + if (!ignore_cc && reply->cache_control) { if (EBIT_TEST(reply->cache_control->mask, CC_PROXY_REVALIDATE)) EBIT_SET(entry->flags, ENTRY_REVALIDATE); else if (EBIT_TEST(reply->cache_control->mask, CC_MUST_REVALIDATE)) @@ -801,7 +830,8 @@ debug(11, 5) ("httpBuildRequestHeader: %s: %s\n", strBuf(e->name), strBuf(e->value)); if (!httpRequestHdrAllowed(e, &strConnection)) { - debug(11, 2) ("'%s' header denied by anonymize_headers configuration\n", + debug(11, + 2) ("'%s' header denied by anonymize_headers configuration\n", strBuf(e->name)); continue; } @@ -874,14 +904,29 @@ /* append Via */ if (Config.onoff.via) { - String strVia = httpHeaderGetList(hdr_in, HDR_VIA); + String strVia; + strVia = httpHeaderGetList(hdr_in, HDR_VIA); snprintf(bbuf, BBUF_SZ, "%d.%d %s", - orig_request->http_ver.major, + orig_request->http_ver.major, orig_request->http_ver.minor, ThisCache); strListAdd(&strVia, bbuf, ','); httpHeaderPutStr(hdr_out, HDR_VIA, strBuf(strVia)); stringClean(&strVia); } + +#if ESI + { + String strSurrogate; + /* Append Surrogate-Capabilities */ + strSurrogate = httpHeaderGetList(hdr_in, HDR_SURROGATE_CAPABILITY); + snprintf(bbuf, BBUF_SZ, "%s=Surrogate/1.0 ESI/1.0", + Config.Accel.surrogate_id); + strListAdd(&strSurrogate, bbuf, ','); + httpHeaderPutStr(hdr_out, HDR_SURROGATE_CAPABILITY, strBuf(strSurrogate)); + stringClean(&strSurrogate); + } +#endif + /* append X-Forwarded-For */ strFwd = httpHeaderGetList(hdr_in, HDR_X_FORWARDED_FOR); if (opt_forwarded_for && orig_request->client_addr.s_addr != no_addr.s_addr) @@ -932,7 +977,8 @@ if (!cc) cc = httpHdrCcCreate(); if (!EBIT_TEST(cc->mask, CC_MAX_AGE)) { - const char *url = entry ? storeUrl(entry) : urlCanonical(orig_request); + const char *url = + entry ? storeUrl(entry) : urlCanonical(orig_request); httpHdrCcSetMaxAge(cc, getMaxAge(url)); if (strLen(request->urlpath)) assert(strstr(url, strBuf(request->urlpath))); @@ -982,6 +1028,7 @@ memBufAppend(mb, crlf, 2); return mb->size - offset; } + /* This will be called when connect completes. Write request. */ static void httpSendRequest(HttpStateData * httpState) @@ -992,7 +1039,8 @@ peer *p = httpState->_peer; CWCB *sendHeaderDone; - debug(11, 5) ("httpSendRequest: FD %d: httpState %p.\n", httpState->fd, httpState); + debug(11, 5) ("httpSendRequest: FD %d: httpState %p.\n", httpState->fd, + httpState); if (httpState->orig_request->body_connection) sendHeaderDone = httpSendRequestEntity; @@ -1012,7 +1060,8 @@ httpState->flags.keepalive = 1; else if (p->stats.n_keepalives_sent < 10) httpState->flags.keepalive = 1; - else if ((double) p->stats.n_keepalives_recv / (double) p->stats.n_keepalives_sent > 0.50) + else if ((double) p->stats.n_keepalives_recv / + (double) p->stats.n_keepalives_sent > 0.50) httpState->flags.keepalive = 1; if (httpState->_peer) if (neighborType(httpState->_peer, httpState->request) == PEER_SIBLING && @@ -1091,8 +1140,7 @@ { HttpStateData *httpState = static_cast(data); aclCheck_t ch; - debug(11, 5) ("httpSendRequestEntityDone: FD %d\n", - fd); + debug(11, 5) ("httpSendRequestEntityDone: FD %d\n", fd); memset(&ch, '\0', sizeof(ch)); ch.request = httpState->request; if (!Config.accessList.brokenPosts) { Index: squid3/src/mem.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/mem.cc,v retrieving revision 1.1 retrieving revision 1.1.6.1 diff -u -r1.1 -r1.1.6.1 --- squid3/src/mem.cc 14 Oct 2002 00:18:19 -0000 1.1 +++ squid3/src/mem.cc 31 Oct 2002 22:57:37 -0000 1.1.6.1 @@ -1,6 +1,6 @@ /* - * $Id: mem.cc,v 1.1 2002/10/14 00:18:19 squidadm Exp $ + * $Id: mem.cc,v 1.1.6.1 2002/10/31 22:57:37 rbcollins Exp $ * * DEBUG: section 13 High Level Memory Pool Management * AUTHOR: Harvest Derived @@ -367,6 +367,8 @@ memDataInit(MEM_HTTP_HDR_CC, "HttpHdrCc", sizeof(HttpHdrCc), 0); memDataInit(MEM_HTTP_HDR_RANGE_SPEC, "HttpHdrRangeSpec", sizeof(HttpHdrRangeSpec), 0); memDataInit(MEM_HTTP_HDR_RANGE, "HttpHdrRange", sizeof(HttpHdrRange), 0); + memDataInit(MEM_HTTP_HDR_SC, "HttpHdrSc", sizeof(HttpHdrSc), 0); + memDataInit(MEM_HTTP_HDR_SCTARGET, "HttpHdrScTarget", sizeof(HttpHdrScTarget), 0); memDataInit(MEM_HTTP_HDR_CONTENT_RANGE, "HttpHdrContRange", sizeof(HttpHdrContRange), 0); memDataInit(MEM_INTLIST, "intlist", sizeof(intlist), 0); memDataInit(MEM_MEMOBJECT, "MemObject", sizeof(MemObject), Index: squid3/src/pinger.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/pinger.cc,v retrieving revision 1.1 retrieving revision 1.1.6.1 diff -u -r1.1 -r1.1.6.1 --- squid3/src/pinger.cc 14 Oct 2002 00:18:19 -0000 1.1 +++ squid3/src/pinger.cc 31 Oct 2002 22:57:38 -0000 1.1.6.1 @@ -1,6 +1,6 @@ /* - * $Id: pinger.cc,v 1.1 2002/10/14 00:18:19 squidadm Exp $ + * $Id: pinger.cc,v 1.1.6.1 2002/10/31 22:57:38 rbcollins Exp $ * * DEBUG: section 42 ICMP Pinger program * AUTHOR: Duane Wessels @@ -118,6 +118,8 @@ static void pingerLog(struct icmphdr *, struct in_addr, int, int); static int ipHops(int ttl); static void pingerSendtoSquid(pingerReplyData * preply); +static void pingerOpen(void); +static void pingerClose(void); void pingerOpen(void) @@ -388,13 +390,16 @@ if (FD_ISSET(0, &R)) if (pingerReadRequest() < 0) { debug(42, 0) ("Pinger exiting.\n"); + pingerClose(); exit(1); } if (FD_ISSET(icmp_sock, &R)) pingerRecv(); if (10 + last_check_time < squid_curtime) { - if (send(1, (char *) &tv, 0, 0) < 0) + if (send(1, (char *) &tv, 0, 0) < 0) { + pingerClose(); exit(1); + } last_check_time = squid_curtime; } } Index: squid3/src/protos.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/protos.h,v retrieving revision 1.4 retrieving revision 1.4.2.1 diff -u -r1.4 -r1.4.2.1 --- squid3/src/protos.h 21 Oct 2002 21:45:43 -0000 1.4 +++ squid3/src/protos.h 31 Oct 2002 22:57:39 -0000 1.4.2.1 @@ -1,6 +1,6 @@ /* - * $Id: protos.h,v 1.4 2002/10/21 21:45:43 squidadm Exp $ + * $Id: protos.h,v 1.4.2.1 2002/10/31 22:57:39 rbcollins Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -163,7 +163,7 @@ SQUIDCEXTERN int commUnsetNonBlocking(int fd); SQUIDCEXTERN void commSetCloseOnExec(int fd); extern int comm_old_accept(int fd, struct sockaddr_in *, struct sockaddr_in *); -extern void _comm_close(int fd, char *file, int line); +extern void _comm_close(int fd, char const *file, int line); #define comm_close(fd) (_comm_close((fd), __FILE__, __LINE__)) SQUIDCEXTERN void comm_reset_close(int fd); #if LINGERING_CLOSE @@ -392,6 +392,32 @@ SQUIDCEXTERN ssize_t httpHdrRangeLowestOffset(const HttpHdrRange * range, ssize_t); SQUIDCEXTERN int httpHdrRangeOffsetLimit(HttpHdrRange *); +/* Http Surrogate Control Header Field */ +extern void httpHdrScStatDumper(StoreEntry * sentry, int idx, double val, double size, int count); +extern void httpHdrScInitModule (void); +extern void httpHdrScCleanModule (void); +extern HttpHdrSc *httpHdrScCreate(void); +extern HttpHdrSc *httpHdrScParseCreate(String const *); +extern void httpHdrScDestroy(HttpHdrSc * sc); +extern HttpHdrSc *httpHdrScDup(const HttpHdrSc * sc); +extern void httpHdrScPackInto(const HttpHdrSc * sc, Packer * p); +extern void httpHdrScJoinWith(HttpHdrSc *, const HttpHdrSc *); +extern void httpHdrScSetMaxAge(HttpHdrSc *, char const *, int); +extern void httpHdrScUpdateStats(const HttpHdrSc *, StatHist *); +extern HttpHdrScTarget * httpHdrScFindTarget (HttpHdrSc *sc, const char *target); +extern HttpHdrScTarget * httpHdrScGetMergedTarget (HttpHdrSc *sc, const char *ourtarget); + +/* Http Surrogate control header field 'targets' */ +extern HttpHdrScTarget * httpHdrScTargetCreate (const char *); +extern void httpHdrScTargetDestroy(HttpHdrScTarget *); +extern HttpHdrScTarget *httpHdrScTargetDup(const HttpHdrScTarget *); +extern void httpHdrScTargetPackInto(const HttpHdrScTarget *, Packer *); +extern void httpHdrScTargetSetMaxAge(HttpHdrScTarget *, int); +extern void httpHdrScTargetUpdateStats(const HttpHdrScTarget *, StatHist *); +extern void httpHdrScTargetJoinWith(HttpHdrScTarget *, const HttpHdrScTarget *); +extern void httpHdrScTargetMergeWith(HttpHdrScTarget *, const HttpHdrScTarget *); +extern void httpHdrScTargetStatDumper(StoreEntry * sentry, int idx, double val, double size, int count); + /* Http Content Range Header Field */ SQUIDCEXTERN HttpHdrContRange *httpHdrContRangeCreate(void); Index: squid3/src/structs.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/structs.h,v retrieving revision 1.4 retrieving revision 1.4.2.1 diff -u -r1.4 -r1.4.2.1 --- squid3/src/structs.h 25 Oct 2002 21:45:57 -0000 1.4 +++ squid3/src/structs.h 31 Oct 2002 22:57:45 -0000 1.4.2.1 @@ -1,6 +1,6 @@ /* - * $Id: structs.h,v 1.4 2002/10/25 21:45:57 squidadm Exp $ + * $Id: structs.h,v 1.4.2.1 2002/10/31 22:57:45 rbcollins Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -400,6 +400,9 @@ struct { int single_host; char *host; +#if ESI + char *surrogate_id; +#endif u_short port; } Accel; char *appendDomain; @@ -498,6 +501,9 @@ int ie_refresh; int vary_ignore_expire; int pipeline_prefetch; +#if ESI + int surrogate_is_remote; +#endif int check_hostnames; int via; int emailErrData; @@ -839,6 +845,21 @@ int len; /* length when packed, not counting terminating '\0' */ }; +/* http surogate control header field */ +struct _HttpHdrScTarget { + dlink_node node; + int mask; + int max_age; + int max_stale; + String content; + String target; +}; + +struct _HttpHdrSc { + dlink_list targets; +}; + +/* Sync changes here with HttpReply.c */ struct _HttpReply { /* unsupported, writable, may disappear/change in the future */ int hdr_sz; /* sums _stored_ status-line, headers, and */ @@ -850,6 +871,7 @@ time_t expires; String content_type; HttpHdrCc *cache_control; + HttpHdrSc *surrogate_control; HttpHdrContRange *content_range; short int keep_alive; @@ -1563,6 +1585,7 @@ char *reply; } ftp; char *request_hdrs; + char *err_msg; /* Preformatted error message from the cache */ }; /* @@ -1703,9 +1726,11 @@ StatHist hdrUCountDistr; StatHist fieldTypeDistr; StatHist ccTypeDistr; + StatHist scTypeDistr; int parsedCount; int ccParsedCount; + int scParsedCount; int destroyedCount; int busyDestroyedCount; };