Resubmissions as I haven't received any comments on the previous merge
request.

This patch fixes Bug #2001 by reworking how the client_side_*.cc code
deals with response headers. Instead of parsing the headers again it
clones the already parsed header and blindly skips the unparsed headers
in the data stream.

3.0 version submitted separately.
# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: [EMAIL PROTECTED]
#   63h3likn45namhsa
# target_branch: file:///data/bzr/squid3/trunk/
# testament_sha1: 861409ffadcaf9c00dc89f6cc2eb48d9dcb8bb25
# timestamp: 2008-04-06 03:37:48 +0200
# base_revision_id: [EMAIL PROTECTED]
#   yff1f2iecpkhoq4t
# 
# 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