]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/HttpHdrRange.cc
Renamed squid.h to squid-old.h and config.h to squid.h
[thirdparty/squid.git] / src / HttpHdrRange.cc
index 1e8d849a2aa6fc89b931daa1a2243a59b20cc95b..f43b7f62f02998c55255b121e7896b07590b104a 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: HttpHdrRange.cc,v 1.38 2003/09/29 10:24:00 robertc Exp $
+ * $Id$
  *
  * DEBUG: section 64    HTTP Range Header
  * AUTHOR: Alex Rousskov
  *  it under the terms of the GNU General Public License as published by
  *  the Free Software Foundation; either version 2 of the License, or
  *  (at your option) any later version.
- *  
+ *
  *  This program is distributed in the hope that it will be useful,
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
- *  
+ *
  *  You should have received a copy of the GNU General Public License
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
  *
  */
 
-#include "squid.h"
+#include "squid-old.h"
 #include "Store.h"
 #include "HttpHeaderRange.h"
 #include "client_side_request.h"
 
 /* globals */
 size_t HttpHdrRange::ParsedCount = 0;
-ssize_t const HttpHdrRangeSpec::UnknownPosition = -1;
+int64_t const HttpHdrRangeSpec::UnknownPosition = -1;
 
 /*
  * Range-Spec
  */
 
-MemPool *HttpHdrRangeSpec::Pool = NULL;
-
-void *
-HttpHdrRangeSpec::operator new(size_t size)
-{
-    assert (size == sizeof (HttpHdrRangeSpec));
-
-    if (!Pool)
-        Pool = memPoolCreate ("HttpHdrRangeSpec", sizeof (HttpHdrRangeSpec));
-
-    return memPoolAlloc(Pool);
-}
-
-void
-HttpHdrRangeSpec::operator delete (void *spec)
-{
-    memPoolFree(Pool, spec);
-}
-
-HttpHdrRangeSpec::HttpHdrRangeSpec() : offset(UnknownPosition), length(UnknownPosition){}
+HttpHdrRangeSpec::HttpHdrRangeSpec() : offset(UnknownPosition), length(UnknownPosition) {}
 
 /* parses range-spec and returns new object on success */
 HttpHdrRangeSpec *
@@ -112,25 +93,31 @@ HttpHdrRangeSpec::parseInit(const char *field, int flen)
 
     /* is it a suffix-byte-range-spec ? */
     if (*field == '-') {
-        if (!httpHeaderParseSize(field + 1, &length))
+        if (!httpHeaderParseOffset(field + 1, &length))
             return false;
     } else
         /* must have a '-' somewhere in _this_ field */
         if (!((p = strchr(field, '-')) || (p - field >= flen))) {
-            debug(64, 2) ("ignoring invalid (missing '-') range-spec near: '%s'\n", field);
+            debugs(64, 2, "invalid (missing '-') range-spec near: '" << field << "'");
             return false;
         } else {
-            if (!httpHeaderParseSize(field, &offset))
+            if (!httpHeaderParseOffset(field, &offset))
                 return false;
 
             p++;
 
             /* do we have last-pos ? */
             if (p - field < flen) {
-                ssize_t last_pos;
+                int64_t last_pos;
+
+                if (!httpHeaderParseOffset(p, &last_pos))
+                    return false;
 
-                if (!httpHeaderParseSize(p, &last_pos))
+                // RFC 2616 s14.35.1 MUST: last-byte-pos >= first-byte-pos
+                if (last_pos < offset) {
+                    debugs(64, 2, "invalid (last-byte-pos < first-byte-pos) range-spec near: " << field);
                     return false;
+                }
 
                 HttpHdrRangeSpec::HttpRange aSpec (offset, last_pos + 1);
 
@@ -138,12 +125,6 @@ HttpHdrRangeSpec::parseInit(const char *field, int flen)
             }
         }
 
-    /* we managed to parse, check if the result makes sence */
-    if (length == 0) {
-        debug(64, 2) ("ignoring invalid (zero length) range-spec near: '%s'\n", field);
-        return false;
-    }
-
     return true;
 }
 
@@ -151,19 +132,20 @@ void
 HttpHdrRangeSpec::packInto(Packer * packer) const
 {
     if (!known_spec(offset))   /* suffix */
-        packerPrintf(packer, "-%ld", (long int) length);
+        packerPrintf(packer, "-%"PRId64,  length);
     else if (!known_spec(length))              /* trailer */
-        packerPrintf(packer, "%ld-", (long int) offset);
+        packerPrintf(packer, "%"PRId64"-", offset);
     else                       /* range */
-        packerPrintf(packer, "%ld-%ld",
-                     (long int) offset, (long int) offset + length - 1);
+        packerPrintf(packer, "%"PRId64"-%"PRId64,
+                     offset, offset + length - 1);
 }
 
 void
 HttpHdrRangeSpec::outputInfo( char const *note) const
 {
-    debug(64, 5) ("HttpHdrRangeSpec::canonize: %s: [%ld, %ld) len: %ld\n",
-                  note, (long int) offset, (long int) offset + length, (long int) length);
+    debugs(64, 5, "HttpHdrRangeSpec::canonize: " << note << ": [" <<
+           offset << ", " << offset + length <<
+           ") len: " << length);
 }
 
 /* fills "absent" positions in range specification based on response body size
@@ -171,17 +153,15 @@ HttpHdrRangeSpec::outputInfo( char const *note) const
  * range is valid if its intersection with [0,length-1] is not empty
  */
 int
-HttpHdrRangeSpec::canonize(size_t clen)
+HttpHdrRangeSpec::canonize(int64_t clen)
 {
     outputInfo ("have");
     HttpRange object(0, clen);
 
-    if (!known_spec(offset))   /* suffix */
-    {
+    if (!known_spec(offset)) { /* suffix */
         assert(known_spec(length));
         offset = object.intersection(HttpRange (clen - length, clen)).start;
-    } else if (!known_spec(length))            /* trailer */
-    {
+    } else if (!known_spec(length)) {  /* trailer */
         assert(known_spec(offset));
         HttpRange newRange = object.intersection(HttpRange (offset, clen));
         length = newRange.size();
@@ -208,8 +188,8 @@ HttpHdrRangeSpec::mergeWith(const HttpHdrRangeSpec * donor)
     bool merged (false);
 #if MERGING_BREAKS_NOTHING
     /* Note: this code works, but some clients may not like its effects */
-    size_t rhs = offset + length;              /* no -1 ! */
-    const size_t donor_rhs = donor->offset + donor->length;    /* no -1 ! */
+    int64_t rhs = offset + length;             /* no -1 ! */
+    const int64_t donor_rhs = donor->offset + donor->length;   /* no -1 ! */
     assert(known_spec(offset));
     assert(known_spec(donor->offset));
     assert(length > 0);
@@ -245,25 +225,6 @@ HttpHdrRangeSpec::mergeWith(const HttpHdrRangeSpec * donor)
  * Range
  */
 
-MemPool *HttpHdrRange::Pool = NULL;
-
-void *
-HttpHdrRange::operator new(size_t size)
-{
-    assert (size == sizeof (HttpHdrRange));
-
-    if (!Pool)
-        Pool = memPoolCreate ("HttpHdrRange", sizeof (HttpHdrRange));
-
-    return memPoolAlloc(Pool);
-}
-
-void
-HttpHdrRange::operator delete (void *address)
-{
-    memPoolFree(Pool, address);
-}
-
 HttpHdrRange::HttpHdrRange () : clen (HttpHdrRangeSpec::UnknownPosition)
 {}
 
@@ -287,35 +248,36 @@ HttpHdrRange::parseInit(const String * range_spec)
     const char *item;
     const char *pos = NULL;
     int ilen;
-    int count = 0;
     assert(this && range_spec);
     ++ParsedCount;
-    debug(64, 8) ("parsing range field: '%s'\n", range_spec->buf());
+    debugs(64, 8, "parsing range field: '" << range_spec << "'");
     /* check range type */
 
     if (range_spec->caseCmp("bytes=", 6))
         return 0;
 
     /* skip "bytes="; hack! */
-    pos = range_spec->buf() + 5;
+    pos = range_spec->termedBuf() + 6;
 
     /* iterate through comma separated list */
     while (strListGetItem(range_spec, ',', &item, &ilen, &pos)) {
         HttpHdrRangeSpec *spec = HttpHdrRangeSpec::Create(item, ilen);
         /*
-         * HTTP/1.1 draft says we must ignore the whole header field if one spec
-         * is invalid. However, RFC 2068 just says that we must ignore that spec.
+         * RFC 2616 section 14.35.1: MUST ignore Range with
+         * at least one syntactically invalid byte-range-specs.
          */
+        if (!spec) {
+            while (!specs.empty())
+                delete specs.pop_back();
+            debugs(64, 2, "ignoring invalid range field: '" << range_spec << "'");
+            break;
+        }
 
-        if (spec)
-            specs.push_back(spec);
-
-        ++count;
+        specs.push_back(spec);
     }
 
-    debugs(64, 8, "parsed range range count: " << count << ", kept " <<
-           specs.size());
-    return specs.count != 0;
+    debugs(64, 8, "got range specs: " << specs.size());
+    return !specs.empty();
 }
 
 HttpHdrRange::~HttpHdrRange()
@@ -380,7 +342,7 @@ HttpHdrRange::merge (Vector<HttpHdrRangeSpec *> &basis)
     /* reset old array */
     specs.clean();
     /* merge specs:
-     * take one spec from "goods" and merge it with specs from 
+     * take one spec from "goods" and merge it with specs from
      * "specs" (if any) until there is no overlap */
     iterator i = basis.begin();
 
@@ -420,9 +382,9 @@ HttpHdrRange::getCanonizedSpecs (Vector<HttpHdrRangeSpec *> &copy)
 
 /*
  * canonizes all range specs within a set preserving the order
- * returns true if the set is valid after canonization; 
- * the set is valid if 
- *   - all range specs are valid and 
+ * returns true if the set is valid after canonization;
+ * the set is valid if
+ *   - all range specs are valid and
  *   - there is at least one range spec
  */
 int
@@ -439,7 +401,7 @@ HttpHdrRange::canonize(HttpReply *rep)
 }
 
 int
-HttpHdrRange::canonize (size_t newClen)
+HttpHdrRange::canonize (int64_t newClen)
 {
     clen = newClen;
     debugs(64, 3, "HttpHdrRange::canonize: started with " << specs.count <<
@@ -457,7 +419,7 @@ HttpHdrRange::canonize (size_t newClen)
 bool
 HttpHdrRange::isComplex() const
 {
-    size_t offset = 0;
+    int64_t offset = 0;
     assert(this);
     /* check that all rangers are in "strong" order */
     const_iterator pos (begin());
@@ -466,7 +428,7 @@ HttpHdrRange::isComplex() const
         /* Ensure typecasts is safe */
         assert ((*pos)->offset >= 0);
 
-        if ((unsigned int)(*pos)->offset < offset)
+        if ((*pos)->offset < offset)
             return 1;
 
         offset = (*pos)->offset + (*pos)->length;
@@ -487,7 +449,7 @@ HttpHdrRange::willBeComplex() const
     assert(this);
     /* check that all rangers are in "strong" order, */
     /* as far as we can tell without the content length */
-    size_t offset = 0;
+    int64_t offset = 0;
 
     for (const_iterator pos (begin()); pos != end(); ++pos) {
         if (!known_spec((*pos)->offset))       /* ignore unknowns */
@@ -496,7 +458,7 @@ HttpHdrRange::willBeComplex() const
         /* Ensure typecasts is safe */
         assert ((*pos)->offset >= 0);
 
-        if ((size_t) (*pos)->offset < offset)
+        if ((*pos)->offset < offset)
             return true;
 
         offset = (*pos)->offset;
@@ -513,10 +475,10 @@ HttpHdrRange::willBeComplex() const
  * or HttpHdrRangeSpec::UnknownPosition
  * this is used for size limiting
  */
-ssize_t
+int64_t
 HttpHdrRange::firstOffset() const
 {
-    ssize_t offset = HttpHdrRangeSpec::UnknownPosition;
+    int64_t offset = HttpHdrRangeSpec::UnknownPosition;
     assert(this);
     const_iterator pos = begin();
 
@@ -536,15 +498,15 @@ HttpHdrRange::firstOffset() const
  * ranges are combined into one, for example FTP REST.
  * Use 0 for size if unknown
  */
-ssize_t
-HttpHdrRange::lowestOffset(ssize_t size) const
+int64_t
+HttpHdrRange::lowestOffset(int64_t size) const
 {
-    ssize_t offset = HttpHdrRangeSpec::UnknownPosition;
+    int64_t offset = HttpHdrRangeSpec::UnknownPosition;
     const_iterator pos = begin();
     assert(this);
 
     while (pos != end()) {
-        ssize_t current = (*pos)->offset;
+        int64_t current = (*pos)->offset;
 
         if (!known_spec(current)) {
             if ((*pos)->length > size || !known_spec((*pos)->length))
@@ -563,33 +525,52 @@ HttpHdrRange::lowestOffset(ssize_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 (-1 == (ssize_t)Config.rangeOffsetLimit)
-        /* disabled */
+    if (limit == 0)
+        /* 0 == disabled */
+        return true;
+
+    if (-1 == limit)
+        /* 'none' == forced */
         return false;
 
     if (firstOffset() == -1)
         /* tail request */
         return true;
 
-    if ((ssize_t)Config.rangeOffsetLimit >= firstOffset())
+    if (limit >= firstOffset())
         /* below the limit */
         return false;
 
     return true;
 }
 
+bool
+HttpHdrRange::contains(HttpHdrRangeSpec& r) const
+{
+    assert(r.length >= 0);
+    HttpHdrRangeSpec::HttpRange rrange(r.offset, r.offset + r.length);
+
+    for (const_iterator i = begin(); i != end(); ++i) {
+        HttpHdrRangeSpec::HttpRange irange((*i)->offset, (*i)->offset + (*i)->length);
+        HttpHdrRangeSpec::HttpRange intersection = rrange.intersection(irange);
+
+        if (intersection.start == irange.start && intersection.size() == irange.size())
+            return true;
+    }
+
+    return false;
+}
+
 const HttpHdrRangeSpec *
 HttpHdrRangeIter::currentSpec() const
 {
@@ -610,17 +591,15 @@ HttpHdrRangeIter::updateSpec()
     }
 }
 
-ssize_t
+int64_t
 HttpHdrRangeIter::debt() const
 {
-    debug(64, 3) ("HttpHdrRangeIter::debt: debt is %d\n",
-                  (int)debt_size);
+    debugs(64, 3, "HttpHdrRangeIter::debt: debt is " << debt_size);
     return debt_size;
 }
 
-void HttpHdrRangeIter::debt(ssize_t newDebt)
+void HttpHdrRangeIter::debt(int64_t newDebt)
 {
-    debug(64, 3) ("HttpHdrRangeIter::debt: was %d now %d\n",
-                  (int)debt_size, (int)newDebt);
+    debugs(64, 3, "HttpHdrRangeIter::debt: was " << debt_size << " now " << newDebt);
     debt_size = newDebt;
 }