--------------------- PatchSet 5259 Date: 2002/10/06 10:20:26 Author: rbcollins Branch: commloops Tag: (none) Log: more extraction of the method Members: src/client_side.c:1.52.4.11->1.52.4.12 src/structs.h:1.51.4.5->1.51.4.6 Index: squid/src/client_side.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/client_side.c,v retrieving revision 1.52.4.11 retrieving revision 1.52.4.12 diff -u -r1.52.4.11 -r1.52.4.12 --- squid/src/client_side.c 6 Oct 2002 08:09:38 -0000 1.52.4.11 +++ squid/src/client_side.c 6 Oct 2002 10:20:26 -0000 1.52.4.12 @@ -1,6 +1,6 @@ /* - * $Id: client_side.c,v 1.52.4.11 2002/10/06 08:09:38 rbcollins Exp $ + * $Id: client_side.c,v 1.52.4.12 2002/10/06 10:20:26 rbcollins Exp $ * * DEBUG: section 33 Client-side Routines * AUTHOR: Duane Wessels @@ -91,6 +91,9 @@ int deferred:1; /* This is a pipelined request waiting for the * current object to complete */ int parsed_ok:1; /* Was this parsed correctly? */ + int mayUseConnection:1; /* This request may use the connection - + * don't read anymore requests for now + */ } flags; struct { clientStreamNode *node; @@ -116,7 +119,7 @@ static void checkFailureRatio(err_type, hier_code); static clientSocketContext *parseHttpRequestAbort(ConnStateData * conn, const char *uri); -static clientSocketContext *parseHttpRequest(ConnStateData *, method_t *, int *, +static clientSocketContext *parseHttpRequest(ConnStateData *, method_t *, char **, size_t *); #if USE_IDENT static IDCB clientIdentDone; @@ -157,7 +160,7 @@ static char *findTrailingHTTPVersion(char *uriAndHTTPVersion); static void trimTrailingSpaces(char *aString, size_t len); static clientSocketContext *parseURIandHTTPVersion(char **url_p, http_version_t * http_ver_p, ConnStateData * conn); -static void setLogUri(clientHttpRequest * http, char *uri); +static void setLogUri(clientHttpRequest * http, char const *uri); static void prepareInternalUrl(clientHttpRequest * http, char *url); static void prepareForwardProxyUrl(clientHttpRequest * http, char *url); static void prepareAcceleratedUrl(clientHttpRequest * http, char *url, char *req_hdr); @@ -831,7 +834,7 @@ http->start = current_time; http->req_sz = conn->in.notYetUsed; http->uri = xstrdup(uri); - http->log_uri = xstrndup(uri, MAX_URL); + setLogUri (http, uri); context = clientSocketContextNew(http); tempBuffer.data = context->reqbuf; tempBuffer.length = HTTP_REQBUF_SZ; @@ -950,8 +953,9 @@ } void -setLogUri(clientHttpRequest * http, char *uri) +setLogUri(clientHttpRequest * http, char const *uri) { + safe_free(http->log_uri); if (!stringHasCntl(uri)) http->log_uri = xstrndup(uri, MAX_URL); else @@ -1043,13 +1047,12 @@ * * Returns * NULL on incomplete requests - * a clientSocketContext structure on success or failure - * Sets *status to -1 if failed to parse the request - * Sets *status to 0 we think we have a partial request - * Sets *status to 1 if we have a good request + * a clientSocketContext structure on success or failure. + * Sets result->flags.parsed_ok to 1 if failed to parse the request. + * Sets result->flags.parsed_ok to 0 if we have a good request. */ static clientSocketContext * -parseHttpRequest(ConnStateData * conn, method_t * method_p, int *status, +parseHttpRequest(ConnStateData * conn, method_t * method_p, char **prefix_p, size_t * req_line_sz_p) { char *inbuf = NULL; @@ -1067,11 +1070,9 @@ /* pre-set these values to make aborting simpler */ *prefix_p = NULL; *method_p = METHOD_NONE; - *status = -1; if ((req_sz = headersEnd(conn->in.buf, conn->in.notYetUsed)) == 0) { debug(33, 5) ("Incomplete request, waiting for end of headers\n"); - *status = 0; return NULL; } assert(req_sz <= conn->in.notYetUsed); @@ -1096,7 +1097,6 @@ header_sz = req_sz - (req_hdr - inbuf); if (0 == header_sz) { debug(33, 3) ("parseHttpRequest: header_sz == 0\n"); - *status = 0; xfree(inbuf); return NULL; } @@ -1146,7 +1146,7 @@ setLogUri(http, http->uri); debug(33, 5) ("parseHttpRequest: Complete request received\n"); xfree(inbuf); - *status = 1; + result->flags.parsed_ok = 1; return result; } @@ -1271,11 +1271,120 @@ } static void +clientMaybeReadData(ConnStateData *conn, int do_next_read) +{ + if (do_next_read) { + conn->flags.readMoreRequests = 1; + clientReadSomeData(conn); + } +} + +static void +clientAfterReadingRequests(int fd, ConnStateData *conn, int do_next_read) +{ + fde *F = &fd_table[fd]; + + /* Check if a half-closed connection was aborted in the middle */ + if (F->flags.socket_eof) { + if (conn->in.notYetUsed != conn->body.size_left) { /* != 0 when no request body */ + /* Partial request received. Abort client connection! */ + debug(33, 3) ("clientReadRequest: FD %d aborted, partial request\n", + fd); + comm_close(fd); + clientMaybeReadData (conn, 0); + return; + } + } + + clientMaybeReadData (conn, do_next_read); +} + +static void +clientProcessRequest(ConnStateData *conn, clientSocketContext *context, request_t *request) +{ + clientHttpRequest *http = context->http; + + request->flags.accelerated = http->flags.accel; + if (!http->flags.internal) { + if (internalCheck(strBuf(request->urlpath))) { + if (internalHostnameIs(request->host) && + request->port == getMyPort()) { + http->flags.internal = 1; + } else if (internalStaticCheck(strBuf(request->urlpath))) { + xstrncpy(request->host, internalHostname(), + SQUIDHOSTNAMELEN); + request->port = getMyPort(); + http->flags.internal = 1; + } + } + } + + /* + * cache the Content-length value in request_t. + */ + request->content_length = httpHeaderGetInt(&request->header, + HDR_CONTENT_LENGTH); + request->flags.internal = http->flags.internal; + setLogUri (http, urlCanonicalClean(request)); + request->client_addr = conn->peer.sin_addr; + request->my_addr = conn->me.sin_addr; + request->my_port = ntohs(conn->me.sin_port); + request->http_ver = http->http_ver; + if (!urlCheckRequest(request) || + httpHeaderHas(&request->header, HDR_TRANSFER_ENCODING)) { + clientStreamNode *node = getClientReplyContext(context); + clientSetReplyToError(node->data, ERR_UNSUP_REQ, + HTTP_NOT_IMPLEMENTED, request->method, NULL, + &conn->peer.sin_addr, request, NULL, NULL); + assert(context->http->out.offset == 0); + clientPullData(context); + conn->flags.readMoreRequests = 0; + return; + } + + + if (!clientIsContentLengthValid(request)) { + clientStreamNode *node = getClientReplyContext(context); + clientSetReplyToError(node->data, ERR_INVALID_REQ, + HTTP_LENGTH_REQUIRED, request->method, NULL, + &conn->peer.sin_addr, request, NULL, NULL); + assert(context->http->out.offset == 0); + clientPullData(context); + conn->flags.readMoreRequests = 0; + return; + } + + http->request = requestLink(request); + + clientSetKeepaliveFlag(http); + /* Do we expect a request-body? */ + if (request->content_length > 0) { + conn->body.size_left = request->content_length; + request->body_connection = conn; + /* Is it too large? */ + if (!clientIsRequestBodyValid(request->content_length) || + clientIsRequestBodyTooLargeForPolicy(request->content_length)) { + clientStreamNode *node = getClientReplyContext(context); + clientSetReplyToError(node->data, ERR_TOO_BIG, + HTTP_REQUEST_ENTITY_TOO_LARGE, METHOD_NONE, NULL, + &conn->peer.sin_addr, http->request, NULL, NULL); + assert(context->http->out.offset == 0); + clientPullData(context); + conn->flags.readMoreRequests = 0; + return; + } + } + + /* If this is a CONNECT, don't schedule a read - ssl.c will handle it */ + if (http->request->method == METHOD_CONNECT) + context->flags.mayUseConnection = 1; + clientAccessCheck(http); +} + +static void clientReadRequest(int fd, char *buf, size_t size, comm_err_t flag, int xerrno, void *data) { ConnStateData *conn = data; - int parser_return_code = 0; - request_t *request = NULL; method_t method; char *prefix = NULL; fde *F = &fd_table[fd]; @@ -1296,8 +1405,8 @@ } else if (flag == COMM_OK && size == 0) { if (connFinishedWithConn(conn, size)) { comm_close(fd); - do_next_read = 0; - goto finish; + clientMaybeReadData (conn, 0); + return; } /* It might be half-closed, we can't tell */ debug(33, 5) ("clientReadRequest: FD %d closed?\n", fd); @@ -1312,8 +1421,8 @@ /* Continue to process previously read data */ } else if (connReadWasError(conn, flag, size)) { comm_close(fd); - do_next_read = 0; - goto finish; + clientMaybeReadData (conn, 0); + return; } /* Process request body if any */ if (conn->in.notYetUsed > 0 && conn->body.callback != NULL) @@ -1331,7 +1440,7 @@ } conn->in.buf[conn->in.notYetUsed] = '\0'; /* Terminate the string */ if (conn->in.notYetUsed == 0) - break; + break; /* conn->in.notYetUsed > 0 && conn->body.size_left == 0 */ /* Limit the number of concurrent requests to 2 */ if (connGetConcurrentRequestCount(conn) >= (Config.onoff.pipeline_prefetch ? 2 : 1)) { debug(33, 3) ("clientReadRequest: FD %d max concurrent requests reached\n", @@ -1340,24 +1449,25 @@ fd); conn->defer.until = squid_curtime + 100; /* Reset when a request is complete */ conn->defer.n++; - goto finish; + clientMaybeReadData (conn, do_next_read); + return; } conn->in.buf[conn->in.notYetUsed] = '\0'; /* Terminate the string */ /* Process request */ context = parseHttpRequest(conn, - &method, &parser_return_code, &prefix, &req_line_sz); + &method, &prefix, &req_line_sz); /* partial or incomplete request */ if (!context) { safe_free(prefix); - assert (parser_return_code == 0); if (!connKeepReadingIncompleteRequest(conn)) connCancelIncompleteRequests(conn); - break; + break; /* conn->in.notYetUsed > 0 && conn->body.size_left == 0 */ } /* status -1 or 1 */ if (context) { clientHttpRequest *http = context->http; + request_t *request = NULL; /* We have an initial client stream in place should it be needed */ /* setup our private context */ connNoteUseOfBuffer(conn, http->req_sz); @@ -1365,7 +1475,7 @@ connAddContextToQueue(conn, context); commSetTimeout(fd, Config.Timeout.lifetime, clientLifetimeTimeout, http); - if (parser_return_code < 0) { + if (context->flags.parsed_ok == 0) { clientStreamNode *node = getClientReplyContext(context); debug(33, 1) ("clientReadRequest: FD %d Invalid Request\n", fd); clientSetReplyToError(node->data, @@ -1394,94 +1504,19 @@ http->uri, prefix); /* continue anyway? */ } - request->flags.accelerated = http->flags.accel; - if (!http->flags.internal) { - if (internalCheck(strBuf(request->urlpath))) { - if (internalHostnameIs(request->host) && - request->port == getMyPort()) { - http->flags.internal = 1; - } else if (internalStaticCheck(strBuf(request->urlpath))) { - xstrncpy(request->host, internalHostname(), - SQUIDHOSTNAMELEN); - request->port = getMyPort(); - http->flags.internal = 1; - } - } - } - /* - * cache the Content-length value in request_t. - */ - request->content_length = httpHeaderGetInt(&request->header, - HDR_CONTENT_LENGTH); - request->flags.internal = http->flags.internal; safe_free(prefix); - safe_free(http->log_uri); - http->log_uri = xstrdup(urlCanonicalClean(request)); - request->client_addr = conn->peer.sin_addr; - request->my_addr = conn->me.sin_addr; - request->my_port = ntohs(conn->me.sin_port); - request->http_ver = http->http_ver; - if (!urlCheckRequest(request) || - httpHeaderHas(&request->header, HDR_TRANSFER_ENCODING)) { - clientStreamNode *node = getClientReplyContext(context); - clientSetReplyToError(node->data, ERR_UNSUP_REQ, - HTTP_NOT_IMPLEMENTED, request->method, NULL, - &conn->peer.sin_addr, request, NULL, NULL); - assert(context->http->out.offset == 0); - clientPullData(context); - break; - } - if (!clientIsContentLengthValid(request)) { - clientStreamNode *node = getClientReplyContext(context); - clientSetReplyToError(node->data, ERR_INVALID_REQ, - HTTP_LENGTH_REQUIRED, request->method, NULL, - &conn->peer.sin_addr, request, NULL, NULL); - assert(context->http->out.offset == 0); - clientPullData(context); + + clientProcessRequest(conn, context, request); + if (!conn->flags.readMoreRequests) { + conn->flags.readMoreRequests = 1; break; } - http->request = requestLink(request); - clientSetKeepaliveFlag(http); - /* Do we expect a request-body? */ - if (request->content_length > 0) { - conn->body.size_left = request->content_length; - request->body_connection = conn; - /* Is it too large? */ - if (!clientIsRequestBodyValid(request->content_length) || - clientIsRequestBodyTooLargeForPolicy(request->content_length)) { - clientStreamNode *node = getClientReplyContext(context); - clientSetReplyToError(node->data, ERR_TOO_BIG, - HTTP_REQUEST_ENTITY_TOO_LARGE, METHOD_NONE, NULL, - &conn->peer.sin_addr, http->request, NULL, NULL); - assert(context->http->out.offset == 0); - clientPullData(context); - break; - } - } - /* If this is a CONNECT, don't schedule a read - ssl.c will handle it */ - if (http->request->method == METHOD_CONNECT) { - do_next_read = 0; - } - clientAccessCheck(http); + if (context->flags.mayUseConnection) + do_next_read = 0; continue; /* while offset > 0 && body.size_left == 0 */ } } /* while offset > 0 && conn->body.size_left == 0 */ - /* Check if a half-closed connection was aborted in the middle */ - if (F->flags.socket_eof) { - if (conn->in.notYetUsed != conn->body.size_left) { /* != 0 when no request body */ - /* Partial request received. Abort client connection! */ - debug(33, 3) ("clientReadRequest: FD %d aborted, partial request\n", - fd); - comm_close(fd); - do_next_read = 0; - goto finish; - } - } - -finish: - if (do_next_read) { - clientReadSomeData(conn); - } + clientAfterReadingRequests(fd, conn, do_next_read); } /* file_read like function, for reading body content */ @@ -1700,6 +1735,7 @@ memcpy(&result->me, me, sizeof(struct sockaddr_in)); result->fd = fd; result->in.buf = memAllocBuf(CLIENT_REQ_BUF_SZ, &result->in.allocatedSize); + result->flags.readMoreRequests = 1; return result; } Index: squid/src/structs.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/structs.h,v retrieving revision 1.51.4.5 retrieving revision 1.51.4.6 diff -u -r1.51.4.5 -r1.51.4.6 --- squid/src/structs.h 6 Oct 2002 07:12:23 -0000 1.51.4.5 +++ squid/src/structs.h 6 Oct 2002 10:20:29 -0000 1.51.4.6 @@ -1,6 +1,6 @@ /* - * $Id: structs.h,v 1.51.4.5 2002/10/06 07:12:23 rbcollins Exp $ + * $Id: structs.h,v 1.51.4.6 2002/10/06 10:20:29 rbcollins Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -1101,6 +1101,9 @@ int n; time_t until; } defer; + struct { + int readMoreRequests:1; + } flags; }; struct _ipcache_addrs {