/*
- * $Id: client_side.cc,v 1.172 1997/12/04 00:07:33 wessels Exp $
+ * $Id: client_side.cc,v 1.173 1997/12/04 23:07:51 wessels Exp $
*
* DEBUG: section 33 Client-side Routines
* AUTHOR: Duane Wessels
storeAbort(entry, 1);
}
+#define SENDING_BODY 0
+#define SENDING_HDRSONLY 1
static int
icpCheckTransferDone(clientHttpRequest * http)
{
+ int sending = SENDING_BODY;
StoreEntry *entry = http->entry;
- MemObject *mem = NULL;
+ MemObject *mem;
+ http_reply *reply;
+ int sendlen;
if (entry == NULL)
return 0;
- if (entry->store_status != STORE_PENDING)
+ /*
+ * Handle STORE_OK and STORE_ABORTED objects.
+ * entry->object_len will be set proprely.
+ */
+ if (entry->store_status != STORE_PENDING) {
if (http->out.offset >= entry->object_len)
return 1;
- if ((mem = entry->mem_obj) == NULL)
- return 0;
- if (mem->reply->content_length < 0) {
- /*
- * for 200 replies, we MUST have a content length,
- * or wait for EOF on the socket.
- */
- if (mem->reply->code == 200)
- return 0;
- /*
- * reply->hdr_sz will be set by httpParseReplyHeaders()
- * if we find the end of the headers. If we find the end,
- * and there is no content length, stick a fork in us.
- */
- else if (mem->reply->hdr_sz == 0)
- return 0;
- else if (http->out.offset >= mem->reply->hdr_sz)
- return 1;
else
return 0;
}
- if (http->out.offset >= mem->reply->content_length + mem->reply->hdr_sz)
- return 1;
- return 0;
+ /*
+ * Now, handle STORE_PENDING objects
+ */
+ mem = entry->mem_obj;
+ assert(mem != NULL);
+ assert(http->request != NULL);
+ reply = mem->reply;
+ if (reply->hdr_sz == 0)
+ return 0; /* haven't found end of headers yet */
+ else if (reply->code == HTTP_OK)
+ sending = SENDING_BODY;
+ else if (reply->content_length < 0)
+ sending = SENDING_HDRSONLY;
+ else if (reply->code == HTTP_NO_CONTENT)
+ sending = SENDING_HDRSONLY;
+ else if (reply->code == HTTP_NOT_MODIFIED)
+ sending = SENDING_HDRSONLY;
+ else if (http->request->method == METHOD_HEAD)
+ sending = SENDING_HDRSONLY;
+ else
+ sending = SENDING_BODY;
+ /*
+ * Figure out how much data we are supposed to send.
+ * If we are sending a body and we don't have a content-length,
+ * then we must wait for the object to become STORE_OK or
+ * STORE_ABORTED.
+ */
+ if (sending == SENDING_HDRSONLY)
+ sendlen = reply->hdr_sz;
+ else if (reply->content_length < 0)
+ return 0;
+ else
+ sendlen = reply->content_length + reply->hdr_sz;
+ /*
+ * Now that we have the expected length, did we send it all?
+ */
+ if (http->out.offset < sendlen)
+ return 0;
+ else
+ return 1;
}
static char *
/*
- * $Id: http.cc,v 1.227 1997/12/03 09:00:18 wessels Exp $
+ * $Id: http.cc,v 1.228 1997/12/04 23:07:52 wessels Exp $
*
* DEBUG: section 11 Hypertext Transfer Protocol (HTTP)
* AUTHOR: Harvest Derived
MemObject *mem = httpState->entry->mem_obj;
struct _http_reply *reply = mem->reply;
debug(11, 3) ("httpPconnTransferDone: FD %d\n", httpState->fd);
+ /*
+ * If we didn't send a Keepalive request header, then this
+ * can not be a persistent connection.
+ */
if (!EBIT_TEST(httpState->flags, HTTP_KEEPALIVE))
return 0;
debug(11, 5) ("httpPconnTransferDone: content_length=%d\n",
reply->content_length);
/*
- * !200 replies maybe don't have content-length, so
- * if we saw the end of the headers then try being persistent.
+ * Deal with gross HTTP stuff
+ * - If we haven't seen the end of the reply headers, we can't
+ * be persistent.
+ * - For "200 OK" check the content-length in the next block.
+ * - For other replies without a content-length, we're done.
+ * - For "204 No Content" (even with content-length) we're done.
+ * - For "304 Not Modified" (even with content-length) we're done.
+ * - For HEAD requests with content-length we're done.
+ * - For other replies with a content length, we continue...
*/
- if (reply->code != 200)
- if (reply->content_length < 0)
- if (httpState->reply_hdr_state > 1)
- return 1;
+ if (httpState->reply_hdr_state < 2)
+ return 0;
+ else if (reply->code == HTTP_OK)
+ (void) 0; /* continue */
+ else if (reply->content_length < 0)
+ return 1;
+ else if (reply->code == HTTP_NO_CONTENT)
+ return 1;
+ else if (reply->code == HTTP_NOT_MODIFIED)
+ return 1;
+ else if (httpState->request->method == METHOD_HEAD)
+ return 1;
/*
- * If there is no content-length, then we probably can't be persistent
+ * If there is no content-length, then we probably can't be
+ * persistent. If there is a content length, then we must
+ * wait until we've seen the end of the body.
*/
if (reply->content_length < 0)
return 0;
- /*
- * If there is a content_length, see if we've got all of it. If so,
- * then we can recycle this connection.
- */
- debug(11, 5) ("httpPconnTransferDone: hdr_sz=%d\n", reply->hdr_sz);
- debug(11, 5) ("httpPconnTransferDone: inmem_hi=%d\n",
- mem->inmem_hi);
- if (mem->inmem_hi < reply->content_length + reply->hdr_sz)
+ else if (mem->inmem_hi < reply->content_length + reply->hdr_sz)
return 0;
- return 1;
+ else
+ return 1;
}
/* This will be called when data is ready to be read from fd. Read until