/*
- * $Id: client_side.cc,v 1.176 1997/12/06 19:38:36 wessels Exp $
+ * $Id: client_side.cc,v 1.177 1997/12/07 00:48:12 wessels Exp $
*
* DEBUG: section 33 Client-side Routines
* AUTHOR: Duane Wessels
clientHttpRequest *http = data;
ConnStateData *conn;
StoreEntry *entry = http->entry;
+ int done;
http->out.size += size;
debug(12, 5) ("clientWriteComplete: FD %d, sz %d, err %d, off %d, len %d\n",
fd, size, errflag, http->out.offset, entry->object_len);
urlParseProtocol(storeUrl(entry)),
http->out.size);
comm_close(fd);
- } else if (icpCheckTransferDone(http) || size == 0) {
+ } else if ((done = icpCheckTransferDone(http)) || size == 0) {
debug(12, 5) ("clientWriteComplete: FD %d transfer is DONE\n", fd);
/* We're finished case */
HTTPCacheInfo->proto_touchobject(HTTPCacheInfo,
http->request->protocol,
http->out.size);
- if (http->entry->mem_obj->reply->content_length < 0) {
+ if (http->entry->mem_obj->reply->content_length < 0 || !done ||
+ EBIT_TEST(entry->flag, ENTRY_BAD_LENGTH)) {
+ /*
+ * Client connection closed due to unknown or invalid
+ * content length. Persistent connection is not possible.
+ * This catches most cases, but probably not all.
+ */
comm_close(fd);
} else if (EBIT_TEST(http->request->flags, REQ_PROXY_KEEPALIVE)) {
debug(12, 5) ("clientWriteComplete: FD %d Keeping Alive\n", fd);
conn = http->conn;
+ conn->defer.until = 0; /* Kick it to read a new request */
httpRequestFree(http);
if ((http = conn->chr) != NULL) {
debug(12, 1) ("clientWriteComplete: FD %d Sending next request\n", fd);
assert(http->request != NULL);
reply = mem->reply;
if (reply->hdr_sz == 0)
- return 0; /* haven't found end of headers yet */
+ return 0; /* haven't found end of headers yet */
else if (reply->code == HTTP_OK)
- sending = SENDING_BODY;
+ sending = SENDING_BODY;
else if (reply->content_length < 0)
sending = SENDING_HDRSONLY;
else if (reply->code == HTTP_NO_CONTENT)
- sending = SENDING_HDRSONLY;
+ sending = SENDING_HDRSONLY;
else if (reply->code == HTTP_NOT_MODIFIED)
- sending = SENDING_HDRSONLY;
+ sending = SENDING_HDRSONLY;
else if (http->request->method == METHOD_HEAD)
- sending = SENDING_HDRSONLY;
+ sending = SENDING_HDRSONLY;
else
sending = SENDING_BODY;
/*
if (http->out.offset < sendlen)
return 0;
else
- return 1;
+ return 1;
}
static char *
/*
- * $Id: http.cc,v 1.229 1997/12/06 01:26:16 wessels Exp $
+ * $Id: http.cc,v 1.230 1997/12/07 00:48:14 wessels Exp $
*
* DEBUG: section 11 Hypertext Transfer Protocol (HTTP)
* AUTHOR: Harvest Derived
err->request = requestLink(httpState->orig_request);
errorAppendEntry(entry, err);
} else {
- storeAbort(entry, 0);
+ storeAbort(entry, 0);
}
comm_close(fd);
}
else if (mem->inmem_hi < reply->content_length + reply->hdr_sz)
return 0;
else
- return 1;
+ return 1;
}
/* This will be called when data is ready to be read from fd. Read until
err->request = requestLink(httpState->orig_request);
errorAppendEntry(entry, err);
} else {
- storeAbort(entry, 0);
+ storeAbort(entry, 0);
}
comm_close(fd);
}
/* Connection closed; retrieval done. */
httpState->eof = 1;
if (httpState->reply_hdr_state < 2)
+ /*
+ * Yes Henrik, there is a point to doing this. When we
+ * called httpProcessReplyHeader() before, we didn't find
+ * the end of headers, but now we are definately at EOF, so
+ * we want to process the reply headers.
+ */
httpProcessReplyHeader(httpState, buf, len);
storeComplete(entry); /* deallocates mem_obj->request */
comm_close(fd);
/*
- * $Id: store.cc,v 1.355 1997/12/06 05:17:01 wessels Exp $
+ * $Id: store.cc,v 1.356 1997/12/07 00:48:15 wessels Exp $
*
* DEBUG: section 20 Storeage Manager
* AUTHOR: Harvest Derived
key = storeKeyScan(keytext);
if (key == NULL) {
- debug(20,1)("storeDoRebuildFromDisk: bad key: '%s'\n", keytext);
+ debug(20, 1) ("storeDoRebuildFromDisk: bad key: '%s'\n", keytext);
continue;
}
e = storeGet(key);
debug(20, 2) ("storeCheckCachable: NO: not cachable\n");
} else if (EBIT_TEST(e->flag, RELEASE_REQUEST)) {
debug(20, 2) ("storeCheckCachable: NO: release requested\n");
- } else if (e->store_status == STORE_OK && !storeEntryValidLength(e)) {
+ } else if (e->store_status == STORE_OK && EBIT_TEST(e->flag, ENTRY_BAD_LENGTH)) {
debug(20, 2) ("storeCheckCachable: NO: wrong content-length\n");
} else if (EBIT_TEST(e->flag, ENTRY_NEGCACHED)) {
debug(20, 2) ("storeCheckCachable: NO: negative cached\n");
e->object_len = e->mem_obj->inmem_hi;
e->store_status = STORE_OK;
assert(e->mem_status == NOT_IN_MEMORY);
+ if (!storeEntryValidLength(e))
+ EBIT_SET(e->flag, ENTRY_BAD_LENGTH);
InvokeHandlers(e);
storeCheckSwapOut(e);
}