Blame SOURCES/squid-3.3-12677.patch

d3a8ee
------------------------------------------------------------
d3a8ee
revno: 12677
d3a8ee
revision-id: squid3@treenet.co.nz-20140309023519-t6wmqou7m816tgnl
d3a8ee
parent: squid3@treenet.co.nz-20140309021524-wtxyrfoagz95ezwp
d3a8ee
author: Alex Rousskov <rousskov@measurement-factory.com>
d3a8ee
committer: Amos Jeffries <squid3@treenet.co.nz>
d3a8ee
branch nick: 3.3
d3a8ee
timestamp: Sat 2014-03-08 19:35:19 -0700
d3a8ee
message:
d3a8ee
  Avoid assertions on Range requests that trigger Squid-generated errors.
d3a8ee
  
d3a8ee
  Added HttpRequest::ignoreRange() to encapsulate range ignoring logic.
d3a8ee
  Currently the new method only contains the code common among all callers. More
d3a8ee
  work is needed to check whether further caller homogenization is possible.
d3a8ee
  
d3a8ee
  Documented that ClientSocketContext::getNextRangeOffset() may sometimes be
d3a8ee
  called before it is ready to do its job.
d3a8ee
------------------------------------------------------------
d3a8ee
# Bazaar merge directive format 2 (Bazaar 0.90)
d3a8ee
# revision_id: squid3@treenet.co.nz-20140309023519-t6wmqou7m816tgnl
d3a8ee
# target_branch: http://bzr.squid-cache.org/bzr/squid3/3.3
d3a8ee
# testament_sha1: 0e0335663a55b0dca989893fb98f81d8d9604572
d3a8ee
# timestamp: 2014-03-09 02:37:50 +0000
d3a8ee
# source_branch: http://bzr.squid-cache.org/bzr/squid3/3.3
d3a8ee
# base_revision_id: squid3@treenet.co.nz-20140309021524-\
d3a8ee
#   wtxyrfoagz95ezwp
d3a8ee
# 
d3a8ee
# Begin patch
d3a8ee
=== modified file 'src/HttpRequest.cc'
d3a8ee
--- src/HttpRequest.cc	2013-09-11 01:03:45 +0000
d3a8ee
+++ src/HttpRequest.cc	2014-03-09 02:35:19 +0000
d3a8ee
@@ -658,6 +658,20 @@
d3a8ee
     return rangeOffsetLimit;
d3a8ee
 }
d3a8ee
 
d3a8ee
+void
d3a8ee
+HttpRequest::ignoreRange(const char *reason)
d3a8ee
+{
d3a8ee
+    if (range) {
d3a8ee
+        debugs(73, 3, static_cast<void*>(range) << " for " << reason);
d3a8ee
+        delete range;
d3a8ee
+        range = NULL;
d3a8ee
+    }
d3a8ee
+    // Some callers also reset isRanged but it may not be safe for all callers:
d3a8ee
+    // isRanged is used to determine whether a weak ETag comparison is allowed,
d3a8ee
+    // and that check should not ignore the Range header if it was present.
d3a8ee
+    // TODO: Some callers also delete HDR_RANGE, HDR_REQUEST_RANGE. Should we?
d3a8ee
+}
d3a8ee
+
d3a8ee
 bool
d3a8ee
 HttpRequest::canHandle1xx() const
d3a8ee
 {
d3a8ee
d3a8ee
=== modified file 'src/HttpRequest.h'
d3a8ee
--- src/HttpRequest.h	2013-07-26 12:21:20 +0000
d3a8ee
+++ src/HttpRequest.h	2014-03-09 02:35:19 +0000
d3a8ee
@@ -246,6 +246,8 @@
d3a8ee
      */
d3a8ee
     CbcPointer<ConnStateData> clientConnectionManager;
d3a8ee
 
d3a8ee
+    /// forgets about the cached Range header (for a reason)
d3a8ee
+    void ignoreRange(const char *reason);
d3a8ee
     int64_t getRangeOffsetLimit(); /* the result of this function gets cached in rangeOffsetLimit */
d3a8ee
 
d3a8ee
 private:
d3a8ee
d3a8ee
=== modified file 'src/client_side.cc'
d3a8ee
--- src/client_side.cc	2013-09-29 17:28:00 +0000
d3a8ee
+++ src/client_side.cc	2014-03-09 02:35:19 +0000
d3a8ee
@@ -1281,9 +1281,7 @@
d3a8ee
          * offset data, but we won't be requesting it.
d3a8ee
          * So, we can either re-request, or generate an error
d3a8ee
          */
d3a8ee
-        debugs(33, 3, "clientBuildRangeHeader: will not do ranges: " << range_err << ".");
d3a8ee
-        delete http->request->range;
d3a8ee
-        http->request->range = NULL;
d3a8ee
+        http->request->ignoreRange(range_err);
d3a8ee
     } else {
d3a8ee
         /* XXX: TODO: Review, this unconditional set may be wrong. - TODO: review. */
d3a8ee
         httpStatusLineSet(&rep->sline, rep->sline.version,
d3a8ee
@@ -1662,9 +1660,16 @@
d3a8ee
 int64_t
d3a8ee
 ClientSocketContext::getNextRangeOffset() const
d3a8ee
 {
d3a8ee
+    debugs (33, 5, "range: " << http->request->range <<
d3a8ee
+            "; http offset " << http->out.offset <<
d3a8ee
+            "; reply " << reply);
d3a8ee
+
d3a8ee
+    // XXX: This method is called from many places, including pullData() which
d3a8ee
+    // may be called before prepareReply() [on some Squid-generated errors].
d3a8ee
+    // Hence, we may not even know yet whether we should honor/do ranges.
d3a8ee
+
d3a8ee
     if (http->request->range) {
d3a8ee
         /* offset in range specs does not count the prefix of an http msg */
d3a8ee
-        debugs (33, 5, "ClientSocketContext::getNextRangeOffset: http offset " << http->out.offset);
d3a8ee
         /* check: reply was parsed and range iterator was initialized */
d3a8ee
         assert(http->range_iter.valid);
d3a8ee
         /* filter out data according to range specs */
d3a8ee
@@ -1701,7 +1706,7 @@
d3a8ee
 void
d3a8ee
 ClientSocketContext::pullData()
d3a8ee
 {
d3a8ee
-    debugs(33, 5, HERE << clientConnection << " attempting to pull upstream data");
d3a8ee
+    debugs(33, 5, reply << " written " << http->out.size << " into " << clientConnection);
d3a8ee
 
d3a8ee
     /* More data will be coming from the stream. */
d3a8ee
     StoreIOBuffer readBuffer;
d3a8ee
@@ -2492,7 +2497,7 @@
d3a8ee
         clientReplyContext *repContext = dynamic_cast<clientReplyContext *>(node->data.getRaw());
d3a8ee
         assert(repContext);
d3a8ee
         debugs(33, 5, "Responding with delated error for " << http->uri);
d3a8ee
-        repContext->setReplyToStoreEntry(sslServerBump->entry);
d3a8ee
+        repContext->setReplyToStoreEntry(sslServerBump->entry, "delayed SslBump error");
d3a8ee
 
d3a8ee
         // save the original request for logging purposes
d3a8ee
         if (!context->http->al->request)
d3a8ee
d3a8ee
=== modified file 'src/client_side_reply.cc'
d3a8ee
--- src/client_side_reply.cc	2013-12-15 05:23:23 +0000
d3a8ee
+++ src/client_side_reply.cc	2014-03-09 02:35:19 +0000
d3a8ee
@@ -134,13 +134,18 @@
d3a8ee
 
d3a8ee
     http->al->http.code = errstate->httpStatus;
d3a8ee
 
d3a8ee
+    if (http->request)
d3a8ee
+        http->request->ignoreRange("responding with a Squid-generated error");
d3a8ee
+
d3a8ee
     createStoreEntry(method, RequestFlags());
d3a8ee
     assert(errstate->callback_data == NULL);
d3a8ee
     errorAppendEntry(http->storeEntry(), errstate);
d3a8ee
     /* Now the caller reads to get this */
d3a8ee
 }
d3a8ee
 
d3a8ee
-void clientReplyContext::setReplyToStoreEntry(StoreEntry *entry)
d3a8ee
+// Assumes that the entry contains an error response without Content-Range.
d3a8ee
+// To use with regular entries, make HTTP Range header removal conditional.
d3a8ee
+void clientReplyContext::setReplyToStoreEntry(StoreEntry *entry, const char *reason)
d3a8ee
 {
d3a8ee
     entry->lock(); // removeClientStoreReference() unlocks
d3a8ee
     sc = storeClientListAdd(entry, this);
d3a8ee
@@ -149,6 +154,8 @@
d3a8ee
 #endif
d3a8ee
     reqofs = 0;
d3a8ee
     reqsize = 0;
d3a8ee
+    if (http->request)
d3a8ee
+        http->request->ignoreRange(reason);
d3a8ee
     flags.storelogiccomplete = 1;
d3a8ee
     http->storeEntry(entry);
d3a8ee
 }
d3a8ee
d3a8ee
=== modified file 'src/client_side_reply.h'
d3a8ee
--- src/client_side_reply.h	2012-09-10 12:49:35 +0000
d3a8ee
+++ src/client_side_reply.h	2014-03-09 02:35:19 +0000
d3a8ee
@@ -73,7 +73,7 @@
d3a8ee
     int storeOKTransferDone() const;
d3a8ee
     int storeNotOKTransferDone() const;
d3a8ee
     /// replaces current response store entry with the given one
d3a8ee
-    void setReplyToStoreEntry(StoreEntry *e);
d3a8ee
+    void setReplyToStoreEntry(StoreEntry *e, const char *reason);
d3a8ee
     /// builds error using clientBuildError() and calls setReplyToError() below
d3a8ee
     void setReplyToError(err_type, http_status, const HttpRequestMethod&, char const *, Ip::Address &, HttpRequest *, const char *,
d3a8ee
 #if USE_AUTH
d3a8ee
d3a8ee
=== modified file 'src/client_side_request.cc'
d3a8ee
--- src/client_side_request.cc	2014-03-09 02:10:07 +0000
d3a8ee
+++ src/client_side_request.cc	2014-03-09 02:35:19 +0000
d3a8ee
@@ -1131,8 +1131,7 @@
d3a8ee
     else {
d3a8ee
         req_hdr->delById(HDR_RANGE);
d3a8ee
         req_hdr->delById(HDR_REQUEST_RANGE);
d3a8ee
-        delete request->range;
d3a8ee
-        request->range = NULL;
d3a8ee
+        request->ignoreRange("neither HEAD nor GET");
d3a8ee
     }
d3a8ee
 
d3a8ee
     if (req_hdr->has(HDR_AUTHORIZATION))
d3a8ee
@@ -1664,7 +1663,7 @@
d3a8ee
             clientStreamNode *node = (clientStreamNode *)client_stream.tail->prev->data;
d3a8ee
             clientReplyContext *repContext = dynamic_cast<clientReplyContext *>(node->data.getRaw());
d3a8ee
             assert (repContext);
d3a8ee
-            repContext->setReplyToStoreEntry(e);
d3a8ee
+            repContext->setReplyToStoreEntry(e, "immediate SslBump error");
d3a8ee
             errorAppendEntry(e, calloutContext->error);
d3a8ee
             calloutContext->error = NULL;
d3a8ee
             if (calloutContext->readNextRequest)
d3a8ee
d3a8ee
=== modified file 'src/http.cc'
d3a8ee
--- src/http.cc	2013-11-21 21:54:29 +0000
d3a8ee
+++ src/http.cc	2014-03-09 02:35:19 +0000
d3a8ee
@@ -1736,8 +1736,7 @@
d3a8ee
         /* don't cache the result */
d3a8ee
         request->flags.cachable = 0;
d3a8ee
         /* pretend it's not a range request */
d3a8ee
-        delete request->range;
d3a8ee
-        request->range = NULL;
d3a8ee
+        request->ignoreRange("want to request the whole object");
d3a8ee
         request->flags.isRanged=false;
d3a8ee
     }
d3a8ee
 
d3a8ee