Merge in IMS refactoring.
Keywords:
Patches applied:
* robertc@squid-cache.org--squid/squid--bug-564--3.0--patch-5
And ESI was broken too.
* robertc@squid-cache.org--squid/squid--bug-564--3.0--patch-4
Fix introduced memleak.
* robertc@squid-cache.org--squid/squid--bug-564--3.0--patch-3
Start tackling the refresh logic.
* robertc@squid-cache.org--squid/squid--bug-564--3.0--patch-2
More steps to fixing bug #564
* robertc@squid-cache.org--squid/squid--bug-564--3.0--patch-1
Towards addressing bug 564
* robertc@squid-cache.org--squid/squid--bug-564--3.0--base-0
tag of robertc@squid-cache.org--squid/squid--HEAD--3.0--patch-125
/*
- * $Id: RefCount.h,v 1.4 2003/03/10 04:56:20 robertc Exp $
+ * $Id: RefCount.h,v 1.5 2003/03/15 04:17:38 robertc Exp $
*
* DEBUG: section xx Refcount allocator
* AUTHOR: Robert Collins
return p.p_ == p_;
}
+ bool operator != (const RefCount &p) const
+ {
+ return p.p_ != p_;
+ }
+
private:
void dereference()
{
/*
- * $Id: ESI.cc,v 1.2 2003/03/11 08:24:42 robertc Exp $
+ * $Id: ESI.cc,v 1.3 2003/03/15 04:17:38 robertc Exp $
*
* DEBUG: section 86 ESI processing
* AUTHOR: Robert Collins
*
*/
-typedef struct _esiStreamContext esiStreamContext;
+class ESIStreamContext;
+
+typedef class ESIStreamContext esiStreamContext;
/* TODO: split this out into separate files ? */
/* Parsing: quick and dirty. ESI files are not valid XML, so a generic
MemPool * esiComment::pool = NULL;
+class esiInclude;
+typedef RefCount<esiInclude> esiIncludePtr;
+
+class ESIStreamContext : public RefCountable
+{
+
+public:
+ typedef RefCount<ESIStreamContext> Pointer;
+ void *operator new(size_t);
+ void operator delete(void *);
+ void deleteSelf() const;
+ ESIStreamContext();
+ ~ESIStreamContext();
+ void freeResources();
+ int finished;
+ esiIncludePtr include;
+ ESISegment::Pointer localbuffer;
+ ESISegment::Pointer buffer;
+
+private:
+ CBDATA_CLASS(ESIStreamContext);
+};
+
+CBDATA_CLASS_INIT (ESIStreamContext);
+
#include "ESILiteral.h"
MemPool *esiLiteral::pool = NULL;
/* esiInclude */
-struct esiInclude : public ESIElement
+class esiInclude : public ESIElement
{
+
+public:
void *operator new (size_t byteCount);
void operator delete (void *address);
void deleteSelf() const;
esiProcessResult_t process (int dovars);
Pointer makeCacheable() const;
Pointer makeUsable(esiTreeParentPtr, esiVarState &) const;
- void subRequestDone (esiStreamContext *, bool);
+ void subRequestDone (ESIStreamContext::Pointer, bool);
struct
{
}
flags;
- esiStreamContext *src;
- esiStreamContext *alt;
+ ESIStreamContext::Pointer src;
+ ESIStreamContext::Pointer alt;
ESISegment::Pointer srccontent;
ESISegment::Pointer altcontent;
esiVarState *varState;
char *srcurl, *alturl;
- void fail(esiStreamContext *);
+ void fail(ESIStreamContext::Pointer);
void finish();
private:
static MemPool *Pool;
- static void Start (esiStreamContext *, char const *, esiVarState *);
+ static void Start (ESIStreamContext::Pointer, char const *, esiVarState *);
esiTreeParentPtr parent;
void start();
bool started;
return reading_;
}
-typedef RefCount<esiInclude> esiIncludePtr;
-
-struct _esiStreamContext
-{
-
-public:
- void *operator new(size_t);
- _esiStreamContext();
- int finished;
- esiIncludePtr include;
- ESISegment::Pointer localbuffer;
- ESISegment::Pointer buffer;
-};
-
-CBDATA_TYPE (esiStreamContext);
-_esiStreamContext::_esiStreamContext() : finished(false), include (NULL), localbuffer (new ESISegment), buffer (NULL)
+ESIStreamContext::ESIStreamContext() : finished(false), include (NULL), localbuffer (new ESISegment), buffer (NULL)
{}
/* Local functions */
/* ESIContext */
static ESIContext *ESIContextNew(HttpReply *, clientStreamNode *, clientHttpRequest *);
/* esiStreamContext */
-static FREE esiStreamContextFree;
static esiStreamContext *esiStreamContextNew (esiIncludePtr);
/* other */
esiStreamRead (clientStreamNode *thisNode, clientHttpRequest *http)
{
clientStreamNode *next;
- ESIContext *context;
/* Test preconditions */
assert (thisNode != NULL);
assert (cbdataReferenceValid (thisNode));
/* we are not in the chain until ESI is detected on a data callback */
- assert (thisNode->data != NULL);
assert (thisNode->node.prev != NULL);
assert (thisNode->node.next != NULL);
- context = (ESIContext *)cbdataReference (thisNode->data);
+ ESIContext::Pointer context = dynamic_cast<ESIContext *>(thisNode->data.getRaw());
+ assert (context.getRaw() != NULL);
if (context->flags.passthrough) {
/* passthru mode - read into supplied buffers */
next = thisNode->next();
clientStreamRead (thisNode, http, next->readBuffer);
- cbdataReferenceDone (context);
return;
}
case ESIContext::ESI_KICK_SENT:
case ESIContext::ESI_KICK_INPROGRESS:
- cbdataReferenceDone (context);
return;
case ESIContext::ESI_KICK_PENDING:
* flow
*/
debug (86,5) ("esiStreamRead: Waiting for async resume of esi processing\n");
- cbdataReferenceDone (context);
return;
}
debug (86,5)("all processing complete, but outbound data still buffered\n");
assert (!context->flags.clientwantsdata);
/* client MUST be processing the last reply */
- cbdataReferenceDone (context);
return;
}
/* We've finished processing, and there is no more data buffered */
debug (86,5)("Telling recipient EOF on READ\n");
clientStreamCallback (thisNode, http, NULL, tempBuffer);
- cbdataReferenceDone (context);
return;
}
- if (context->reading()) {
- cbdataReferenceDone (context);
+ if (context->reading())
return;
- }
/* no data that is ready to send, and still reading? well, lets get some */
/* secure a buffer */
context->startRead();
clientStreamRead (thisNode, http, tempBuffer);
}
-
- cbdataReferenceDone (context);
}
clientStream_status_t
assert (thisNode != NULL);
assert (cbdataReferenceValid (thisNode));
/* we are not in the chain until ESI is detected on a data callback */
- assert (thisNode->data != NULL);
assert (thisNode->node.prev != NULL);
assert (thisNode->node.next != NULL);
- ESIContext *context = (ESIContext *)cbdataReference (thisNode->data);
+ ESIContext::Pointer context = dynamic_cast<ESIContext *>(thisNode->data.getRaw());
+ assert (context.getRaw() != NULL);
- if (context->flags.passthrough) {
- cbdataReferenceDone (context);
+ if (context->flags.passthrough)
return clientStreamStatus (thisNode, http);
- }
if (context->flags.oktosend && context->flags.finished &&
!(context->outbound.getRaw() && context->outbound_offset < context->outbound->len)) {
- cbdataReferenceDone (context);
debug (86,5) ("Telling recipient EOF on STATUS\n");
return STREAM_UNPLANNED_COMPLETE; /* we don't know lengths in advance */
}
/* ?? RC: we can't be aborted / fail ? */
- cbdataReferenceDone (context);
-
return STREAM_NONE;
}
esiStreamDetach (clientStreamNode *thisNode, clientHttpRequest *http)
{
/* if we have pending callbacks, tell them we're done. */
- ESIContext *context;
/* test preconditions */
assert (thisNode != NULL);
assert (cbdataReferenceValid (thisNode));
- context = ( ESIContext *)cbdataReference(thisNode->data);
+ ESIContext::Pointer context = dynamic_cast<ESIContext *>(thisNode->data.getRaw());
+ assert (context.getRaw() != NULL);
/* detach from the stream */
clientStreamDetach (thisNode,http);
/* if we have pending callbacks (from subincludes), tell them we're done. */
context->parserState.stack[0] = NULL;
/* allow refcount logic to trigger */
context->cbdataLocker = NULL;
- cbdataReferenceDone (context);
}
/* Process incoming data for ESI tags */
void
esiProcessStream (clientStreamNode *thisNode, clientHttpRequest *http, HttpReply *rep, StoreIOBuffer recievedData)
{
- ESIContext *context;
/* test preconditions */
assert (thisNode != NULL);
/* ESI TODO: handle thisNode rather than asserting - it should only ever
* if data is NULL thisNode is the first entrance. If rep is also NULL,
* something is wrong.
* */
- assert (thisNode->data != NULL || rep);
+ assert (thisNode->data.getRaw() != NULL || rep);
assert (thisNode->node.next != NULL);
- if (!thisNode->data)
+ if (!thisNode->data.getRaw())
/* setup ESI context from reply headers */
thisNode->data = ESIContextNew(rep, thisNode, http);
- context = (ESIContext *)cbdataReference(thisNode->data);
+ ESIContext::Pointer context = dynamic_cast<ESIContext *>(thisNode->data.getRaw());
+
+ assert (context.getRaw() != NULL);
context->finishRead();
* has been detected to prevent ESI processing the error body
*/
if (context->flags.passthrough) {
- cbdataReferenceDone(context);
clientStreamCallback (thisNode, http, rep, recievedData);
return;
}
- debug (86, 3)("esiProcessStream: Processing thisNode %p context %p offset %d length %u\n",thisNode, context, (int) recievedData.offset, (unsigned int)recievedData.length);
+ debug (86, 3)("esiProcessStream: Processing thisNode %p context %p offset %d length %u\n",thisNode, context.getRaw(), (int) recievedData.offset, (unsigned int)recievedData.length);
/* once we finish the template, we *cannot* return here */
assert (!context->flags.finishedtemplate);
if (rep == NULL && recievedData.data == NULL && recievedData.length == 0 && !context->flags.finishedtemplate) {
/* TODO: get stream status to test the entry for aborts */
/* else flush the esi processor */
- debug (86,5)("esiProcess: %p Finished reading upstream data\n", context);
+ debug (86,5)("esiProcess: %p Finished reading upstream data\n", context.getRaw());
/* This is correct */
context->flags.finishedtemplate = 1;
}
/* thisNode can not happen - processing can't fail until we have data,
* and when we come here we have sent data to the client
*/
- cbdataReferenceDone (context);
return;
case ESIContext::ESI_KICK_SENT:
case ESIContext::ESI_KICK_INPROGRESS:
- cbdataReferenceDone (context);
return;
case ESIContext::ESI_KICK_PENDING:
tempBuffer.data = &context->incoming->buf[context->incoming->len];
context->startRead();
clientStreamRead (thisNode, http, tempBuffer);
- cbdataReferenceDone (context);
return;
}
debug (86,3)("esiProcessStream: no data to send, no data to read, awaiting a callback\n");
- cbdataReferenceDone(context);
}
ESIContext::~ESIContext()
void
esiBufferRecipient (clientStreamNode *node, clientHttpRequest *http, HttpReply *rep, StoreIOBuffer recievedData)
{
- esiStreamContext *esiStream;
/* Test preconditions */
assert (node != NULL);
/* ESI TODO: handle thisNode rather than asserting
* itself shouldn't happen, so it stays as an
* assert for now. */
assert (cbdataReferenceValid (node));
- assert (node->data != NULL);
assert (node->node.next == NULL);
assert (http->conn == NULL);
- esiStream = (esiStreamContext *)cbdataReference (node->data);
+ esiStreamContext::Pointer esiStream = dynamic_cast<esiStreamContext *>(node->data.getRaw());
+ assert (esiStream.getRaw() != NULL);
/* If segments become more flexible, ignore thisNode */
assert (recievedData.length <= sizeof(esiStream->localbuffer->buf));
assert (!esiStream->finished);
rep = NULL;
esiStream->include->fail (esiStream);
esiStream->finished = 1;
- cbdataReferenceDone (esiStream);
httpRequestFree (http);
return;
}
debug (86,5)("Finished reading upstream data in subrequest\n");
esiStream->include->subRequestDone (esiStream, true);
esiStream->finished = 1;
- cbdataReferenceDone (esiStream);
httpRequestFree (http);
return;
}
* we call */
if (clientHttpRequestStatus(-1, http)) {
/* TODO: Does thisNode if block leak htto ? */
- esiStreamContext *temp = esiStream;
- esiStream->include->fail (esiStream);
+ /* XXX when reviewing ESI this is the first place to look */
+ node->data = NULL;
esiStream->finished = 1;
- cbdataReferenceDone (esiStream);
- cbdataFree (temp); /* free the request */
+ esiStream->include->fail (esiStream);
return;
};
debug (86,3)("ESI subrequest finished OK\n");
esiStream->include->subRequestDone (esiStream, true);
esiStream->finished = 1;
- cbdataReferenceDone (esiStream);
httpRequestFree (http);
return;
debug (86,1)("ESI subrequest failed transfer\n");
esiStream->include->fail (esiStream);
esiStream->finished = 1;
- cbdataReferenceDone (esiStream);
httpRequestFree (http);
return;
fatal ("Hit unreachable code in esiBufferRecipient\n");
}
- cbdataReferenceDone (esiStream);
}
/* esiStream functions */
+ESIStreamContext::~ESIStreamContext()
+{
+ assert (this);
+ freeResources();
+}
+
void
-esiStreamContextFree (void *data)
+ESIStreamContext::freeResources()
{
- esiStreamContext *esiStream = (esiStreamContext *)data;
- assert (esiStream);
- esiStream->buffer = NULL;
- esiStream->localbuffer = NULL;
- esiStream->include = NULL;
- debug (86,5)("Freeing stream context\n");
+ debug (86,5)("Freeing stream context resources.\n");
+ buffer = NULL;
+ localbuffer = NULL;
+ include = NULL;
}
void *
-_esiStreamContext::operator new (size_t count)
+ESIStreamContext::operator new(size_t byteCount)
{
- CBDATA_INIT_TYPE_FREECB(esiStreamContext, esiStreamContextFree);
- return cbdataAlloc(esiStreamContext);
+ assert (byteCount == sizeof (ESIStreamContext));
+ CBDATA_INIT_TYPE(ESIStreamContext);
+ ESIStreamContext *result = cbdataAlloc(ESIStreamContext);
+ /* Mark result as being owned - we want the refcounter to do the
+ * delete call
+ */
+ cbdataReference(result);
+ return result;
+}
+
+void
+ESIStreamContext::operator delete (void *address)
+{
+ ESIStreamContext *t = static_cast<ESIStreamContext *>(address);
+ cbdataFree(t);
+ /* And allow the memory to be freed */
+ cbdataReferenceDone (address);
+}
+
+void
+ESIStreamContext::deleteSelf() const
+{
+ delete this;
}
esiStreamContext *
esiStreamContextNew (esiIncludePtr include)
{
- esiStreamContext *rv = new _esiStreamContext;
+ esiStreamContext *rv = new ESIStreamContext;
rv->include = include;
return rv;
}
}
void
-esiInclude::Start (esiStreamContext *stream, char const *url, esiVarState *vars)
+esiInclude::Start (ESIStreamContext::Pointer stream, char const *url, esiVarState *vars)
{
HttpHeader tempheaders;
- if (!stream)
+ if (!stream.getRaw())
return;
httpHeaderInit (&tempheaders, hoRequest);
debug (86,5)("esiIncludeStart: Starting subrequest with url '%s'\n", tempUrl);
- if (clientBeginRequest(METHOD_GET, tempUrl, esiBufferRecipient, esiBufferDetach, stream, &tempheaders, stream->localbuffer->buf, HTTP_REQBUF_SZ)) {
+ if (clientBeginRequest(METHOD_GET, tempUrl, esiBufferRecipient, esiBufferDetach, stream.getRaw(), &tempheaders, stream->localbuffer->buf, HTTP_REQBUF_SZ)) {
debug (86,0) ("starting new ESI subrequest failed\n");
}
/* Start a request for thisNode url */
debug (86,5)("esiIncludeNew: Requesting source '%s'\n",attr[i+1]);
/* TODO: don't assert on thisNode, ignore the duplicate */
- assert (src == NULL);
+ assert (src.getRaw() == NULL);
src = esiStreamContextNew (this);
- assert (src != NULL);
+ assert (src.getRaw() != NULL);
srcurl = xstrdup ( attr[i+1]);
} else if (!strcmp(attr[i],"alt")) {
/* Start a secondary request for thisNode url */
* for the src to fail
*/
debug (86,5)("esiIncludeNew: Requesting alternate '%s'\n",attr[i+1]);
- assert (alt == NULL); /* TODO: FIXME */
+ assert (alt.getRaw() == NULL); /* TODO: FIXME */
alt = esiStreamContextNew (this);
- assert (alt != NULL);
+ assert (alt.getRaw() != NULL);
alturl = xstrdup (attr[i+1]);
} else if (!strcmp(attr[i],"onerror")) {
if (!strcmp(attr[i+1], "continue")) {
started = true;
- if (src) {
+ if (src.getRaw()) {
Start (src, srcurl, varState);
Start (alt, alturl, varState);
} else {
- if (alt)
- cbdataFree (alt);
+ alt = NULL;
debug (86,1)("esiIncludeNew: esi:include with no src attributes\n");
}
void
-esiInclude::fail (esiStreamContext *stream)
+esiInclude::fail (ESIStreamContext::Pointer stream)
{
subRequestDone (stream, false);
}
}
void
-esiInclude::subRequestDone (esiStreamContext *stream, bool success)
+esiInclude::subRequestDone (ESIStreamContext::Pointer stream, bool success)
{
assert (this);
/* Fail if there is no alt being retrieved */
debug (86,3)("esiIncludeSubRequestDone: Src FAILED\n");
- if (!(alt || altcontent.getRaw())) {
+ if (!(alt.getRaw() || altcontent.getRaw())) {
debug (86,3)("esiIncludeSubRequestDone: Include FAILED - No ALT\n");
flags.failed = 1;
} else if (altcontent.getRaw()) {
ESISegment::ListTransfer (stream->localbuffer, altcontent);
/* we're done! */
- if (!(src || srccontent.getRaw())) {
+ if (!(src.getRaw() || srccontent.getRaw())) {
/* src already failed, kick ESI processor */
debug (86,3)("esiIncludeSubRequestDone: Include PASSED - SRC already failed.\n");
flags.finished = 1;
}
} else {
- if (!(src || srccontent.getRaw())) {
+ if (!(src.getRaw() || srccontent.getRaw())) {
debug (86,3)("esiIncludeSubRequestDone: ALT FAILED, Include FAILED - SRC already failed\n");
/* src already failed */
flags.failed = 1;
if (flags.finished || flags.failed) {
/* Kick ESI Processor */
- debug (86,5)("esiInclude %p SubRequest %p completed, kicking processor , status %s\n", this, stream, flags.finished ? "OK" : "FAILED");
+ debug (86,5)("esiInclude %p SubRequest %p completed, kicking processor , status %s\n", this, stream.getRaw(), flags.finished ? "OK" : "FAILED");
assert (parent.getRaw());
if (!flags.failed) {
/*
- * $Id: ESIContext.h,v 1.1 2003/03/10 04:56:35 robertc Exp $
+ * $Id: ESIContext.h,v 1.2 2003/03/15 04:17:38 robertc Exp $
*
*
* SQUID Web Proxy Cache http://www.squid-cache.org/
#define SQUID_ESICONTEXT_H
#include "ESIElement.h"
+#include "clientStream.h"
class esiVarState;
-class clientStreamNode;
-
class ClientHttpRequest;
#include "ESIParser.h"
{
public:
+ typedef RefCount<ESIContext> Pointer;
void *operator new (size_t byteCount);
void operator delete (void *address);
void deleteSelf() const;
/*
- * $Id: HttpReply.cc,v 1.58 2003/03/10 04:56:36 robertc Exp $
+ * $Id: HttpReply.cc,v 1.59 2003/03/15 04:17:38 robertc Exp $
*
* DEBUG: section 58 HTTP Reply (Response)
* AUTHOR: Alex Rousskov
{
memPoolFree (Pool, address);
}
+
+bool
+HttpReply::isBodyTooLarge(ssize_t clen) const
+{
+ if (0 == maxBodySize)
+ return 0; /* disabled */
+
+ if (clen < 0)
+ return 0; /* unknown */
+
+ return (unsigned int)clen > maxBodySize;
+}
#
# Makefile for the Squid Object Cache server
#
-# $Id: Makefile.am,v 1.67 2003/03/13 07:39:53 hno Exp $
+# $Id: Makefile.am,v 1.68 2003/03/15 04:17:39 robertc Exp $
#
# Uncomment and customize the following to suit your needs:
#
if USE_DNSSERVER
DNSSOURCE = dns.cc
-DNSSERVER = dnsserver
-else
-DNSSOURCE = dns_internal.cc
-DNSSERVER =
-endif
-
-if USE_SNMP
-SNMPSOURCE = snmp_core.cc snmp_agent.cc
-else
-SNMPSOURCE =
-endif
-
-if USE_DELAY_POOLS
-DELAY_POOL_SOURCE = \
- CommonPool.h \
- CompositePoolNode.h \
- delay_pools.cc \
- DelayId.cc \
- DelayId.h \
- DelayIdComposite.h \
- DelayBucket.cc \
- DelayBucket.h \
- DelayConfig.cc \
- DelayConfig.h \
- DelayPool.cc \
- DelayPool.h \
- DelayPools.h \
- DelaySpec.cc \
- DelaySpec.h \
- DelayUser.cc \
- DelayUser.h \
- DelayVector.cc \
- DelayVector.h \
- NullDelayId.cc \
- NullDelayId.h
-else
-DELAY_POOL_SOURCE =
-endif
-
-ESI_ALL_SOURCE = \
- ElementList.h \
- ESI.cc \
- ESI.h \
- ESIAttempt.h \
- ESIContext.cc \
- ESIContext.h \
- ESICustomParser.cc \
- ESICustomParser.h \
- ESIElement.h \
- ESIExcept.h \
- ESIExpatParser.cc \
- ESIExpatParser.h \
- ESIExpression.cc \
- ESILiteral.h \
- ESIParser.cc \
- ESIParser.h \
- ESISegment.cc \
- ESISegment.h \
- ESISequence.cc \
- ESISequence.h
-if USE_ESI
- ESI_SOURCE = $(ESI_ALL_SOURCE)
-else
- ESI_SOURCE =
-endif
-
-if ENABLE_XPROF_STATS
-XPROF_STATS_SOURCE = ProfStats.cc
-else
-XPROF_STATS_SOURCE =
-endif
-
-if ENABLE_HTCP
-HTCPSOURCE = htcp.cc
-endif
-
-if MAKE_LEAKFINDER
-LEAKFINDERSOURCE = leakfinder.cc
-else
-LEAKFINDERSOURCE =
-endif
-
-if ENABLE_UNLINKD
-UNLINKDSOURCE = unlinkd.cc
-UNLINKD = unlinkd
-else
-UNLINKDSOURCE =
-UNLINKD =
-endif
-
-if ENABLE_PINGER
-PINGER = pinger
-else
-PINGER =
-endif
-
-if ENABLE_SSL
-SSLSOURCE = \
- ACLCertificateData.cc \
- ACLCertificateData.h \
- ACLCertificate.cc \
- ACLCertificate.h \
- ssl_support.cc
-else
-SSLSOURCE =
-endif
-
-if ENABLE_WIN32SPECIFIC
-WIN32SOURCE = win32.cc
-else
-WIN32SOURCE =
-endif
-
-if ENABLE_IDENT
-IDENTSOURCE = ACLIdent.cc ACLIdent.h ident.cc
-else
-IDENTSOURCE =
-endif
-
-if ENABLE_ARP_ACL
-ARP_ACL_SOURCE = ACLARP.cc ACLARP.h
-else
-ARP_ACL_SOURCE =
-endif
-
-AM_CFLAGS = @SQUID_CFLAGS@
-AM_CXXFLAGS = @SQUID_CXXFLAGS@
-
-SUBDIRS = fs repl auth
-
-INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/include -I$(top_srcdir)/include -I$(top_srcdir)/lib/libTrie/include
-
-EXTRA_PROGRAMS = \
- unlinkd \
- pinger \
- dnsserver \
- recv-announce \
- ufsdump
-
-noinst_PROGRAMS = \
- cf_gen
-
-sbin_PROGRAMS = \
- squid
-
-bin_PROGRAMS = \
- squidclient
-
-
-libexec_PROGRAMS = \
- $(PINGER) \
- $(DNSSERVER) \
- $(UNLINKD) \
- cachemgr$(CGIEXT)
-
-cf_gen_SOURCES = cf_gen.cc defines.h
-nodist_cf_gen_HEADER = cf_gen_defines.h
-cf_gen.$(OBJEXT): cf_gen_defines.h
-squidclient_SOURCES = client.cc
-cachemgr__CGIEXT__SOURCES = cachemgr.cc
-
-EXTRA_squid_SOURCES = \
- $(ARP_ACL_SOURCE) \
- $(DELAY_POOL_SOURCE) \
- dns.cc \
- dnsserver.cc \
- dns_internal.cc \
- htcp.cc \
- $(ESI_ALL_SOURCE) \
- ProfStats.cc \
- leakfinder.cc \
- snmp_core.cc \
- snmp_agent.cc \
- unlinkd.cc \
- ssl_support.cc \
- ssl_support.h \
- win32.cc
-
-squid_ACLSOURCES = \
- $(ARP_ACL_SOURCE) \
- ACLASN.cc \
- ACLASN.h \
- ACLDestinationASN.h \
- ACLSourceASN.h \
- ACLBrowser.cc \
- ACLBrowser.h \
- ACLData.h \
- ACLDestinationDomain.cc \
- ACLDestinationDomain.h \
- ACLDestinationIP.cc \
- ACLDestinationIP.h \
- ACLDomainData.h \
- ACLDomainData.cc \
- ACLIntRange.cc \
- ACLIntRange.h \
- ACLIP.cc \
- ACLIP.h \
- ACLMaxConnection.cc \
- ACLMaxConnection.h \
- ACLMaxUserIP.cc \
- ACLMaxUserIP.h \
- ACLMethod.cc \
- ACLMethod.h \
- ACLMethodData.cc \
- ACLMethodData.h \
- ACLMyIP.cc \
- ACLMyIP.h \
- ACLMyPort.cc \
- ACLMyPort.h \
- ACLProtocol.cc \
- ACLProtocol.h \
- ACLProtocolData.cc \
- ACLProtocolData.h \
- ACLProxyAuth.cc \
- ACLProxyAuth.h \
- ACLReferer.cc \
- ACLReferer.h \
- ACLRegexData.cc \
- ACLRegexData.h \
- ACLReplyHeaderStrategy.h \
- ACLReplyMIMEType.cc \
- ACLReplyMIMEType.h \
- ACLRequestHeaderStrategy.h \
- ACLRequestMIMEType.cc \
- ACLRequestMIMEType.h \
- ACLSourceDomain.cc \
- ACLSourceDomain.h \
- ACLSourceIP.cc \
- ACLSourceIP.h \
- ACLStrategised.cc \
- ACLStrategised.h \
- ACLStrategy.h \
- ACLStringData.cc \
- ACLStringData.h \
- ACLTime.cc \
- ACLTime.h \
- ACLTimeData.cc \
- ACLTimeData.h \
- ACLUrl.cc \
- ACLUrl.h \
- ACLUrlPath.cc \
- ACLUrlPath.h \
- ACLUrlPort.cc \
- ACLUrlPort.h \
- ACLUserData.cc \
- ACLUserData.h
-
-squid_SOURCES = \
- access_log.cc \
- acl.cc \
- ACL.h \
- ACLChecklist.cc \
- ACLChecklist.h \
- $(squid_ACLSOURCES) \
- asn.cc \
- authenticate.cc \
- authenticate.h \
- cache_cf.cc \
- CacheDigest.cc \
- cache_manager.cc \
- carp.cc \
- cbdata.cc \
- client_db.cc \
- client_side.cc \
- client_side.h \
- client_side_reply.cc \
- client_side_request.cc \
- client_side_request.h \
- clientStream.cc \
- clientStream.h \
- comm.cc \
- comm.h \
- comm_select.cc \
- comm_poll.cc \
- comm_kqueue.cc \
- comm_epoll.cc \
- CommRead.h \
- ConfigParser.h \
- ConnectionDetail.h \
- debug.cc \
- Debug.h \
- defines.h \
- $(DELAY_POOL_SOURCE) \
- disk.cc \
- $(DNSSOURCE) \
- enums.h \
- errorpage.cc \
- $(ESI_SOURCE) \
- ETag.cc \
- event.cc \
- external_acl.cc \
- ExternalACL.h \
- fd.cc \
- fde.cc \
- fde.h \
- filemap.cc \
- forward.cc \
- fqdncache.cc \
- ftp.cc \
- Generic.h \
- globals.h \
- gopher.cc \
- helper.cc \
- $(HTCPSOURCE) \
- http.cc \
- http.h \
- HttpStatusLine.cc \
- HttpHdrCc.cc \
- HttpHdrRange.cc \
- HttpHdrSc.cc \
- HttpHdrScTarget.cc \
- HttpHdrContRange.cc \
- HttpHdrContRange.h \
- HttpHeader.cc \
- HttpHeader.h \
- HttpHeaderRange.h \
- HttpHeaderTools.cc \
- HttpBody.cc \
- HttpMsg.cc \
- HttpReply.cc \
- HttpReply.h \
- HttpRequest.cc \
- HttpRequest.h \
- icmp.cc \
- ICP.h \
- icp_v2.cc \
- icp_v3.cc \
- $(IDENTSOURCE) \
- int.cc \
- internal.cc \
- ipc.cc \
- ipcache.cc \
- IPInterception.cc \
- IPInterception.h \
- $(LEAKFINDERSOURCE) \
- logfile.cc \
- main.cc \
- mem.cc \
- mem_node.cc \
- mem_node.h \
- Mem.h \
- MemBuf.cc \
- MemObject.cc \
- MemObject.h \
- mime.cc \
- multicast.cc \
- neighbors.cc \
- net_db.cc \
- Packer.cc \
- $(XPROF_STATS_SOURCE) \
- pconn.cc \
- peer_digest.cc \
- peer_select.cc \
- protos.h \
- redirect.cc \
- referer.cc \
- refresh.cc \
- send-announce.cc \
- $(SNMPSOURCE) \
- squid.h \
- tunnel.cc \
- $(SSLSOURCE) \
- stat.cc \
- StatHist.cc \
- String.cc \
- stmem.cc \
- stmem.h \
- store.cc \
- Store.h \
- store_io.cc \
- StoreIOBuffer.h \
- StoreIOState.cc \
- StoreIOState.h \
- store_client.cc \
- StoreClient.h \
- store_digest.cc \
- store_dir.cc \
- store_key_md5.cc \
- store_log.cc \
- store_rebuild.cc \
- store_swapin.cc \
- store_swapmeta.cc \
- store_swapout.cc \
- StoreMeta.cc \
- StoreMeta.h \
- StoreMetaMD5.cc \
- StoreMetaMD5.h \
- StoreMetaSTD.cc \
- StoreMetaSTD.h \
- StoreMetaUnpacker.cc \
- StoreMetaUnpacker.h \
- StoreMetaURL.cc \
- StoreMetaURL.h \
- StoreMetaVary.cc \
- StoreMetaVary.h \
- structs.h \
- SwapDir.cc \
- SwapDir.h \
- tools.cc \
- typedefs.h \
- ufscommon.cc \
- ufscommon.h \
- $(UNLINKDSOURCE) \
- url.cc \
- urn.cc \
- useragent.cc \
- wais.cc \
- wccp.cc \
- whois.cc \
- $(WIN32SOURCE)
-
-noinst_HEADERS = MemBuf.cci \
- MemBuf.h \
- Store.cci \
- String.cci \
- SquidString.h \
- ufscommon.cci
-
-nodist_squid_SOURCES = \
- repl_modules.cc \
- auth_modules.cc \
- store_modules.cc \
- cf_parser.h \
- globals.cc \
- string_arrays.c
-
-squid_LDADD = \
- -L../lib \
- @XTRA_OBJS@ \
- @REPL_OBJS@ \
- @STORE_OBJS@ \
- @AUTH_OBJS@ \
- @CRYPTLIB@ \
- @REGEXLIB@ \
- @SNMPLIB@ \
- @LIB_MALLOC@ \
- @SSLLIB@ \
- -lmiscutil \
- @XTRA_LIBS@ \
- @EPOLL_LIBS@
-squid_DEPENDENCIES = $(top_builddir)/lib/libmiscutil.a @STORE_OBJS@
-
-unlinkd_SOURCES = unlinkd.cc
-unlinkd_CXXFLAGS = -DUNLINK_DAEMON
-
-pinger_SOURCES = \
- pinger.cc \
- debug.cc
-
-dnsserver_SOURCES = dnsserver.cc
-recv_announce_SOURCES = recv-announce.cc
-
-ufsdump_SOURCES = debug.cc \
- int.cc \
- ufsdump.cc \
- store.cc \
- StoreMeta.cc \
- StoreMeta.h \
- StoreMetaMD5.cc \
- StoreMetaMD5.h \
- StoreMetaSTD.cc \
- StoreMetaSTD.h \
- StoreMetaUnpacker.cc \
- StoreMetaUnpacker.h \
- StoreMetaURL.cc \
- StoreMetaURL.h \
- StoreMetaVary.cc \
- StoreMetaVary.h \
- access_log.cc \
- acl.cc \
- ACLChecklist.cc \
- $(squid_ACLSOURCES) \
- ACLChecklist.cc \
- asn.cc \
- authenticate.cc \
- cache_cf.cc \
- CacheDigest.cc \
- cache_manager.cc \
- carp.cc \
- cbdata.cc \
- client_db.cc \
- client_side.cc \
- client_side_reply.cc \
- client_side_request.cc \
- client_side_request.h \
- clientStream.cc \
- clientStream.h \
- comm.cc \
- comm.h \
- comm_select.cc \
- comm_poll.cc \
- comm_kqueue.cc \
- comm_epoll.cc \
- defines.h \
- $(DELAY_POOL_SOURCE) \
- disk.cc \
- $(DNSSOURCE) \
- enums.h \
- errorpage.cc \
- $(ESI_SOURCE) \
- ETag.cc \
- event.cc \
- external_acl.cc \
- fd.cc \
- fde.cc \
- fde.h \
- filemap.cc \
- forward.cc \
- fqdncache.cc \
- ftp.cc \
- gopher.cc \
- helper.cc \
- $(HTCPSOURCE) \
- http.cc \
- HttpStatusLine.cc \
- HttpHdrCc.cc \
- HttpHdrRange.cc \
- HttpHdrSc.cc \
- HttpHdrScTarget.cc \
- HttpHdrContRange.cc \
- HttpHeader.cc \
- HttpHeaderTools.cc \
- HttpBody.cc \
- HttpMsg.cc \
- HttpReply.cc \
- HttpRequest.cc \
- HttpRequest.h \
- icmp.cc \
- icp_v2.cc \
- icp_v3.cc \
- $(IDENTSOURCE) \
- internal.cc \
- ipc.cc \
- ipcache.cc \
- IPInterception.cc \
- IPInterception.h \
- $(LEAKFINDERSOURCE) \
- logfile.cc \
- mem.cc \
- mem_node.cc \
- mem_node.h \
- Mem.h \
- MemBuf.cc \
- MemObject.cc \
- MemObject.h \
- mime.cc \
- multicast.cc \
- neighbors.cc \
- net_db.cc \
- Packer.cc \
- $(XPROF_STATS_SOURCE) \
- pconn.cc \
- peer_digest.cc \
- peer_select.cc \
- protos.h \
- redirect.cc \
- referer.cc \
- refresh.cc \
- send-announce.cc \
- $(SNMPSOURCE) \
- squid.h \
- $(SSLSOURCE) \
- tunnel.cc \
- stat.cc \
- StatHist.cc \
- String.cc \
- stmem.cc \
- store_io.cc \
- StoreIOBuffer.h \
- StoreIOState.cc \
- store_client.cc \
- StoreClient.h \
- store_digest.cc \
- store_dir.cc \
- store_key_md5.cc \
- store_log.cc \
- store_rebuild.cc \
- store_swapin.cc \
- store_swapmeta.cc \
- store_swapout.cc \
- structs.h \
- SwapDir.cc \
- tools.cc \
- typedefs.h \
- ufscommon.cc \
- ufscommon.h \
- $(UNLINKDSOURCE) \
- url.cc \
- urn.cc \
- useragent.cc \
- wais.cc \
- wccp.cc \
- whois.cc \
- $(WIN32SOURCE)
-ufsdump_LDADD = \
- -L../lib \
- @XTRA_OBJS@ \
- @REPL_OBJS@ \
- @STORE_OBJS@ \
- @AUTH_OBJS@ \
- @CRYPTLIB@ \
- @REGEXLIB@ \
- @SNMPLIB@ \
- @LIB_MALLOC@ \
- @SSLLIB@ \
- -lmiscutil \
- @XTRA_LIBS@ \
- @EPOLL_LIBS@
-ufsdump_DEPENDENCIES = $(top_builddir)/lib/libmiscutil.a
-nodist_ufsdump_SOURCES = \
- repl_modules.cc \
- auth_modules.cc \
- store_modules.cc \
- cf_parser.h \
- globals.cc \
- string_arrays.c
-
-nodist_pinger_SOURCES = \
- globals.cc
-
-BUILT_SOURCES = \
- cf_gen_defines.h \
- cf_parser.h \
- globals.cc \
- string_arrays.c \
- repl_modules.cc \
- auth_modules.cc \
- store_modules.cc
-
-sysconf_DATA = \
- squid.conf.default \
- mime.conf.default
-
-data_DATA = \
- mib.txt
-
-LDADD = -L../lib -lmiscutil @XTRA_LIBS@ @EPOLL_LIBS@
-
-EXTRA_DIST = \
- cf_gen_defines \
- cf.data.pre \
- mk-globals-c.pl \
- mk-string-arrays.pl \
- auth_modules.sh \
- store_modules.sh \
- repl_modules.sh \
- mib.txt \
- mime.conf.default
-
-DEFAULT_PREFIX = $(prefix)
-DEFAULT_CONFIG_FILE = $(sysconfdir)/squid.conf
-DEFAULT_MIME_TABLE = $(sysconfdir)/mime.conf
-DEFAULT_DNSSERVER = $(libexecdir)/dnsserver$(EXEEXT)
-DEFAULT_LOG_PREFIX = $(localstatedir)/logs
-DEFAULT_CACHE_LOG = $(DEFAULT_LOG_PREFIX)/cache.log
-DEFAULT_ACCESS_LOG = $(DEFAULT_LOG_PREFIX)/access.log
-DEFAULT_STORE_LOG = $(DEFAULT_LOG_PREFIX)/store.log
-DEFAULT_PID_FILE = $(DEFAULT_LOG_PREFIX)/squid.pid
-DEFAULT_SWAP_DIR = $(localstatedir)/cache
-DEFAULT_PINGER = $(libexecdir)/pinger$(EXEEXT)
-DEFAULT_UNLINKD = $(libexecdir)/unlinkd$(EXEEXT)
-DEFAULT_DISKD = $(libexecdir)/diskd$(EXEEXT)
-DEFAULT_ICON_DIR = $(datadir)/icons
-DEFAULT_ERROR_DIR = $(datadir)/errors/@ERR_DEFAULT_LANGUAGE@
-DEFAULT_MIB_PATH = $(datadir)/mib.txt
-DEFAULT_HOSTS = @OPT_DEFAULT_HOSTS@
-
-DEFS = @DEFS@ -DDEFAULT_CONFIG_FILE=\"$(DEFAULT_CONFIG_FILE)\"
-
-$(OBJS): $(top_srcdir)/include/version.h ../include/autoconf.h
-
-snmp_core.o snmp_agent.o: ../snmplib/libsnmp.a $(top_srcdir)/include/cache_snmp.h
-
-globals.cc: globals.h mk-globals-c.pl
- $(PERL) $(srcdir)/mk-globals-c.pl < $(srcdir)/globals.h > $@
-
-string_arrays.c: enums.h mk-string-arrays.pl
- $(PERL) $(srcdir)/mk-string-arrays.pl < $(srcdir)/enums.h > $@
-
-cache_diff: cache_diff.o debug.o globals.o store_key_md5.o
- $(CC) -o $@ $(LDFLAGS) $@.o debug.o globals.o store_key_md5.o $(STD_APP_LIBS)
-
-test_cache_digest: test_cache_digest.o CacheDigest.o debug.o globals.o store_key_md5.o
- $(CC) -o $@ $(LDFLAGS) $@.o CacheDigest.o debug.o globals.o store_key_md5.o $(STD_APP_LIBS)
+ DNSSERVER = dnsserver
+ else
+ DNSSOURCE = dns_internal.cc
+ DNSSERVER =
+ endif
+
+ if USE_SNMP
+ SNMPSOURCE = snmp_core.cc snmp_agent.cc
+ else
+ SNMPSOURCE =
+ endif
+
+ if USE_DELAY_POOLS
+ DELAY_POOL_SOURCE = \
+ CommonPool.h \
+ CompositePoolNode.h \
+ delay_pools.cc \
+ DelayId.cc \
+ DelayId.h \
+ DelayIdComposite.h \
+ DelayBucket.cc \
+ DelayBucket.h \
+ DelayConfig.cc \
+ DelayConfig.h \
+ DelayPool.cc \
+ DelayPool.h \
+ DelayPools.h \
+ DelaySpec.cc \
+ DelaySpec.h \
+ DelayUser.cc \
+ DelayUser.h \
+ DelayVector.cc \
+ DelayVector.h \
+ NullDelayId.cc \
+ NullDelayId.h
+ else
+ DELAY_POOL_SOURCE =
+ endif
+
+ ESI_ALL_SOURCE = \
+ ElementList.h \
+ ESI.cc \
+ ESI.h \
+ ESIAttempt.h \
+ ESIContext.cc \
+ ESIContext.h \
+ ESICustomParser.cc \
+ ESICustomParser.h \
+ ESIElement.h \
+ ESIExcept.h \
+ ESIExpatParser.cc \
+ ESIExpatParser.h \
+ ESIExpression.cc \
+ ESILiteral.h \
+ ESIParser.cc \
+ ESIParser.h \
+ ESISegment.cc \
+ ESISegment.h \
+ ESISequence.cc \
+ ESISequence.h
+ if USE_ESI
+ ESI_SOURCE = $(ESI_ALL_SOURCE)
+ else
+ ESI_SOURCE =
+ endif
+
+ if ENABLE_XPROF_STATS
+ XPROF_STATS_SOURCE = ProfStats.cc
+ else
+ XPROF_STATS_SOURCE =
+ endif
+
+ if ENABLE_HTCP
+ HTCPSOURCE = htcp.cc
+ endif
+
+ if MAKE_LEAKFINDER
+ LEAKFINDERSOURCE = leakfinder.cc
+ else
+ LEAKFINDERSOURCE =
+ endif
+
+ if ENABLE_UNLINKD
+ UNLINKDSOURCE = unlinkd.cc
+ UNLINKD = unlinkd
+ else
+ UNLINKDSOURCE =
+ UNLINKD =
+ endif
+
+ if ENABLE_PINGER
+ PINGER = pinger
+ else
+ PINGER =
+ endif
+
+ if ENABLE_SSL
+ SSLSOURCE = \
+ ACLCertificateData.cc \
+ ACLCertificateData.h \
+ ACLCertificate.cc \
+ ACLCertificate.h \
+ ssl_support.cc
+ else
+ SSLSOURCE =
+ endif
+
+ if ENABLE_WIN32SPECIFIC
+ WIN32SOURCE = win32.cc
+ else
+ WIN32SOURCE =
+ endif
+
+ if ENABLE_IDENT
+ IDENTSOURCE = ACLIdent.cc ACLIdent.h ident.cc
+ else
+ IDENTSOURCE =
+ endif
+
+ if ENABLE_ARP_ACL
+ ARP_ACL_SOURCE = ACLARP.cc ACLARP.h
+ else
+ ARP_ACL_SOURCE =
+ endif
+
+ AM_CFLAGS = @SQUID_CFLAGS@
+ AM_CXXFLAGS = @SQUID_CXXFLAGS@
+
+ SUBDIRS = fs repl auth
+
+ INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/include -I$(top_srcdir)/include -I$(top_srcdir)/lib/libTrie/include
+
+ EXTRA_PROGRAMS = \
+ unlinkd \
+ pinger \
+ dnsserver \
+ recv-announce \
+ ufsdump
+
+ noinst_PROGRAMS = \
+ cf_gen
+
+ sbin_PROGRAMS = \
+ squid
+
+ bin_PROGRAMS = \
+ squidclient
+
+
+ libexec_PROGRAMS = \
+ $(PINGER) \
+ $(DNSSERVER) \
+ $(UNLINKD) \
+ cachemgr$(CGIEXT)
+
+ cf_gen_SOURCES = cf_gen.cc defines.h
+ nodist_cf_gen_HEADER = cf_gen_defines.h
+ cf_gen.$(OBJEXT): cf_gen_defines.h
+ squidclient_SOURCES = client.cc
+ cachemgr__CGIEXT__SOURCES = cachemgr.cc
+
+ EXTRA_squid_SOURCES = \
+ $(ARP_ACL_SOURCE) \
+ $(DELAY_POOL_SOURCE) \
+ dns.cc \
+ dnsserver.cc \
+ dns_internal.cc \
+ htcp.cc \
+ $(ESI_ALL_SOURCE) \
+ ProfStats.cc \
+ leakfinder.cc \
+ snmp_core.cc \
+ snmp_agent.cc \
+ unlinkd.cc \
+ ssl_support.cc \
+ ssl_support.h \
+ win32.cc
+
+ squid_ACLSOURCES = \
+ $(ARP_ACL_SOURCE) \
+ ACLASN.cc \
+ ACLASN.h \
+ ACLDestinationASN.h \
+ ACLSourceASN.h \
+ ACLBrowser.cc \
+ ACLBrowser.h \
+ ACLData.h \
+ ACLDestinationDomain.cc \
+ ACLDestinationDomain.h \
+ ACLDestinationIP.cc \
+ ACLDestinationIP.h \
+ ACLDomainData.h \
+ ACLDomainData.cc \
+ ACLIntRange.cc \
+ ACLIntRange.h \
+ ACLIP.cc \
+ ACLIP.h \
+ ACLMaxConnection.cc \
+ ACLMaxConnection.h \
+ ACLMaxUserIP.cc \
+ ACLMaxUserIP.h \
+ ACLMethod.cc \
+ ACLMethod.h \
+ ACLMethodData.cc \
+ ACLMethodData.h \
+ ACLMyIP.cc \
+ ACLMyIP.h \
+ ACLMyPort.cc \
+ ACLMyPort.h \
+ ACLProtocol.cc \
+ ACLProtocol.h \
+ ACLProtocolData.cc \
+ ACLProtocolData.h \
+ ACLProxyAuth.cc \
+ ACLProxyAuth.h \
+ ACLReferer.cc \
+ ACLReferer.h \
+ ACLRegexData.cc \
+ ACLRegexData.h \
+ ACLReplyHeaderStrategy.h \
+ ACLReplyMIMEType.cc \
+ ACLReplyMIMEType.h \
+ ACLRequestHeaderStrategy.h \
+ ACLRequestMIMEType.cc \
+ ACLRequestMIMEType.h \
+ ACLSourceDomain.cc \
+ ACLSourceDomain.h \
+ ACLSourceIP.cc \
+ ACLSourceIP.h \
+ ACLStrategised.cc \
+ ACLStrategised.h \
+ ACLStrategy.h \
+ ACLStringData.cc \
+ ACLStringData.h \
+ ACLTime.cc \
+ ACLTime.h \
+ ACLTimeData.cc \
+ ACLTimeData.h \
+ ACLUrl.cc \
+ ACLUrl.h \
+ ACLUrlPath.cc \
+ ACLUrlPath.h \
+ ACLUrlPort.cc \
+ ACLUrlPort.h \
+ ACLUserData.cc \
+ ACLUserData.h
+
+ squid_SOURCES = \
+ access_log.cc \
+ acl.cc \
+ ACL.h \
+ ACLChecklist.cc \
+ ACLChecklist.h \
+ $(squid_ACLSOURCES) \
+ asn.cc \
+ authenticate.cc \
+ authenticate.h \
+ cache_cf.cc \
+ CacheDigest.cc \
+ cache_manager.cc \
+ carp.cc \
+ cbdata.cc \
+ client_db.cc \
+ client_side.cc \
+ client_side.h \
+ client_side_reply.cc \
+ client_side_request.cc \
+ client_side_request.h \
+ clientStream.cc \
+ clientStream.h \
+ comm.cc \
+ comm.h \
+ comm_select.cc \
+ comm_poll.cc \
+ comm_kqueue.cc \
+ comm_epoll.cc \
+ CommRead.h \
+ ConfigParser.h \
+ ConnectionDetail.h \
+ debug.cc \
+ Debug.h \
+ defines.h \
+ $(DELAY_POOL_SOURCE) \
+ disk.cc \
+ $(DNSSOURCE) \
+ enums.h \
+ errorpage.cc \
+ $(ESI_SOURCE) \
+ ETag.cc \
+ event.cc \
+ external_acl.cc \
+ ExternalACL.h \
+ fd.cc \
+ fde.cc \
+ fde.h \
+ filemap.cc \
+ forward.cc \
+ fqdncache.cc \
+ ftp.cc \
+ Generic.h \
+ globals.h \
+ gopher.cc \
+ helper.cc \
+ $(HTCPSOURCE) \
+ http.cc \
+ http.h \
+ HttpStatusLine.cc \
+ HttpHdrCc.cc \
+ HttpHdrRange.cc \
+ HttpHdrSc.cc \
+ HttpHdrScTarget.cc \
+ HttpHdrContRange.cc \
+ HttpHdrContRange.h \
+ HttpHeader.cc \
+ HttpHeader.h \
+ HttpHeaderRange.h \
+ HttpHeaderTools.cc \
+ HttpBody.cc \
+ HttpMsg.cc \
+ HttpReply.cc \
+ HttpReply.h \
+ HttpRequest.cc \
+ HttpRequest.h \
+ icmp.cc \
+ ICP.h \
+ icp_v2.cc \
+ icp_v3.cc \
+ $(IDENTSOURCE) \
+ int.cc \
+ internal.cc \
+ ipc.cc \
+ ipcache.cc \
+ IPInterception.cc \
+ IPInterception.h \
+ $(LEAKFINDERSOURCE) \
+ logfile.cc \
+ main.cc \
+ mem.cc \
+ mem_node.cc \
+ mem_node.h \
+ Mem.h \
+ MemBuf.cc \
+ MemObject.cc \
+ MemObject.h \
+ mime.cc \
+ multicast.cc \
+ neighbors.cc \
+ net_db.cc \
+ Packer.cc \
+ $(XPROF_STATS_SOURCE) \
+ pconn.cc \
+ peer_digest.cc \
+ peer_select.cc \
+ protos.h \
+ redirect.cc \
+ referer.cc \
+ refresh.cc \
+ send-announce.cc \
+ $(SNMPSOURCE) \
+ squid.h \
+ tunnel.cc \
+ $(SSLSOURCE) \
+ stat.cc \
+ StatHist.cc \
+ String.cc \
+ stmem.cc \
+ stmem.h \
+ store.cc \
+ Store.h \
+ store_io.cc \
+ StoreIOBuffer.h \
+ StoreIOState.cc \
+ StoreIOState.h \
+ store_client.cc \
+ StoreClient.h \
+ store_digest.cc \
+ store_dir.cc \
+ store_key_md5.cc \
+ store_log.cc \
+ store_rebuild.cc \
+ store_swapin.cc \
+ store_swapmeta.cc \
+ store_swapout.cc \
+ StoreMeta.cc \
+ StoreMeta.h \
+ StoreMetaMD5.cc \
+ StoreMetaMD5.h \
+ StoreMetaSTD.cc \
+ StoreMetaSTD.h \
+ StoreMetaUnpacker.cc \
+ StoreMetaUnpacker.h \
+ StoreMetaURL.cc \
+ StoreMetaURL.h \
+ StoreMetaVary.cc \
+ StoreMetaVary.h \
+ structs.h \
+ SwapDir.cc \
+ SwapDir.h \
+ tools.cc \
+ typedefs.h \
+ ufscommon.cc \
+ ufscommon.h \
+ $(UNLINKDSOURCE) \
+ url.cc \
+ urn.cc \
+ useragent.cc \
+ wais.cc \
+ wccp.cc \
+ whois.cc \
+ $(WIN32SOURCE)
+
+ noinst_HEADERS = MemBuf.cci \
+ MemBuf.h \
+ Store.cci \
+ String.cci \
+ SquidString.h \
+ ufscommon.cci
+
+ nodist_squid_SOURCES = \
+ repl_modules.cc \
+ auth_modules.cc \
+ store_modules.cc \
+ cf_parser.h \
+ globals.cc \
+ string_arrays.c
+
+ squid_LDADD = \
+ -L../lib \
+ @XTRA_OBJS@ \
+ @REPL_OBJS@ \
+ @STORE_OBJS@ \
+ @AUTH_OBJS@ \
+ @CRYPTLIB@ \
+ @REGEXLIB@ \
+ @SNMPLIB@ \
+ @LIB_MALLOC@ \
+ @SSLLIB@ \
+ -lmiscutil \
+ @XTRA_LIBS@ \
+ @EPOLL_LIBS@
+ squid_DEPENDENCIES = $(top_builddir)/lib/libmiscutil.a @STORE_OBJS@
+
+ unlinkd_SOURCES = unlinkd.cc
+ unlinkd_CXXFLAGS = -DUNLINK_DAEMON
+
+ pinger_SOURCES = \
+ pinger.cc \
+ debug.cc
+
+ dnsserver_SOURCES = dnsserver.cc
+ recv_announce_SOURCES = recv-announce.cc
+
+ ufsdump_SOURCES = debug.cc \
+ int.cc \
+ ufsdump.cc \
+ store.cc \
+ StoreMeta.cc \
+ StoreMeta.h \
+ StoreMetaMD5.cc \
+ StoreMetaMD5.h \
+ StoreMetaSTD.cc \
+ StoreMetaSTD.h \
+ StoreMetaUnpacker.cc \
+ StoreMetaUnpacker.h \
+ StoreMetaURL.cc \
+ StoreMetaURL.h \
+ StoreMetaVary.cc \
+ StoreMetaVary.h \
+ access_log.cc \
+ acl.cc \
+ ACLChecklist.cc \
+ $(squid_ACLSOURCES) \
+ asn.cc \
+ authenticate.cc \
+ cache_cf.cc \
+ CacheDigest.cc \
+ cache_manager.cc \
+ carp.cc \
+ cbdata.cc \
+ client_db.cc \
+ client_side.cc \
+ client_side_reply.cc \
+ client_side_request.cc \
+ client_side_request.h \
+ clientStream.cc \
+ clientStream.h \
+ comm.cc \
+ comm.h \
+ comm_select.cc \
+ comm_poll.cc \
+ comm_kqueue.cc \
+ comm_epoll.cc \
+ defines.h \
+ $(DELAY_POOL_SOURCE) \
+ disk.cc \
+ $(DNSSOURCE) \
+ enums.h \
+ errorpage.cc \
+ $(ESI_SOURCE) \
+ ETag.cc \
+ event.cc \
+ external_acl.cc \
+ fd.cc \
+ fde.cc \
+ fde.h \
+ filemap.cc \
+ forward.cc \
+ fqdncache.cc \
+ ftp.cc \
+ gopher.cc \
+ helper.cc \
+ $(HTCPSOURCE) \
+ http.cc \
+ HttpStatusLine.cc \
+ HttpHdrCc.cc \
+ HttpHdrRange.cc \
+ HttpHdrSc.cc \
+ HttpHdrScTarget.cc \
+ HttpHdrContRange.cc \
+ HttpHeader.cc \
+ HttpHeaderTools.cc \
+ HttpBody.cc \
+ HttpMsg.cc \
+ HttpReply.cc \
+ HttpRequest.cc \
+ HttpRequest.h \
+ icmp.cc \
+ icp_v2.cc \
+ icp_v3.cc \
+ $(IDENTSOURCE) \
+ internal.cc \
+ ipc.cc \
+ ipcache.cc \
+ IPInterception.cc \
+ IPInterception.h \
+ $(LEAKFINDERSOURCE) \
+ logfile.cc \
+ mem.cc \
+ mem_node.cc \
+ mem_node.h \
+ Mem.h \
+ MemBuf.cc \
+ MemObject.cc \
+ MemObject.h \
+ mime.cc \
+ multicast.cc \
+ neighbors.cc \
+ net_db.cc \
+ Packer.cc \
+ $(XPROF_STATS_SOURCE) \
+ pconn.cc \
+ peer_digest.cc \
+ peer_select.cc \
+ protos.h \
+ redirect.cc \
+ referer.cc \
+ refresh.cc \
+ send-announce.cc \
+ $(SNMPSOURCE) \
+ squid.h \
+ $(SSLSOURCE) \
+ tunnel.cc \
+ stat.cc \
+ StatHist.cc \
+ String.cc \
+ stmem.cc \
+ store_io.cc \
+ StoreIOBuffer.h \
+ StoreIOState.cc \
+ store_client.cc \
+ StoreClient.h \
+ store_digest.cc \
+ store_dir.cc \
+ store_key_md5.cc \
+ store_log.cc \
+ store_rebuild.cc \
+ store_swapin.cc \
+ store_swapmeta.cc \
+ store_swapout.cc \
+ structs.h \
+ SwapDir.cc \
+ tools.cc \
+ typedefs.h \
+ ufscommon.cc \
+ ufscommon.h \
+ $(UNLINKDSOURCE) \
+ url.cc \
+ urn.cc \
+ useragent.cc \
+ wais.cc \
+ wccp.cc \
+ whois.cc \
+ $(WIN32SOURCE)
+ ufsdump_LDADD = \
+ -L../lib \
+ @XTRA_OBJS@ \
+ @REPL_OBJS@ \
+ @STORE_OBJS@ \
+ @AUTH_OBJS@ \
+ @CRYPTLIB@ \
+ @REGEXLIB@ \
+ @SNMPLIB@ \
+ @LIB_MALLOC@ \
+ @SSLLIB@ \
+ -lmiscutil \
+ @XTRA_LIBS@ \
+ @EPOLL_LIBS@
+ ufsdump_DEPENDENCIES = $(top_builddir)/lib/libmiscutil.a
+ nodist_ufsdump_SOURCES = \
+ repl_modules.cc \
+ auth_modules.cc \
+ store_modules.cc \
+ cf_parser.h \
+ globals.cc \
+ string_arrays.c
+
+ nodist_pinger_SOURCES = \
+ globals.cc
+
+ BUILT_SOURCES = \
+ cf_gen_defines.h \
+ cf_parser.h \
+ globals.cc \
+ string_arrays.c \
+ repl_modules.cc \
+ auth_modules.cc \
+ store_modules.cc
+
+ sysconf_DATA = \
+ squid.conf.default \
+ mime.conf.default
+
+ data_DATA = \
+ mib.txt
+
+ LDADD = -L../lib -lmiscutil @XTRA_LIBS@ @EPOLL_LIBS@
+
+ EXTRA_DIST = \
+ cf_gen_defines \
+ cf.data.pre \
+ mk-globals-c.pl \
+ mk-string-arrays.pl \
+ auth_modules.sh \
+ store_modules.sh \
+ repl_modules.sh \
+ mib.txt \
+ mime.conf.default
+
+ DEFAULT_PREFIX = $(prefix)
+ DEFAULT_CONFIG_FILE = $(sysconfdir)/squid.conf
+ DEFAULT_MIME_TABLE = $(sysconfdir)/mime.conf
+ DEFAULT_DNSSERVER = $(libexecdir)/dnsserver$(EXEEXT)
+ DEFAULT_LOG_PREFIX = $(localstatedir)/logs
+ DEFAULT_CACHE_LOG = $(DEFAULT_LOG_PREFIX)/cache.log
+ DEFAULT_ACCESS_LOG = $(DEFAULT_LOG_PREFIX)/access.log
+ DEFAULT_STORE_LOG = $(DEFAULT_LOG_PREFIX)/store.log
+ DEFAULT_PID_FILE = $(DEFAULT_LOG_PREFIX)/squid.pid
+ DEFAULT_SWAP_DIR = $(localstatedir)/cache
+ DEFAULT_PINGER = $(libexecdir)/pinger$(EXEEXT)
+ DEFAULT_UNLINKD = $(libexecdir)/unlinkd$(EXEEXT)
+ DEFAULT_DISKD = $(libexecdir)/diskd$(EXEEXT)
+ DEFAULT_ICON_DIR = $(datadir)/icons
+ DEFAULT_ERROR_DIR = $(datadir)/errors/@ERR_DEFAULT_LANGUAGE@
+ DEFAULT_MIB_PATH = $(datadir)/mib.txt
+ DEFAULT_HOSTS = @OPT_DEFAULT_HOSTS@
+
+ DEFS = @DEFS@ -DDEFAULT_CONFIG_FILE=\"$(DEFAULT_CONFIG_FILE)\"
+
+ $(OBJS): $(top_srcdir)/include/version.h ../include/autoconf.h
+
+ snmp_core.o snmp_agent.o: ../snmplib/libsnmp.a $(top_srcdir)/include/cache_snmp.h
+
+ globals.cc: globals.h mk-globals-c.pl
+ $(PERL) $(srcdir)/mk-globals-c.pl < $(srcdir)/globals.h > $@
+
+ string_arrays.c: enums.h mk-string-arrays.pl
+ $(PERL) $(srcdir)/mk-string-arrays.pl < $(srcdir)/enums.h > $@
+
+ cache_diff: cache_diff.o debug.o globals.o store_key_md5.o
+ $(CC) -o $@ $(LDFLAGS) $@.o debug.o globals.o store_key_md5.o $(STD_APP_LIBS)
+
+ test_cache_digest: test_cache_digest.o CacheDigest.o debug.o globals.o store_key_md5.o
+ $(CC) -o $@ $(LDFLAGS) $@.o CacheDigest.o debug.o globals.o store_key_md5.o $(STD_APP_LIBS)
## If autodependency works well this is not needed anymore
-cache_cf.o: cf_parser.h
+ cache_cf.o: cf_parser.h
-squid.conf.default: cf_parser.h
- $(SHELL) -c "test -f squid.conf.default || ./cf_gen cf.data"
+ squid.conf.default: cf_parser.h
+ $(SHELL) -c "test -f squid.conf.default || ./cf_gen cf.data"
-cf_parser.h: cf.data cf_gen$(EXEEXT)
- ./cf_gen cf.data
+ cf_parser.h: cf.data cf_gen$(EXEEXT)
+ ./cf_gen cf.data
-cf_gen_defines.h: $(srcdir)/cf_gen_defines $(srcdir)/cf.data.pre
- awk -f $(srcdir)/cf_gen_defines <$(srcdir)/cf.data.pre >cf_gen_defines.h
+ cf_gen_defines.h: $(srcdir)/cf_gen_defines $(srcdir)/cf.data.pre
+ awk -f $(srcdir)/cf_gen_defines <$(srcdir)/cf.data.pre >cf_gen_defines.h
## FIXME: generate a sed command file from configure. Then this doesn't
-## depend on the Makefile.
-cf.data: cf.data.pre Makefile
- sed "\
- s%@DEFAULT_MIME_TABLE@%$(DEFAULT_MIME_TABLE)%g;\
- s%@DEFAULT_DNSSERVER@%$(DEFAULT_DNSSERVER)%g;\
- s%@DEFAULT_UNLINKD@%$(DEFAULT_UNLINKD)%g;\
- s%@DEFAULT_PINGER@%$(DEFAULT_PINGER)%g;\
- s%@DEFAULT_DISKD@%$(DEFAULT_DISKD)%g;\
- s%@DEFAULT_CACHE_LOG@%$(DEFAULT_CACHE_LOG)%g;\
- s%@DEFAULT_ACCESS_LOG@%$(DEFAULT_ACCESS_LOG)%g;\
- s%@DEFAULT_STORE_LOG@%$(DEFAULT_STORE_LOG)%g;\
- s%@DEFAULT_PID_FILE@%$(DEFAULT_PID_FILE)%g;\
- s%@DEFAULT_SWAP_DIR@%$(DEFAULT_SWAP_DIR)%g;\
- s%@DEFAULT_ICON_DIR@%$(DEFAULT_ICON_DIR)%g;\
- s%@DEFAULT_MIB_PATH@%$(DEFAULT_MIB_PATH)%g;\
- s%@DEFAULT_ERROR_DIR@%$(DEFAULT_ERROR_DIR)%g;\
- s%@DEFAULT_PREFIX@%$(DEFAULT_PREFIX)%g;\
- s%@DEFAULT_HOSTS@%$(DEFAULT_HOSTS)%g;\
- s%@[V]ERSION@%$(VERSION)%g;"\
- < $(srcdir)/cf.data.pre >$@
-
-store_modules.cc: store_modules.sh Makefile
- $(SHELL) $(srcdir)/store_modules.sh $(STORE_MODULES) >store_modules.cc
-
-repl_modules.cc: repl_modules.sh Makefile
- $(SHELL) $(srcdir)/repl_modules.sh $(REPL_POLICIES) > repl_modules.cc
-
-auth_modules.cc: auth_modules.sh Makefile
- @$(SHELL) $(srcdir)/auth_modules.sh $(AUTH_MODULES) >auth_modules.cc
-
-install-data-local: install-sysconfDATA install-dataDATA
- @if test -f $(DESTDIR)$(DEFAULT_MIME_TABLE) ; then \
- echo "$@ will not overwrite existing $(DESTDIR)$(DEFAULT_MIME_TABLE)" ; \
- else \
- echo "$(INSTALL_DATA) $(srcdir)/mime.conf.default $(DESTDIR)$(DEFAULT_MIME_TABLE)" ;\
- $(INSTALL_DATA) $(srcdir)/mime.conf.default $(DESTDIR)$(DEFAULT_MIME_TABLE); \
- fi
- @if test -f $(DESTDIR)$(DEFAULT_CONFIG_FILE) ; then \
- echo "$@ will not overwrite existing $(DESTDIR)$(DEFAULT_CONFIG_FILE)" ; \
- else \
- echo "$(INSTALL_DATA) squid.conf.default $(DESTDIR)$(DEFAULT_CONFIG_FILE)"; \
- $(INSTALL_DATA) squid.conf.default $(DESTDIR)$(DEFAULT_CONFIG_FILE); \
- fi
- $(mkinstalldirs) $(DESTDIR)$(DEFAULT_LOG_PREFIX)
+## depend on the Makefile.
+ cf.data: cf.data.pre Makefile
+ sed "\
+ s%@DEFAULT_MIME_TABLE@%$(DEFAULT_MIME_TABLE)%g;
+
+ \
+ s%@DEFAULT_DNSSERVER@%$(DEFAULT_DNSSERVER)%g;
+
+ \
+ s%@DEFAULT_UNLINKD@%$(DEFAULT_UNLINKD)%g;
+
+ \
+ s%@DEFAULT_PINGER@%$(DEFAULT_PINGER)%g;
+
+ \
+ s%@DEFAULT_DISKD@%$(DEFAULT_DISKD)%g;
+
+ \
+ s%@DEFAULT_CACHE_LOG@%$(DEFAULT_CACHE_LOG)%g;
+
+ \
+ s%@DEFAULT_ACCESS_LOG@%$(DEFAULT_ACCESS_LOG)%g;
+
+ \
+ s%@DEFAULT_STORE_LOG@%$(DEFAULT_STORE_LOG)%g;
+
+ \
+ s%@DEFAULT_PID_FILE@%$(DEFAULT_PID_FILE)%g;
+
+ \
+ s%@DEFAULT_SWAP_DIR@%$(DEFAULT_SWAP_DIR)%g;
+
+ \
+ s%@DEFAULT_ICON_DIR@%$(DEFAULT_ICON_DIR)%g;
+
+ \
+ s%@DEFAULT_MIB_PATH@%$(DEFAULT_MIB_PATH)%g;
+
+ \
+ s%@DEFAULT_ERROR_DIR@%$(DEFAULT_ERROR_DIR)%g;
+
+ \
+ s%@DEFAULT_PREFIX@%$(DEFAULT_PREFIX)%g;
+
+ \
+ s%@DEFAULT_HOSTS@%$(DEFAULT_HOSTS)%g;
+
+ \
+ s%@[V]ERSION@%$(VERSION)%g;"\
+
+ < $(srcdir)/cf.data.pre >$@
+
+ store_modules.cc: store_modules.sh Makefile
+ $(SHELL) $(srcdir)/store_modules.sh $(STORE_MODULES) >store_modules.cc
+
+ repl_modules.cc: repl_modules.sh Makefile
+ $(SHELL) $(srcdir)/repl_modules.sh $(REPL_POLICIES) > repl_modules.cc
+
+ auth_modules.cc: auth_modules.sh Makefile
+ @$(SHELL) $(srcdir)/auth_modules.sh $(AUTH_MODULES) >auth_modules.cc
+
+ install-data-local: install-sysconfDATA install-dataDATA
+ @if test -f $(DESTDIR)$(DEFAULT_MIME_TABLE) ; then \
+echo "
+$@ will not overwrite existing $(DESTDIR)$(DEFAULT_MIME_TABLE)" ; \
+else \
+ echo "$(INSTALL_DATA) $(srcdir)/mime.conf.default $(DESTDIR)$(DEFAULT_MIME_TABLE)" ;\
+$(INSTALL_DATA) $(srcdir)/mime.conf.default $(DESTDIR)$(DEFAULT_MIME_TABLE); \
+fi
+@if test -f $(DESTDIR)$(DEFAULT_CONFIG_FILE) ; then \
+echo "$@ will not overwrite existing $(DESTDIR)$(DEFAULT_CONFIG_FILE)" ; \
+else \
+ echo "$(INSTALL_DATA) squid.conf.default $(DESTDIR)$(DEFAULT_CONFIG_FILE)"; \
+$(INSTALL_DATA) squid.conf.default $(DESTDIR)$(DEFAULT_CONFIG_FILE); \
+fi
+$(mkinstalldirs) $(DESTDIR)$(DEFAULT_LOG_PREFIX)
uninstall-local:
- @if test -f $(DESTDIR)$(DEFAULT_MIME_TABLE) ; then \
- echo "rm -f $(DESTDIR)$(DEFAULT_MIME_TABLE)"; \
- $(RM) -f $(DESTDIR)$(DEFAULT_MIME_TABLE); \
- fi
+@if test -f $(DESTDIR)$(DEFAULT_MIME_TABLE) ; then \
+echo "rm -f $(DESTDIR)$(DEFAULT_MIME_TABLE)"; \
+$(RM) -f $(DESTDIR)$(DEFAULT_MIME_TABLE); \
+fi
# Don't automatically uninstall config files
# @if test -f $(DESTDIR)$(DEFAULT_CONFIG_FILE) ; then \
# fi
DISTCLEANFILES = cf_gen_defines.h cf.data cf_parser.h squid.conf.default \
- globals.cc string_arrays.c repl_modules.cc auth_modules.cc store_modules.cc
+ globals.cc string_arrays.c repl_modules.cc auth_modules.cc store_modules.cc
##install-pinger:
## @f=$(PINGER_EXE); \
/*
- * $Id: Store.h,v 1.9 2003/03/10 04:56:36 robertc Exp $
+ * $Id: Store.h,v 1.10 2003/03/15 04:17:39 robertc Exp $
*
*
* SQUID Web Proxy Cache http://www.squid-cache.org/
void delayAwareRead(int fd, char *buf, int len, IOCB *handler, void *data);
void setNoDelay (bool const);
+ bool modifiedSince(request_t * request) const;
MemObject *mem_obj;
RemovalPolicyNode repl;
/*
- * $Id: clientStream.cc,v 1.6 2003/03/10 04:56:37 robertc Exp $
+ * $Id: clientStream.cc,v 1.7 2003/03/15 04:17:39 robertc Exp $
*
* DEBUG: section 87 Client-side Stream routines.
* AUTHOR: Robert Collins
*
* (i.e.
* mycontext = thisObject->data;
- * cbdataReferenceDone (mycontext);
+ * thisObject->data = NULL;
* clientStreamFreeLinst (thisObject->head);
- * cbdataFree (mycontext);
+ * mycontext = NULL;
* return;
*/
clientStreamNode *
clientStreamNew(CSR * readfunc, CSCB * callback, CSD * detach, CSS * status,
- void *data)
+ ClientStreamData data)
{
clientStreamNode *temp;
CBDATA_INIT_TYPE_FREECB(clientStreamNode, clientStreamFree);
*/
void
clientStreamInit(dlink_list * list, CSR * func, CSD * rdetach, CSS * readstatus,
- void *readdata, CSCB * callback, CSD * cdetach, void *callbackdata,
+ ClientStreamData readdata, CSCB * callback, CSD * cdetach, ClientStreamData callbackdata,
StoreIOBuffer tailBuffer)
{
clientStreamNode *temp = clientStreamNew(func, NULL, rdetach, readstatus,
*/
void
clientStreamInsertHead(dlink_list * list, CSR * func, CSCB * callback,
- CSD * detach, CSS * status, void *data)
+ CSD * detach, CSS * status, ClientStreamData data)
{
- clientStreamNode *temp;
/* test preconditions */
assert(list != NULL);
assert(list->head);
- temp = clientStreamNew(func, callback, detach, status, data);
+ clientStreamNode *temp = clientStreamNew(func, callback, detach, status, data);
temp->head = list;
debug(87, 3)
("clientStreamInsertHead: Inserted node %p with data %p after head\n",
- temp, data);
+ temp, data.getRaw());
if (list->head->next)
temp->readBuffer = ((clientStreamNode *)list->head->next->data)->readBuffer;
debug(87,
3) ("clientStreamCallback: Calling %p with cbdata %p from node %p\n",
- next->callback, next->data, thisObject);
+ next->callback, next->data.getRaw(), thisObject);
next->callback(next, http, rep, replyBuffer);
}
prev = thisObject->prev();
debug(87, 3) ("clientStreamRead: Calling %p with cbdata %p from node %p\n",
- prev->readfunc, prev->data, thisObject);
+ prev->readfunc, prev->data.getRaw(), thisObject);
thisObject->readBuffer = readBuffer;
prev->readfunc(prev, http);
}
void
clientStreamDetach(clientStreamNode * thisObject, clientHttpRequest * http)
{
- clientStreamNode *prev = thisObject->prev();
clientStreamNode *temp = thisObject;
assert(thisObject->node.next == NULL);
debug(87, 3) ("clientStreamDetach: Detaching node %p\n", thisObject);
/* And clean up thisObject node */
/* ESI TODO: push refcount class through to head */
+ clientStreamNode *prev = NULL;
+
+ if (thisObject->prev())
+ prev = cbdataReference(thisObject->prev());
+
+ thisObject->removeFromStream();
+
cbdataReferenceDone(temp);
+
cbdataFree(thisObject);
+
/* and tell the prev that the detach has occured */
/*
* We do it in thisObject order so that the detaching node is always
if (prev) {
debug(87, 3) ("clientStreamDetach: Calling %p with cbdata %p\n",
- prev->detach, prev->data);
- prev->detach(prev, http);
+ prev->detach, prev->data.getRaw());
+
+ if (cbdataReferenceValid(prev))
+ prev->detach(prev, http);
+
+ cbdataReferenceDone(prev);
}
}
}
/* Local function bodies */
+void
+clientStreamNode::removeFromStream()
+{
+ if (head)
+ dlinkDelete(&node, head);
+
+ head = NULL;
+}
+
void
clientStreamFree(void *foo)
{
debug(87, 3) ("Freeing clientStreamNode %p\n", thisObject);
- if (thisObject->data) {
- cbdataFree(thisObject->data);
- }
-
- if (thisObject->node.next || thisObject->node.prev) {
- dlinkDelete(&thisObject->node, thisObject->head);
- }
-
+ thisObject->removeFromStream();
+ thisObject->data = NULL;
}
clientStreamNode *
/*
- * $Id: clientStream.h,v 1.5 2003/03/10 04:56:37 robertc Exp $
+ * $Id: clientStream.h,v 1.6 2003/03/15 04:17:39 robertc Exp $
*
*
* SQUID Web Proxy Cache http://www.squid-cache.org/
#define SQUID_CLIENTSTREAM_H
#include "StoreIOBuffer.h"
+#include "RefCount.h"
+
+typedef RefCount<RefCountable_> ClientStreamData;
class clientStreamNode;
public:
clientStreamNode *prev() const;
clientStreamNode *next() const;
+ void removeFromStream();
dlink_node node;
dlink_list *head; /* sucks I know, but hey, the interface is limited */
CSR *readfunc;
CSCB *callback;
CSD *detach; /* tell this node the next one downstream wants no more data */
CSS *status;
- void *data; /* Context for the node */
+ ClientStreamData data; /* Context for the node */
StoreIOBuffer readBuffer; /* what, where and how much this node wants */
};
/* clientStream.c */
-SQUIDCEXTERN void clientStreamInit(dlink_list *, CSR *, CSD *, CSS *, void *, CSCB *, CSD *, void *, StoreIOBuffer tailBuffer);
-SQUIDCEXTERN void clientStreamInsertHead(dlink_list *, CSR *, CSCB *, CSD *, CSS *, void *);
-SQUIDCEXTERN clientStreamNode *clientStreamNew(CSR *, CSCB *, CSD *, CSS *, void *);
+SQUIDCEXTERN void clientStreamInit(dlink_list *, CSR *, CSD *, CSS *, ClientStreamData, CSCB *, CSD *, ClientStreamData, StoreIOBuffer tailBuffer);
+SQUIDCEXTERN void clientStreamInsertHead(dlink_list *, CSR *, CSCB *, CSD *, CSS *, ClientStreamData);
+SQUIDCEXTERN clientStreamNode *clientStreamNew(CSR *, CSCB *, CSD *, CSS *, ClientStreamData);
SQUIDCEXTERN void clientStreamCallback(clientStreamNode *, ClientHttpRequest *, HttpReply *, StoreIOBuffer replyBuffer);
SQUIDCEXTERN void clientStreamRead(clientStreamNode *, ClientHttpRequest *, StoreIOBuffer readBuffer);
SQUIDCEXTERN void clientStreamDetach(clientStreamNode *, ClientHttpRequest *);
/*
- * $Id: client_side.cc,v 1.633 2003/03/13 07:51:38 hno Exp $
+ * $Id: client_side.cc,v 1.634 2003/03/15 04:17:39 robertc Exp $
*
* DEBUG: section 33 Client-side Routines
* AUTHOR: Duane Wessels
#include "client_side_request.h"
#include "ACLChecklist.h"
#include "ConnectionDetail.h"
+#include "client_side_reply.h"
#if LINGERING_CLOSE
#define comm_close comm_lingering_close
/* our socket-related context */
-class ClientSocketContext
-{
-
-public:
- clientHttpRequest *http; /* we own this */
- char reqbuf[HTTP_REQBUF_SZ];
- ClientSocketContext *next;
- struct
- {
+CBDATA_CLASS_INIT(ClientSocketContext);
-int deferred:
- 1; /* This is a pipelined request waiting for the current object to complete */
-
-int parsed_ok:
- 1; /* Was this parsed correctly? */
- }
-
- flags;
- bool mayUseConnection() const {return mayUseConnection_;}
-
- void mayUseConnection(bool aBool)
- {
- mayUseConnection_ = aBool;
- debug (33,3)("ClientSocketContext::mayUseConnection: This %p marked %d\n",
- this, aBool);
- }
+void *
+ClientSocketContext::operator new (size_t byteCount)
+{
+ /* derived classes with different sizes must implement their own new */
+ assert (byteCount == sizeof (ClientSocketContext));
+ CBDATA_INIT_TYPE(ClientSocketContext);
+ return cbdataAlloc(ClientSocketContext);
+}
- struct
- {
- clientStreamNode *node;
- HttpReply *rep;
- StoreIOBuffer queuedBuffer;
- }
-
- deferredparams;
- off_t writtenToSocket;
- void pullData();
- off_t getNextRangeOffset() const;
- bool canPackMoreRanges() const;
- clientStream_status_t socketState();
- void sendBody(HttpReply * rep, StoreIOBuffer bodyData);
- void sendStartOfMessage(HttpReply * rep, StoreIOBuffer bodyData);
- size_t lengthToSend(size_t maximum);
- void noteSentBodyBytes(size_t);
- void buildRangeHeader(HttpReply * rep);
- int fd() const;
- clientStreamNode * getTail() const;
- clientStreamNode * getClientReplyContext() const;
- void removeFromConnectionList(ConnStateData * conn);
- void deferRecipientForLater(clientStreamNode * node, HttpReply * rep, StoreIOBuffer recievedData);
- bool multipartRangeRequest() const;
- void packRange(const char **buf,
- size_t size,
- MemBuf * mb);
-
-private:
- void prepareReply(HttpReply * rep);
- bool mayUseConnection_; /* This request may use the connection. Don't read anymore requests for now */
-};
-
-CBDATA_TYPE(ClientSocketContext);
+void
+ClientSocketContext::operator delete (void *address)
+{
+ cbdataFree (address);
+}
+void
+ClientSocketContext::deleteSelf() const
+{
+ delete this;
+}
/* Local functions */
/* ClientSocketContext */
-static FREE ClientSocketContextFree;
static ClientSocketContext *ClientSocketContextNew(clientHttpRequest *);
/* other */
static CWCB clientWriteComplete;
static bool clientPingHasFinished(ping_data const *aPing);
static void clientPrepareLogWithRequestDetails(request_t *, AccessLogEntry *);
static int connIsUsable(ConnStateData * conn);
-static ClientSocketContext *connGetCurrentContext(ConnStateData const * conn);
static int responseFinishedOrFailed(HttpReply * rep, StoreIOBuffer const &recievedData);
-static int contextStartOfOutput(ClientSocketContext * context);
-static void ClientSocketContextPushDeferredIfNeeded(ClientSocketContext * deferredRequest, ConnStateData * conn);
+static void ClientSocketContextPushDeferredIfNeeded(ClientSocketContext::Pointer deferredRequest, ConnStateData * conn);
static void clientUpdateSocketStats(log_type logType, size_t size);
static ClientSocketContext *clientParseRequestMethod(char *inbuf, method_t * method_p, ConnStateData * conn);
#endif
static ClientSocketContext *parseURIandHTTPVersion(char **url_p, http_version_t * http_ver_p, ConnStateData * conn, char *http_version_str);
static void setLogUri(clientHttpRequest * http, char const *uri);
-static void connAddContextToQueue(ConnStateData * conn, ClientSocketContext * context);
-static int connGetConcurrentRequestCount(ConnStateData * conn);
static int connReadWasError(ConnStateData * conn, comm_err_t, int size, int xerrno);
static int connFinishedWithConn(ConnStateData * conn, int size);
static void connNoteUseOfBuffer(ConnStateData * conn, size_t byteCount);
clientStreamNode *
ClientSocketContext::getTail() const
{
- return (clientStreamNode *)http->client_stream.tail->data;
+ if (http->client_stream.tail)
+ return (clientStreamNode *)http->client_stream.tail->data;
+
+ return NULL;
}
clientStreamNode *
void
ClientSocketContext::removeFromConnectionList(ConnStateData * conn)
{
- ClientSocketContext **tempContextPointer;
+ ClientSocketContext::Pointer *tempContextPointer;
assert(conn);
- assert(connGetCurrentContext(conn) != NULL);
+ assert(conn->getCurrentContext().getRaw() != NULL);
/* Unlink us from the connection request list */
- tempContextPointer = (ClientSocketContext **) & conn->currentobject;
+ tempContextPointer = & conn->currentobject;
- while (*tempContextPointer) {
+ while (tempContextPointer->getRaw()) {
if (*tempContextPointer == this)
break;
tempContextPointer = &(*tempContextPointer)->next;
}
- assert(*tempContextPointer != NULL);
+ assert(tempContextPointer->getRaw() != NULL);
*tempContextPointer = next;
next = NULL;
}
-void
-ClientSocketContextFree(void *data)
+ClientSocketContext::~ClientSocketContext()
{
- ClientSocketContext *context = (ClientSocketContext *)data;
- ConnStateData *conn = context->http->conn;
- clientStreamNode *node = context->getTail();
- /* We are *always* the tail - prevent recursive free */
- assert(context == node->data);
- node->data = NULL;
- httpRequestFree(context->http);
+ clientStreamNode *node = getTail();
+
+ if (node) {
+ ClientSocketContext *streamContext = dynamic_cast<ClientSocketContext *> (node->data.getRaw());
+
+ if (streamContext) {
+ /* We are *always* the tail - prevent recursive free */
+ assert(this == streamContext);
+ node->data = NULL;
+ }
+ }
+
+ if (connRegistered_)
+ deRegisterWithConn();
+
+ httpRequestFree(http);
+
/* clean up connection links to us */
- assert(context != context->next);
+ assert(this != next.getRaw());
+}
- if (conn)
- context->removeFromConnectionList(conn);
+void
+ClientSocketContext::registerWithConn()
+{
+ assert (!connRegistered_);
+ assert (http);
+ assert (http->conn);
+ connRegistered_ = true;
+ http->conn->addContextToQueue(this);
+}
+
+void
+ClientSocketContext::deRegisterWithConn()
+{
+ assert (connRegistered_);
+ removeFromConnectionList(http->conn);
+ connRegistered_ = false;
+}
+
+void
+ClientSocketContext::connIsFinished()
+{
+ assert (http);
+ assert (http->conn);
+ deRegisterWithConn();
+ /* we can't handle any more stream data - detach */
+ clientStreamDetach(getTail(), http);
+}
+
+ClientSocketContext::ClientSocketContext() : http(NULL), next(NULL),
+ writtenToSocket(0),
+ mayUseConnection_ (false),
+ connRegistered_ (false)
+{
+ memset (reqbuf, '\0', sizeof (reqbuf));
+ flags.deferred = 0;
+ flags.parsed_ok = 0;
+ deferredparams.node = NULL;
+ deferredparams.rep = NULL;
}
ClientSocketContext *
{
ClientSocketContext *newContext;
assert(http != NULL);
- CBDATA_INIT_TYPE_FREECB(ClientSocketContext, ClientSocketContextFree);
- newContext = cbdataAlloc(ClientSocketContext);
+ newContext = new ClientSocketContext;
newContext->http = http;
return newContext;
}
ConnStateData::areAllContextsForThisConnection() const
{
assert(this != NULL);
- ClientSocketContext *context = connGetCurrentContext(this);
+ ClientSocketContext::Pointer context = getCurrentContext();
- while (context) {
+ while (context.getRaw()) {
if (context->http->conn != this)
return false;
void
ConnStateData::freeAllContexts()
{
- ClientSocketContext *context;
+ ClientSocketContext::Pointer context;
- while ((context = connGetCurrentContext(this)) != NULL) {
- assert(connGetCurrentContext(this) !=
- connGetCurrentContext(this)->next);
- cbdataFree(context);
+ while ((context = getCurrentContext()).getRaw() != NULL) {
+ assert(getCurrentContext() !=
+ getCurrentContext()->next);
+ context->connIsFinished();
+ assert (context != currentobject);
}
}
return 1;
}
-ClientSocketContext *
-connGetCurrentContext(ConnStateData const * conn)
+ClientSocketContext::Pointer
+ConnStateData::getCurrentContext() const
{
- assert(conn);
- return (ClientSocketContext *)conn->currentobject;
+ assert(this);
+ return currentobject;
}
void
return 0;
}
-int
-contextStartOfOutput(ClientSocketContext * context)
+bool
+ClientSocketContext::startOfOutput() const
{
- return context->http->out.size == 0 ? 1 : 0;
+ return http->out.size == 0;
}
size_t
HttpReply * rep, StoreIOBuffer recievedData)
{
int fd;
- ClientSocketContext *context;
/* Test preconditions */
assert(node != NULL);
/* TODO: handle this rather than asserting
* However, that itself shouldn't happen, so it stays as an assert for now.
*/
assert(cbdataReferenceValid(node));
- assert(node->data != NULL);
assert(node->node.next == NULL);
- context = (ClientSocketContext *)node->data;
+ ClientSocketContext::Pointer context = dynamic_cast<ClientSocketContext *>(node->data.getRaw());
+ assert(context.getRaw() != NULL);
assert(connIsUsable(http->conn));
fd = http->conn->fd;
/* TODO: check offset is what we asked for */
- if (connGetCurrentContext(http->conn) != context) {
+ if (context != http->conn->getCurrentContext()) {
context->deferRecipientForLater(node, rep, recievedData);
return;
}
if (responseFinishedOrFailed(rep, recievedData)) {
- clientWriteComplete(fd, NULL, 0, COMM_OK, context);
+ context->writeComplete(fd, NULL, 0, COMM_OK);
return;
}
- if (!contextStartOfOutput(context))
+ if (!context->startOfOutput())
context->sendBody(rep, recievedData);
else
context->sendStartOfMessage(rep, recievedData);
void
clientSocketDetach(clientStreamNode * node, clientHttpRequest * http)
{
- ClientSocketContext *context;
/* Test preconditions */
assert(node != NULL);
/* TODO: handle this rather than asserting
*/
assert(cbdataReferenceValid(node));
/* Set null by ContextFree */
- assert(node->data == NULL);
assert(node->node.next == NULL);
- context = (ClientSocketContext *)node->data;
+ ClientSocketContext *context = dynamic_cast<ClientSocketContext *>(node->data.getRaw());
+ /* this is the assert discussed above */
+ assert(context == NULL);
/* We are only called when the client socket shutsdown.
* Tell the prev pipeline member we're finished
*/
}
void
-ClientSocketContextPushDeferredIfNeeded(ClientSocketContext * deferredRequest, ConnStateData * conn)
+ClientSocketContextPushDeferredIfNeeded(ClientSocketContext::Pointer deferredRequest, ConnStateData * conn)
{
debug(33, 2) ("ClientSocketContextPushDeferredIfNeeded: FD %d Sending next\n",
conn->fd);
*/
}
-static void
-clientKeepaliveNextRequest(ClientSocketContext * context)
+void
+ClientSocketContext::keepaliveNextRequest()
{
- clientHttpRequest *http = context->http;
ConnStateData *conn = http->conn;
- ClientSocketContext *deferredRequest;
- debug(33, 3) ("clientKeepaliveNextRequest: FD %d\n", conn->fd);
- cbdataFree(context);
+ debug(33, 3) ("ClientSocketContext::keepaliveNextRequest: FD %d\n", conn->fd);
+ connIsFinished();
+
+ ClientSocketContext::Pointer deferredRequest;
- if ((deferredRequest = connGetCurrentContext(conn)) == NULL)
+ if ((deferredRequest = conn->getCurrentContext()).getRaw() == NULL)
conn->readNextRequest();
else
ClientSocketContextPushDeferredIfNeeded(deferredRequest, conn);
clientWriteComplete(int fd, char *bufnotused, size_t size, comm_err_t errflag, void *data)
{
ClientSocketContext *context = (ClientSocketContext *)data;
- clientHttpRequest *http = context->http;
+ context->writeComplete (fd, bufnotused, size, errflag);
+}
+
+void
+ClientSocketContext::writeComplete(int fd, char *bufnotused, size_t size, comm_err_t errflag)
+{
StoreEntry *entry = http->entry;
http->out.size += size;
assert(fd > -1);
return;
}
- switch (context->socketState()) {
+ switch (socketState()) {
case STREAM_NONE:
- context->pullData();
+ pullData();
break;
case STREAM_COMPLETE:
debug(33, 5) ("clientWriteComplete: FD %d Keeping Alive\n", fd);
- clientKeepaliveNextRequest(context);
+ keepaliveNextRequest();
return;
case STREAM_UNPLANNED_COMPLETE:
tempBuffer.data = context->reqbuf;
tempBuffer.length = HTTP_REQBUF_SZ;
clientStreamInit(&http->client_stream, clientGetMoreData, clientReplyDetach,
- clientReplyStatus, clientReplyNewContext(http), clientSocketRecipient,
+ clientReplyStatus, new clientReplyContext(http), clientSocketRecipient,
clientSocketDetach, context, tempBuffer);
dlinkAdd(http, &http->active, &ClientActiveRequests);
return context;
tempBuffer.length = HTTP_REQBUF_SZ;
+ ClientStreamData newServer = new clientReplyContext(http);
+
+ ClientStreamData newClient = result;
+
clientStreamInit(&http->client_stream, clientGetMoreData, clientReplyDetach,
- clientReplyStatus, clientReplyNewContext(http), clientSocketRecipient,
- clientSocketDetach, result, tempBuffer);
+ clientReplyStatus, newServer, clientSocketRecipient,
+ clientSocketDetach, newClient, tempBuffer);
*prefix_p = (char *)xmalloc(prefix_sz + 1);
}
void
-connAddContextToQueue(ConnStateData * conn, ClientSocketContext * context)
+ConnStateData::addContextToQueue(ClientSocketContext * context)
{
- ClientSocketContext **S;
+ ClientSocketContext::Pointer *S;
- for (S = (ClientSocketContext **) & conn->currentobject; *S;
+ for (S = (ClientSocketContext::Pointer *) & currentobject; S->getRaw();
S = &(*S)->next)
;
*S = context;
- ++conn->nrequests;
+ ++nrequests;
}
int
-connGetConcurrentRequestCount(ConnStateData * conn)
+ConnStateData::getConcurrentRequestCount() const
{
int result = 0;
- ClientSocketContext **T;
+ ClientSocketContext::Pointer *T;
- for (T = (ClientSocketContext **) & conn->currentobject;
- *T; T = &(*T)->next, ++result)
+ for (T = (ClientSocketContext::Pointer *) ¤tobject;
+ T->getRaw(); T = &(*T)->next, ++result)
;
return result;
connFinishedWithConn(ConnStateData * conn, int size)
{
if (size == 0) {
- if (connGetConcurrentRequestCount(conn) == 0 && conn->in.notYetUsed == 0) {
+ if (conn->getConcurrentRequestCount() == 0 && conn->in.notYetUsed == 0) {
/* no current or pending requests */
debug(33, 4) ("connFinishedWithConn: FD %d closed\n", conn->fd);
return 1;
(unsigned) conn->in.notYetUsed);
debug(33, 1) ("Config 'request_header_max_size'= %ld bytes.\n",
(long int) Config.maxRequestHeaderSize);
- clientSetReplyToError(node->data, ERR_TOO_BIG,
- HTTP_REQUEST_ENTITY_TOO_LARGE, METHOD_NONE, NULL,
- &conn->peer.sin_addr, NULL, NULL, NULL);
- connAddContextToQueue(conn, context);
+ clientReplyContext *repContext = dynamic_cast<clientReplyContext *>(node->data.getRaw());
+ assert (repContext);
+ repContext->setReplyToError(ERR_TOO_BIG,
+ HTTP_REQUEST_ENTITY_TOO_LARGE, METHOD_NONE, NULL,
+ &conn->peer.sin_addr, NULL, NULL, NULL);
+ context->registerWithConn();
context->pullData();
}
/* setup our private context */
connNoteUseOfBuffer(conn, http->req_sz);
- connAddContextToQueue(conn, context);
+ context->registerWithConn();
if (context->flags.parsed_ok == 0) {
clientStreamNode *node = context->getClientReplyContext();
debug(33, 1) ("clientReadRequest: Invalid Request\n");
- clientSetReplyToError(node->data,
- ERR_INVALID_REQ, HTTP_BAD_REQUEST, method, NULL,
- &conn->peer.sin_addr, NULL, conn->in.buf, NULL);
+ clientReplyContext *repContext = dynamic_cast<clientReplyContext *>(node->data.getRaw());
+ assert (repContext);
+ repContext->setReplyToError(ERR_INVALID_REQ, HTTP_BAD_REQUEST, method, NULL,
+ &conn->peer.sin_addr, NULL, conn->in.buf, NULL);
assert(context->http->out.offset == 0);
context->pullData();
conn->flags.readMoreRequests = 0;
if ((request = urlParse(method, http->uri)) == NULL) {
clientStreamNode *node = context->getClientReplyContext();
debug(33, 5) ("Invalid URL: %s\n", http->uri);
- clientSetReplyToError(node->data,
- ERR_INVALID_URL, HTTP_BAD_REQUEST, method, http->uri,
- &conn->peer.sin_addr, NULL, NULL, NULL);
+ clientReplyContext *repContext = dynamic_cast<clientReplyContext *>(node->data.getRaw());
+ assert (repContext);
+ repContext->setReplyToError(
+ ERR_INVALID_URL, HTTP_BAD_REQUEST, method, http->uri,
+ &conn->peer.sin_addr, NULL, NULL, NULL);
assert(context->http->out.offset == 0);
context->pullData();
conn->flags.readMoreRequests = 0;
if (!urlCheckRequest(request) ||
httpHeaderHas(&request->header, HDR_TRANSFER_ENCODING)) {
clientStreamNode *node = context->getClientReplyContext();
- clientSetReplyToError(node->data, ERR_UNSUP_REQ,
- HTTP_NOT_IMPLEMENTED, request->method, NULL,
- &conn->peer.sin_addr, request, NULL, NULL);
+ clientReplyContext *repContext = dynamic_cast<clientReplyContext *>(node->data.getRaw());
+ assert (repContext);
+ repContext->setReplyToError(ERR_UNSUP_REQ,
+ HTTP_NOT_IMPLEMENTED, request->method, NULL,
+ &conn->peer.sin_addr, request, NULL, NULL);
assert(context->http->out.offset == 0);
context->pullData();
conn->flags.readMoreRequests = 0;
if (!clientIsContentLengthValid(request)) {
clientStreamNode *node = context->getClientReplyContext();
- clientSetReplyToError(node->data, ERR_INVALID_REQ,
- HTTP_LENGTH_REQUIRED, request->method, NULL,
- &conn->peer.sin_addr, request, NULL, NULL);
+ clientReplyContext *repContext = dynamic_cast<clientReplyContext *>(node->data.getRaw());
+ assert (repContext);
+ repContext->setReplyToError(ERR_INVALID_REQ,
+ HTTP_LENGTH_REQUIRED, request->method, NULL,
+ &conn->peer.sin_addr, request, NULL, NULL);
assert(context->http->out.offset == 0);
context->pullData();
conn->flags.readMoreRequests = 0;
if (!clientIsRequestBodyValid(request->content_length) ||
clientIsRequestBodyTooLargeForPolicy(request->content_length)) {
clientStreamNode *node = context->getClientReplyContext();
- clientSetReplyToError(node->data, ERR_TOO_BIG,
- HTTP_REQUEST_ENTITY_TOO_LARGE, METHOD_NONE, NULL,
- &conn->peer.sin_addr, http->request, NULL, NULL);
+ clientReplyContext *repContext = dynamic_cast<clientReplyContext *>(node->data.getRaw());
+ assert (repContext);
+ repContext->setReplyToError(ERR_TOO_BIG,
+ HTTP_REQUEST_ENTITY_TOO_LARGE, METHOD_NONE, NULL,
+ &conn->peer.sin_addr, http->request, NULL, NULL);
assert(context->http->out.offset == 0);
context->pullData();
conn->flags.readMoreRequests = 0;
static int
connOkToAddRequest(ConnStateData *conn)
{
- int result = connGetConcurrentRequestCount(conn) < (Config.onoff.pipeline_prefetch ? 2 : 1);
+ int result = conn->getConcurrentRequestCount() < (Config.onoff.pipeline_prefetch ? 2 : 1);
if (!result) {
debug(33, 3) ("clientReadRequest: FD %d max concurrent requests reached\n",
clientProcessBody(conn);
/* Process next request */
- if (connGetConcurrentRequestCount(conn) == 0)
+ if (conn->getConcurrentRequestCount() == 0)
fd_note(conn->fd, "Reading next request");
/* XXX: if we read *exactly* two requests, and the client sends no more,
clientHttpRequest *http =
parseHttpRequestAbort(conn, "error:Connection%20lifetime%20expired");
node = http->client_stream.tail->prev->data;
- clientSetReplyToError(node->data, ERR_LIFETIME_EXP,
- HTTP_REQUEST_TIMEOUT, METHOD_NONE, "N/A", &conn->peer.sin_addr,
- NULL, NULL, NULL);
+ clientReplyContext *repContext = dynamic_cast<clientReplyContext *>(node->data.getRaw());
+ assert (repContext);
+ repContext->setReplyToError(ERR_LIFETIME_EXP,
+ HTTP_REQUEST_TIMEOUT, METHOD_NONE, "N/A", &conn->peer.sin_addr,
+ NULL, NULL, NULL);
/* No requests can be outstanded */
assert(conn->chr == NULL);
/* add to the client request queue */
/*
- * $Id: client_side.h,v 1.1 2003/03/04 02:57:50 robertc Exp $
+ * $Id: client_side.h,v 1.2 2003/03/15 04:17:39 robertc Exp $
*
*
* SQUID Web Proxy Cache http://www.squid-cache.org/
#ifndef SQUID_CLIENTSIDE_H
#define SQUID_CLIENTSIDE_H
+#include "StoreIOBuffer.h"
+
+class ConnStateData;
+
+class ClientHttpRequest;
+
+class clientStreamNode;
+
+class ClientSocketContext : public RefCountable
+{
+
+public:
+ typedef RefCount<ClientSocketContext> Pointer;
+ void *operator new(size_t);
+ void operator delete(void *);
+ void deleteSelf() const;
+ ClientSocketContext();
+ ~ClientSocketContext();
+ bool startOfOutput() const;
+ void writeComplete(int fd, char *bufnotused, size_t size, comm_err_t errflag);
+ void keepaliveNextRequest();
+ ClientHttpRequest *http; /* we own this */
+ char reqbuf[HTTP_REQBUF_SZ];
+ Pointer next;
+
+ struct
+ {
+
+int deferred:
+ 1; /* This is a pipelined request waiting for the current object to complete */
+
+int parsed_ok:
+ 1; /* Was this parsed correctly? */
+ }
+
+ flags;
+ bool mayUseConnection() const {return mayUseConnection_;}
+
+ void mayUseConnection(bool aBool)
+ {
+ mayUseConnection_ = aBool;
+ debug (33,3)("ClientSocketContext::mayUseConnection: This %p marked %d\n",
+ this, aBool);
+ }
+
+ struct
+ {
+ clientStreamNode *node;
+ HttpReply *rep;
+ StoreIOBuffer queuedBuffer;
+ }
+
+ deferredparams;
+ off_t writtenToSocket;
+ void pullData();
+ off_t getNextRangeOffset() const;
+ bool canPackMoreRanges() const;
+ clientStream_status_t socketState();
+ void sendBody(HttpReply * rep, StoreIOBuffer bodyData);
+ void sendStartOfMessage(HttpReply * rep, StoreIOBuffer bodyData);
+ size_t lengthToSend(size_t maximum);
+ void noteSentBodyBytes(size_t);
+ void buildRangeHeader(HttpReply * rep);
+ int fd() const;
+ clientStreamNode * getTail() const;
+ clientStreamNode * getClientReplyContext() const;
+ void connIsFinished();
+ void removeFromConnectionList(ConnStateData * conn);
+ void deferRecipientForLater(clientStreamNode * node, HttpReply * rep, StoreIOBuffer recievedData);
+ bool multipartRangeRequest() const;
+ void packRange(const char **buf,
+ size_t size,
+ MemBuf * mb);
+ void registerWithConn();
+
+private:
+ CBDATA_CLASS(ClientSocketContext);
+ void prepareReply(HttpReply * rep);
+ void deRegisterWithConn();
+ bool mayUseConnection_; /* This request may use the connection. Don't read anymore requests for now */
+ bool connRegistered_;
+};
+
class ConnStateData
{
void freeAllContexts();
void readNextRequest();
void makeSpaceAvailable();
+ ClientSocketContext::Pointer getCurrentContext() const;
+ void addContextToQueue(ClientSocketContext * context);
+ int getConcurrentRequestCount() const;
int fd;
/* note this is ONLY connection based because NTLM is against HTTP spec */
/* the user details for connection based authentication */
auth_user_request_t *auth_user_request;
- void *currentobject; /* used by the owner of the connection. Opaque otherwise */
+ /* TODO: generalise the connection owner concept */
+ ClientSocketContext::Pointer currentobject; /* used by the owner of the connection. Opaque otherwise */
struct sockaddr_in peer;
/*
- * $Id: client_side_reply.cc,v 1.46 2003/03/11 08:24:42 robertc Exp $
+ * $Id: client_side_reply.cc,v 1.47 2003/03/15 04:17:39 robertc Exp $
*
* DEBUG: section 88 Client-side Reply Routines
* AUTHOR: Robert Collins (Originally Duane Wessels in client_side.c)
*/
#include "squid.h"
+#include "client_side_reply.h"
#include "StoreClient.h"
#include "Store.h"
#include "HttpReply.h"
#include "ESI.h"
#endif
#include "MemObject.h"
-#include "client_side_request.h"
#include "ACLChecklist.h"
#include "ACL.h"
#if DELAY_POOLS
#endif
#include "client_side.h"
-static STCB clientHandleIMSReply;
-static STCB clientSendMoreData;
-
-class clientReplyContext : public StoreClient
-{
-
-public:
- void *operator new (size_t byteCount);
- void operator delete (void *address);
-
- void saveState(clientHttpRequest *);
- void restoreState(clientHttpRequest *);
- void purgeRequest ();
- void purgeRequestFindObjectToPurge();
- void purgeDoMissPurge();
- void purgeFoundGet(StoreEntry *newEntry);
- void purgeFoundHead(StoreEntry *newEntry);
- void purgeFoundObject(StoreEntry *entry);
- void sendClientUpstreamResponse();
- void purgeDoPurgeGet(StoreEntry *entry);
- void purgeDoPurgeHead(StoreEntry *entry);
- void doGetMoreData();
- void identifyStoreObject();
- void identifyFoundObject(StoreEntry *entry);
- int storeOKTransferDone() const;
- int storeNotOKTransferDone() const;
-
- http_status purgeStatus;
-
- /* state variable - replace with class to handle storeentries at some point */
- int lookingforstore;
- virtual void created (StoreEntry *newEntry);
-
- clientHttpRequest *http;
- int headers_sz;
- store_client *sc; /* The store_client we're using */
- store_client *old_sc; /* ... for entry to be validated */
- StoreIOBuffer tempBuffer; /* For use in validating requests via IMS */
- int old_reqsize; /* ... again, for the buffer */
- size_t reqsize;
- off_t reqofs;
- char tempbuf[HTTP_REQBUF_SZ]; /* a temporary buffer if we need working storage */
-#if USE_CACHE_DIGESTS
-
- const char *lookup_type; /* temporary hack: storeGet() result: HIT/MISS/NONE */
-#endif
-
- struct
- {
-
-int storelogiccomplete:
- 1;
-
-int complete:
- 1; /* we have read all we can from upstream */
- bool headersSent;
- }
-
- flags;
- clientStreamNode *ourNode; /* This will go away if/when this file gets refactored some more */
-
-private:
- friend void clientSendMoreData(void *data, StoreIOBuffer result);
- friend void clientHandleIMSReply(void *data, StoreIOBuffer result);
- static STCB clientSendMoreData;
- clientStreamNode *getNextNode() const;
- void sendMoreData (StoreIOBuffer result);
- void makeThisHead();
- bool errorInStream(StoreIOBuffer const &result, size_t const &sizeToProcess)const ;
- void sendStreamError(StoreIOBuffer const &result);
- void pushStreamData(StoreIOBuffer const &result, char *source);
- void waitForMoreData (StoreIOBuffer const &result);
- clientStreamNode * next() const;
- void startSendProcess();
- StoreIOBuffer holdingBuffer;
- HttpReply *holdingReply;
- void processReplyAccess();
- static PF ProcessReply;
- void processReply(bool accessAllowed);
-};
-
-CBDATA_TYPE(clientReplyContext);
+CBDATA_CLASS_INIT(clientReplyContext);
/* Local functions */
-static int clientGotNotEnough(clientHttpRequest const *);
-static int clientReplyBodyTooLarge(HttpReply const *, ssize_t);
-static int clientOnlyIfCached(clientHttpRequest * http);
-static void clientProcessExpired(clientReplyContext *);
-static void clientProcessMiss(clientReplyContext *);
-static STCB clientCacheHit;
-static void clientProcessOnlyIfCachedMiss(clientReplyContext *);
-static int clientGetsOldEntry(StoreEntry *, StoreEntry * old,
- request_t * request);
-
-static int modifiedSince(StoreEntry *, request_t *);
-static void clientTraceReply(clientStreamNode *, clientReplyContext *);
-static StoreEntry *clientCreateStoreEntry(clientReplyContext *, method_t,
- request_flags);
-
-static void clientRemoveStoreReference(clientReplyContext *, store_client **,
- StoreEntry **);
extern "C" CSS clientReplyStatus;
extern ErrorState *clientBuildError(err_type, http_status, char const *,
struct in_addr *, request_t *);
-static void startError(clientReplyContext * context, clientHttpRequest * http, ErrorState * err);
-static void triggerInitialStoreReadWithClientParameters(clientReplyContext * context, clientHttpRequest * http);
-static int clientCheckTransferDone(clientReplyContext * context);
-static void clientObeyConnectionHeader(clientHttpRequest * http, HttpReply * rep);
-
-/* The clientReply clean interface */
/* privates */
-static FREE clientReplyFree;
-void
-clientReplyFree(void *data)
+clientReplyContext::~clientReplyContext()
{
- clientReplyContext *thisClient = (clientReplyContext *)data;
- clientRemoveStoreReference(thisClient, &thisClient->sc, &thisClient->http->entry);
+ removeStoreReference(&sc, &http->entry);
/* old_entry might still be set if we didn't yet get the reply
- * code in clientHandleIMSReply() */
- clientRemoveStoreReference(thisClient, &thisClient->old_sc, &thisClient->http->old_entry);
- safe_free(thisClient->tempBuffer.data);
- cbdataReferenceDone(thisClient->http);
+ * code in HandleIMSReply() */
+ removeStoreReference(&old_sc, &old_entry);
+ safe_free(tempBuffer.data);
+ cbdataReferenceDone(http);
}
-void *
-clientReplyNewContext(clientHttpRequest * clientContext)
-{
- clientReplyContext *context = new clientReplyContext;
- context->http = cbdataReference(clientContext);
- return context;
-}
+clientReplyContext::clientReplyContext(clientHttpRequest *clientContext) : http (cbdataReference(clientContext)), old_entry (NULL), old_sc(NULL)
+{}
/* create an error in the store awaiting the client side to read it. */
+/* This may be better placed in the clientStream logic, but it has not been
+ * relocated there yet
+ */
void
-clientSetReplyToError(void *data,
- err_type err, http_status status, method_t method, char const *uri,
+clientReplyContext::setReplyToError(
+ err_type err, http_status status, method_t method, char const *uri,
- struct in_addr *addr, request_t * failedrequest, char *unparsedrequest,
- auth_user_request_t * auth_user_request)
+ struct in_addr *addr, request_t * failedrequest, char *unparsedrequest,
+ auth_user_request_t * auth_user_request)
{
- clientReplyContext *context = (clientReplyContext *)data;
ErrorState *errstate =
clientBuildError(err, status, uri, addr, failedrequest);
if (unparsedrequest)
errstate->request_hdrs = xstrdup(unparsedrequest);
- if (status == HTTP_NOT_IMPLEMENTED && context->http->request)
+ if (status == HTTP_NOT_IMPLEMENTED && http->request)
/* prevent confusion over whether we default to persistent or not */
- context->http->request->flags.proxy_keepalive = 0;
+ http->request->flags.proxy_keepalive = 0;
- context->http->al.http.code = errstate->httpStatus;
+ http->al.http.code = errstate->httpStatus;
- context->http->entry =
- clientCreateStoreEntry(context, method, request_flags());
+ createStoreEntry(method, request_flags());
if (auth_user_request)
{
}
assert(errstate->callback_data == NULL);
- errorAppendEntry(context->http->entry, errstate);
+ errorAppendEntry(http->entry, errstate);
/* Now the caller reads to get this */
}
void
-clientRemoveStoreReference(clientReplyContext * context, store_client ** scp,
- StoreEntry ** ep)
+clientReplyContext::removeStoreReference(store_client ** scp,
+ StoreEntry ** ep)
{
StoreEntry *e;
store_client *sc = *scp;
if ((e = *ep) != NULL) {
*ep = NULL;
- storeUnregister(sc, e, context);
+ storeUnregister(sc, e, this);
*scp = NULL;
storeUnlockObject(e);
}
{
/* derived classes with different sizes must implement their own new */
assert (byteCount == sizeof (clientReplyContext));
- CBDATA_INIT_TYPE_FREECB(clientReplyContext, clientReplyFree);
+ CBDATA_INIT_TYPE(clientReplyContext);
return cbdataAlloc(clientReplyContext);
}
cbdataFree (address);
}
+void
+clientReplyContext::deleteSelf() const
+{
+ delete this;
+}
void
-clientReplyContext::saveState(clientHttpRequest * http)
+clientReplyContext::saveState()
{
assert(old_sc == NULL);
debug(88, 3)("clientReplyContext::saveState: saving store context\n");
- http->old_entry = http->entry;
+ old_entry = http->entry;
old_sc = sc;
old_reqsize = reqsize;
tempBuffer.offset = reqofs;
}
void
-clientReplyContext::restoreState(clientHttpRequest * http)
+clientReplyContext::restoreState()
{
assert(old_sc != NULL);
debug(88, 3)("clientReplyContext::restoreState: Restoring store context\n");
- http->entry = http->old_entry;
+ removeStoreReference(&sc, &http->entry);
+ http->entry = old_entry;
sc = old_sc;
reqsize = old_reqsize;
reqofs = tempBuffer.offset;
/* Prevent accessed the old saved entries */
- http->old_entry = NULL;
+ old_entry = NULL;
old_sc = NULL;
old_reqsize = 0;
tempBuffer.offset = 0;
}
void
-startError(clientReplyContext * context, clientHttpRequest * http, ErrorState * err)
+clientReplyContext::startError(ErrorState * err)
{
- http->entry = clientCreateStoreEntry(context, http->request->method, request_flags());
- triggerInitialStoreReadWithClientParameters(context, http);
+ createStoreEntry(http->request->method, request_flags());
+ triggerInitialStoreRead();
errorAppendEntry(http->entry, err);
}
* header offset
*/
void
-triggerInitialStoreReadWithClientParameters(clientReplyContext * context, clientHttpRequest * http)
+clientReplyContext::triggerInitialStoreRead()
{
- clientStreamNode *next = (clientStreamNode *)http->client_stream.head->next->data;
StoreIOBuffer tempBuffer;
- /* collapse this to one object if we never tickle the assert */
- assert(context->http == http);
- /* when confident, 0 becomes context->reqofs, and then this factors into
+ /* when confident, 0 becomes reqofs, and then this factors into
* startSendProcess
*/
- assert(context->reqofs == 0);
+ assert(reqofs == 0);
tempBuffer.offset = 0;
- tempBuffer.length = next->readBuffer.length;
- tempBuffer.data = next->readBuffer.data;
- storeClientCopy(context->sc, http->entry, tempBuffer, clientSendMoreData, context);
+ tempBuffer.length = next()->readBuffer.length;
+ tempBuffer.data = next()->readBuffer.data;
+ storeClientCopy(sc, http->entry, tempBuffer, SendMoreData, this);
}
/* there is an expired entry in the store.
* setup a temporary buffer area and perform an IMS to the origin
*/
-static void
-clientProcessExpired(clientReplyContext * context)
+void
+clientReplyContext::processExpired()
{
- clientHttpRequest *http = context->http;
char *url = http->uri;
StoreEntry *entry = NULL;
- debug(88, 3)("clientProcessExpired: '%s'", http->uri);
+ debug(88, 3)("clientReplyContext::processExpired: '%s'", http->uri);
assert(http->entry->lastmod >= 0);
/*
* check if we are allowed to contact other servers
* a stale entry *if* it matches client requirements
*/
- if (clientOnlyIfCached(http)) {
- clientProcessOnlyIfCachedMiss(context);
+ if (http->onlyIfCached()) {
+ processOnlyIfCachedMiss();
return;
}
#if STORE_CLIENT_LIST_DEBUG
/* Prevent a race with the store client memory free routines
*/
- assert(storeClientIsThisAClient(context->sc, context));
+ assert(storeClientIsThisAClient(sc, this));
#endif
/* Prepare to make a new temporary request */
- context->saveState(http);
+ saveState();
entry = storeCreateEntry(url,
http->log_uri, http->request->flags, http->request->method);
/* NOTE, don't call storeLockObject(), storeCreateEntry() does it */
- context->sc = storeClientListAdd(entry, context);
+ sc = storeClientListAdd(entry, this);
#if DELAY_POOLS
/* delay_id is already set on original store client */
- context->sc->setDelayId(DelayId::DelayClient(http));
+ sc->setDelayId(DelayId::DelayClient(http));
#endif
- http->request->lastmod = http->old_entry->lastmod;
- debug(88, 5)("clientProcessExpired : lastmod %ld",
+ http->request->lastmod = old_entry->lastmod;
+ debug(88, 5)("clientReplyContext::processExpired : lastmod %ld",
(long int) entry->lastmod);
http->entry = entry;
assert(http->out.offset == 0);
/* Register with storage manager to receive updates when data comes in. */
if (EBIT_TEST(entry->flags, ENTRY_ABORTED))
- debug(88, 0) ("clientProcessExpired: Found ENTRY_ABORTED object");
+ debug(88, 0) ("clientReplyContext::processExpired: Found ENTRY_ABORTED object");
{
- StoreIOBuffer tempBuffer;
/* start counting the length from 0 */
- tempBuffer.offset = 0;
- tempBuffer.length = HTTP_REQBUF_SZ;
- tempBuffer.data = context->tempbuf;
- storeClientCopy(context->sc, entry,
- tempBuffer, clientHandleIMSReply, context);
- }
-}
-
-int
-modifiedSince(StoreEntry * entry, request_t * request)
-{
- int object_length;
- time_t mod_time = entry->lastmod;
- debug(88, 3) ("modifiedSince: '%s'\n", storeUrl(entry));
-
- if (mod_time < 0)
- mod_time = entry->timestamp;
-
- debug(88, 3) ("modifiedSince: mod_time = %ld\n", (long int) mod_time);
-
- if (mod_time < 0)
- return 1;
-
- /* Find size of the object */
- object_length = entry->getReply()->content_length;
-
- if (object_length < 0)
- object_length = contentLen(entry);
-
- if (mod_time > request->ims) {
- debug(88, 3) ("--> YES: entry newer than client\n");
- return 1;
- } else if (mod_time < request->ims) {
- debug(88, 3) ("--> NO: entry older than client\n");
- return 0;
- } else if (request->imslen < 0) {
- debug(88, 3) ("--> NO: same LMT, no client length\n");
- return 0;
- } else if (request->imslen == object_length) {
- debug(88, 3) ("--> NO: same LMT, same length\n");
- return 0;
- } else {
- debug(88, 3) ("--> YES: same LMT, different length\n");
- return 1;
+ StoreIOBuffer tempBuffer(HTTP_REQBUF_SZ, 0, tempbuf);
+ storeClientCopy(sc, entry, tempBuffer, HandleIMSReply, this);
}
}
-static int
-clientGetsOldEntry(StoreEntry * new_entry, StoreEntry * old_entry,
- request_t * request)
+bool
+clientReplyContext::clientGetsOldEntry()const
{
- const http_status status = new_entry->getReply()->sline.status;
+ const http_status status = http->entry->getReply()->sline.status;
if (0 == status) {
debug(88, 5) ("clientGetsOldEntry: YES, broken HTTP reply\n");
- return 1;
+ return true;
}
/* If the reply is a failure then send the old object as a last
* resort */
if (status >= 500 && status < 600) {
debug(88, 3) ("clientGetsOldEntry: YES, failure reply=%d\n", status);
- return 1;
+ return true;
}
/* If the reply is anything but "Not Modified" then
* we must forward it to the client */
if (HTTP_NOT_MODIFIED != status) {
debug(88, 5) ("clientGetsOldEntry: NO, reply=%d\n", status);
- return 0;
+ return false;
}
/* If the client did not send IMS in the request, then it
* must get the old object, not this "Not Modified" reply
* REGARDLESS of validation */
- if (!request->flags.ims) {
+ if (!http->request->flags.ims) {
debug(88, 5) ("clientGetsOldEntry: YES, no client IMS\n");
- return 1;
+ return true;
}
/* If key metadata in the reply are not consistent with the
/* This is a duplicate call through the HandleIMS code path.
* Can we guarantee we don't need it elsewhere?
*/
- if (!httpReplyValidatorsMatch(new_entry->getReply(),
+ if (!httpReplyValidatorsMatch(http->entry->getReply(),
old_entry->getReply())) {
debug(88, 5) ("clientGetsOldEntry: NO, Old object has been invalidated"
"by the new one\n");
- return 0;
+ return false;
}
/* If the client IMS time is prior to the entry LASTMOD time we
* need to send the old object */
- if (modifiedSince(old_entry, request)) {
+ if (old_entry->modifiedSince(http->request)) {
debug(88, 5) ("clientGetsOldEntry: YES, modified since %ld\n",
- (long int) request->ims);
- return 1;
+ (long int) http->request->ims);
+ return true;
}
debug(88, 5) ("clientGetsOldEntry: NO, new one is fine\n");
- return 0;
+ return false;
}
void
{
StoreIOBuffer tempresult;
http->logType = LOG_TCP_REFRESH_MISS;
- clientRemoveStoreReference(this, &old_sc, &http->old_entry);
+ removeStoreReference(&old_sc, &old_entry);
/* here the data to send is the data we just recieved */
tempBuffer.offset = 0;
old_reqsize = 0;
- /* clientSendMoreData tracks the offset as well.
+ /* sendMoreData tracks the offset as well.
* Force it back to zero */
reqofs = 0;
assert(!EBIT_TEST(http->entry->flags, ENTRY_ABORTED));
- /* TODO: provide SendMoreData with the ready parsed reply */
+ /* TODO: provide sendMoreData with the ready parsed reply */
tempresult.length = reqsize;
tempresult.data = tempbuf;
- clientSendMoreData(this, tempresult);
+ sendMoreData(tempresult);
}
void
-clientHandleIMSReply(void *data, StoreIOBuffer result)
+clientReplyContext::HandleIMSReply(void *data, StoreIOBuffer result)
{
clientReplyContext *context = (clientReplyContext *)data;
- clientHttpRequest *http = context->http;
- StoreEntry *entry = http->entry;
- const char *url = storeUrl(entry);
- int unlink_request = 0;
- StoreEntry *oldentry;
- http_status status;
- debug(88, 3) ("clientHandleIMSReply: %s, %lu bytes\n", url,
- (long unsigned) result.length);
-
- if (entry == NULL) {
- return;
- }
-
- if (result.flags.error && !EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
- return;
- }
+ context->handleIMSReply(result);
+}
- /* update size of the request */
- context->reqsize = result.length + context->reqofs;
+void
+clientReplyContext::sendClientOldEntry()
+{
+ /* Get the old request back */
+ restoreState();
+ /* here the data to send is in the next nodes buffers already */
+ assert(!EBIT_TEST(http->entry->flags, ENTRY_ABORTED));
+ /* sendMoreData tracks the offset as well.
+ * Force it back to zero */
+ reqofs = 0;
+ StoreIOBuffer tempresult (reqsize, reqofs, next()->readBuffer.data);
+ sendMoreData(tempresult);
+}
- status = entry->getReply()->sline.status;
+void
+clientReplyContext::cleanUpAfterIMSCheck()
+{
+ debug(88, 3) ("clientHandleIMSReply: ABORTED '%s'\n", storeUrl(http->entry));
+ /* We have an existing entry, but failed to validate it */
+ /* Its okay to send the old one anyway */
+ http->logType = LOG_TCP_REFRESH_FAIL_HIT;
+ sendClientOldEntry();
+}
- if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
- debug(88, 3) ("clientHandleIMSReply: ABORTED '%s'\n", url);
- /* We have an existing entry, but failed to validate it */
- /* Its okay to send the old one anyway */
+void
+clientReplyContext::handlePartialIMSHeaders()
+{
+ /* more headers needed to decide */
+ debug(88, 3) ("clientHandleIMSReply: Incomplete headers for '%s'\n",
+ storeUrl(http->entry));
+
+ if (reqsize >= HTTP_REQBUF_SZ) {
+ /* will not get any bigger than that */
+ debug(88, 3)
+ ("clientHandleIMSReply: Reply is too large '%s', using old entry\n",
+ storeUrl(http->entry));
+ /* use old entry, this repeats the code above */
http->logType = LOG_TCP_REFRESH_FAIL_HIT;
- clientRemoveStoreReference(context, &context->sc, &entry);
- /* Get the old request back */
- context->restoreState(http);
- entry = http->entry;
- return;
+ sendClientOldEntry();
+ } else {
+ reqofs = reqsize;
+ waitForMoreData();
}
+}
- if (STORE_PENDING == entry->store_status && 0 == status) {
- /* more headers needed to decide */
- debug(88, 3) ("clientHandleIMSReply: Incomplete headers for '%s'\n",
- url);
-
- if (result.length + context->reqsize >= HTTP_REQBUF_SZ) {
- /* will not get any bigger than that */
- debug(88, 3)
- ("clientHandleIMSReply: Reply is too large '%s', using old entry\n",
- url);
- /* use old entry, this repeats the code abovez */
- http->logType = LOG_TCP_REFRESH_FAIL_HIT;
- clientRemoveStoreReference(context, &context->sc, &entry);
- entry = http->entry = http->old_entry;
- /* Get the old request back */
- context->restoreState(http);
- entry = http->entry;
- } else {
- context->reqofs += result.length;
- context->waitForMoreData(result);
+void
+clientReplyContext::handleIMSGiveClientUpdatedOldEntry()
+{
+ /* We initiated the IMS request and the IMS is compatible with
+ * our object. As the client is not expecting
+ * 304, so put the good one back. First, make sure the old entry
+ * headers have been loaded from disk. */
+ http->logType = LOG_TCP_REFRESH_HIT;
+
+ if (httpReplyValidatorsMatch(http->entry->getReply(),
+ old_entry->getReply())) {
+ int unlink_request = 0;
+
+ if (old_entry->mem_obj->request == NULL) {
+ old_entry->mem_obj->request = requestLink(http->entry->mem_obj->request);
+ unlink_request = 1;
}
- return;
- }
-
- if (clientGetsOldEntry(entry, http->old_entry, http->request)) {
- /* We initiated the IMS request and the IMS is compatible with
- * our object. As the client is not expecting
- * 304, so put the good one back. First, make sure the old entry
- * headers have been loaded from disk. */
- clientStreamNode *next = (clientStreamNode *)context->http->client_stream.head->next->data;
- StoreIOBuffer tempresult;
- oldentry = http->old_entry;
- http->logType = LOG_TCP_REFRESH_HIT;
-
- if (httpReplyValidatorsMatch(entry->getReply(),
- http->old_entry->getReply())) {
- if (oldentry->mem_obj->request == NULL) {
- oldentry->mem_obj->request = requestLink(entry->mem_obj->request);
- unlink_request = 1;
- }
-
- /* Don't memcpy() the whole reply structure here. For example,
- * www.thegist.com (Netscape/1.13) returns a content-length for
- * 304's which seems to be the length of the 304 HEADERS!!! and
- * not the body they refer to. */
- httpReplyUpdateOnNotModified((HttpReply *)oldentry->getReply(), entry->getReply());
+ /* Don't memcpy() the whole reply structure here. For example,
+ * www.thegist.com (Netscape/1.13) returns a content-length for
+ * 304's which seems to be the length of the 304 HEADERS!!! and
+ * not the body they refer to. */
+ httpReplyUpdateOnNotModified((HttpReply *)old_entry->getReply(), http->entry->getReply());
- storeTimestampsSet(oldentry);
+ storeTimestampsSet(old_entry);
- clientRemoveStoreReference(context, &context->sc, &entry);
+ old_entry->timestamp = squid_curtime;
- oldentry->timestamp = squid_curtime;
-
- if (unlink_request) {
- requestUnlink(oldentry->mem_obj->request);
- oldentry->mem_obj->request = NULL;
- }
+ if (unlink_request) {
+ requestUnlink(old_entry->mem_obj->request);
+ old_entry->mem_obj->request = NULL;
}
+ }
- /* Get the old request back */
- context->restoreState(http);
+ sendClientOldEntry();
+}
+
+void
+clientReplyContext::handleIMSGiveClientNewEntry()
+{
+ /* The client gets the new entry,
+ * either as a 304 (they initiated the IMS) or
+ * as a full request from the upstream
+ * The new entry is *not* a 304 reply, or
+ * is a 304 that is incompatible with our cached entities.
+ */
- entry = http->entry;
+ if (http->request->flags.ims) {
+ /* The client asked for a IMS, and can deal
+ * with any reply
+ * XXX TODO: invalidate our object if it's not valid any more.
+ * Send the IMS reply to the client.
+ */
+ sendClientUpstreamResponse();
+ } else if (httpReplyValidatorsMatch (http->entry->getReply(),
+ old_entry->getReply())) {
+ /* Our object is usable once updated */
+ /* the client did not ask for IMS, send the whole object
+ */
+ /* the client needs to get this reply */
+ StoreIOBuffer tempresult;
+ http->logType = LOG_TCP_REFRESH_MISS;
- /* here the data to send is in the next nodes buffers already */
- assert(!EBIT_TEST(entry->flags, ENTRY_ABORTED));
+ if (HTTP_NOT_MODIFIED == http->entry->getReply()->sline.status) {
+ httpReplyUpdateOnNotModified((HttpReply *)old_entry->getReply(),
+ http->entry->getReply());
+ storeTimestampsSet(old_entry);
+ http->logType = LOG_TCP_REFRESH_HIT;
+ }
- tempresult.length = context->reqsize;
+ removeStoreReference(&old_sc, &old_entry);
+ /* here the data to send is the data we just recieved */
+ tempBuffer.offset = 0;
+ old_reqsize = 0;
+ /* clientSendMoreData tracks the offset as well.
+ * Force it back to zero */
+ reqofs = 0;
+ assert(!EBIT_TEST(http->entry->flags, ENTRY_ABORTED));
+ /* TODO: provide SendMoreData with the ready parsed reply */
+ tempresult.length = reqsize;
+ tempresult.data = tempbuf;
+ sendMoreData(tempresult);
+ } else {
+ /* the client asked for the whole object, and
+ * 1) our object was stale
+ * 2) our internally generated IMS failed to validate
+ * 3) the server sent incompatible headers in it's reply
+ */
+ http->logType = LOG_TCP_REFRESH_MISS;
+ processMiss();
+ /* We start over for everything except IMS because:
+ * 1) HEAD requests will go straight through now
+ * 2) GET requests will go straight through now
+ * 3) IMS requests are a corner case. If the server
+ * decided to give us different data, we should give
+ * that to the client, which means returning our IMS request.
+ */
+ }
+}
- tempresult.data = next->readBuffer.data;
+void
+clientReplyContext::handleIMSReply(StoreIOBuffer result)
+{
+ debug(88, 3) ("clientHandleIMSReply: %s, %lu bytes\n",
+ storeUrl(http->entry),
+ (long unsigned) result.length);
- clientSendMoreData(context, tempresult);
+ if (http->entry == NULL)
+ return;
+ if (result.flags.error && !EBIT_TEST(http->entry->flags, ENTRY_ABORTED))
return;
- } else {
- /* The client gets the new entry,
- * either as a 304 (they initiated the IMS) or
- * as a full request from the upstream
- * The new entry is *not* a 304 reply, or
- * is a 304 that is incompatible with our cached entities.
- */
- if (http->request->flags.ims) {
- /* The client asked for a IMS, and can deal
- * with any reply
- * XXX TODO: invalidate our object if it's not valid any more.
- * Send the IMS reply to the client.
- */
- context->sendClientUpstreamResponse();
- } else if (httpReplyValidatorsMatch (entry->getReply(),
- http->old_entry->getReply())) {
- /* Our object is usable once updated */
- /* the client did not ask for IMS, send the whole object
- */
- /* the client needs to get this reply */
- StoreIOBuffer tempresult;
- http->logType = LOG_TCP_REFRESH_MISS;
+ /* update size of the request */
+ reqsize = result.length + reqofs;
- if (HTTP_NOT_MODIFIED == entry->getReply()->sline.status) {
- httpReplyUpdateOnNotModified((HttpReply *)http->old_entry->getReply(),
- entry->getReply());
- storeTimestampsSet(http->old_entry);
- http->logType = LOG_TCP_REFRESH_HIT;
- }
+ http_status status = http->entry->getReply()->sline.status;
- clientRemoveStoreReference(context, &context->old_sc, &http->old_entry);
- /* here the data to send is the data we just recieved */
- context->tempBuffer.offset = 0;
- context->old_reqsize = 0;
- /* clientSendMoreData tracks the offset as well.
- * Force it back to zero */
- context->reqofs = 0;
- assert(!EBIT_TEST(entry->flags, ENTRY_ABORTED));
- /* TODO: provide SendMoreData with the ready parsed reply */
- tempresult.length = context->reqsize;
- tempresult.data = context->tempbuf;
- clientSendMoreData(context, tempresult);
- } else {
- /* the client asked for the whole object, and
- * 1) our object was stale
- * 2) our internally generated IMS failed to validate
- * 3) the server sent incompatible headers in it's reply
- */
- http->logType = LOG_TCP_REFRESH_MISS;
- clientProcessMiss(context);
- /* We start over for everything except IMS because:
- * 1) HEAD requests will go straight through now
- * 2) GET requests will go straight through now
- * 3) IMS requests are a corner case. If the server
- * decided to give us different data, we should give
- * that to the client, which means returning our IMS request.
- */
- }
- }
+ if (EBIT_TEST(http->entry->flags, ENTRY_ABORTED))
+ cleanUpAfterIMSCheck();
+ else if (STORE_PENDING == http->entry->store_status && 0 == status)
+ handlePartialIMSHeaders();
+ else if (clientGetsOldEntry())
+ handleIMSGiveClientUpdatedOldEntry();
+ else
+ handleIMSGiveClientNewEntry();
}
extern "C" CSR clientGetMoreData;
* clientCacheHit should only be called until the HTTP reply headers
* have been parsed. Normally this should be a single call, but
* it might take more than one. As soon as we have the headers,
- * we hand off to clientSendMoreData, clientProcessExpired, or
- * clientProcessMiss.
+ * we hand off to clientSendMoreData, processExpired, or
+ * processMiss.
*/
void
-clientCacheHit(void *data, StoreIOBuffer result)
+clientReplyContext::CacheHit(void *data, StoreIOBuffer result)
{
clientReplyContext *context = (clientReplyContext *)data;
- clientHttpRequest *http = context->http;
+ context->cacheHit (result);
+}
+
+void
+clientReplyContext::cacheHit(StoreIOBuffer result)
+{
StoreEntry *e = http->entry;
request_t *r = http->request;
debug(88, 3) ("clientCacheHit: %s, %ud bytes\n", http->uri, (unsigned int)result.length);
/* swap in failure */
debug(88, 3) ("clientCacheHit: swapin failure for %s\n", http->uri);
http->logType = LOG_TCP_SWAPFAIL_MISS;
- clientRemoveStoreReference(context, &context->sc, &http->entry);
- clientProcessMiss(context);
+ removeStoreReference(&sc, &http->entry);
+ processMiss();
return;
}
*/
/* treat as a miss */
http->logType = LOG_TCP_MISS;
- clientProcessMiss(context);
+ processMiss();
return;
}
assert(!EBIT_TEST(e->flags, ENTRY_ABORTED));
/* update size of the request */
- context->reqsize = result.length + context->reqofs;
+ reqsize = result.length + reqofs;
if (e->getReply()->sline.status == 0) {
/*
*/
if (e->mem_status == IN_MEMORY || e->store_status == STORE_OK) {
- clientProcessMiss(context);
- } else if (result.length + context->reqofs >= HTTP_REQBUF_SZ
+ processMiss();
+ } else if (result.length + reqofs >= HTTP_REQBUF_SZ
&& http->out.offset == 0) {
- clientProcessMiss(context);
+ processMiss();
} else {
- clientStreamNode *next;
- StoreIOBuffer tempBuffer;
debug(88, 3) ("clientCacheHit: waiting for HTTP reply headers\n");
- context->reqofs += result.length;
- assert(context->reqofs <= HTTP_REQBUF_SZ);
+ reqofs += result.length;
+ assert(reqofs <= HTTP_REQBUF_SZ);
/* get the next users' buffer */
- /* FIXME: HTTP_REQBUF_SZ must be wrong here ??!
- */
- next = (clientStreamNode *)context->http->client_stream.head->next->data;
- tempBuffer.offset = http->out.offset + context->reqofs;
- tempBuffer.length = HTTP_REQBUF_SZ;
- tempBuffer.data = next->readBuffer.data + context->reqofs;
- storeClientCopy(context->sc, e,
- tempBuffer, clientCacheHit, context);
+ StoreIOBuffer tempBuffer;
+ tempBuffer.offset = http->out.offset + reqofs;
+ tempBuffer.length = next()->readBuffer.length - reqofs;
+ tempBuffer.data = next()->readBuffer.data + reqofs;
+ storeClientCopy(sc, e,
+ tempBuffer, CacheHit, this);
}
return;
/* This is not the correct entity for this request. We need
* to requery the cache.
*/
- clientRemoveStoreReference(context, &context->sc, &http->entry);
+ removeStoreReference(&sc, &http->entry);
e = NULL;
/* Note: varyEvalyateMatch updates the request with vary information
* so we only get here once. (it also takes care of cancelling loops)
*/
debug(88, 2) ("clientProcessHit: Vary detected!\n");
- clientGetMoreData(context->ourNode, http);
+ clientGetMoreData(ourNode, http);
return;
case VARY_CANCEL:
/* varyEvaluateMatch found a object loop. Process as miss */
debug(88, 1) ("clientProcessHit: Vary object loop!\n");
- clientProcessMiss(context);
+ processMiss();
return;
}
if (r->method == METHOD_PURGE) {
- clientRemoveStoreReference(context, &context->sc, &http->entry);
+ removeStoreReference(&sc, &http->entry);
e = NULL;
- context->purgeRequest();
+ purgeRequest();
return;
}
if (storeCheckNegativeHit(e)) {
http->logType = LOG_TCP_NEGATIVE_HIT;
- clientSendMoreData(context, result);
+ sendMoreData(result);
} else if (!Config.onoff.offline && refreshCheckHTTP(e, r) && !http->flags.internal) {
debug(88, 5) ("clientCacheHit: in refreshCheck() block\n");
/*
* we cannot revalidate it.
*/
http->logType = LOG_TCP_MISS;
- clientProcessMiss(context);
+ processMiss();
} else if (r->flags.nocache) {
/*
* This did not match a refresh pattern that overrides no-cache
* we should honour the client no-cache header.
*/
http->logType = LOG_TCP_CLIENT_REFRESH_MISS;
- clientProcessMiss(context);
+ processMiss();
} else if (r->protocol == PROTO_HTTP) {
/*
* Object needs to be revalidated
* XXX This could apply to FTP as well, if Last-Modified is known.
*/
http->logType = LOG_TCP_REFRESH_MISS;
- clientProcessExpired(context);
+ processExpired();
} else {
/*
* We don't know how to re-validate other protocols. Handle
* them as if the object has expired.
*/
http->logType = LOG_TCP_MISS;
- clientProcessMiss(context);
+ processMiss();
}
} else if (r->flags.ims) {
/*
debug(88, 4) ("clientCacheHit: Reply code %d != 200\n",
e->getReply()->sline.status);
http->logType = LOG_TCP_MISS;
- clientProcessMiss(context);
- } else if (modifiedSince(e, http->request)) {
+ processMiss();
+ } else if (e->modifiedSince(http->request)) {
http->logType = LOG_TCP_IMS_HIT;
- clientSendMoreData(context, result);
+ sendMoreData(result);
} else {
- time_t timestamp = e->timestamp;
+ time_t const timestamp = e->timestamp;
HttpReply *temprep = httpReplyMake304 (e->getReply());
http->logType = LOG_TCP_IMS_HIT;
- clientRemoveStoreReference(context, &context->sc, &http->entry);
- http->entry = e =
- clientCreateStoreEntry(context, http->request->method,
- request_flags());
+ removeStoreReference(&sc, &http->entry);
+ createStoreEntry(http->request->method,
+ request_flags());
+ e = http->entry;
/*
* Copy timestamp from the original entry so the 304
* reply has a meaningful Age: header.
* Simply mark the request complete in our context and
* write the reply struct to the client side
*/
- triggerInitialStoreReadWithClientParameters(context, http);
+ triggerInitialStoreRead();
}
} else {
/*
else if (Config.onoff.offline)
http->logType = LOG_TCP_OFFLINE_HIT;
- clientSendMoreData(context, result);
+ sendMoreData(result);
}
}
* Prepare to fetch the object as it's a cache miss of some kind.
*/
void
-clientProcessMiss(clientReplyContext * context)
+clientReplyContext::processMiss()
{
- clientHttpRequest *http = context->http;
char *url = http->uri;
request_t *r = http->request;
ErrorState *err = NULL;
storeEntryDump(http->entry, 1);
}
- clientRemoveStoreReference(context, &context->sc, &http->entry);
+ removeStoreReference(&sc, &http->entry);
}
if (r->method == METHOD_PURGE) {
- context->purgeRequest();
+ purgeRequest();
return;
}
- if (clientOnlyIfCached(http)) {
- clientProcessOnlyIfCachedMiss(context);
+ if (http->onlyIfCached()) {
+ processOnlyIfCachedMiss();
return;
}
err =
clientBuildError(ERR_ACCESS_DENIED, HTTP_FORBIDDEN, NULL,
&http->conn->peer.sin_addr, http->request);
- http->entry =
- clientCreateStoreEntry(context, r->method, request_flags());
+ createStoreEntry(r->method, request_flags());
errorAppendEntry(http->entry, err);
- triggerInitialStoreReadWithClientParameters(context, http);
+ triggerInitialStoreRead();
return;
} else {
assert(http->out.offset == 0);
- http->entry = clientCreateStoreEntry(context, r->method, r->flags);
- triggerInitialStoreReadWithClientParameters(context, http);
+ createStoreEntry(r->method, r->flags);
+ triggerInitialStoreRead();
if (http->redirect.status) {
HttpReply *rep = httpReplyCreate();
* contacting other servers;
* respond with a 504 (Gateway Timeout) as suggested in [RFC 2068]
*/
-static void
-clientProcessOnlyIfCachedMiss(clientReplyContext * context)
+void
+clientReplyContext::processOnlyIfCachedMiss()
{
- clientHttpRequest *http = context->http;
- char *url = http->uri;
- request_t *r = http->request;
ErrorState *err = NULL;
debug(88, 4) ("clientProcessOnlyIfCachedMiss: '%s %s'\n",
- RequestMethodStr[r->method], url);
+ RequestMethodStr[http->request->method], http->uri);
http->al.http.code = HTTP_GATEWAY_TIMEOUT;
err = clientBuildError(ERR_ONLY_IF_CACHED_MISS, HTTP_GATEWAY_TIMEOUT, NULL,
&http->conn->peer.sin_addr, http->request);
- clientRemoveStoreReference(context, &context->sc, &http->entry);
- startError(context, http, err);
+ removeStoreReference(&sc, &http->entry);
+ startError(err);
}
void
http->logType = LOG_TCP_HIT;
reqofs = 0;
tempBuffer.offset = http->out.offset;
- clientStreamNode *next = (clientStreamNode *)http->client_stream.head->next->data;
- tempBuffer.length = next->readBuffer.length;
- tempBuffer.data = next->readBuffer.data;
+ tempBuffer.length = next()->readBuffer.length;
+ tempBuffer.data = next()->readBuffer.data;
storeClientCopy(sc, http->entry,
- tempBuffer, clientCacheHit, this);
+ tempBuffer, CacheHit, this);
}
void
ErrorState *err =
clientBuildError(ERR_ACCESS_DENIED, HTTP_FORBIDDEN, NULL,
&http->conn->peer.sin_addr, http->request);
- startError(this, http, err);
+ startError(err);
return;
}
/* FIXME: This doesn't need to go through the store. Simply
* push down the client chain
*/
- http->entry =
- clientCreateStoreEntry(this, http->request->method,
- request_flags());
+ createStoreEntry(http->request->method, request_flags());
- triggerInitialStoreReadWithClientParameters(this, http);
+ triggerInitialStoreRead();
r = httpReplyCreate();
}
void
-clientTraceReply(clientStreamNode * node, clientReplyContext * context)
+clientReplyContext::traceReply(clientStreamNode * node)
{
HttpReply *rep;
http_version_t version;
clientStreamNode *next = (clientStreamNode *)node->node.next->data;
StoreIOBuffer tempBuffer;
- assert(context->http->request->max_forwards == 0);
- context->http->entry =
- clientCreateStoreEntry(context, context->http->request->method,
- request_flags());
- tempBuffer.offset = next->readBuffer.offset + context->headers_sz;
+ assert(http->request->max_forwards == 0);
+ createStoreEntry(http->request->method, request_flags());
+ tempBuffer.offset = next->readBuffer.offset + headers_sz;
tempBuffer.length = next->readBuffer.length;
tempBuffer.data = next->readBuffer.data;
- storeClientCopy(context->sc, context->http->entry,
- tempBuffer, clientSendMoreData, context);
- storeReleaseRequest(context->http->entry);
- storeBuffer(context->http->entry);
+ storeClientCopy(sc, http->entry,
+ tempBuffer, SendMoreData, this);
+ storeReleaseRequest(http->entry);
+ storeBuffer(http->entry);
rep = httpReplyCreate();
httpBuildVersion(&version, 1, 0);
httpReplySetHeaders(rep, version, HTTP_OK, NULL, "text/plain",
- httpRequestPrefixLen(context->http->request), 0, squid_curtime);
- httpReplySwapOut(rep, context->http->entry);
- httpRequestSwapOut(context->http->request, context->http->entry);
- context->http->entry->complete();
+ httpRequestPrefixLen(http->request), 0, squid_curtime);
+ httpReplySwapOut(rep, http->entry);
+ httpRequestSwapOut(http->request, http->entry);
+ http->entry->complete();
}
#define SENDING_BODY 0
#define SENDING_HDRSONLY 1
int
-clientCheckTransferDone(clientReplyContext * context)
+clientReplyContext::checkTransferDone()
{
- StoreEntry *entry = context->http->entry;
+ StoreEntry *entry = http->entry;
if (entry == NULL)
return 0;
* For now, 'done_copying' is used for special cases like
* Range and HEAD requests.
*/
- if (context->http->flags.done_copying)
+ if (http->flags.done_copying)
return 1;
/*
* RC: Yes.
*/
if (entry->store_status == STORE_OK) {
- return context->storeOKTransferDone();
+ return storeOKTransferDone();
} else {
- return context->storeNotOKTransferDone();
+ return storeNotOKTransferDone();
}
}
}
-
-int
-clientGotNotEnough(clientHttpRequest const *http)
-{
- int cl =
- httpReplyBodySize(http->request->method, http->entry->mem_obj->getReply());
- assert(cl >= 0);
-
- if (http->out.offset < cl)
- return 1;
-
- return 0;
-}
-
-
/* A write has completed, what is the next status based on the
* canonical request data?
* 1 something is wrong
clientStream_status_t
clientReplyStatus(clientStreamNode * aNode, clientHttpRequest * http)
{
- clientReplyContext *context = (clientReplyContext *)aNode->data;
+ clientReplyContext *context = dynamic_cast<clientReplyContext *>(aNode->data.getRaw());
+ assert (context);
+ assert (context->http == http);
+ return context->replyStatus();
+}
+
+clientStream_status_t
+clientReplyContext::replyStatus()
+{
int done;
/* Here because lower nodes don't need it */
*/
return STREAM_FAILED;
- if ((done = clientCheckTransferDone(context)) != 0 || context->flags.complete) {
+ if ((done = checkTransferDone()) != 0 || flags.complete) {
debug(88, 5) ("clientReplyStatus: transfer is DONE\n");
/* Ok we're finished, but how? */
return STREAM_FAILED;
}
- if (clientGotNotEnough(http)) {
+ if (!http->gotEnough()) {
debug(88, 5) ("clientReplyStatus: client didn't get all it expected\n");
return STREAM_UNPLANNED_COMPLETE;
}
return STREAM_UNPLANNED_COMPLETE;
}
- if (clientReplyBodyTooLarge(http->entry->getReply(), http->out.offset)) {
+ if (http->entry->getReply()->isBodyTooLarge(http->out.offset)) {
debug(88, 5) ("clientReplyStatus: client reply body is too large\n");
return STREAM_FAILED;
}
* can choose to block these responses where appropriate, but won't get
* mysterious breakages.
*/
-static int
-clientAlwaysAllowResponse(http_status sline)
+bool
+clientReplyContext::alwaysAllowResponse(http_status sline) const
{
switch (sline) {
case HTTP_NO_CONTENT:
case HTTP_NOT_MODIFIED:
- return 1;
+ return true;
/* unreached */
break;
default:
- return 0;
+ return false;
}
}
void
-clientObeyConnectionHeader(clientHttpRequest * http, HttpReply * rep)
+clientReplyContext::obeyConnectionHeader()
{
- HttpHeader *hdr = &rep->header;
+ HttpHeader *hdr = &holdingReply->header;
if (httpHeaderHas(hdr, HDR_CONNECTION)) {
/* anything that matches Connection list member will be deleted */
* adds extra entries if we have more info than origin server
* adds Squid specific entries
*/
-static void
-clientBuildReplyHeader(clientReplyContext *context, HttpReply * rep)
+void
+clientReplyContext::buildReplyHeader()
{
- clientHttpRequest * http = context->http;
- HttpHeader *hdr = &rep->header;
+ HttpHeader *hdr = &holdingReply->header;
int is_hit = logTypeIsATcpHit(http->logType);
request_t *request = http->request;
#if DONT_FILTER_THESE
if (is_hit)
httpHeaderDelById(hdr, HDR_SET_COOKIE);
- clientObeyConnectionHeader(http, rep);
+ obeyConnectionHeader();
// if (request->range)
- // clientBuildRangeHeader(http, rep);
+ // clientBuildRangeHeader(http, holdingReply);
/*
* Add a estimated Age header on cache hits.
*/
/* Handle authentication headers */
if (request->auth_user_request)
- authenticateFixHeader(rep, request->auth_user_request, request,
+ authenticateFixHeader(holdingReply, request->auth_user_request, request,
http->flags.accel, 0);
/* Append X-Cache */
#if USE_CACHE_DIGESTS
/* Append X-Cache-Lookup: -- temporary hack, to be removed @?@ @?@ */
httpHeaderPutStrf(hdr, HDR_X_CACHE_LOOKUP, "%s from %s:%d",
- context->lookup_type ? context->lookup_type : "NONE",
+ lookup_type ? lookup_type : "NONE",
getMyHostname(), getMyPort());
#endif
- if (httpReplyBodySize(request->method, rep) < 0) {
+ if (httpReplyBodySize(request->method, holdingReply) < 0) {
debug(88,
3)
("clientBuildReplyHeader: can't keep-alive, unknown body size\n");
LOCAL_ARRAY(char, bbuf, MAX_URL + 32);
String strVia = httpHeaderGetList(hdr, HDR_VIA);
snprintf(bbuf, sizeof(bbuf), "%d.%d %s",
- rep->sline.version.major,
- rep->sline.version.minor,
+ holdingReply->sline.version.major,
+ holdingReply->sline.version.minor,
ThisCache);
strListAdd(&strVia, bbuf, ',');
httpHeaderDelById(hdr, HDR_VIA);
}
-static HttpReply *
-clientBuildReply(clientReplyContext *context, const char *buf, size_t size)
+void
+clientReplyContext::buildReply(const char *buf, size_t size)
{
- HttpReply *rep = httpReplyCreate();
size_t k = headersEnd(buf, size);
- if (k && httpReplyParse(rep, buf, k)) {
- /* enforce 1.0 reply version */
- httpBuildVersion(&rep->sline.version, 1, 0);
- /* do header conversions */
- clientBuildReplyHeader(context, rep);
- } else {
+ if (!k)
+ return;
+
+ holdReply(httpReplyCreate());
+
+ if (!httpReplyParse(holdingReply, buf, k)) {
/* parsing failure, get rid of the invalid reply */
- httpReplyDestroy(rep);
- rep = NULL;
+ httpReplyDestroy(holdingReply);
+ holdReply (NULL);
/* This is wrong. httpReplyDestroy should to the rep
* for us, and we can destroy our own range info
*/
- if (context->http->request->range) {
+ if (http->request->range) {
/* this will fail and destroy request->range */
- // clientBuildRangeHeader(context->http, rep);
+ // clientBuildRangeHeader(http, holdingReply);
}
}
- return rep;
+ /* enforce 1.0 reply version */
+ httpBuildVersion(&holdingReply->sline.version, 1, 0);
+
+ /* do header conversions */
+ buildReplyHeader();
}
void
void
clientGetMoreData(clientStreamNode * aNode, clientHttpRequest * http)
{
- clientStreamNode *next;
- clientReplyContext *context;
/* Test preconditions */
assert(aNode != NULL);
assert(cbdataReferenceValid(aNode));
- assert(aNode->data != NULL);
assert(aNode->node.prev == NULL);
assert(aNode->node.next != NULL);
- context = (clientReplyContext *)aNode->data;
+ clientReplyContext *context = dynamic_cast<clientReplyContext *>(aNode->data.getRaw());
+ assert (context);
assert(context->http == http);
- next = ( clientStreamNode *)aNode->node.next->data;
+ clientStreamNode *next = ( clientStreamNode *)aNode->node.next->data;
if (!context->ourNode)
context->ourNode = aNode;
tempBuffer.data = next->readBuffer.data;
storeClientCopy(context->sc, http->entry,
- tempBuffer, clientSendMoreData, context);
+ tempBuffer, clientReplyContext::SendMoreData, context);
return;
}
if (context->http->request->method == METHOD_TRACE) {
if (context->http->request->max_forwards == 0) {
- clientTraceReply(aNode, context);
+ context->traceReply(aNode);
return;
}
tempBuffer.length = getNextNode()->readBuffer.length;
tempBuffer.data = getNextNode()->readBuffer.data;
storeClientCopy(sc, http->entry,
- tempBuffer, clientCacheHit, this);
+ tempBuffer, CacheHit, this);
} else {
/* MISS CASE, http->logType is already set! */
- clientProcessMiss(this);
+ processMiss();
}
}
clientReplyDetach(clientStreamNode * node, clientHttpRequest * http)
{
/* detach from the stream */
- /* NB: This cbdataFrees our context,
- * so the clientSendMoreData callback (if any)
- * pending in the store will not trigger
- */
clientStreamDetach(node, http);
}
* such, writes processed message to the message recipient
*/
void
-clientSendMoreData(void *data, StoreIOBuffer result)
-{
- clientReplyContext::clientSendMoreData (data, result);
-}
-
-void
-clientReplyContext::clientSendMoreData (void *data, StoreIOBuffer result)
+clientReplyContext::SendMoreData(void *data, StoreIOBuffer result)
{
clientReplyContext *context = static_cast<clientReplyContext *>(data);
context->sendMoreData (result);
}
void
-clientReplyContext::waitForMoreData (StoreIOBuffer const &result)
+clientReplyContext::waitForMoreData ()
{
debug(88,5)("clientReplyContext::waitForMoreData: Waiting for more data to parse reply headers in client side.\n");
/* We don't have enough to parse the metadata yet */
void
clientReplyContext::startSendProcess()
{
- debug(88,5)("clientReplyContext::startSendProcess: triggering store read to clientSendMoreData\n");
+ debug(88,5)("clientReplyContext::startSendProcess: triggering store read to SendMoreData\n");
assert(reqofs <= HTTP_REQBUF_SZ);
/* TODO: copy into the supplied buffer */
StoreIOBuffer tempBuffer;
tempBuffer.length = next()->readBuffer.length - reqofs;
tempBuffer.data = next()->readBuffer.data + reqofs;
storeClientCopy(sc, http->entry,
- tempBuffer, clientSendMoreData, this);
+ tempBuffer, SendMoreData, this);
+}
+
+void
+clientReplyContext::holdReply(HttpReply *aReply)
+{
+ assert (!holdingReply || !aReply);
+ holdingReply = aReply;
}
void
clientReplyContext::processReplyAccess ()
{
HttpReply *rep = holdingReply;
- holdingReply = NULL;
+ holdReply(NULL);
httpReplyBodyBuildSize(http->request, rep, &Config.ReplyBodySize);
- if (clientReplyBodyTooLarge(rep, rep->content_length)) {
+ if (rep->isBodyTooLarge(rep->content_length)) {
ErrorState *err =
clientBuildError(ERR_TOO_BIG, HTTP_FORBIDDEN, NULL,
http->conn ? &http->conn->peer.sin_addr : &no_addr,
http->request);
- clientRemoveStoreReference(this, &sc, &http->entry);
- startError(this, http, err);
+ removeStoreReference(&sc, &http->entry);
+ startError(err);
httpReplyDestroy(rep);
return;
}
ACLChecklist *replyChecklist;
replyChecklist = clientAclChecklistCreate(Config.accessList.reply, http);
replyChecklist->reply = rep;
- holdingReply = rep;
- replyChecklist->nonBlockingCheck(ProcessReply, this);
+ holdReply (rep);
+ replyChecklist->nonBlockingCheck(ProcessReplyAccessResult, this);
}
void
-clientReplyContext::ProcessReply (int rv, void *voidMe)
+clientReplyContext::ProcessReplyAccessResult (int rv, void *voidMe)
{
clientReplyContext *me = static_cast<clientReplyContext *>(voidMe);
- me->processReply(rv);
+ me->processReplyAccessResult(rv);
}
void
-clientReplyContext::processReply(bool accessAllowed)
+clientReplyContext::processReplyAccessResult(bool accessAllowed)
{
debug(88, 2) ("The reply for %s %s is %s, because it matched '%s'\n",
RequestMethodStr[http->request->method], http->uri,
accessAllowed ? "ALLOWED" : "DENIED",
AclMatchedName ? AclMatchedName : "NO ACL's");
HttpReply *rep = holdingReply;
- holdingReply = NULL;
+ holdReply (NULL);
if (!accessAllowed && rep->sline.status != HTTP_FORBIDDEN
- && !clientAlwaysAllowResponse(rep->sline.status)) {
+ && !alwaysAllowResponse(rep->sline.status)) {
/* the if above is slightly broken, but there is no way
* to tell if this is a squid generated error page, or one from
* upstream at this point. */
clientBuildError(ERR_ACCESS_DENIED, HTTP_FORBIDDEN, NULL,
http->conn ? &http->conn->peer.sin_addr : &no_addr,
http->request);
- clientRemoveStoreReference(this, &sc, &http->entry);
- startError(this, http, err);
+ removeStoreReference(&sc, &http->entry);
+ startError(err);
httpReplyDestroy(rep);
return;
}
ssize_t body_size = reqofs - rep->hdr_sz;
assert(body_size >= 0);
debug(88,3)
- ("clientSendMoreData: Appending %d bytes after %d bytes of headers\n",
+ ("clientReplyContext::sendMoreData: Appending %d bytes after %d bytes of headers\n",
(int) body_size, rep->hdr_sz);
#if ESI
if (http->flags.accel && rep->sline.status != HTTP_FORBIDDEN &&
- !clientAlwaysAllowResponse(rep->sline.status) &&
+ !alwaysAllowResponse(rep->sline.status) &&
esiEnableProcessing(rep)) {
debug(88, 2) ("Enabling ESI processing for %s\n", http->uri);
clientStreamInsertHead(&http->client_stream, esiStreamRead,
tempBuffer.data = body_buf;
}
- /* TODO: move the data in the buffer back by the request header size */
+ /* TODO??: move the data in the buffer back by the request header size */
clientStreamCallback((clientStreamNode *)http->client_stream.head->data,
http, rep, tempBuffer);
StoreEntry *entry = http->entry;
ConnStateData *conn = http->conn;
int fd = conn ? conn->fd : -1;
- HttpReply *rep = NULL;
char *buf = next()->readBuffer.data;
char *body_buf = buf;
makeThisHead();
- debug(88, 5) ("clientSendMoreData: %s, %d bytes (%u new bytes)\n",
+ debug(88, 5) ("clientReplyContext::sendMoreData: %s, %d bytes (%u new bytes)\n",
http->uri, (int) reqofs, (unsigned int)result.length);
- debug(88, 5) ("clientSendMoreData: FD %d '%s', out.offset=%ld \n",
+ debug(88, 5) ("clientReplyContext::sendMoreData: FD %d '%s', out.offset=%ld \n",
fd, storeUrl(entry), (long int) http->out.offset);
/* update size of the request */
}
}
- rep = clientBuildReply(this, buf, reqofs);
+ buildReply(buf, reqofs);
ssize_t body_size = reqofs;
- if (rep) {
- holdingReply = rep;
+ if (holdingReply) {
holdingBuffer = result;
processReplyAccess ();
return;
} else if (reqofs < HTTP_REQBUF_SZ && entry->store_status == STORE_PENDING) {
- waitForMoreData(result);
+ waitForMoreData();
return;
} else if (http->request->method == METHOD_HEAD) {
/*
* If we are here, then store_status == STORE_OK and it
* seems we have a HEAD repsponse which is missing the
* empty end-of-headers line (home.mira.net, phttpd/0.99.72
- * does this). Because clientBuildReply() fails we just
+ * does this). Because buildReply() fails we just
* call this reply a body, set the done_copying flag and
* continue...
*/
*/
http->request->flags.proxy_keepalive = 0;
- StoreIOBuffer tempBuffer;
assert(body_buf && body_size);
- tempBuffer.length = body_size;
- tempBuffer.data = body_buf;
+ StoreIOBuffer tempBuffer (body_size, 0 ,body_buf);
clientStreamCallback((clientStreamNode *)http->client_stream.head->data,
http, NULL, tempBuffer);
} else {
debug (88,0)("clientReplyContext::sendMoreData: Unable to parse reply headers within a single HTTP_REQBUF_SZ length buffer\n");
StoreIOBuffer tempBuffer;
tempBuffer.flags.error = 1;
+ /* XXX FIXME: make an html error page here */
sendStreamError(tempBuffer);
return;
}
fatal ("clientReplyContext::sendMoreData: Unreachable code reached \n");
}
-int
-clientReplyBodyTooLarge(HttpReply const * rep, ssize_t clen)
-{
- if (0 == rep->maxBodySize)
- return 0; /* disabled */
-
- if (clen < 0)
- return 0; /* unknown */
- if ((unsigned int)clen > rep->maxBodySize)
- return 1; /* too large */
-
- return 0;
-}
-
-/*
- * returns true if client specified that the object must come from the cache
- * without contacting origin server
- */
-static int
-clientOnlyIfCached(clientHttpRequest * http)
-{
- const request_t *r = http->request;
- assert(r);
- return r->cache_control &&
- EBIT_TEST(r->cache_control->mask, CC_ONLY_IF_CACHED);
-}
/* Using this breaks the client layering just a little!
*/
-StoreEntry *
-clientCreateStoreEntry(clientReplyContext * context, method_t m,
- request_flags flags)
+void
+clientReplyContext::createStoreEntry(method_t m, request_flags flags)
{
- clientHttpRequest *h = context->http;
- StoreEntry *e;
- assert(h != NULL);
+ assert(http != NULL);
/*
* For erroneous requests, we might not have a h->request,
* so make a fake one.
*/
- if (h->request == NULL)
- h->request = requestLink(requestCreate(m, PROTO_NONE, null_string));
+ if (http->request == NULL)
+ http->request = requestLink(requestCreate(m, PROTO_NONE, null_string));
- e = storeCreateEntry(h->uri, h->log_uri, flags, m);
+ StoreEntry *e = storeCreateEntry(http->uri, http->log_uri, flags, m);
- context->sc = storeClientListAdd(e, context);
+ sc = storeClientListAdd(e, this);
#if DELAY_POOLS
- context->sc->setDelayId(DelayId::DelayClient(h));
+ sc->setDelayId(DelayId::DelayClient(http));
#endif
- context->reqofs = 0;
+ reqofs = 0;
- context->reqsize = 0;
+ reqsize = 0;
/* I don't think this is actually needed! -- adrian */
- /* h->reqbuf = h->norm_reqbuf; */
- // assert(h->reqbuf == h->norm_reqbuf);
+ /* http->reqbuf = http->norm_reqbuf; */
+ // assert(http->reqbuf == http->norm_reqbuf);
/* The next line is illegal because we don't know if the client stream
* buffers have been set up
*/
- // storeClientCopy(h->sc, e, 0, HTTP_REQBUF_SZ, h->reqbuf,
- // clientSendMoreData, context);
+ // storeClientCopy(http->sc, e, 0, HTTP_REQBUF_SZ, http->reqbuf,
+ // SendMoreData, this);
/* So, we mark the store logic as complete */
- context->flags.storelogiccomplete = 1;
+ this->flags.storelogiccomplete = 1;
/* and get the caller to request a read, from whereever they are */
/* NOTE: after ANY data flows down the pipe, even one step,
* this function CAN NOT be used to manage errors
*/
- return e;
+ http->entry = e;
}
ErrorState *
/*
- * $Id: client_side_request.cc,v 1.19 2003/03/04 01:40:27 robertc Exp $
+ * $Id: client_side_request.cc,v 1.20 2003/03/15 04:17:39 robertc Exp $
*
* DEBUG: section 85 Client-side Request Routines
* AUTHOR: Robert Collins (Originally Duane Wessels in client_side.c)
#include "ACLChecklist.h"
#include "ACL.h"
#include "client_side.h"
+#include "client_side_reply.h"
+#include "Store.h"
+#include "HttpReply.h"
#if LINGERING_CLOSE
#define comm_close comm_lingering_close
static const char *const crlf = "\r\n";
-class ClientRequestContext
+class ClientRequestContext : public RefCountable
{
public:
start = current_time;
}
+/*
+ * returns true if client specified that the object must come from the cache
+ * without contacting origin server
+ */
+bool
+ClientHttpRequest::onlyIfCached()const
+{
+ assert(request);
+ return request->cache_control &&
+ EBIT_TEST(request->cache_control->mask, CC_ONLY_IF_CACHED);
+}
+
/*
* This function is designed to serve a fairly specific purpose.
* Occasionally our vBNS-connected caches can talk to each other, but not
*/
int /* returns nonzero on failure */
clientBeginRequest(method_t method, char const *url, CSCB * streamcallback,
- CSD * streamdetach, void *streamdata, HttpHeader const *header,
+ CSD * streamdetach, ClientStreamData streamdata, HttpHeader const *header,
char *tailbuf, size_t taillen)
{
size_t url_sz;
tempBuffer.data = tailbuf;
/* client stream setup */
clientStreamInit(&http->client_stream, clientGetMoreData, clientReplyDetach,
- clientReplyStatus, clientReplyNewContext(http), streamcallback,
+ clientReplyStatus, new clientReplyContext(http), streamcallback,
streamdetach, streamdata, tempBuffer);
/* make it visible in the 'current acctive requests list' */
dlinkAdd(http, &http->active, &ClientActiveRequests);
page_id = ERR_ACCESS_DENIED;
}
- clientSetReplyToError(node->data, page_id, status,
- http->request->method, NULL,
- http->conn ? &http->conn->peer.sin_addr : &no_addr, http->request,
- NULL, http->conn
- && http->conn->auth_user_request ? http->conn->
- auth_user_request : http->request->auth_user_request);
+ clientReplyContext *repContext = dynamic_cast<clientReplyContext *>(node->data.getRaw());
+ assert (repContext);
+ repContext->setReplyToError(page_id, status,
+ http->request->method, NULL,
+ http->conn ? &http->conn->peer.sin_addr : &no_addr, http->request,
+ NULL, http->conn
+ && http->conn->auth_user_request ? http->conn->
+ auth_user_request : http->request->auth_user_request);
node = (clientStreamNode *)http->client_stream.tail->data;
clientStreamRead(node, http, node->readBuffer);
}
clientStreamNode *node = (clientStreamNode *)client_stream.tail->data;
clientStreamRead(node, this, node->readBuffer);
}
+
+bool
+ClientHttpRequest::gotEnough() const
+{
+ int contentLength =
+ httpReplyBodySize(request->method, entry->mem_obj->getReply());
+ assert(contentLength >= 0);
+
+ if (out.offset < contentLength)
+ return false;
+
+ return true;
+}
+
/*
- * $Id: client_side_request.h,v 1.8 2003/02/22 14:59:34 hno Exp $
+ * $Id: client_side_request.h,v 1.9 2003/03/15 04:17:39 robertc Exp $
*
*
* SQUID Web Proxy Cache http://www.squid-cache.org/
#include "clientStream.h"
/* client_side_request.c - client side request related routines (pure logic) */
-extern int clientBeginRequest(method_t, char const *, CSCB *, CSD *, void *, HttpHeader const *, char *, size_t);
+extern int clientBeginRequest(method_t, char const *, CSCB *, CSD *, ClientStreamData, HttpHeader const *, char *, size_t);
class MemObject;
bool multipartRangeRequest() const;
void processRequest();
void httpStart();
+ bool onlyIfCached()const;
+ bool gotEnough() const;
+
ConnStateData *conn;
request_t *request; /* Parsed URL ... */
char *uri;
HttpHdrRangeIter range_iter; /* data for iterating thru range specs */
size_t req_sz; /* raw request size on input, not current request size */
StoreEntry *entry;
- StoreEntry *old_entry;
log_type logType;
struct timeval start;
/* client http based routines */
SQUIDCEXTERN char *clientConstructTraceEcho(clientHttpRequest *);
SQUIDCEXTERN ACLChecklist *clientAclChecklistCreate(const acl_access * acl, const clientHttpRequest * http);
-SQUIDCEXTERN void *clientReplyNewContext(clientHttpRequest *);
SQUIDCEXTERN int clientHttpRequestStatus(int fd, clientHttpRequest const *http);
SQUIDCEXTERN void clientAccessCheck(ClientHttpRequest *);
/*
- * $Id: protos.h,v 1.473 2003/03/10 04:56:38 robertc Exp $
+ * $Id: protos.h,v 1.474 2003/03/15 04:17:39 robertc Exp $
*
*
* SQUID Web Proxy Cache http://www.squid-cache.org/
extern void clientAccessCheck(void *);
-/* client_side_reply.c - client side reply related routines (pure logic, no comms) */
-
-SQUIDCEXTERN void clientSetReplyToError(void *, err_type, http_status, method_t, char const *, struct in_addr *, request_t *, char *, auth_user_request_t * auth_user_request);
-
/* comm.c */
extern void comm_calliocallback(void);
/*
- * $Id: stat.cc,v 1.371 2003/03/04 01:40:29 robertc Exp $
+ * $Id: stat.cc,v 1.372 2003/03/15 04:17:41 robertc Exp $
*
* DEBUG: section 18 Cache Manager Statistics
* AUTHOR: Harvest Derived
storeAppendPrintf(s, "req_sz %ld\n", (long int) http->req_sz);
e = http->entry;
storeAppendPrintf(s, "entry %p/%s\n", e, e ? e->getMD5Text() : "N/A");
+#if 0
+ /* Not a member anymore */
e = http->old_entry;
storeAppendPrintf(s, "old_entry %p/%s\n", e, e ? e->getMD5Text() : "N/A");
+#endif
+
storeAppendPrintf(s, "start %ld.%06d (%f seconds ago)\n",
(long int) http->start.tv_sec,
(int) http->start.tv_usec,
/*
- * $Id: store.cc,v 1.564 2003/03/10 04:56:38 robertc Exp $
+ * $Id: store.cc,v 1.565 2003/03/15 04:17:41 robertc Exp $
*
* DEBUG: section 20 Storage Manager
* AUTHOR: Harvest Derived
}
}
+bool
+StoreEntry::modifiedSince(request_t * request) const
+{
+ int object_length;
+ time_t mod_time = lastmod;
+
+ if (mod_time < 0)
+ mod_time = timestamp;
+
+ debug(88, 3) ("modifiedSince: '%s'\n", storeUrl(this));
+
+ debug(88, 3) ("modifiedSince: mod_time = %ld\n", (long int) mod_time);
+
+ if (mod_time < 0)
+ return true;
+
+ /* Find size of the object */
+ object_length = getReply()->content_length;
+
+ if (object_length < 0)
+ object_length = contentLen(this);
+
+ if (mod_time > request->ims) {
+ debug(88, 3) ("--> YES: entry newer than client\n");
+ return true;
+ } else if (mod_time < request->ims) {
+ debug(88, 3) ("--> NO: entry older than client\n");
+ return false;
+ } else if (request->imslen < 0) {
+ debug(88, 3) ("--> NO: same LMT, no client length\n");
+ return false;
+ } else if (request->imslen == object_length) {
+ debug(88, 3) ("--> NO: same LMT, same length\n");
+ return false;
+ } else {
+ debug(88, 3) ("--> YES: same LMT, different length\n");
+ return true;
+ }
+}
+
+
/* NullStoreEntry */
NullStoreEntry NullStoreEntry::_instance;
/*
- * $Id: structs.h,v 1.459 2003/03/10 04:56:39 robertc Exp $
+ * $Id: structs.h,v 1.460 2003/03/15 04:17:41 robertc Exp $
*
*
* SQUID Web Proxy Cache http://www.squid-cache.org/
public:
void *operator new (size_t);
void operator delete (void *);
+ bool isBodyTooLarge(ssize_t clen) const;
/* unsupported, writable, may disappear/change in the future */
int hdr_sz; /* sums _stored_ status-line, headers, and <CRLF> */