]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Author: Matthew Morgan <atcs.matthew@gmail.com>
authorAmos Jeffries <squid3@treenet.co.nz>
Wed, 7 Apr 2010 09:49:57 +0000 (21:49 +1200)
committerAmos Jeffries <squid3@treenet.co.nz>
Wed, 7 Apr 2010 09:49:57 +0000 (21:49 +1200)
Add acl support to range_offset_limit.

It is being parsed using the same data types as reply_body_max_size,
which means the limit value gets run through parseBytesLine64, and the
acl is optional.

If people are using the old global style of range_offset_limit, they
shouldn't have to do anything to their configs.

getRangeOffsetLimit is now a member of HttpRequest, and it caches it's
value the same way reply_body_max_size does for faster repeat checking.

src/HttpHdrRange.cc
src/HttpHeaderRange.h
src/HttpRequest.cc
src/HttpRequest.h
src/cf.data.pre
src/client_side.cc
src/http.cc
src/store_client.cc
src/structs.h

index 858ff6d7953a7a71632cc9c6eddea2d066d41447..8139d32e6af221c3289cee02bc188432bc373ef0 100644 (file)
@@ -524,31 +524,29 @@ HttpHdrRange::lowestOffset(int64_t size) const
 }
 
 /*
- * Return true if the first range offset is larger than the configured
- * limit.
- * Note that exceeding the limit (returning true) results in only
- * grabbing the needed range elements from the origin.
+ * \retval true   Fetch only requested ranges. The first range is larger that configured limit.
+ * \retval false  Full download. Not a range request, no limit, or the limit is not yet reached.
  */
 bool
-HttpHdrRange::offsetLimitExceeded() const
+HttpHdrRange::offsetLimitExceeded(const int64_t limit) const
 {
     if (NULL == this)
         /* not a range request */
         return false;
 
-    if (Config.rangeOffsetLimit == 0)
-        /* disabled */
+    if (limit == 0)
+        /* 0 == disabled */
         return true;
 
-    if (-1 == Config.rangeOffsetLimit)
-        /* forced */
+    if (-1 == limit)
+        /* 'none' == forced */
         return false;
 
     if (firstOffset() == -1)
         /* tail request */
         return true;
 
-    if (Config.rangeOffsetLimit >= firstOffset())
+    if (limit >= firstOffset())
         /* below the limit */
         return false;
 
index a608b61af40719371d72bb52b6ff5c592204b1ea..6c377493817d8503ded8fcb20af5d34622a315ec 100644 (file)
@@ -103,7 +103,7 @@ public:
     bool willBeComplex() const;
     int64_t firstOffset() const;
     int64_t lowestOffset(int64_t) const;
-    bool offsetLimitExceeded() const;
+    bool offsetLimitExceeded(const int64_t limit) const;
     bool contains(HttpHdrRangeSpec& r) const;
     Vector<HttpHdrRangeSpec *> specs;
 
index cc9a0604942cc0b03c205af72b452f3d777a0ba9..e6f8e93dc89565190918cab28ca2e49204b70d66 100644 (file)
@@ -43,6 +43,7 @@
 #if ICAP_CLIENT
 #include "adaptation/icap/icap_log.h"
 #endif
+#include "acl/FilledChecklist.h"
 
 HttpRequest::HttpRequest() : HttpMsg(hoRequest)
 {
@@ -115,6 +116,7 @@ HttpRequest::init()
 #if ICAP_CLIENT
     icapHistory_ = NULL;
 #endif
+    rangeOffsetLimit = -2; //a value of -2 means not checked yet
 }
 
 void
@@ -614,3 +616,30 @@ void HttpRequest::recordLookup(const DnsLookupDetails &dns)
             dnsWait = dns.wait;
     }
 }
+
+int64_t
+HttpRequest::getRangeOffsetLimit()
+{
+    /* -2 is the starting value of rangeOffsetLimit.
+     * If it is -2, that means we haven't checked it yet.
+     *  Otherwise, return the current value */
+    if(rangeOffsetLimit != -2)
+        return rangeOffsetLimit;
+
+    rangeOffsetLimit = 0; // default value for rangeOffsetLimit
+
+    ACLFilledChecklist ch(NULL, this, NULL);
+    ch.src_addr = client_addr;
+    ch.my_addr =  my_addr;
+
+    for (acl_size_t *l = Config.rangeOffsetLimit; l; l = l -> next) {
+        /* if there is no ACL list or if the ACLs listed match use this limit value */
+        if (!l->aclList || ch.matchAclListFast(l->aclList)) {
+            debugs(58, 4, HERE << "rangeOffsetLimit=" << rangeOffsetLimit);
+            rangeOffsetLimit = l->size; // may be -1
+            break;
+        }
+    }
+
+    return rangeOffsetLimit;
+}
index 8946ff27152c4ab703495229f0a16558b7474819..c0b4f56fb550110e84f9b0b818451da5ae28da5a 100644 (file)
@@ -249,9 +249,13 @@ public:
         cbdataReferenceDone(pinned_connection);
     }
 
+    int64_t getRangeOffsetLimit(); /* the result of this function gets cached in rangeOffsetLimit */
+
 private:
     const char *packableURI(bool full_uri) const;
 
+    mutable int64_t rangeOffsetLimit;  /* caches the result of getRangeOffsetLimit */
+
 protected:
     virtual void packFirstLineInto(Packer * p, bool full_uri) const;
 
index 11c00bbd5bf67c19ad12a7bd23ea07aa05ff7649..3ac8210caab6d0346bf618ca661a4acdba6867e6 100644 (file)
@@ -2107,7 +2107,7 @@ DOC_START
        usage: neighbor_type_domain neighbor parent|sibling domain domain ...
 
        Modifying the neighbor type for specific domains is now
-       possible.  You can treat some domains differently than the the
+       possible.  You can treat some domains differently than the
        default neighbor type specified on the 'cache_peer' line.
        Normally it should only be necessary to list domains which
        should be treated differently because the default neighbor type
@@ -3566,28 +3566,42 @@ DOC_START
 DOC_END
 
 NAME: range_offset_limit
-COMMENT: (bytes)
-TYPE: b_int64_t
+COMMENT: size [acl acl...]
+TYPE: acl_b_size_t
 LOC: Config.rangeOffsetLimit
-DEFAULT: 0 KB
+DEFAULT: none
 DOC_START
-       Sets a upper limit on how far into the the file a Range request
-       may be to cause Squid to prefetch the whole file. If beyond this
-       limit Squid forwards the Range request as it is and the result
-       is NOT cached.
-
+       usage: (size) [units] [[!]aclname]
+       
+       Sets an upper limit on how far (number of bytes) into the file 
+       a Range request may be to cause Squid to prefetch the whole file. 
+       If beyond this limit, Squid forwards the Range request as it is and 
+       the result is NOT cached.
+       
        This is to stop a far ahead range request (lets say start at 17MB)
        from making Squid fetch the whole object up to that point before
        sending anything to the client.
-
-       A value of 0 causes Squid to never fetch more than the
+       
+       Multiple range_offset_limit lines may be specified, and they will 
+       be searched from top to bottom on each request until a match is found. 
+       The first match found will be used.  If no line matches a request, the 
+       default limit of 0 bytes will be used.
+       
+       'size' is the limit specified as a number of units.
+       
+       'units' specifies whether to use bytes, KB, MB, etc.
+       If no units are specified bytes are assumed.
+       
+       A size of 0 causes Squid to never fetch more than the
        client requested. (default)
-
-       A value of -1 causes Squid to always fetch the object from the
+       
+       A size of 'none' causes Squid to always fetch the object from the
        beginning so it may cache the result. (2.0 style)
-
-       NP: Using -1 here will override any quick_abort settings that may
-           otherwise apply to the range request. The range request will
+       
+       'aclname' is the name of a defined ACL.
+       
+       NP: Using 'none' as the byte value here will override any quick_abort settings 
+           that may otherwise apply to the range request. The range request will
            be fully fetched from start to finish regardless of the client
            actions. This affects bandwidth usage.
 DOC_END
index a1075ec3f3b3e5c47445f19cfb3db81b4363f178..bb12a18c4bee47727d435327b6cdf8441d9cb559 100644 (file)
@@ -1127,6 +1127,8 @@ ClientSocketContext::buildRangeHeader(HttpReply * rep)
     assert(request->range);
     /* check if we still want to do ranges */
 
+    int64_t roffLimit = request->getRangeOffsetLimit();
+
     if (!rep)
         range_err = "no [parse-able] reply";
     else if ((rep->sline.status != HTTP_OK) && (rep->sline.status != HTTP_PARTIAL_CONTENT))
@@ -1147,7 +1149,7 @@ ClientSocketContext::buildRangeHeader(HttpReply * rep)
         range_err = "canonization failed";
     else if (http->request->range->isComplex())
         range_err = "too complex range header";
-    else if (!logTypeIsATcpHit(http->logType) && http->request->range->offsetLimitExceeded())
+    else if (!logTypeIsATcpHit(http->logType) && http->request->range->offsetLimitExceeded(roffLimit))
         range_err = "range outside range_offset_limit";
 
     /* get rid of our range specs on error */
index 23ae05ce3b5085e5b5a5156efa4842be0444674c..f8eb0262912604f060160f1b1c489de79e37b075 100644 (file)
@@ -1936,8 +1936,10 @@ HttpStateData::decideIfWeDoRanges (HttpRequest * orig_request)
      *  the server and fetch only the requested content)
      */
 
+    int64_t roffLimit = orig_request->getRangeOffsetLimit();
+
     if (NULL == orig_request->range || !orig_request->flags.cachable
-            || orig_request->range->offsetLimitExceeded() || orig_request->flags.connection_auth)
+            || orig_request->range->offsetLimitExceeded(roffLimit) || orig_request->flags.connection_auth)
         result = false;
 
     debugs(11, 8, "decideIfWeDoRanges: range specs: " <<
index 39706e58fc0fb078c78e80adfeeaa89db8b7cf60..20d4ddb88ff8efaf7acd8ab1ea655770b27a72e6 100644 (file)
@@ -796,7 +796,9 @@ CheckQuickAbort2(StoreEntry * entry)
         return 0;
     }
 
-    if ( Config.rangeOffsetLimit < 0 && mem->request && mem->request->range ) {
+    int64_t roffLimit = mem->request->getRangeOffsetLimit();
+
+    if ( roffLimit < 0 && mem->request && mem->request->range ) {
         /* Don't abort if the admin has configured range_ofset -1 to download fully for caching. */
         debugs(90, 3, "CheckQuickAbort2: NO admin configured range replies to full-download");
         return 0;
index 6a7e71711bc18076a56457fd9447bbdc64e0b621..5282e9319f4b80d3d6cfd1f7bb2425e7b29d603f 100644 (file)
@@ -551,7 +551,7 @@ struct SquidConfig {
     } comm_incoming;
     int max_open_disk_fds;
     int uri_whitespace;
-    int64_t rangeOffsetLimit;
+    acl_size_t *rangeOffsetLimit;
 #if MULTICAST_MISS_STREAM
 
     struct {