This is the second half of the patch for Bug #2001, adding support for
large response headers.

What this patch does is to make client_side_reply clone the already
parsed HTTP response and skip over the ascii HTTP header received from
the store, similar to the change Adrian did earlier in Squid-2 but for
other reasons.

# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: [EMAIL PROTECTED]
#   xk0b7qlireb5frg2
# target_branch: file:///data/bzr/squid3/trunk/
# testament_sha1: a3df357ae862b61434bb557e1faf88f8ae965680
# timestamp: 2008-03-30 17:29:53 +0200
# base_revision_id: [EMAIL PROTECTED]
#   so853tluhwlx6qc5
# 
# Begin patch
=== modified file 'src/HttpReply.cc'
--- src/HttpReply.cc	2008-02-09 01:27:59 +0000
+++ src/HttpReply.cc	2008-03-15 19:09:52 +0000
@@ -551,3 +551,17 @@
         }
     }
 }
+
+HttpReply *
+HttpReply::clone() const
+{
+    HttpReply *rep = new HttpReply();
+    rep->header.append(&header);
+    rep->hdrCacheInit();
+    rep->hdr_sz = hdr_sz;
+    rep->http_ver = http_ver;
+    rep->pstate = pstate;
+    rep->protocol = protocol;
+    rep->sline = sline;
+    return rep;
+}

=== modified file 'src/HttpReply.h'
--- src/HttpReply.h	2008-03-16 00:50:50 +0000
+++ src/HttpReply.h	2008-03-16 00:53:56 +0000
@@ -127,6 +127,11 @@
 
     void packHeadersInto(Packer * p) const;
 
+    /// Clone this reply.
+    /// Could be done as a copy-contructor but we do not want to
+    /// accidently copy a HttpReply..
+    HttpReply *clone() const;
+
 private:
     /* initialize */
     void init();

=== modified file 'src/client_side_reply.cc'
--- src/client_side_reply.cc	2008-03-20 23:20:58 +0000
+++ src/client_side_reply.cc	2008-03-30 13:34:01 +0000
@@ -352,68 +352,47 @@
         sendClientOldEntry();
     }
 
-    // we have a partial reply from the origin
-    else if (STORE_PENDING == http->storeEntry()->store_status && 0 == status) {
-        // header is too large, send old entry
-
-        if (reqsize >= HTTP_REQBUF_SZ) {
-            debugs(88, 3, "handleIMSReply: response from origin is too large '" << http->storeEntry()->url() << "', sending old entry to client" );
-            http->logType = LOG_TCP_REFRESH_FAIL;
-            sendClientOldEntry();
-        }
-
-        // everything looks fine, we're just waiting for more data
-        else {
-            debugs(88, 3, "handleIMSReply: incomplete headers for '" << http->storeEntry()->url() << "', waiting for more data" );
-            reqofs = reqsize;
-            waitForMoreData();
-        }
-    }
-
-    // we have a reply from the origin
+    HttpReply *old_rep = (HttpReply *) old_entry->getReply();
+
+    // origin replied 304
+
+    if (status == HTTP_NOT_MODIFIED) {
+	http->logType = LOG_TCP_REFRESH_UNMODIFIED;
+
+	// update headers on existing entry
+	HttpReply *old_rep = (HttpReply *) old_entry->getReply();
+	old_rep->updateOnNotModified(http->storeEntry()->getReply());
+	old_entry->timestampsSet();
+
+	// if client sent IMS
+
+	if (http->request->flags.ims) {
+	    // forward the 304 from origin
+	    debugs(88, 3, "handleIMSReply: origin replied 304, revalidating existing entry and forwarding 304 to client");
+	    sendClientUpstreamResponse();
+	} else {
+	    // send existing entry, it's still valid
+	    debugs(88, 3, "handleIMSReply: origin replied 304, revalidating existing entry and sending " <<
+		   old_rep->sline.status << " to client");
+	    sendClientOldEntry();
+	}
+    }
+
+    // origin replied with a non-error code
+    else if (status > HTTP_STATUS_NONE && status < HTTP_INTERNAL_SERVER_ERROR) {
+	// forward response from origin
+	http->logType = LOG_TCP_REFRESH_MODIFIED;
+	debugs(88, 3, "handleIMSReply: origin replied " << status << ", replacing existing entry and forwarding to client");
+	sendClientUpstreamResponse();
+    }
+
+    // origin replied with an error
     else {
-        HttpReply *old_rep = (HttpReply *) old_entry->getReply();
-
-        // origin replied 304
-
-        if (status == HTTP_NOT_MODIFIED) {
-            http->logType = LOG_TCP_REFRESH_UNMODIFIED;
-
-            // update headers on existing entry
-            HttpReply *old_rep = (HttpReply *) old_entry->getReply();
-            old_rep->updateOnNotModified(http->storeEntry()->getReply());
-            old_entry->timestampsSet();
-
-            // if client sent IMS
-
-            if (http->request->flags.ims) {
-                // forward the 304 from origin
-                debugs(88, 3, "handleIMSReply: origin replied 304, revalidating existing entry and forwarding 304 to client");
-                sendClientUpstreamResponse();
-            } else {
-                // send existing entry, it's still valid
-                debugs(88, 3, "handleIMSReply: origin replied 304, revalidating existing entry and sending " <<
-                       old_rep->sline.status << " to client");
-                sendClientOldEntry();
-            }
-        }
-
-        // origin replied with a non-error code
-        else if (status > HTTP_STATUS_NONE && status < HTTP_INTERNAL_SERVER_ERROR) {
-            // forward response from origin
-            http->logType = LOG_TCP_REFRESH_MODIFIED;
-            debugs(88, 3, "handleIMSReply: origin replied " << status << ", replacing existing entry and forwarding to client");
-            sendClientUpstreamResponse();
-        }
-
-        // origin replied with an error
-        else {
-            // ignore and let client have old entry
-            http->logType = LOG_TCP_REFRESH_FAIL;
-            debugs(88, 3, "handleIMSReply: origin replied with error " <<
-                   status << ", sending old entry (" << old_rep->sline.status << ") to client");
-            sendClientOldEntry();
-        }
+	// ignore and let client have old entry
+	http->logType = LOG_TCP_REFRESH_FAIL;
+	debugs(88, 3, "handleIMSReply: origin replied with error " <<
+	       status << ", sending old entry (" << old_rep->sline.status << ") to client");
+	sendClientOldEntry();
     }
 }
 
@@ -472,33 +451,6 @@
     /* update size of the request */
     reqsize = result.length + reqofs;
 
-    if (e->getReply()->sline.status == 0) {
-        /*
-         * we don't have full reply headers yet; either wait for more or
-         * punt to clientProcessMiss.
-         */
-
-        if (e->mem_status == IN_MEMORY || e->store_status == STORE_OK) {
-            processMiss();
-        } else if (result.length + reqofs >= HTTP_REQBUF_SZ
-                   && http->out.offset == 0) {
-            processMiss();
-        } else {
-            debugs(88, 3, "clientCacheHit: waiting for HTTP reply headers");
-            reqofs += result.length;
-            assert(reqofs <= HTTP_REQBUF_SZ);
-            /* get the next users' buffer */
-            StoreIOBuffer tempBuffer;
-            tempBuffer.offset = http->out.offset + reqofs;
-            tempBuffer.length = next()->readBuffer.length - reqofs;
-            tempBuffer.data = next()->readBuffer.data + reqofs;
-            storeClientCopy(sc, e,
-                            tempBuffer, CacheHit, this);
-        }
-
-        return;
-    }
-
     /*
      * Got the headers, now grok them
      */
@@ -1390,32 +1342,14 @@
 
 
 void
-clientReplyContext::buildReply(const char *buf, size_t size)
+clientReplyContext::cloneReply()
 {
-    size_t k = headersEnd(buf, size);
-
-    if (!k)
-        return;
-
     assert(reply == NULL);
 
-    HttpReply *rep = new HttpReply;
+    HttpReply *rep = http->storeEntry()->getReply()->clone();
 
     reply = HTTPMSGLOCK(rep);
 
-    if (!reply->parseCharBuf(buf, k)) {
-        /* parsing failure, get rid of the invalid reply */
-        HTTPMSGUNLOCK(reply);
-
-        if (http->request->range) {
-            debugs(0,0,HERE << "look for bug here");
-            /* this will fail and destroy request->range */
-            //          clientBuildRangeHeader(http, reply);
-        }
-
-        return;
-    }
-
     /* enforce 1.0 reply version */
     reply->sline.version = HttpVersion(1,0);
 
@@ -1721,32 +1655,6 @@
 }
 
 void
-clientReplyContext::waitForMoreData ()
-{
-    debugs(88, 5, "clientReplyContext::waitForMoreData: Waiting for more data to parse reply headers in client side.");
-    /* We don't have enough to parse the metadata yet */
-    /* TODO: the store should give us out of band metadata and
-     * obsolete this routine 
-     */
-    /* wait for more to arrive */
-    startSendProcess();
-}
-
-void
-clientReplyContext::startSendProcess()
-{
-    debugs(88, 5, "clientReplyContext::startSendProcess: triggering store read to SendMoreData");
-    assert(reqofs <= HTTP_REQBUF_SZ);
-    /* TODO: copy into the supplied buffer */
-    StoreIOBuffer tempBuffer;
-    tempBuffer.offset = reqofs;
-    tempBuffer.length = next()->readBuffer.length - reqofs;
-    tempBuffer.data = next()->readBuffer.data + reqofs;
-    storeClientCopy(sc, http->storeEntry(),
-                    tempBuffer, SendMoreData, this);
-}
-
-void
 clientReplyContext::sendBodyTooLargeError()
 {
     IPAddress tmp_noaddr; tmp_noaddr.SetNoAddr(); // TODO: make a global const
@@ -1835,8 +1743,10 @@
     http->loggingEntry(http->storeEntry());
 
     ssize_t body_size = reqofs - reply->hdr_sz;
-
-    assert(body_size >= 0);
+    if (body_size < 0) {
+	reqofs = reply->hdr_sz;
+	body_size = 0;
+    }
 
     debugs(88, 3, "clientReplyContext::sendMoreData: Appending " <<
            (int) body_size << " bytes after " << reply->hdr_sz <<
@@ -1866,7 +1776,7 @@
 
     StoreIOBuffer tempBuffer;
     char *buf = next()->readBuffer.data;
-    char *body_buf = buf + reply->hdr_sz;
+    char *body_buf = buf + reply->hdr_sz - next()->readBuffer.offset;
 
     //Server side may disable ranges under some circumstances.
 
@@ -1910,23 +1820,11 @@
 
     char *body_buf = buf;
 
-    /* This is always valid until we get the headers as metadata from
-     * storeClientCopy. 
-     * Then it becomes reqofs == next->readBuffer.offset()
-     */
-    assert(reqofs == 0 || flags.storelogiccomplete);
-
-    if (flags.headersSent && buf != result.data) {
+    if (buf != result.data) {
         /* we've got to copy some data */
         assert(result.length <= next()->readBuffer.length);
         xmemcpy(buf, result.data, result.length);
         body_buf = buf;
-    } else if (!flags.headersSent &&
-               buf + reqofs !=result.data) {
-        /* we've got to copy some data */
-        assert(result.length + reqofs <= next()->readBuffer.length);
-        xmemcpy(buf + reqofs, result.data, result.length);
-        body_buf = buf;
     }
 
     /* We've got the final data to start pushing... */
@@ -1965,38 +1863,23 @@
         return;
     }
 
-    buildReply(buf, reqofs);
-
-    if (reply) {
-
-        /* handle headers */
-
-        if (Config.onoff.log_mime_hdrs) {
-            size_t k;
-
-            if ((k = headersEnd(buf, reqofs))) {
-                safe_free(http->al.headers.reply);
-                http->al.headers.reply = (char *)xcalloc(k + 1, 1);
-                xstrncpy(http->al.headers.reply, buf, k);
-            }
-        }
-
-        holdingBuffer = result;
-        processReplyAccess();
-        return;
-
-    } else if (reqofs < HTTP_REQBUF_SZ && entry->store_status == STORE_PENDING) {
-        waitForMoreData();
-        return;
-    } else {
-        debugs(88, 0, "clientReplyContext::sendMoreData: Unable to parse reply headers within a single HTTP_REQBUF_SZ length buffer");
-        StoreIOBuffer tempBuffer;
-        tempBuffer.flags.error = 1;
-        /* XXX FIXME: make an html error page here */
-        sendStreamError(tempBuffer);
-        return;
+    cloneReply();
+
+    /* handle headers */
+
+    if (Config.onoff.log_mime_hdrs) {
+	size_t k;
+
+	if ((k = headersEnd(buf, reqofs))) {
+	    safe_free(http->al.headers.reply);
+	    http->al.headers.reply = (char *)xcalloc(k + 1, 1);
+	    xstrncpy(http->al.headers.reply, buf, k);
+	}
     }
-    fatal ("clientReplyContext::sendMoreData: Unreachable code reached \n");
+
+    holdingBuffer = result;
+    processReplyAccess();
+    return;
 }
 
 

=== modified file 'src/client_side_reply.h'
--- src/client_side_reply.h	2008-03-16 22:10:18 +0000
+++ src/client_side_reply.h	2008-03-22 01:47:25 +0000
@@ -122,15 +122,13 @@
     bool errorInStream(StoreIOBuffer const &result, size_t const &sizeToProcess)const ;
     void sendStreamError(StoreIOBuffer const &result);
     void pushStreamData(StoreIOBuffer const &result, char *source);
-    void waitForMoreData ();
     clientStreamNode * next() const;
-    void startSendProcess();
     StoreIOBuffer holdingBuffer;
     HttpReply *reply;
     void processReplyAccess();
     static PF ProcessReplyAccessResult;
     void processReplyAccessResult(bool accessAllowed);
-    void buildReply(const char *buf, size_t size);
+    void cloneReply();
     void buildReplyHeader ();
     bool alwaysAllowResponse(http_status sline) const;
     int checkTransferDone();

# Begin bundle
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

Reply via email to