--------------------- PatchSet 7072 Date: 2005/10/05 14:48:14 Author: adri Branch: tidyup_deferred_reads Tag: (none) Log: Reverse my changes for now. They'll come back, but after my next move. Members: src/http.c:1.17.6.27.4.8->1.17.6.27.4.9 Index: squid/src/http.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/http.c,v retrieving revision 1.17.6.27.4.8 retrieving revision 1.17.6.27.4.9 diff -u -r1.17.6.27.4.8 -r1.17.6.27.4.9 --- squid/src/http.c 5 Oct 2005 13:50:43 -0000 1.17.6.27.4.8 +++ squid/src/http.c 5 Oct 2005 14:48:14 -0000 1.17.6.27.4.9 @@ -1,6 +1,6 @@ /* - * $Id: http.c,v 1.17.6.27.4.8 2005/10/05 13:50:43 adri Exp $ + * $Id: http.c,v 1.17.6.27.4.9 2005/10/05 14:48:14 adri Exp $ * * DEBUG: section 11 Hypertext Transfer Protocol (HTTP) * AUTHOR: Harvest Derived @@ -550,28 +550,38 @@ return 1; } - -static int -httpReadReplyData(int fd, HttpStateData *httpState, char *buf, int *read_sz) +/* This will be called when data is ready to be read from fd. Read until + * error or connection closed. */ +/* XXX this function is too long! */ +static void +httpReadReply(int fd, void *data) { + HttpStateData *httpState = data; + LOCAL_ARRAY(char, buf, SQUID_TCP_SO_RCVBUF); + StoreEntry *entry = httpState->entry; const request_t *request = httpState->request; int len; int bin; int clen; + size_t read_sz = SQUID_TCP_SO_RCVBUF; #if DELAY_POOLS delay_id delay_id; #endif + if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) { + comm_close(fd); + return; + } #if DELAY_POOLS /* special "if" only for http (for nodelay proxy conns) */ if (delayIsNoDelay(fd)) delay_id = 0; else - delay_id = delayMostBytesAllowed(entry->mem_obj, read_sz); + delay_id = delayMostBytesAllowed(entry->mem_obj, &read_sz); #endif errno = 0; statCounter.syscalls.sock.reads++; - len = FD_READ_METHOD(fd, buf, *read_sz); + len = FD_READ_METHOD(fd, buf, read_sz); debug(11, 5) ("httpReadReply: FD %d: len %d.\n", fd, len); if (len > 0) { fd_bytes(fd, len, FD_READ); @@ -585,51 +595,17 @@ clen >>= 1; IOStats.Http.read_hist[bin]++; } - return len; -} - -static int -httpSkipWhitespace(int fd, HttpStateData *httpState, char *buf, int *len) -{ - if (!httpState->reply_hdr.size && *len > 0 && fd_table[fd].uses > 1) { + if (!httpState->reply_hdr.size && len > 0 && fd_table[fd].uses > 1) { /* Skip whitespace */ - while (*len > 0 && xisspace(*buf)) - xmemmove(buf, buf + 1, *len--); - if (*len == 0) { - return 1; - } - } - return 0; -} - - -/* This will be called when data is ready to be read from fd. Read until - * error or connection closed. */ -/* XXX this function is too long! */ -static void -httpReadReply(int fd, void *data) -{ - HttpStateData *httpState = data; - LOCAL_ARRAY(char, buf, SQUID_TCP_SO_RCVBUF); - StoreEntry *entry = httpState->entry; - const request_t *request = httpState->request; - int len; - size_t read_sz = SQUID_TCP_SO_RCVBUF; - - if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) { - comm_close(fd); - return; - } - - len = httpReadReplyData(fd, httpState, buf, &read_sz); - - if (httpSkipWhitespace(fd, httpState, buf, &len)) { + while (len > 0 && xisspace(*buf)) + xmemmove(buf, buf + 1, len--); + if (len == 0) { /* Continue to read... */ /* Timeout NOT increased. This whitespace was from previous reply */ commSetSelect(fd, COMM_SELECT_READ, httpReadReply, httpState, 0); return; + } } - if (len < 0) { debug(50, 2) ("httpReadReply: FD %d: read failure: %s.\n", fd, xstrerror()); @@ -642,12 +618,10 @@ fwdFail(httpState->fwd, err); comm_close(fd); } - return; } else if (len == 0 && entry->mem_obj->inmem_hi == 0) { fwdFail(httpState->fwd, errorCon(ERR_ZERO_SIZE_OBJECT, HTTP_BAD_GATEWAY)); httpState->eof = 1; comm_close(fd); - return; } else if (len == 0) { /* Connection closed; retrieval done. */ httpState->eof = 1; @@ -672,137 +646,130 @@ } comm_close(fd); return; - } - - /* Valid data: process */ - if (httpState->reply_hdr_state < 2) { - httpProcessReplyHeader(httpState, buf, len); - if (httpState->reply_hdr_state == 2) { - http_status s = entry->mem_obj->reply->sline.status; - if (s == HTTP_HEADER_TOO_LARGE) { - debug(11, 1) ("WARNING: %s:%d: HTTP header too large\n", __FILE__, __LINE__); - storeEntryReset(entry); - fwdFail(httpState->fwd, errorCon(ERR_TOO_BIG, HTTP_BAD_GATEWAY)); - httpState->fwd->flags.dont_retry = 1; - comm_close(fd); - return; - } - if (s == HTTP_INVALID_HEADER && - !(entry->mem_obj->reply->sline.version.major == 0 && - entry->mem_obj->reply->sline.version.minor == 9)) { - storeEntryReset(entry); - fwdFail(httpState->fwd, errorCon(ERR_INVALID_RESP, HTTP_BAD_GATEWAY)); - httpState->fwd->flags.dont_retry = 1; - comm_close(fd); - return; - } + } else { + if (httpState->reply_hdr_state < 2) { + httpProcessReplyHeader(httpState, buf, len); + if (httpState->reply_hdr_state == 2) { + http_status s = entry->mem_obj->reply->sline.status; + if (s == HTTP_HEADER_TOO_LARGE) { + debug(11, 1) ("WARNING: %s:%d: HTTP header too large\n", __FILE__, __LINE__); + storeEntryReset(entry); + fwdFail(httpState->fwd, errorCon(ERR_TOO_BIG, HTTP_BAD_GATEWAY)); + httpState->fwd->flags.dont_retry = 1; + comm_close(fd); + return; + } + if (s == HTTP_INVALID_HEADER && !(entry->mem_obj->reply->sline.version.major == 0 && entry->mem_obj->reply->sline.version.minor == 9)) { + storeEntryReset(entry); + fwdFail(httpState->fwd, errorCon(ERR_INVALID_RESP, HTTP_BAD_GATEWAY)); + httpState->fwd->flags.dont_retry = 1; + comm_close(fd); + return; + } #if WIP_FWD_LOG - fwdStatus(httpState->fwd, s); + fwdStatus(httpState->fwd, s); #endif - /* - * If its not a reply that we will re-forward, then - * allow the client to get it. - */ - if (!fwdReforwardableStatus(s)) - EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT); - } - } - - storeAppend(entry, buf, len); - if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) { - /* - * the above storeAppend() call could ABORT this entry, - * in that case, the server FD should already be closed. - * there's nothing for us to do. - */ - return; - } - switch (httpPconnTransferDone(httpState)) { - case 1: - { - int keep_alive = 1; - /* - * If we didn't send a keep-alive request header, then this - * can not be a persistent connection. - */ - if (!httpState->flags.keepalive) - keep_alive = 0; - /* - * If we haven't sent the whole request then this can not be a persistent - * connection. - */ - if (!httpState->flags.request_sent) { - debug(11, 1) ("httpReadReply: Request not yet fully sent \"%s %s\"\n", - RequestMethodStr[httpState->orig_request->method], - storeUrl(entry)); - keep_alive = 0; - } - /* - * What does the reply have to say about keep-alive? - */ - if (!entry->mem_obj->reply->keep_alive) - keep_alive = 0; - /* - * Verify that the connection is clean - */ - if (len == read_sz) { - statCounter.syscalls.sock.reads++; - len = FD_READ_METHOD(fd, buf, SQUID_TCP_SO_RCVBUF); - if ((len < 0 && !ignoreErrno(errno)) || len == 0) { - keep_alive = 0; - } else if (len > 0) { - debug(11, Config.onoff.relaxed_header_parser <= 0 || keep_alive ? 1 : 2) - ("httpReadReply: Excess data from \"%s %s\"\n", - RequestMethodStr[httpState->orig_request->method], - storeUrl(entry)); - storeAppend(entry, buf, len); - keep_alive = 0; - } - } - if (keep_alive) { - /* yes we have to clear all these! */ - commSetDefer(fd, NULL, NULL); - commSetTimeout(fd, -1, NULL, NULL); - commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0); + /* + * If its not a reply that we will re-forward, then + * allow the client to get it. + */ + if (!fwdReforwardableStatus(s)) + EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT); + } + } + storeAppend(entry, buf, len); + if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) { + /* + * the above storeAppend() call could ABORT this entry, + * in that case, the server FD should already be closed. + * there's nothing for us to do. + */ + return; + } + switch (httpPconnTransferDone(httpState)) { + case 1: + { + int keep_alive = 1; + /* + * If we didn't send a keep-alive request header, then this + * can not be a persistent connection. + */ + if (!httpState->flags.keepalive) + keep_alive = 0; + /* + * If we haven't sent the whole request then this can not be a persistent + * connection. + */ + if (!httpState->flags.request_sent) { + debug(11, 1) ("httpReadReply: Request not yet fully sent \"%s %s\"\n", + RequestMethodStr[httpState->orig_request->method], + storeUrl(entry)); + keep_alive = 0; + } + /* + * What does the reply have to say about keep-alive? + */ + if (!entry->mem_obj->reply->keep_alive) + keep_alive = 0; + /* + * Verify that the connection is clean + */ + if (len == read_sz) { + statCounter.syscalls.sock.reads++; + len = FD_READ_METHOD(fd, buf, SQUID_TCP_SO_RCVBUF); + if ((len < 0 && !ignoreErrno(errno)) || len == 0) { + keep_alive = 0; + } else if (len > 0) { + debug(11, Config.onoff.relaxed_header_parser <= 0 || keep_alive ? 1 : 2) + ("httpReadReply: Excess data from \"%s %s\"\n", + RequestMethodStr[httpState->orig_request->method], + storeUrl(entry)); + storeAppend(entry, buf, len); + keep_alive = 0; + } + } + if (keep_alive) { + /* yes we have to clear all these! */ + commSetDefer(fd, NULL, NULL); + commSetTimeout(fd, -1, NULL, NULL); + commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0); #if DELAY_POOLS - delayClearNoDelay(fd); + delayClearNoDelay(fd); #endif - comm_remove_close_handler(fd, httpStateFree, httpState); - fwdUnregister(fd, httpState->fwd); - pconnPush(fd, request->host, request->port); - fwdComplete(httpState->fwd); - httpState->fd = -1; - httpStateFree(fd, httpState); - } else { - fwdComplete(httpState->fwd); - comm_close(fd); - } - } - return; - - case 0: - /* Wait for more data or EOF condition */ - if (httpState->flags.keepalive_broken) { - commSetTimeout(fd, 10, NULL, NULL); - } else { - commSetTimeout(fd, Config.Timeout.read, NULL, NULL); - } - commSetSelect(fd, COMM_SELECT_READ, httpReadReply, httpState, 0); - return; - - case -1: - /* Server is nasty on us. Shut down */ - debug(11, Config.onoff.relaxed_header_parser <= 0 || entry->mem_obj->reply->keep_alive ? 1 : 2) - ("httpReadReply: Excess data from \"%s %s\"\n", - RequestMethodStr[httpState->orig_request->method], - storeUrl(entry)); - fwdComplete(httpState->fwd); - comm_close(fd); - return; - - default: - fatal("Unexpected httpPconnTransferDone() status\n"); - break; + comm_remove_close_handler(fd, httpStateFree, httpState); + fwdUnregister(fd, httpState->fwd); + pconnPush(fd, request->host, request->port); + fwdComplete(httpState->fwd); + httpState->fd = -1; + httpStateFree(fd, httpState); + } else { + fwdComplete(httpState->fwd); + comm_close(fd); + } + } + return; + case 0: + /* Wait for more data or EOF condition */ + if (httpState->flags.keepalive_broken) { + commSetTimeout(fd, 10, NULL, NULL); + } else { + commSetTimeout(fd, Config.Timeout.read, NULL, NULL); + } + commSetSelect(fd, COMM_SELECT_READ, httpReadReply, httpState, 0); + return; + case -1: + /* Server is nasty on us. Shut down */ + debug(11, Config.onoff.relaxed_header_parser <= 0 || entry->mem_obj->reply->keep_alive ? 1 : 2) + ("httpReadReply: Excess data from \"%s %s\"\n", + RequestMethodStr[httpState->orig_request->method], + storeUrl(entry)); + fwdComplete(httpState->fwd); + comm_close(fd); + return; + default: + fatal("Unexpected httpPconnTransferDone() status\n"); + break; + } } }