From: Amos Jeffries Date: Thu, 3 Apr 2014 09:39:35 +0000 (-0700) Subject: Merge from trunk X-Git-Tag: merge-candidate-3-v1~506^2~49 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0dd12dbad45fd09fd46d8f0b64eb3ace32435cdf;p=thirdparty%2Fsquid.git Merge from trunk --- 0dd12dbad45fd09fd46d8f0b64eb3ace32435cdf diff --cc src/client_side.cc index 67eab966a5,5fa2894764..b7cabe6d53 --- a/src/client_side.cc +++ b/src/client_side.cc @@@ -2406,18 -2460,32 +2393,11 @@@ ConnStateData::connFinishedWithConn(in void connNoteUseOfBuffer(ConnStateData* conn, size_t byteCount) { - assert(byteCount > 0 && byteCount <= conn->in.notYetUsed); - conn->in.notYetUsed -= byteCount; - debugs(33, 5, HERE << "conn->in.notYetUsed = " << conn->in.notYetUsed); - /* - * If there is still data that will be used, - * move it to the beginning. - */ - - if (conn->in.notYetUsed > 0) - memmove(conn->in.buf, conn->in.buf + byteCount, conn->in.notYetUsed); + assert(byteCount > 0 && byteCount <= conn->in.buf.length()); + conn->in.buf.consume(byteCount); + debugs(33, 5, "conn->in.buf has " << conn->in.buf.length() << " bytes unused."); } -/// respond with ERR_TOO_BIG if request header exceeds request_header_max_size -void -ConnStateData::checkHeaderLimits() -{ - if (in.buf.length() < Config.maxRequestHeaderSize) - return; // can accumulte more header data - - debugs(33, 3, "Request header is too large (" << in.buf.length() << " > " << - Config.maxRequestHeaderSize << " bytes)"); - - ClientSocketContext *context = parseHttpRequestAbort(this, "error:request-too-large"); - clientStreamNode *node = context->getClientReplyContext(); - clientReplyContext *repContext = dynamic_cast(node->data.getRaw()); - assert (repContext); - repContext->setReplyToError(ERR_TOO_BIG, - Http::scBadRequest, Http::METHOD_NONE, NULL, - clientConnection->remote, NULL, NULL, NULL); - context->registerWithConn(); - context->pullData(); -} - void ConnStateData::clientAfterReadingRequests() { @@@ -2528,10 -2596,10 +2508,10 @@@ bool ConnStateData::serveDelayedError(C return false; } - #endif // USE_SSL + #endif // USE_OPENSSL static void -clientProcessRequest(ConnStateData *conn, HttpParser *hp, ClientSocketContext *context, const HttpRequestMethod& method, Http::ProtocolVersion http_ver) +clientProcessRequest(ConnStateData *conn, Http1::RequestParser &hp, ClientSocketContext *context) { ClientHttpRequest *http = context->http; HttpRequest::Pointer request; @@@ -2554,22 -2621,17 +2534,21 @@@ setLogUri(http, http->uri, true); clientReplyContext *repContext = dynamic_cast(node->data.getRaw()); assert (repContext); - switch (hp->request_parse_status) { + switch (hp.request_parse_status) { case Http::scHeaderTooLarge: - repContext->setReplyToError(ERR_TOO_BIG, Http::scBadRequest, method, http->uri, - conn->clientConnection->remote, NULL, conn->in.buf, NULL); + repContext->setReplyToError(ERR_TOO_BIG, Http::scBadRequest, method, http->uri, conn->clientConnection->remote, NULL, conn->in.buf.c_str(), NULL); break; case Http::scMethodNotAllowed: repContext->setReplyToError(ERR_UNSUP_REQ, Http::scMethodNotAllowed, method, http->uri, - conn->clientConnection->remote, NULL, conn->in.buf, NULL); + conn->clientConnection->remote, NULL, conn->in.buf.c_str(), NULL); break; + case Http::scHttpVersionNotSupported: + repContext->setReplyToError(ERR_UNSUP_HTTPVERSION, Http::scHttpVersionNotSupported, method, http->uri, + conn->clientConnection->remote, NULL, conn->in.buf, NULL); + break; default: - repContext->setReplyToError(ERR_INVALID_REQ, hp.request_parse_status, method, http->uri, - conn->clientConnection->remote, NULL, conn->in.buf, NULL); + repContext->setReplyToError(ERR_INVALID_REQ, hp->request_parse_status, method, http->uri, + conn->clientConnection->remote, NULL, conn->in.buf.c_str(), NULL); } assert(context->http->out.offset == 0); context->pullData(); @@@ -2830,10 -2926,11 +2809,10 @@@ ConnStateData::clientParseRequests( // Loop while we have read bytes that are not needed for producing the body // On errors, bodyPipe may become nil, but readMore will be cleared - while (in.notYetUsed > 0 && !bodyPipe && flags.readMore) { + while (!in.buf.isEmpty() && !bodyPipe && flags.readMore) { - connStripBufferWhitespace(this); /* Don't try to parse if the buffer is empty */ - if (in.notYetUsed == 0) + if (in.buf.isEmpty()) break; /* Limit the number of concurrent requests */ @@@ -2842,23 -2939,20 +2821,23 @@@ /* Begin the parsing */ PROF_start(parseHttpRequest); - HttpParserInit(&parser_, in.buf.c_str(), in.buf.length()); - /* Process request */ - Http::ProtocolVersion http_ver; - ClientSocketContext *context = parseHttpRequest(this, &parser_, &method, &http_ver); - PROF_stop(parseHttpRequest); + // parser is incremental. Generate new parser state if we, + // a) dont have one already + // b) have completed the previous request parsing already + if (!parser_ || parser_->isDone()) - parser_ = new Http1::RequestParser(in.buf, in.notYetUsed); ++ parser_ = new Http1::RequestParser(in.buf.c_str(), in.buf.length()); + else // update the buffer space being parsed - parser_->bufsiz = in.notYetUsed; ++ parser_->bufsiz = in.buf.length(); - /* partial or incomplete request */ - if (!context) { - // TODO: why parseHttpRequest can just return parseHttpRequestAbort - // (which becomes context) but checkHeaderLimits cannot? - checkHeaderLimits(); - break; + /* Process request */ + ClientSocketContext *context = parseHttpRequest(this, *parser_); + if (parser_->doneBytes()) { + // we are done with some of the buffer. consume it now. + connNoteUseOfBuffer(this, parser_->doneBytes()); + parser_->noteBufferShift(parser_->doneBytes()); } + PROF_stop(parseHttpRequest); /* status -1 or 1 */ if (context) { diff --cc src/client_side.h index 2a1cd45445,7ec69f182b..a49c02a8e7 --- a/src/client_side.h +++ b/src/client_side.h @@@ -35,7 -35,8 +35,8 @@@ #include "comm.h" #include "HttpControlMsg.h" -#include "HttpParser.h" +#include "http/forward.h" + #include "SBuf.h" #if USE_AUTH #include "auth/UserRequest.h" #endif @@@ -397,10 -395,11 +394,10 @@@ private Auth::UserRequest::Pointer auth_; #endif - HttpParser parser_; - - // XXX: CBDATA plays with public/private and leaves the following 'private' fields all public... :( + /// the parser state for current HTTP/1.x input buffer processing + Http1::RequestParserPointer parser_; - #if USE_SSL + #if USE_OPENSSL bool switchedToHttps_; /// The SSL server host name appears in CONNECT request or the server ip address for the intercepted requests String sslConnectHostOrIp; ///< The SSL server host name as passed in the CONNECT request diff --cc src/tests/stub_client_side.cc index b332363e86,d1a4fc94e9..1717467462 --- a/src/tests/stub_client_side.cc +++ b/src/tests/stub_client_side.cc @@@ -38,9 -37,8 +37,7 @@@ void ConnStateData::readNextRequest() S void ConnStateData::addContextToQueue(ClientSocketContext * context) STUB int ConnStateData::getConcurrentRequestCount() const STUB_RETVAL(0) bool ConnStateData::isOpen() const STUB_RETVAL(false) -void ConnStateData::checkHeaderLimits() STUB void ConnStateData::sendControlMsg(HttpControlMsg msg) STUB - char *ConnStateData::In::addressToReadInto() const STUB_RETVAL(NULL) int64_t ConnStateData::mayNeedToReadMoreBody() const STUB_RETVAL(0) #if USE_AUTH void ConnStateData::setAuth(const Auth::UserRequest::Pointer &aur, const char *cause) STUB