/*
- * $Id: HttpReply.cc,v 1.99 2008/02/03 10:00:29 amosjeffries Exp $
+ * $Id: HttpReply.cc,v 1.100 2008/02/08 18:27:59 rousskov Exp $
*
* DEBUG: section 58 HTTP Reply (Response)
* AUTHOR: Alex Rousskov
#include "HttpHdrContRange.h"
#include "HttpHdrSc.h"
#include "ACLChecklist.h"
+#include "HttpRequest.h"
#include "MemBuf.h"
/* local constants */
httpHeaderCalcMask(&Denied304HeadersMask, Denied304HeadersArr, countof(Denied304HeadersArr));
}
-HttpReply::HttpReply() : HttpMsg(hoReply), date (0), last_modified (0), expires (0), surrogate_control (NULL), content_range (NULL), keep_alive (0), protoPrefix("HTTP/")
+HttpReply::HttpReply() : HttpMsg(hoReply), date (0), last_modified (0),
+ expires (0), surrogate_control (NULL), content_range (NULL), keep_alive (0),
+ protoPrefix("HTTP/"), bodySizeMax(-2)
{
init();
}
hdrCacheClean();
header.clean();
httpStatusLineClean(&sline);
+ bodySizeMax = -2; // hack: make calculatedBodySizeMax() false
}
void
return expectBody;
}
+
+bool
+HttpReply::receivedBodyTooLarge(HttpRequest& request, int64_t receivedSize)
+{
+ calcMaxBodySize(request);
+ debugs(58, 3, HERE << receivedSize << " >? " << bodySizeMax);
+ return bodySizeMax >= 0 && receivedSize > bodySizeMax;
+}
+
+bool
+HttpReply::expectedBodyTooLarge(HttpRequest& request)
+{
+ calcMaxBodySize(request);
+ debugs(58, 7, HERE << "bodySizeMax=" << bodySizeMax);
+
+ if (bodySizeMax < 0) // no body size limit
+ return false;
+
+ int64_t expectedSize = -1;
+ if (!expectingBody(request.method, expectedSize))
+ return false;
+
+ debugs(58, 6, HERE << expectedSize << " >? " << bodySizeMax);
+
+ if (expectedSize < 0) // expecting body of an unknown length
+ return false;
+
+ return expectedSize > bodySizeMax;
+}
+
+void
+HttpReply::calcMaxBodySize(HttpRequest& request)
+{
+ // hack: -2 is used as "we have not calculated max body size yet" state
+ if (bodySizeMax != -2) // already tried
+ return;
+ bodySizeMax = -1;
+
+ ACLChecklist ch;
+ ch.src_addr = request.client_addr;
+ ch.my_addr = request.my_addr;
+ ch.reply = HTTPMSGLOCK(this); // XXX: this lock makes method non-const
+ ch.request = HTTPMSGLOCK(&request);
+ for (acl_size_t *l = Config.ReplyBodySize; l; l = l -> next) {
+ if (ch.matchAclListFast(l->aclList)) {
+ debugs(58, 4, HERE << "bodySizeMax=" << bodySizeMax);
+ bodySizeMax = l->size; // may be -1
+ break;
+ }
+ }
+}
/*
- * $Id: HttpReply.h,v 1.22 2008/01/20 08:54:28 amosjeffries Exp $
+ * $Id: HttpReply.h,v 1.23 2008/02/08 18:27:59 rousskov Exp $
*
*
* SQUID Web Proxy Cache http://www.squid-cache.org/
int64_t bodySize(const HttpRequestMethod&) const;
+ /// Checks whether received body exceeds known maximum size.
+ /// Requires a prior call to calcMaxBodySize().
+ bool receivedBodyTooLarge(HttpRequest&, int64_t receivedBodySize);
+
+ /// Checks whether expected body exceeds known maximum size.
+ /// Requires a prior call to calcMaxBodySize().
+ bool expectedBodyTooLarge(HttpRequest& request);
+
int validatorsMatch (HttpReply const *other) const;
void packHeadersInto(Packer * p) const;
/* header manipulation */
time_t hdrExpirationTime();
+ // Calculates and stores maximum body size if needed. Used by
+ // receivedBodyTooLarge() and expectedBodyTooLarge().
+ void calcMaxBodySize(HttpRequest& request);
+
+ mutable int64_t bodySizeMax; // cached result of calcMaxBodySize
+
protected:
virtual void packFirstLineInto(Packer * p, bool) const;
/*
- * $Id: client_side_request.cc,v 1.102 2008/02/03 10:00:30 amosjeffries Exp $
+ * $Id: client_side_request.cc,v 1.103 2008/02/08 18:27:59 rousskov Exp $
*
* DEBUG: section 85 Client-side Request Routines
* AUTHOR: Robert Collins (Originally Duane Wessels in client_side.c)
return true;
}
-void
-ClientHttpRequest::maxReplyBodySize(int64_t clen)
-{
- maxReplyBodySize_ = clen;
-}
-
-int64_t
-ClientHttpRequest::maxReplyBodySize() const
-{
- return maxReplyBodySize_;
-}
-
-bool
-ClientHttpRequest::isReplyBodyTooLarge(int64_t clen) const
-{
- if (0 == maxReplyBodySize())
- return 0; /* disabled */
-
- if (clen < 0)
- return 0; /* unknown */
-
- return clen > maxReplyBodySize();
-}
-
void
ClientHttpRequest::storeEntry(StoreEntry *newEntry)
{