/*
- * $Id: HttpHdrRange.cc,v 1.36 2003/07/14 14:15:56 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.
/* 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);
-}
-
-void
-HttpHdrRangeSpec::deleteSelf() const
-{
- delete this;
-}
-
-HttpHdrRangeSpec::HttpHdrRangeSpec() : offset(UnknownPosition), length(UnknownPosition){}
+HttpHdrRangeSpec::HttpHdrRangeSpec() : offset(UnknownPosition), length(UnknownPosition) {}
/* parses range-spec and returns new object on success */
HttpHdrRangeSpec *
/* 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, "ignoring 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 (!httpHeaderParseSize(p, &last_pos))
+ if (!httpHeaderParseOffset(p, &last_pos))
return false;
HttpHdrRangeSpec::HttpRange aSpec (offset, last_pos + 1);
/* 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);
+ debugs(64, 2, "ignoring invalid (zero length) range-spec near: '" << field << "'");
return false;
}
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
* 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();
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);
* 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);
-}
-
-void
-HttpHdrRange::deleteSelf() const
-{
- delete this;
-}
-
HttpHdrRange::HttpHdrRange () : clen (HttpHdrRangeSpec::UnknownPosition)
{}
HttpHdrRange *r = new HttpHdrRange;
if (!r->parseInit(range_spec)) {
- r->deleteSelf();
+ delete r;
r = NULL;
}
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->buf() << "'");
/* check range type */
if (range_spec->caseCmp("bytes=", 6))
return 0;
/* skip "bytes="; hack! */
- pos = range_spec->buf() + 5;
+ pos = range_spec->buf() + 6;
/* iterate through comma separated list */
while (strListGetItem(range_spec, ',', &item, &ilen, &pos)) {
++count;
}
- debug(64, 8) ("parsed range range count: %d, kept %d\n", count, specs.size());
+ debugs(64, 8, "parsed range range count: " << count << ", kept " <<
+ specs.size());
return specs.count != 0;
}
HttpHdrRange::~HttpHdrRange()
{
while (specs.size())
- specs.pop_back()->deleteSelf();
+ delete specs.pop_back();
}
HttpHdrRange::HttpHdrRange(HttpHdrRange const &old) : specs()
/* 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();
while (i != basis.end()) {
if (specs.size() && (*i)->mergeWith(specs.back())) {
/* merged with current so get rid of the prev one */
- specs.pop_back()->deleteSelf();
+ delete specs.pop_back();
continue; /* re-iterate */
}
++i; /* progress */
}
- debug(64, 3) ("HttpHdrRange::merge: had %d specs, merged %d specs\n",
- basis.size(), basis.size() - specs.size());
+ debugs(64, 3, "HttpHdrRange::merge: had " << basis.size() <<
+ " specs, merged " << basis.size() - specs.size() << " specs");
}
if ((*pos)->canonize(clen))
copy.push_back (*pos);
else
- (*pos)->deleteSelf();
+ delete (*pos);
}
- debug(64, 3) ("HttpHdrRange::getCanonizedSpecs: found %d bad specs\n",
- specs.size() - copy.size());
+ debugs(64, 3, "HttpHdrRange::getCanonizedSpecs: found " <<
+ specs.size() - copy.size() << " bad specs");
}
#include "HttpHdrContRange.h"
/*
* 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
}
int
-HttpHdrRange::canonize (size_t newClen)
+HttpHdrRange::canonize (int64_t newClen)
{
clen = newClen;
- debug(64, 3) ("HttpHdrRange::canonize: started with %d specs, clen: %ld\n", specs.count, (long int) clen);
+ debugs(64, 3, "HttpHdrRange::canonize: started with " << specs.count <<
+ " specs, clen: " << clen);
Vector<HttpHdrRangeSpec*> goods;
getCanonizedSpecs(goods);
merge (goods);
- debug(64, 3) ("HttpHdrRange::canonize: finished with %d specs\n",
- specs.count);
+ debugs(64, 3, "HttpHdrRange::canonize: finished with " << specs.count <<
+ " specs");
return specs.count > 0;
}
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());
/* 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;
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 */
/* Ensure typecasts is safe */
assert ((*pos)->offset >= 0);
- if ((size_t) (*pos)->offset < offset)
+ if ((*pos)->offset < offset)
return true;
offset = (*pos)->offset;
* 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();
* 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))
/*
* Return true if the first range offset is larger than the configured
* limit.
- * Note that exceeding the limit (returning true) results in only
+ * Note that exceeding the limit (returning true) results in only
* grabbing the needed range elements from the origin.
*/
bool
/* not a range request */
return false;
- if (-1 == (ssize_t)Config.rangeOffsetLimit)
+ if (Config.rangeOffsetLimit == 0)
/* disabled */
+ return true;
+
+ if (-1 == Config.rangeOffsetLimit)
+ /* forced */
return false;
if (firstOffset() == -1)
/* tail request */
return true;
- if ((ssize_t)Config.rangeOffsetLimit >= firstOffset())
+ if (Config.rangeOffsetLimit >= 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
{
}
}
-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;
}