-
/*
- * DEBUG: section 64 HTTP Range Header
- * AUTHOR: Alex Rousskov
- *
- * SQUID Web Proxy Cache http://www.squid-cache.org/
- * ----------------------------------------------------------
- *
- * Squid is the result of efforts by numerous individuals from
- * the Internet community; see the CONTRIBUTORS file for full
- * details. Many organizations have provided support for Squid's
- * development; see the SPONSORS file for full details. Squid is
- * Copyrighted (C) 2001 by the Regents of the University of
- * California; see the COPYRIGHT file for full details. Squid
- * incorporates software developed and/or copyrighted by other
- * sources; see the CREDITS file for full details.
- *
- * This program is free software; you can redistribute it and/or modify
- * 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.
+ * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
*
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
*/
+/* DEBUG: section 64 HTTP Range Header */
+
#include "squid.h"
-#include "Store.h"
-#include "HttpHeaderRange.h"
#include "client_side_request.h"
-#include "HttpReply.h"
+#include "http/Stream.h"
+#include "HttpHeaderRange.h"
#include "HttpHeaderTools.h"
+#include "HttpReply.h"
+#include "Store.h"
#include "StrList.h"
/*
HttpHdrRangeSpec spec;
if (!spec.parseInit(field, flen))
- return NULL;
+ return nullptr;
return new HttpHdrRangeSpec(spec);
}
/* is it a suffix-byte-range-spec ? */
if (*field == '-') {
- if (!httpHeaderParseOffset(field + 1, &length))
+ if (!httpHeaderParseOffset(field + 1, &length) || !known_spec(length))
return false;
} else
/* must have a '-' somewhere in _this_ field */
debugs(64, 2, "invalid (missing '-') range-spec near: '" << field << "'");
return false;
} else {
- if (!httpHeaderParseOffset(field, &offset))
+ if (!httpHeaderParseOffset(field, &offset) || !known_spec(offset))
return false;
++p;
if (p - field < flen) {
int64_t last_pos;
- if (!httpHeaderParseOffset(p, &last_pos))
+ if (!httpHeaderParseOffset(p, &last_pos) || !known_spec(last_pos))
return false;
// RFC 2616 s14.35.1 MUST: last-byte-pos >= first-byte-pos
}
void
-HttpHdrRangeSpec::packInto(Packer * packer) const
+HttpHdrRangeSpec::packInto(Packable * p) const
{
- if (!known_spec(offset)) /* suffix */
- packerPrintf(packer, "-%" PRId64, length);
- else if (!known_spec(length)) /* trailer */
- packerPrintf(packer, "%" PRId64 "-", offset);
- else /* range */
- packerPrintf(packer, "%" PRId64 "-%" PRId64,
- offset, offset + length - 1);
+ if (!known_spec(offset)) /* suffix */
+ p->appendf("-%" PRId64, length);
+ else if (!known_spec(length)) /* trailer */
+ p->appendf("%" PRId64 "-", offset);
+ else /* range */
+ p->appendf("%" PRId64 "-%" PRId64, offset, offset + length - 1);
}
void
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();
return length > 0;
}
-/* merges recepient with donor if possible; returns true on success
+/* merges recipient with donor if possible; returns true on success
* both specs must be canonized prior to merger, of course */
bool
HttpHdrRangeSpec::mergeWith(const HttpHdrRangeSpec * donor)
bool merged (false);
#if MERGING_BREAKS_NOTHING
/* Note: this code works, but some clients may not like its effects */
- int64_t rhs = offset + length; /* no -1 ! */
- const int64_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);
/* do we have a left hand side overlap? */
if (donor->offset < offset && offset <= donor_rhs) {
- offset = donor->offset; /* decrease left offset */
+ offset = donor->offset; /* decrease left offset */
merged = 1;
}
/* do we have a right hand side overlap? */
if (donor->offset <= rhs && rhs < donor_rhs) {
- rhs = donor_rhs; /* increase right offset */
+ rhs = donor_rhs; /* increase right offset */
merged = 1;
}
assert(rhs > offset);
length = rhs - offset;
} else {
- /* does recepient contain donor? */
+ /* does recipient contain donor? */
merged =
offset <= donor->offset && donor->offset < rhs;
}
+#else
+ (void)donor;
#endif
return merged;
}
* Range
*/
-HttpHdrRange::HttpHdrRange () : clen (HttpHdrRangeSpec::UnknownPosition)
+HttpHdrRange::HttpHdrRange() : clen(HttpHdrRangeSpec::UnknownPosition)
{}
HttpHdrRange *
if (!r->parseInit(range_spec)) {
delete r;
- r = NULL;
+ r = nullptr;
}
return r;
HttpHdrRange::parseInit(const String * range_spec)
{
const char *item;
- const char *pos = NULL;
+ const char *pos = nullptr;
int ilen;
- assert(this && range_spec);
+ assert(range_spec);
++ParsedCount;
- debugs(64, 8, "parsing range field: '" << range_spec << "'");
+ debugs(64, 8, "parsing range field: '" << *range_spec << "'");
/* check range type */
if (range_spec->caseCmp("bytes=", 6))
* 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 << "'");
+ while (!specs.empty()) {
+ delete specs.back();
+ specs.pop_back();
+ }
+ debugs(64, 2, "ignoring invalid range field: '" << *range_spec << "'");
break;
}
HttpHdrRange::~HttpHdrRange()
{
- while (specs.size())
- delete specs.pop_back();
+ while (!specs.empty()) {
+ delete specs.back();
+ specs.pop_back();
+ }
}
-HttpHdrRange::HttpHdrRange(HttpHdrRange const &old) : specs()
+HttpHdrRange::HttpHdrRange(HttpHdrRange const &old) :
+ specs(),
+ clen(HttpHdrRangeSpec::UnknownPosition)
{
specs.reserve(old.specs.size());
}
void
-HttpHdrRange::packInto(Packer * packer) const
+HttpHdrRange::packInto(Packable * packer) const
{
const_iterator pos = begin();
- assert(this);
while (pos != end()) {
if (pos != begin())
- packerAppend(packer, ",", 1);
+ packer->append(",", 1);
(*pos)->packInto(packer);
}
void
-HttpHdrRange::merge (Vector<HttpHdrRangeSpec *> &basis)
+HttpHdrRange::merge (std::vector<HttpHdrRangeSpec *> &basis)
{
/* reset old array */
- specs.clean();
+ specs.clear();
/* merge specs:
* take one spec from "goods" and merge it with specs from
* "specs" (if any) until there is no overlap */
while (i != basis.end()) {
if (specs.size() && (*i)->mergeWith(specs.back())) {
/* merged with current so get rid of the prev one */
- delete specs.pop_back();
- continue; /* re-iterate */
+ delete specs.back();
+ specs.pop_back();
+ continue; /* re-iterate */
}
specs.push_back (*i);
- ++i; /* progress */
+ ++i; /* progress */
}
debugs(64, 3, "HttpHdrRange::merge: had " << basis.size() <<
}
void
-HttpHdrRange::getCanonizedSpecs (Vector<HttpHdrRangeSpec *> ©)
+HttpHdrRange::getCanonizedSpecs(std::vector<HttpHdrRangeSpec *> ©)
{
/* canonize each entry and destroy bad ones if any */
delete (*pos);
}
- debugs(64, 3, "HttpHdrRange::getCanonizedSpecs: found " <<
- specs.size() - copy.size() << " bad specs");
+ debugs(64, 3, "found " << specs.size() - copy.size() << " bad specs");
}
#include "HttpHdrContRange.h"
int
HttpHdrRange::canonize(HttpReply *rep)
{
- assert(this && rep);
+ assert(rep);
- if (rep->content_range)
- clen = rep->content_range->elength;
+ if (rep->contentRange())
+ clen = rep->contentRange()->elength;
else
clen = rep->content_length;
HttpHdrRange::canonize (int64_t newClen)
{
clen = newClen;
- debugs(64, 3, "HttpHdrRange::canonize: started with " << specs.count <<
+ debugs(64, 3, "HttpHdrRange::canonize: started with " << specs.size() <<
" specs, clen: " << clen);
- Vector<HttpHdrRangeSpec*> goods;
+ std::vector<HttpHdrRangeSpec*> goods;
getCanonizedSpecs(goods);
merge (goods);
- debugs(64, 3, "HttpHdrRange::canonize: finished with " << specs.count <<
+ debugs(64, 3, "HttpHdrRange::canonize: finished with " << specs.size() <<
" specs");
- return specs.count > 0;
+ return specs.size() > 0; // TODO: should return bool
}
/* hack: returns true if range specs are too "complex" for Squid to handle */
HttpHdrRange::isComplex() const
{
int64_t offset = 0;
- assert(this);
/* check that all rangers are in "strong" order */
const_iterator pos (begin());
bool
HttpHdrRange::willBeComplex() const
{
- assert(this);
/* check that all rangers are in "strong" order, */
/* as far as we can tell without the content length */
int64_t offset = 0;
for (const_iterator pos (begin()); pos != end(); ++pos) {
- if (!known_spec((*pos)->offset)) /* ignore unknowns */
+ if (!known_spec((*pos)->offset)) /* ignore unknowns */
continue;
/* Ensure typecasts is safe */
offset = (*pos)->offset;
- if (known_spec((*pos)->length)) /* avoid unknowns */
+ if (known_spec((*pos)->length)) /* avoid unknowns */
offset += (*pos)->length;
}
HttpHdrRange::firstOffset() const
{
int64_t offset = HttpHdrRangeSpec::UnknownPosition;
- assert(this);
const_iterator pos = begin();
while (pos != end()) {
{
int64_t offset = HttpHdrRangeSpec::UnknownPosition;
const_iterator pos = begin();
- assert(this);
while (pos != end()) {
int64_t current = (*pos)->offset;
if (!known_spec(current)) {
if ((*pos)->length > size || !known_spec((*pos)->length))
- return 0; /* Unknown. Assume start of file */
+ return 0; /* Unknown. Assume start of file */
current = size - (*pos)->length;
}
bool
HttpHdrRange::offsetLimitExceeded(const int64_t limit) const
{
- if (NULL == this)
- /* not a range request */
- return false;
-
if (limit == 0)
/* 0 == disabled */
return true;
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
{
- if (pos.incrementable())
+ if (pos != end)
return *pos;
- return NULL;
+ return nullptr;
}
void
assert (debt_size == 0);
assert (valid);
- if (pos.incrementable()) {
+ if (pos != end) {
debt(currentSpec()->length);
}
}
debugs(64, 3, "HttpHdrRangeIter::debt: was " << debt_size << " now " << newDebt);
debt_size = newDebt;
}
+