Revision: 14468
Author: adrian.chadd
Date: Sat Mar 20 18:59:26 2010
Log: Migrate the mostly decoupled client-side request parsing code out of
client_side.c.
http://code.google.com/p/lusca-cache/source/detail?r=14468
Added:
/branches/LUSCA_HEAD/src/client_side_request_parse.c
/branches/LUSCA_HEAD/src/client_side_request_parse.h
Modified:
/branches/LUSCA_HEAD/src/Makefile.am
/branches/LUSCA_HEAD/src/client_side.c
/branches/LUSCA_HEAD/src/client_side.h
=======================================
--- /dev/null
+++ /branches/LUSCA_HEAD/src/client_side_request_parse.c Sat Mar 20
18:59:26 2010
@@ -0,0 +1,635 @@
+
+/*
+ * $Id: client_side.c 14461 2010-03-17 16:16:07Z adrian.chadd $
+ *
+ * DEBUG: section 33 Client-side Routines
+ * AUTHOR: Duane Wessels
+ *
+ * SQUID Web Proxy Cache http://www.squid-cache.org/
+ * ----------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from
+ * the Internet community; see the CONTRIBUTORS file for full
+ * details. Many organizations have provided support for Squid's
+ * development; see the SPONSORS file for full details. Squid is
+ * Copyrighted (C) 2001 by the Regents of the University of
+ * California; see the COPYRIGHT file for full details. Squid
+ * incorporates software developed and/or copyrighted by other
+ * sources; see the CREDITS file for full details.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+ *
+ */
+
+#include "squid.h"
+
+#include "client_side_conn.h"
+#include "client_side_body.h"
+
+#include "client_side_request.h"
+
+#include "client_side_ranges.h"
+
+#include "client_side.h"
+
+static const char *const crlf = "\r\n";
+
+#define FAILURE_MODE_TIME 300
+
+/* Local functions */
+
+static clientHttpRequest *parseHttpRequestAbort(ConnStateData * conn,
method_t ** method_p, const char *uri);
+static clientHttpRequest *parseHttpRequest(ConnStateData *, HttpMsgBuf *,
method_t **, int *);
+
+CBDATA_TYPE(clientHttpRequest);
+
+/*
+ * clientSetKeepaliveFlag() sets request->flags.proxy_keepalive.
+ * This is the client-side persistent connection flag. We need
+ * to set this relatively early in the request processing
+ * to handle hacks for broken servers and clients.
+ */
+static void
+clientSetKeepaliveFlag(clientHttpRequest * http)
+{
+ request_t *request = http->request;
+ const HttpHeader *req_hdr = &request->header;
+
+ debug(33, 3) ("clientSetKeepaliveFlag: http_ver = %d.%d\n",
+ request->http_ver.major, request->http_ver.minor);
+ debug(33, 3) ("clientSetKeepaliveFlag: method = %s\n",
+ urlMethodGetConstStr(request->method));
+ {
+ http_version_t http_ver;
+ if (http->conn->port->http11)
+ http_ver = request->http_ver;
+ else
+ httpBuildVersion(&http_ver, 1, 0); /* we are HTTP/1.0, no
matter what the client requests... */
+ if (httpMsgIsPersistent(http_ver, req_hdr))
+ request->flags.proxy_keepalive = 1;
+ }
+}
+
+static int
+clientCheckContentLength(request_t * r)
+{
+ switch (r->method->code) {
+ case METHOD_GET:
+ case METHOD_HEAD:
+ /* We do not want to see a request entity on GET/HEAD requests */
+ return (r->content_length <= 0 || Config.onoff.request_entities);
+ default:
+ /* For other types of requests we don't care */
+ return 1;
+ }
+ /* NOT REACHED */
+}
+
+/*
+ * Calculates the maximum size allowed for an HTTP request body
+ */
+static void
+clientMaxRequestBodySize(request_t * request, clientHttpRequest * http)
+{
+ body_size *bs;
+ aclCheck_t *checklist;
+ if (http->log_type == LOG_TCP_DENIED)
+ return;
+ bs = (body_size *) Config.RequestBodySize.head;
+ http->maxRequestBodySize = 0;
+ while (bs) {
+ checklist = clientAclChecklistCreate(bs->access_list, http);
+ if (aclCheckFast(bs->access_list, checklist) != 1) {
+ /* deny - skip this entry */
+ bs = (body_size *) bs->node.next;
+ } else {
+ /* Allow - use this entry */
+ http->maxRequestBodySize = bs->maxsize;
+ bs = NULL;
+ debug(58, 3) ("clientMaxRequestBodySize: Setting
maxRequestBodySize to %ld\n", (long int) http->maxRequestBodySize);
+ }
+ aclChecklistFree(checklist);
+ }
+}
+
+static int
+clientRequestBodyTooLarge(clientHttpRequest * http, request_t * request)
+{
+
+ if (http->maxRequestBodySize == -1) {
+ clientMaxRequestBodySize(request, http);
+ }
+ if (0 == http->maxRequestBodySize)
+ return 0; /* disabled */
+ if (request->content_length < 0)
+ return 0; /* unknown, bug? */
+ if (request->content_length > http->maxRequestBodySize)
+ return 1; /* too large */
+ return 0;
+}
+
+static clientHttpRequest *
+parseHttpRequestAbort(ConnStateData * conn, method_t ** method_p, const
char *uri)
+{
+ clientHttpRequest *http;
+ CBDATA_INIT_TYPE(clientHttpRequest);
+ http = cbdataAlloc(clientHttpRequest);
+ http->conn = conn;
+ http->start = current_time;
+ http->req_sz = conn->in.offset;
+ http->uri = xstrdup(uri);
+ http->log_uri = xstrdup(uri);
+ http->range_iter.boundary = StringNull;
+ httpBuildVersion(&http->http_ver, 1, 0);
+ dlinkAdd(http, &http->active, &ClientActiveRequests);
+ if (method_p && !*method_p)
+ *method_p = urlMethodGetKnownByCode(METHOD_NONE);
+ return http;
+}
+
+static int
+parseHttpConnectRequest(ConnStateData *conn, clientHttpRequest *http)
+{
+ if (http->http_ver.major < 1) {
+ debug(33, 1) ("parseHttpRequest: Invalid HTTP version\n");
+ return 0;
+ }
+ if (conn->port->accel) {
+ debug(33, 1) ("parseHttpRequest: CONNECT not valid in accelerator
mode\n");
+ return 0;
+ }
+ return 1;
+}
+
+static int
+parseHttpInternalRequest(ConnStateData *conn, clientHttpRequest *http,
const char *url)
+{
+ http->uri = xstrdup(internalStoreUri("", url));
+ http->flags.internal = 1;
+ http->flags.accel = 1;
+ debug(33, 5) ("INTERNAL REWRITE: '%s'\n", http->uri);
+ return 1;
+}
+static int
+parseHttpTransparentRequest(ConnStateData *conn, clientHttpRequest *http,
const char *url, const char *req_hdr)
+{
+ int port = 0;
+ const char *host = mime_get_header(req_hdr, "Host");
+ char *portstr;
+
+ if (host && (portstr = strchr(host, ':')) != NULL) {
+ *portstr++ = '\0';
+ port = atoi(portstr);
+ }
+ http->flags.transparent = 1;
+
+ if (Config.onoff.accel_no_pmtu_disc)
+ commSetNoPmtuDiscover(conn->fd);
+
+ if (conn->port->transparent && clientNatLookup(conn) == 0)
+ conn->transparent = 1;
+ if (!host && conn->transparent) {
+ port = ntohs(conn->me.sin_port);
+ if (!host)
+ host = inet_ntoa(conn->me.sin_addr);
+ }
+ if (host) {
+ size_t url_sz = 10 + strlen(host) + 6 + strlen(url) + 32 +
Config.appendDomainLen;
+ http->uri = xcalloc(url_sz, 1);
+ if (port) {
+ snprintf(http->uri, url_sz, "%s://%s:%d%s",
+ conn->port->protocol, host, port, url);
+ } else {
+ snprintf(http->uri, url_sz, "%s://%s%s",
+ conn->port->protocol, host, url);
+ }
+ } else if (internalCheck(url)) {
+ parseHttpInternalRequest(conn, http, url);
+ } else {
+ return 0;
+ }
+ return 1;
+}
+
+static int
+parseHttpAccelRequest(ConnStateData *conn, clientHttpRequest *http, const
char *url, const char *req_hdr)
+{
+ int vhost = conn->port->vhost;
+ int vport = conn->port->vport;
+ const char *t = NULL;
+
+ http->flags.accel = 1;
+ if (*url != '/' && !vhost && strncasecmp(url, "cache_object://", 15) !=
0) {
+ url = strstr(url, "//");
+ if (!url)
+ return 0;
+ url = strchr(url + 2, '/');
+ if (!url)
+ url = (char *) "/";
+ }
+ if (*url != '/') {
+ /* Fully qualified URL. Nothing special to do */
+ } else if (conn->port->accel) {
+ const char *host = NULL;
+ int port;
+ size_t url_sz;
+ if (vport > 0)
+ port = vport;
+ else
+ port = htons(http->conn->me.sin_port);
+ if (vhost && (t = mime_get_header(req_hdr, "Host")))
+ host = t;
+ else if (conn->port->defaultsite)
+ host = conn->port->defaultsite;
+ else if (vport == -1)
+ host = inet_ntoa(http->conn->me.sin_addr);
+ else
+ host = getMyHostname();
+ url_sz = strlen(url) + 32 + Config.appendDomainLen + strlen(host);
+ http->uri = xcalloc(url_sz, 1);
+ if (strchr(host, ':'))
+ snprintf(http->uri, url_sz, "%s://%s%s",
+ conn->port->protocol, host, url);
+ else
+ snprintf(http->uri, url_sz, "%s://%s:%d%s",
+ conn->port->protocol, host, port, url);
+ debug(33, 5) ("VHOST REWRITE: '%s'\n", http->uri);
+ } else if (internalCheck(url)) {
+ parseHttpInternalRequest(conn, http, url);
+ } else {
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * parseHttpRequest()
+ *
+ * Returns
+ * NULL on error or incomplete request
+ * a clientHttpRequest structure on success
+ */
+static clientHttpRequest *
+parseHttpRequest(ConnStateData * conn, HttpMsgBuf * hmsg, method_t **
method_p, int *status)
+{
+ LOCAL_ARRAY(char, urlbuf, MAX_URL);
+ char *url = urlbuf;
+ const char *req_hdr = NULL;
+ http_version_t http_ver;
+ size_t header_sz; /* size of headers, not including first line */
+ size_t prefix_sz; /* size of whole request (req-line + headers) */
+ size_t req_sz;
+ method_t *method;
+ clientHttpRequest *http = NULL;
+#if THIS_VIOLATES_HTTP_SPECS_ON_URL_TRANSFORMATION
+ char *t;
+#endif
+ int ret;
+
+ /* pre-set these values to make aborting simpler */
+ *method_p = urlMethodGetKnownByCode(METHOD_NONE);
+ *status = -1;
+
+ /* Parse the request line */
+ ret = httpMsgParseRequestLine(hmsg);
+ if (ret == -1)
+ return parseHttpRequestAbort(conn, method_p, "error:invalid-request");
+ if (ret == 0) {
+ debug(33, 5) ("Incomplete request, waiting for end of request line\n");
+ *status = 0;
+ return NULL;
+ }
+ /* If HTTP/0.9 then there's no headers */
+ if (hmsg->v_maj == 0 && hmsg->v_min == 9) {
+ req_sz = hmsg->r_len;
+ } else {
+ req_sz = httpMsgFindHeadersEnd(hmsg);
+ if (req_sz == 0) {
+ debug(33, 5) ("Incomplete request, waiting for end of headers\n");
+ *status = 0;
+ return NULL;
+ }
+ }
+ /* Set version */
+ httpBuildVersion(&http_ver, hmsg->v_maj, hmsg->v_min);
+
+ /* Enforce max_request_size */
+ if (req_sz >= Config.maxRequestHeaderSize) {
+ debug(33, 5) ("parseHttpRequest: Too large request\n");
+ return parseHttpRequestAbort(conn, method_p, "error:request-too-large");
+ }
+ /* Wrap the request method */
+ method = urlMethodGet(hmsg->buf + hmsg->m_start, hmsg->m_len);
+
+ debug(33, 5) ("parseHttpRequest: Method is '%s'\n",
urlMethodGetConstStr(method));
+ if (method->code == METHOD_OTHER) {
+ debug(33, 5) ("parseHttpRequest: Unknown method, continuing
regardless");
+ }
+ *method_p = method;
+
+ /* Make sure URL fits inside MAX_URL */
+ if (hmsg->u_len >= MAX_URL) {
+ debug(33, 1) ("parseHttpRequest: URL too big (%d) chars: %s\n",
hmsg->u_len, hmsg->buf + hmsg->u_start);
+ return parseHttpRequestAbort(conn, method_p, "error:request-too-large");
+ }
+ xmemcpy(urlbuf, hmsg->buf + hmsg->u_start, hmsg->u_len);
+ /* XXX off-by-one termination error? */
+ urlbuf[hmsg->u_len] = '\0';
+ debug(33, 5) ("parseHttpRequest: URI is '%s'\n", urlbuf);
+
+ /*
+ * Process headers after request line
+ * XXX at this point we really should just parse the damned headers
rather than doing
+ * it later, allowing us to then do the URL acceleration stuff withuot
too much hackery.
+ */
+ /* XXX re-evaluate all of these values and use whats in hmsg instead!
*/
+ req_hdr = hmsg->buf + hmsg->r_len;
+ header_sz = hmsg->h_len;
+ debug(33, 3) ("parseHttpRequest: req_hdr = {%s}\n", req_hdr);
+
+ prefix_sz = req_sz;
+ debug(33, 3) ("parseHttpRequest: prefix_sz = %d, req_line_sz = %d\n",
+ (int) prefix_sz, (int) hmsg->r_len);
+ assert(prefix_sz <= conn->in.offset);
+
+ /* Ok, all headers are received */
+ CBDATA_INIT_TYPE(clientHttpRequest);
+ http = cbdataAlloc(clientHttpRequest);
+ http->http_ver = http_ver;
+ http->conn = conn;
+ http->start = current_time;
+ http->req_sz = prefix_sz;
+ http->range_iter.boundary = StringNull;
+ http->maxRequestBodySize = -1;
+ dlinkAdd(http, &http->active, &ClientActiveRequests);
+
+ debug(33, 5) ("parseHttpRequest: Request Header is\n%s\n", hmsg->buf +
hmsg->req_end);
+
+#if THIS_VIOLATES_HTTP_SPECS_ON_URL_TRANSFORMATION
+ if ((t = strchr(url, '#'))) /* remove HTML anchors */
+ *t = '\0';
+#endif
+
+ /* handle "accelerated" objects (and internal) */
+ if (method->code == METHOD_CONNECT) {
+ if (! parseHttpConnectRequest(conn, http))
+ goto invalid_request;
+ } else if (*url == '/' && Config.onoff.global_internal_static &&
internalCheck(url)) {
+ (void) parseHttpInternalRequest(conn, http, url);
+ } else if (*url == '/' && conn->port->transparent) {
+ if (! parseHttpTransparentRequest(conn, http, url, req_hdr))
+ goto invalid_request;
+ } else if (*url == '/' || conn->port->accel) {
+ if (! parseHttpAccelRequest(conn, http, url, req_hdr))
+ goto invalid_request;
+ }
+ if (!http->uri) {
+ /* No special rewrites have been applied above, use the
+ * requested url. may be rewritten later, so make extra room */
+ size_t url_sz = strlen(url) + Config.appendDomainLen + 5;
+ http->uri = xcalloc(url_sz, 1);
+ strcpy(http->uri, url);
+ }
+ debug(33, 5) ("parseHttpRequest: Complete request received\n");
+ *status = 1;
+ return http;
+
+ invalid_request:
+ /* This tries to back out what is done above */
+ dlinkDelete(&http->active, &ClientActiveRequests);
+ safe_free(http->uri);
+ cbdataFree(http);
+ return parseHttpRequestAbort(conn, method_p, "error:invalid-request");
+}
+
+/*
+ * Attempt to parse a request in the conn buffer
+ *
+ * Return the number of bytes to consume from the buffer.
+ * >0 : consume X bytes and try parsing next request
+ * =0 : couldn't consume anything this trip (partial request); stop
parsing & read more data
+ * <0 : error; stop parsing
+ */
+int
+clientTryParseRequest(ConnStateData * conn)
+{
+ int fd = conn->fd;
+ int nrequests;
+ dlink_node *n;
+ clientHttpRequest *http = NULL;
+ method_t *method;
+ ErrorState *err = NULL;
+ int parser_return_code = 0;
+ request_t *request = NULL;
+ HttpMsgBuf msg;
+
+
+ /* Skip leading (and trailing) whitespace */
+ while (conn->in.offset > 0 && xisspace(conn->in.buf[0])) {
+ xmemmove(conn->in.buf, conn->in.buf + 1, conn->in.offset - 1);
+ conn->in.offset--;
+ }
+ conn->in.buf[conn->in.offset] = '\0'; /* Terminate the string */
+ if (conn->in.offset == 0)
+ return 0;
+
+ HttpMsgBufInit(&msg, conn->in.buf, conn->in.offset); /* XXX for now
there's no deallocation function needed but this may change */
+ /* Limit the number of concurrent requests to 2 */
+ for (n = conn->reqs.head, nrequests = 0; n; n = n->next, nrequests++);
+ if (nrequests >= (Config.onoff.pipeline_prefetch ? 2 : 1)) {
+ debug(33, 3) ("clientTryParseRequest: FD %d max concurrent requests
reached\n", fd);
+ debug(33, 5) ("clientTryParseRequest: FD %d defering new request until
one is done\n", fd);
+ conn->defer.until = squid_curtime + 100; /* Reset when a request is
complete */
+ return 0;
+ }
+ conn->in.buf[conn->in.offset] = '\0'; /* Terminate the string */
+ if (nrequests == 0)
+ fd_note_static(conn->fd, "Reading next request");
+ /* Process request */
+ http = parseHttpRequest(conn, &msg, &method, &parser_return_code);
+ if (!http) {
+ /* falls through here to the "if parser_return_code == 0"; not sure what
will
+ * happen if http == NULL and parser_return_code != 0 .. */
+ }
+ if (http) {
+ /* add to the client request queue */
+ dlinkAddTail(http, &http->node, &conn->reqs);
+ conn->nrequests++;
+ commSetTimeout(fd, Config.Timeout.lifetime, clientLifetimeTimeout,
http);
+ if (parser_return_code < 0) {
+ debug(33, 1) ("clientTryParseRequest: FD %d (%s:%d) Invalid
Request\n", fd, fd_table[fd].ipaddrstr, fd_table[fd].remote_port);
+ err = errorCon(ERR_INVALID_REQ, HTTP_BAD_REQUEST, NULL);
+ err->src_addr = conn->peer.sin_addr;
+ err->request_hdrs = xstrdup(conn->in.buf);
+ http->log_type = LOG_TCP_DENIED;
+ http->entry = clientCreateStoreEntry(http, method,
null_request_flags);
+ errorAppendEntry(http->entry, err);
+ return -1;
+ }
+ if ((request = urlParse(method, http->uri)) == NULL) {
+ debug(33, 5) ("Invalid URL: %s\n", http->uri);
+ err = errorCon(ERR_INVALID_URL, HTTP_BAD_REQUEST, NULL);
+ err->src_addr = conn->peer.sin_addr;
+ err->url = xstrdup(http->uri);
+ http->al.http.code = err->http_status;
+ http->log_type = LOG_TCP_DENIED;
+ http->entry = clientCreateStoreEntry(http, method,
null_request_flags);
+ errorAppendEntry(http->entry, err);
+ return -1;
+ }
+ /* compile headers */
+ /* we should skip request line! */
+ if ((http->http_ver.major >= 1) && !httpMsgParseRequestHeader(request,
&msg)) {
+ debug(33, 1) ("Failed to parse request headers: %s\n%s\n",
+ http->uri, msg.buf + msg.req_end);
+ err = errorCon(ERR_INVALID_URL, HTTP_BAD_REQUEST, request);
+ err->url = xstrdup(http->uri);
+ http->al.http.code = err->http_status;
+ http->log_type = LOG_TCP_DENIED;
+ http->entry = clientCreateStoreEntry(http, method,
null_request_flags);
+ errorAppendEntry(http->entry, err);
+ return -1;
+ }
+ /*
+ * If we read past the end of this request, move the remaining
+ * data to the beginning
+ */
+ assert(conn->in.offset >= http->req_sz);
+ conn->in.offset -= http->req_sz;
+ debug(33, 5) ("removing %d bytes; conn->in.offset = %d\n", (int)
http->req_sz, (int) conn->in.offset);
+ if (conn->in.offset > 0)
+ xmemmove(conn->in.buf, conn->in.buf + http->req_sz,
conn->in.offset);
+
+ if (!http->flags.internal && internalCheck(strBuf(request->urlpath))) {
+ if (internalHostnameIs(request->host))
+ http->flags.internal = 1;
+ else if (Config.onoff.global_internal_static &&
internalStaticCheck(strBuf(request->urlpath)))
+ http->flags.internal = 1;
+ if (http->flags.internal) {
+ request_t *old_request = requestLink(request);
+ request = urlParse(method, internalStoreUri("",
strBuf(request->urlpath)));
+ httpHeaderAppend(&request->header, &old_request->header);
+ requestUnlink(old_request);
+ }
+ }
+ if (conn->port->urlgroup)
+ request->urlgroup = xstrdup(conn->port->urlgroup);
+ request->flags.tproxy = conn->port->tproxy && need_linux_tproxy;
+ request->flags.accelerated = http->flags.accel;
+ request->flags.no_direct =
request->flags.accelerated ? !conn->port->allow_direct : 0;
+ request->flags.transparent = http->flags.transparent;
+ /*
+ * cache the Content-length value in request_t.
+ */
+ request->content_length = httpHeaderGetSize(&request->header,
+ HDR_CONTENT_LENGTH);
+ request->flags.internal = http->flags.internal;
+ request->client_addr = conn->peer.sin_addr;
+ request->client_port = ntohs(conn->peer.sin_port);
+#if FOLLOW_X_FORWARDED_FOR
+ request->indirect_client_addr = request->client_addr;
+#endif /* FOLLOW_X_FORWARDED_FOR */
+ request->my_addr = conn->me.sin_addr;
+ request->my_port = ntohs(conn->me.sin_port);
+ request->http_ver = http->http_ver;
+ if (!urlCheckRequest(request)) {
+ err = errorCon(ERR_UNSUP_REQ, HTTP_NOT_IMPLEMENTED, request);
+ request->flags.proxy_keepalive = 0;
+ http->al.http.code = err->http_status;
+ http->log_type = LOG_TCP_DENIED;
+ http->entry = clientCreateStoreEntry(http, request->method,
null_request_flags);
+ errorAppendEntry(http->entry, err);
+ return -1;
+ }
+ if (!clientCheckContentLength(request) || httpHeaderHas(&request->header,
HDR_TRANSFER_ENCODING)) {
+ err = errorCon(ERR_INVALID_REQ, HTTP_LENGTH_REQUIRED, request);
+ http->al.http.code = err->http_status;
+ http->log_type = LOG_TCP_DENIED;
+ http->entry = clientCreateStoreEntry(http, request->method,
null_request_flags);
+ errorAppendEntry(http->entry, err);
+ return -1;
+ }
+ http->request = requestLink(request);
+ http->orig_request = requestLink(request);
+ clientSetKeepaliveFlag(http);
+ /* Do we expect a request-body? */
+ if (request->content_length > 0) {
+ conn->body.size_left = request->content_length;
+ debug(33, 2) ("clientTryParseRequest: %p: FD %d: request body is %d
bytes in size\n", request, conn->fd, (int) conn->body.size_left);
+ request->body_reader = clientReadBody;
+ request->body_reader_data = conn;
+ cbdataLock(conn);
+ /* Is it too large? */
+ if (clientRequestBodyTooLarge(http, request)) {
+ err = errorCon(ERR_TOO_BIG, HTTP_REQUEST_ENTITY_TOO_LARGE,
request);
+ http->log_type = LOG_TCP_DENIED;
+ http->entry = clientCreateStoreEntry(http,
urlMethodGetKnownByCode(METHOD_NONE), null_request_flags);
+ errorAppendEntry(http->entry, err);
+ return -1;
+ }
+ }
+ if (request->method->code == METHOD_CONNECT) {
+ /* Stop reading requests... */
+ commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0);
+ if (!DLINK_ISEMPTY(conn->reqs) && DLINK_HEAD(conn->reqs) == http)
+ clientCheckFollowXForwardedFor(http);
+ else {
+ debug(33, 1) ("WARNING: pipelined CONNECT request seen from %s\n",
inet_ntoa(http->conn->peer.sin_addr));
+ debugObj(33, 1, "Previous request:\n", ((clientHttpRequest *)
DLINK_HEAD(conn->reqs))->request,
+ (ObjPackMethod) & httpRequestPackDebug);
+ debugObj(33, 1, "This request:\n", request, (ObjPackMethod) &
httpRequestPackDebug);
+ }
+ return -2;
+ } else {
+ clientCheckFollowXForwardedFor(http);
+ }
+ } else if (parser_return_code == 0) {
+ /*
+ * Partial request received; reschedule until parseHttpRequest()
+ * is happy with the input
+ */
+ if (conn->in.offset >= Config.maxRequestHeaderSize) {
+ /* The request is too large to handle */
+ debug(33, 1) ("Request header is too large (%d bytes)\n",
+ (int) conn->in.offset);
+ debug(33, 1) ("Config 'request_header_max_size'= %ld bytes.\n",
+ (long int) Config.maxRequestHeaderSize);
+ err = errorCon(ERR_TOO_BIG, HTTP_REQUEST_URI_TOO_LONG, NULL);
+ err->src_addr = conn->peer.sin_addr;
+ http = parseHttpRequestAbort(conn,
&method, "error:request-too-large");
+ /* add to the client request queue */
+ dlinkAddTail(http, &http->node, &conn->reqs);
+ http->log_type = LOG_TCP_DENIED;
+ http->entry = clientCreateStoreEntry(http, method,
null_request_flags);
+ errorAppendEntry(http->entry, err);
+ return -1;
+ }
+ return 0;
+ }
+ if (!cbdataValid(conn))
+ return -1;
+
+ /*
+ * For now we assume "here" means "we parsed a valid request. This
might not be the case
+ * as I might've broken up clientReadRequest() wrong. Quite a bit more
work should be
+ * done to simplify this code anyway so the first step is identifying
the cases where
+ * this isn't true.
+ */
+ assert(http != NULL);
+ assert(http->req_sz > 0);
+
+ return http->req_sz;
+}
+
=======================================
--- /dev/null
+++ /branches/LUSCA_HEAD/src/client_side_request_parse.h Sat Mar 20
18:59:26 2010
@@ -0,0 +1,6 @@
+#ifndef __CLIENT_SIDE_REQUEST_PARSE_H__
+#define __CLIENT_SIDE_REQUEST_PARSE_H__
+
+extern int clientTryParseRequest(ConnStateData * conn) ;
+
+#endif
=======================================
--- /branches/LUSCA_HEAD/src/Makefile.am Sun Feb 28 05:49:39 2010
+++ /branches/LUSCA_HEAD/src/Makefile.am Sat Mar 20 18:59:26 2010
@@ -110,6 +110,7 @@
client_side_body.c \
client_side_etag.c \
client_side_request.c \
+ client_side_request_parse.c \
client_side_reply.c \
client_side_conn.c \
client_side_nat.c \
=======================================
--- /branches/LUSCA_HEAD/src/client_side.c Wed Mar 17 09:16:07 2010
+++ /branches/LUSCA_HEAD/src/client_side.c Sat Mar 20 18:59:26 2010
@@ -44,6 +44,7 @@
#include "client_side_etag.h"
#include "client_side_ims.h"
#include "client_side_purge.h"
+#include "client_side_request_parse.h"
#include "client_side.h"
@@ -64,27 +65,21 @@
static CWCB clientWriteBodyComplete;
static PF clientReadRequest;
static PF requestTimeout;
-static PF clientLifetimeTimeout;
static int clientCheckTransferDone(clientHttpRequest *);
static int clientGotNotEnough(clientHttpRequest *);
static void checkFailureRatio(err_type, hier_code);
static void clientBuildReplyHeader(clientHttpRequest * http, HttpReply *
rep);
-static clientHttpRequest *parseHttpRequestAbort(ConnStateData * conn,
method_t ** method_p, const char *uri);
-static clientHttpRequest *parseHttpRequest(ConnStateData *, HttpMsgBuf *,
method_t **, int *);
#if USE_IDENT
static IDCB clientIdentDone;
#endif
static STNCB clientSendMoreData;
-static void clientSetKeepaliveFlag(clientHttpRequest *);
static int clientCachable(clientHttpRequest * http);
static int clientHierarchical(clientHttpRequest * http);
-static int clientCheckContentLength(request_t * r);
static DEFER httpAcceptDefer;
static log_type clientProcessRequest2(clientHttpRequest * http);
static int clientReplyBodyTooLarge(clientHttpRequest *, squid_off_t clen);
-static int clientRequestBodyTooLarge(clientHttpRequest *, request_t *);
#if USE_SSL
static void httpsAcceptSSL(ConnStateData * connState, SSL_CTX *
sslContext);
#endif
@@ -557,48 +552,6 @@
debug(33, 5) ("clientInterpretRequestHeaders: REQ_HIERARCHICAL = %s\n",
request->flags.hierarchical ? "SET" : "NOT SET");
}
-
-/*
- * clientSetKeepaliveFlag() sets request->flags.proxy_keepalive.
- * This is the client-side persistent connection flag. We need
- * to set this relatively early in the request processing
- * to handle hacks for broken servers and clients.
- */
-static void
-clientSetKeepaliveFlag(clientHttpRequest * http)
-{
- request_t *request = http->request;
- const HttpHeader *req_hdr = &request->header;
-
- debug(33, 3) ("clientSetKeepaliveFlag: http_ver = %d.%d\n",
- request->http_ver.major, request->http_ver.minor);
- debug(33, 3) ("clientSetKeepaliveFlag: method = %s\n",
- urlMethodGetConstStr(request->method));
- {
- http_version_t http_ver;
- if (http->conn->port->http11)
- http_ver = request->http_ver;
- else
- httpBuildVersion(&http_ver, 1, 0); /* we are HTTP/1.0, no matter what
the client requests... */
- if (httpMsgIsPersistent(http_ver, req_hdr))
- request->flags.proxy_keepalive = 1;
- }
-}
-
-static int
-clientCheckContentLength(request_t * r)
-{
- switch (r->method->code) {
- case METHOD_GET:
- case METHOD_HEAD:
- /* We do not want to see a request entity on GET/HEAD requests */
- return (r->content_length <= 0 || Config.onoff.request_entities);
- default:
- /* For other types of requests we don't care */
- return 1;
- }
- /* NOT REACHED */
-}
static int
clientCachable(clientHttpRequest * http)
@@ -1416,50 +1369,6 @@
}
return http->maxRequestBodyDelayForwardSize;
}
-
-/*
- * Calculates the maximum size allowed for an HTTP request body
- */
-static void
-clientMaxRequestBodySize(request_t * request, clientHttpRequest * http)
-{
- body_size *bs;
- aclCheck_t *checklist;
- if (http->log_type == LOG_TCP_DENIED)
- return;
- bs = (body_size *) Config.RequestBodySize.head;
- http->maxRequestBodySize = 0;
- while (bs) {
- checklist = clientAclChecklistCreate(bs->access_list, http);
- if (aclCheckFast(bs->access_list, checklist) != 1) {
- /* deny - skip this entry */
- bs = (body_size *) bs->node.next;
- } else {
- /* Allow - use this entry */
- http->maxRequestBodySize = bs->maxsize;
- bs = NULL;
- debug(58, 3) ("clientMaxRequestBodySize: Setting maxRequestBodySize
to %ld\n", (long int) http->maxRequestBodySize);
- }
- aclChecklistFree(checklist);
- }
-}
-
-static int
-clientRequestBodyTooLarge(clientHttpRequest * http, request_t * request)
-{
-
- if (http->maxRequestBodySize == -1) {
- clientMaxRequestBodySize(request, http);
- }
- if (0 == http->maxRequestBodySize)
- return 0; /* disabled */
- if (request->content_length < 0)
- return 0; /* unknown, bug? */
- if (request->content_length > http->maxRequestBodySize)
- return 1; /* too large */
- return 0;
-}
-
/* Responses with no body will not have a content-type header,
* which breaks the rep_mime_type acl, which
@@ -2436,282 +2345,6 @@
}
clientBeginForwarding(http);
}
-
-CBDATA_TYPE(clientHttpRequest);
-
-static clientHttpRequest *
-parseHttpRequestAbort(ConnStateData * conn, method_t ** method_p, const
char *uri)
-{
- clientHttpRequest *http;
- CBDATA_INIT_TYPE(clientHttpRequest);
- http = cbdataAlloc(clientHttpRequest);
- http->conn = conn;
- http->start = current_time;
- http->req_sz = conn->in.offset;
- http->uri = xstrdup(uri);
- http->log_uri = xstrdup(uri);
- http->range_iter.boundary = StringNull;
- httpBuildVersion(&http->http_ver, 1, 0);
- dlinkAdd(http, &http->active, &ClientActiveRequests);
- if (method_p && !*method_p)
- *method_p = urlMethodGetKnownByCode(METHOD_NONE);
- return http;
-}
-
-static int
-parseHttpConnectRequest(ConnStateData *conn, clientHttpRequest *http)
-{
- if (http->http_ver.major < 1) {
- debug(33, 1) ("parseHttpRequest: Invalid HTTP version\n");
- return 0;
- }
- if (conn->port->accel) {
- debug(33, 1) ("parseHttpRequest: CONNECT not valid in accelerator
mode\n");
- return 0;
- }
- return 1;
-}
-
-static int
-parseHttpInternalRequest(ConnStateData *conn, clientHttpRequest *http,
const char *url)
-{
- http->uri = xstrdup(internalStoreUri("", url));
- http->flags.internal = 1;
- http->flags.accel = 1;
- debug(33, 5) ("INTERNAL REWRITE: '%s'\n", http->uri);
- return 1;
-}
-static int
-parseHttpTransparentRequest(ConnStateData *conn, clientHttpRequest *http,
const char *url, const char *req_hdr)
-{
- int port = 0;
- const char *host = mime_get_header(req_hdr, "Host");
- char *portstr;
-
- if (host && (portstr = strchr(host, ':')) != NULL) {
- *portstr++ = '\0';
- port = atoi(portstr);
- }
- http->flags.transparent = 1;
-
- if (Config.onoff.accel_no_pmtu_disc)
- commSetNoPmtuDiscover(conn->fd);
-
- if (conn->port->transparent && clientNatLookup(conn) == 0)
- conn->transparent = 1;
- if (!host && conn->transparent) {
- port = ntohs(conn->me.sin_port);
- if (!host)
- host = inet_ntoa(conn->me.sin_addr);
- }
- if (host) {
- size_t url_sz = 10 + strlen(host) + 6 + strlen(url) + 32 +
Config.appendDomainLen;
- http->uri = xcalloc(url_sz, 1);
- if (port) {
- snprintf(http->uri, url_sz, "%s://%s:%d%s",
- conn->port->protocol, host, port, url);
- } else {
- snprintf(http->uri, url_sz, "%s://%s%s",
- conn->port->protocol, host, url);
- }
- } else if (internalCheck(url)) {
- parseHttpInternalRequest(conn, http, url);
- } else {
- return 0;
- }
- return 1;
-}
-
-static int
-parseHttpAccelRequest(ConnStateData *conn, clientHttpRequest *http, const
char *url, const char *req_hdr)
-{
- int vhost = conn->port->vhost;
- int vport = conn->port->vport;
- const char *t = NULL;
-
- http->flags.accel = 1;
- if (*url != '/' && !vhost && strncasecmp(url, "cache_object://", 15) !=
0) {
- url = strstr(url, "//");
- if (!url)
- return 0;
- url = strchr(url + 2, '/');
- if (!url)
- url = (char *) "/";
- }
- if (*url != '/') {
- /* Fully qualified URL. Nothing special to do */
- } else if (conn->port->accel) {
- const char *host = NULL;
- int port;
- size_t url_sz;
- if (vport > 0)
- port = vport;
- else
- port = htons(http->conn->me.sin_port);
- if (vhost && (t = mime_get_header(req_hdr, "Host")))
- host = t;
- else if (conn->port->defaultsite)
- host = conn->port->defaultsite;
- else if (vport == -1)
- host = inet_ntoa(http->conn->me.sin_addr);
- else
- host = getMyHostname();
- url_sz = strlen(url) + 32 + Config.appendDomainLen + strlen(host);
- http->uri = xcalloc(url_sz, 1);
- if (strchr(host, ':'))
- snprintf(http->uri, url_sz, "%s://%s%s",
- conn->port->protocol, host, url);
- else
- snprintf(http->uri, url_sz, "%s://%s:%d%s",
- conn->port->protocol, host, port, url);
- debug(33, 5) ("VHOST REWRITE: '%s'\n", http->uri);
- } else if (internalCheck(url)) {
- parseHttpInternalRequest(conn, http, url);
- } else {
- return 0;
- }
- return 1;
-}
-
-/*
- * parseHttpRequest()
- *
- * Returns
- * NULL on error or incomplete request
- * a clientHttpRequest structure on success
- */
-static clientHttpRequest *
-parseHttpRequest(ConnStateData * conn, HttpMsgBuf * hmsg, method_t **
method_p, int *status)
-{
- LOCAL_ARRAY(char, urlbuf, MAX_URL);
- char *url = urlbuf;
- const char *req_hdr = NULL;
- http_version_t http_ver;
- size_t header_sz; /* size of headers, not including first line */
- size_t prefix_sz; /* size of whole request (req-line + headers) */
- size_t req_sz;
- method_t *method;
- clientHttpRequest *http = NULL;
-#if THIS_VIOLATES_HTTP_SPECS_ON_URL_TRANSFORMATION
- char *t;
-#endif
- int ret;
-
- /* pre-set these values to make aborting simpler */
- *method_p = urlMethodGetKnownByCode(METHOD_NONE);
- *status = -1;
-
- /* Parse the request line */
- ret = httpMsgParseRequestLine(hmsg);
- if (ret == -1)
- return parseHttpRequestAbort(conn, method_p, "error:invalid-request");
- if (ret == 0) {
- debug(33, 5) ("Incomplete request, waiting for end of request line\n");
- *status = 0;
- return NULL;
- }
- /* If HTTP/0.9 then there's no headers */
- if (hmsg->v_maj == 0 && hmsg->v_min == 9) {
- req_sz = hmsg->r_len;
- } else {
- req_sz = httpMsgFindHeadersEnd(hmsg);
- if (req_sz == 0) {
- debug(33, 5) ("Incomplete request, waiting for end of headers\n");
- *status = 0;
- return NULL;
- }
- }
- /* Set version */
- httpBuildVersion(&http_ver, hmsg->v_maj, hmsg->v_min);
-
- /* Enforce max_request_size */
- if (req_sz >= Config.maxRequestHeaderSize) {
- debug(33, 5) ("parseHttpRequest: Too large request\n");
- return parseHttpRequestAbort(conn, method_p, "error:request-too-large");
- }
- /* Wrap the request method */
- method = urlMethodGet(hmsg->buf + hmsg->m_start, hmsg->m_len);
-
- debug(33, 5) ("parseHttpRequest: Method is '%s'\n",
urlMethodGetConstStr(method));
- if (method->code == METHOD_OTHER) {
- debug(33, 5) ("parseHttpRequest: Unknown method, continuing
regardless");
- }
- *method_p = method;
-
- /* Make sure URL fits inside MAX_URL */
- if (hmsg->u_len >= MAX_URL) {
- debug(33, 1) ("parseHttpRequest: URL too big (%d) chars: %s\n",
hmsg->u_len, hmsg->buf + hmsg->u_start);
- return parseHttpRequestAbort(conn, method_p, "error:request-too-large");
- }
- xmemcpy(urlbuf, hmsg->buf + hmsg->u_start, hmsg->u_len);
- /* XXX off-by-one termination error? */
- urlbuf[hmsg->u_len] = '\0';
- debug(33, 5) ("parseHttpRequest: URI is '%s'\n", urlbuf);
-
- /*
- * Process headers after request line
- * XXX at this point we really should just parse the damned headers
rather than doing
- * it later, allowing us to then do the URL acceleration stuff withuot
too much hackery.
- */
- /* XXX re-evaluate all of these values and use whats in hmsg instead!
*/
- req_hdr = hmsg->buf + hmsg->r_len;
- header_sz = hmsg->h_len;
- debug(33, 3) ("parseHttpRequest: req_hdr = {%s}\n", req_hdr);
-
- prefix_sz = req_sz;
- debug(33, 3) ("parseHttpRequest: prefix_sz = %d, req_line_sz = %d\n",
- (int) prefix_sz, (int) hmsg->r_len);
- assert(prefix_sz <= conn->in.offset);
-
- /* Ok, all headers are received */
- CBDATA_INIT_TYPE(clientHttpRequest);
- http = cbdataAlloc(clientHttpRequest);
- http->http_ver = http_ver;
- http->conn = conn;
- http->start = current_time;
- http->req_sz = prefix_sz;
- http->range_iter.boundary = StringNull;
- http->maxRequestBodySize = -1;
- dlinkAdd(http, &http->active, &ClientActiveRequests);
-
- debug(33, 5) ("parseHttpRequest: Request Header is\n%s\n", hmsg->buf +
hmsg->req_end);
-
-#if THIS_VIOLATES_HTTP_SPECS_ON_URL_TRANSFORMATION
- if ((t = strchr(url, '#'))) /* remove HTML anchors */
- *t = '\0';
-#endif
-
- /* handle "accelerated" objects (and internal) */
- if (method->code == METHOD_CONNECT) {
- if (! parseHttpConnectRequest(conn, http))
- goto invalid_request;
- } else if (*url == '/' && Config.onoff.global_internal_static &&
internalCheck(url)) {
- (void) parseHttpInternalRequest(conn, http, url);
- } else if (*url == '/' && conn->port->transparent) {
- if (! parseHttpTransparentRequest(conn, http, url, req_hdr))
- goto invalid_request;
- } else if (*url == '/' || conn->port->accel) {
- if (! parseHttpAccelRequest(conn, http, url, req_hdr))
- goto invalid_request;
- }
- if (!http->uri) {
- /* No special rewrites have been applied above, use the
- * requested url. may be rewritten later, so make extra room */
- size_t url_sz = strlen(url) + Config.appendDomainLen + 5;
- http->uri = xcalloc(url_sz, 1);
- strcpy(http->uri, url);
- }
- debug(33, 5) ("parseHttpRequest: Complete request received\n");
- *status = 1;
- return http;
-
- invalid_request:
- /* This tries to back out what is done above */
- dlinkDelete(&http->active, &ClientActiveRequests);
- safe_free(http->uri);
- cbdataFree(http);
- return parseHttpRequestAbort(conn, method_p, "error:invalid-request");
-}
static int
clientReadDefer(int fd, void *data)
@@ -2737,225 +2370,6 @@
}
}
}
-
-/*
- * Attempt to parse a request in the conn buffer
- *
- * Return the number of bytes to consume from the buffer.
- * >0 : consume X bytes and try parsing next request
- * =0 : couldn't consume anything this trip (partial request); stop
parsing & read more data
- * <0 : error; stop parsing
- */
-static int
-clientTryParseRequest(ConnStateData * conn)
-{
- int fd = conn->fd;
- int nrequests;
- dlink_node *n;
- clientHttpRequest *http = NULL;
- method_t *method;
- ErrorState *err = NULL;
- int parser_return_code = 0;
- request_t *request = NULL;
- HttpMsgBuf msg;
-
-
- /* Skip leading (and trailing) whitespace */
- while (conn->in.offset > 0 && xisspace(conn->in.buf[0])) {
- xmemmove(conn->in.buf, conn->in.buf + 1, conn->in.offset - 1);
- conn->in.offset--;
- }
- conn->in.buf[conn->in.offset] = '\0'; /* Terminate the string */
- if (conn->in.offset == 0)
- return 0;
-
- HttpMsgBufInit(&msg, conn->in.buf, conn->in.offset); /* XXX for now
there's no deallocation function needed but this may change */
- /* Limit the number of concurrent requests to 2 */
- for (n = conn->reqs.head, nrequests = 0; n; n = n->next, nrequests++);
- if (nrequests >= (Config.onoff.pipeline_prefetch ? 2 : 1)) {
- debug(33, 3) ("clientTryParseRequest: FD %d max concurrent requests
reached\n", fd);
- debug(33, 5) ("clientTryParseRequest: FD %d defering new request until
one is done\n", fd);
- conn->defer.until = squid_curtime + 100; /* Reset when a request is
complete */
- return 0;
- }
- conn->in.buf[conn->in.offset] = '\0'; /* Terminate the string */
- if (nrequests == 0)
- fd_note_static(conn->fd, "Reading next request");
- /* Process request */
- http = parseHttpRequest(conn, &msg, &method, &parser_return_code);
- if (!http) {
- /* falls through here to the "if parser_return_code == 0"; not sure what
will
- * happen if http == NULL and parser_return_code != 0 .. */
- }
- if (http) {
- /* add to the client request queue */
- dlinkAddTail(http, &http->node, &conn->reqs);
- conn->nrequests++;
- commSetTimeout(fd, Config.Timeout.lifetime, clientLifetimeTimeout,
http);
- if (parser_return_code < 0) {
- debug(33, 1) ("clientTryParseRequest: FD %d (%s:%d) Invalid
Request\n", fd, fd_table[fd].ipaddrstr, fd_table[fd].remote_port);
- err = errorCon(ERR_INVALID_REQ, HTTP_BAD_REQUEST, NULL);
- err->src_addr = conn->peer.sin_addr;
- err->request_hdrs = xstrdup(conn->in.buf);
- http->log_type = LOG_TCP_DENIED;
- http->entry = clientCreateStoreEntry(http, method,
null_request_flags);
- errorAppendEntry(http->entry, err);
- return -1;
- }
- if ((request = urlParse(method, http->uri)) == NULL) {
- debug(33, 5) ("Invalid URL: %s\n", http->uri);
- err = errorCon(ERR_INVALID_URL, HTTP_BAD_REQUEST, NULL);
- err->src_addr = conn->peer.sin_addr;
- err->url = xstrdup(http->uri);
- http->al.http.code = err->http_status;
- http->log_type = LOG_TCP_DENIED;
- http->entry = clientCreateStoreEntry(http, method,
null_request_flags);
- errorAppendEntry(http->entry, err);
- return -1;
- }
- /* compile headers */
- /* we should skip request line! */
- if ((http->http_ver.major >= 1) && !httpMsgParseRequestHeader(request,
&msg)) {
- debug(33, 1) ("Failed to parse request headers: %s\n%s\n",
- http->uri, msg.buf + msg.req_end);
- err = errorCon(ERR_INVALID_URL, HTTP_BAD_REQUEST, request);
- err->url = xstrdup(http->uri);
- http->al.http.code = err->http_status;
- http->log_type = LOG_TCP_DENIED;
- http->entry = clientCreateStoreEntry(http, method,
null_request_flags);
- errorAppendEntry(http->entry, err);
- return -1;
- }
- /*
- * If we read past the end of this request, move the remaining
- * data to the beginning
- */
- assert(conn->in.offset >= http->req_sz);
- conn->in.offset -= http->req_sz;
- debug(33, 5) ("removing %d bytes; conn->in.offset = %d\n", (int)
http->req_sz, (int) conn->in.offset);
- if (conn->in.offset > 0)
- xmemmove(conn->in.buf, conn->in.buf + http->req_sz,
conn->in.offset);
-
- if (!http->flags.internal && internalCheck(strBuf(request->urlpath))) {
- if (internalHostnameIs(request->host))
- http->flags.internal = 1;
- else if (Config.onoff.global_internal_static &&
internalStaticCheck(strBuf(request->urlpath)))
- http->flags.internal = 1;
- if (http->flags.internal) {
- request_t *old_request = requestLink(request);
- request = urlParse(method, internalStoreUri("",
strBuf(request->urlpath)));
- httpHeaderAppend(&request->header, &old_request->header);
- requestUnlink(old_request);
- }
- }
- if (conn->port->urlgroup)
- request->urlgroup = xstrdup(conn->port->urlgroup);
- request->flags.tproxy = conn->port->tproxy && need_linux_tproxy;
- request->flags.accelerated = http->flags.accel;
- request->flags.no_direct =
request->flags.accelerated ? !conn->port->allow_direct : 0;
- request->flags.transparent = http->flags.transparent;
- /*
- * cache the Content-length value in request_t.
- */
- request->content_length = httpHeaderGetSize(&request->header,
- HDR_CONTENT_LENGTH);
- request->flags.internal = http->flags.internal;
- request->client_addr = conn->peer.sin_addr;
- request->client_port = ntohs(conn->peer.sin_port);
-#if FOLLOW_X_FORWARDED_FOR
- request->indirect_client_addr = request->client_addr;
-#endif /* FOLLOW_X_FORWARDED_FOR */
- request->my_addr = conn->me.sin_addr;
- request->my_port = ntohs(conn->me.sin_port);
- request->http_ver = http->http_ver;
- if (!urlCheckRequest(request)) {
- err = errorCon(ERR_UNSUP_REQ, HTTP_NOT_IMPLEMENTED, request);
- request->flags.proxy_keepalive = 0;
- http->al.http.code = err->http_status;
- http->log_type = LOG_TCP_DENIED;
- http->entry = clientCreateStoreEntry(http, request->method,
null_request_flags);
- errorAppendEntry(http->entry, err);
- return -1;
- }
- if (!clientCheckContentLength(request) || httpHeaderHas(&request->header,
HDR_TRANSFER_ENCODING)) {
- err = errorCon(ERR_INVALID_REQ, HTTP_LENGTH_REQUIRED, request);
- http->al.http.code = err->http_status;
- http->log_type = LOG_TCP_DENIED;
- http->entry = clientCreateStoreEntry(http, request->method,
null_request_flags);
- errorAppendEntry(http->entry, err);
- return -1;
- }
- http->request = requestLink(request);
- http->orig_request = requestLink(request);
- clientSetKeepaliveFlag(http);
- /* Do we expect a request-body? */
- if (request->content_length > 0) {
- conn->body.size_left = request->content_length;
- debug(33, 2) ("clientTryParseRequest: %p: FD %d: request body is %d
bytes in size\n", request, conn->fd, (int) conn->body.size_left);
- request->body_reader = clientReadBody;
- request->body_reader_data = conn;
- cbdataLock(conn);
- /* Is it too large? */
- if (clientRequestBodyTooLarge(http, request)) {
- err = errorCon(ERR_TOO_BIG, HTTP_REQUEST_ENTITY_TOO_LARGE,
request);
- http->log_type = LOG_TCP_DENIED;
- http->entry = clientCreateStoreEntry(http,
urlMethodGetKnownByCode(METHOD_NONE), null_request_flags);
- errorAppendEntry(http->entry, err);
- return -1;
- }
- }
- if (request->method->code == METHOD_CONNECT) {
- /* Stop reading requests... */
- commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0);
- if (!DLINK_ISEMPTY(conn->reqs) && DLINK_HEAD(conn->reqs) == http)
- clientCheckFollowXForwardedFor(http);
- else {
- debug(33, 1) ("WARNING: pipelined CONNECT request seen from %s\n",
inet_ntoa(http->conn->peer.sin_addr));
- debugObj(33, 1, "Previous request:\n", ((clientHttpRequest *)
DLINK_HEAD(conn->reqs))->request,
- (ObjPackMethod) & httpRequestPackDebug);
- debugObj(33, 1, "This request:\n", request, (ObjPackMethod) &
httpRequestPackDebug);
- }
- return -2;
- } else {
- clientCheckFollowXForwardedFor(http);
- }
- } else if (parser_return_code == 0) {
- /*
- * Partial request received; reschedule until parseHttpRequest()
- * is happy with the input
- */
- if (conn->in.offset >= Config.maxRequestHeaderSize) {
- /* The request is too large to handle */
- debug(33, 1) ("Request header is too large (%d bytes)\n",
- (int) conn->in.offset);
- debug(33, 1) ("Config 'request_header_max_size'= %ld bytes.\n",
- (long int) Config.maxRequestHeaderSize);
- err = errorCon(ERR_TOO_BIG, HTTP_REQUEST_URI_TOO_LONG, NULL);
- err->src_addr = conn->peer.sin_addr;
- http = parseHttpRequestAbort(conn,
&method, "error:request-too-large");
- /* add to the client request queue */
- dlinkAddTail(http, &http->node, &conn->reqs);
- http->log_type = LOG_TCP_DENIED;
- http->entry = clientCreateStoreEntry(http, method,
null_request_flags);
- errorAppendEntry(http->entry, err);
- return -1;
- }
- return 0;
- }
- if (!cbdataValid(conn))
- return -1;
-
- /*
- * For now we assume "here" means "we parsed a valid request. This
might not be the case
- * as I might've broken up clientReadRequest() wrong. Quite a bit more
work should be
- * done to simplify this code anyway so the first step is identifying
the cases where
- * this isn't true.
- */
- assert(http != NULL);
- assert(http->req_sz > 0);
-
- return http->req_sz;
-}
static void
clientReadRequest(int fd, void *data)
@@ -3081,7 +2495,7 @@
comm_close(fd);
}
-static void
+void
clientLifetimeTimeout(int fd, void *data)
{
clientHttpRequest *http = data;
=======================================
--- /branches/LUSCA_HEAD/src/client_side.h Sun Feb 28 05:49:39 2010
+++ /branches/LUSCA_HEAD/src/client_side.h Sat Mar 20 18:59:26 2010
@@ -16,6 +16,7 @@
extern void clientKeepaliveNextRequest(clientHttpRequest * http);
extern STHCB clientSendHeaders;
extern int clientOnlyIfCached(clientHttpRequest * http);
+extern PF clientLifetimeTimeout;
/*
* XXX this is JUST for clientPurgeRequest() and JUST for now.
--
You received this message because you are subscribed to the Google Groups
"lusca-commit" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/lusca-commit?hl=en.