|
|
fb5d65b |
diff --git a/src/client_side.cc b/src/client_side.cc
|
|
|
fb5d65b |
index f488fc4..69586df 100644
|
|
|
fb5d65b |
--- a/src/client_side.cc
|
|
|
fb5d65b |
+++ b/src/client_side.cc
|
|
|
fb5d65b |
@@ -932,7 +932,7 @@ ConnStateData::kick()
|
|
|
fb5d65b |
* We are done with the response, and we are either still receiving request
|
|
|
fb5d65b |
* body (early response!) or have already stopped receiving anything.
|
|
|
fb5d65b |
*
|
|
|
fb5d65b |
- * If we are still receiving, then clientParseRequest() below will fail.
|
|
|
fb5d65b |
+ * If we are still receiving, then parseRequests() below will fail.
|
|
|
fb5d65b |
* (XXX: but then we will call readNextRequest() which may succeed and
|
|
|
fb5d65b |
* execute a smuggled request as we are not done with the current request).
|
|
|
fb5d65b |
*
|
|
|
fb5d65b |
@@ -952,28 +952,12 @@ ConnStateData::kick()
|
|
|
fb5d65b |
* Attempt to parse a request from the request buffer.
|
|
|
fb5d65b |
* If we've been fed a pipelined request it may already
|
|
|
fb5d65b |
* be in our read buffer.
|
|
|
fb5d65b |
- *
|
|
|
fb5d65b |
- \par
|
|
|
fb5d65b |
- * This needs to fall through - if we're unlucky and parse the _last_ request
|
|
|
fb5d65b |
- * from our read buffer we may never re-register for another client read.
|
|
|
fb5d65b |
*/
|
|
|
fb5d65b |
|
|
|
fb5d65b |
- if (clientParseRequests()) {
|
|
|
fb5d65b |
- debugs(33, 3, clientConnection << ": parsed next request from buffer");
|
|
|
fb5d65b |
- }
|
|
|
fb5d65b |
+ parseRequests();
|
|
|
fb5d65b |
|
|
|
fb5d65b |
- /** \par
|
|
|
fb5d65b |
- * Either we need to kick-start another read or, if we have
|
|
|
fb5d65b |
- * a half-closed connection, kill it after the last request.
|
|
|
fb5d65b |
- * This saves waiting for half-closed connections to finished being
|
|
|
fb5d65b |
- * half-closed _AND_ then, sometimes, spending "Timeout" time in
|
|
|
fb5d65b |
- * the keepalive "Waiting for next request" state.
|
|
|
fb5d65b |
- */
|
|
|
fb5d65b |
- if (commIsHalfClosed(clientConnection->fd) && pipeline.empty()) {
|
|
|
fb5d65b |
- debugs(33, 3, "half-closed client with no pending requests, closing");
|
|
|
fb5d65b |
- clientConnection->close();
|
|
|
fb5d65b |
+ if (!isOpen())
|
|
|
fb5d65b |
return;
|
|
|
fb5d65b |
- }
|
|
|
fb5d65b |
|
|
|
fb5d65b |
/** \par
|
|
|
fb5d65b |
* At this point we either have a parsed request (which we've
|
|
|
fb5d65b |
@@ -1893,16 +1877,11 @@ ConnStateData::receivedFirstByte()
|
|
|
fb5d65b |
resetReadTimeout(Config.Timeout.request);
|
|
|
fb5d65b |
}
|
|
|
fb5d65b |
|
|
|
fb5d65b |
-/**
|
|
|
fb5d65b |
- * Attempt to parse one or more requests from the input buffer.
|
|
|
fb5d65b |
- * Returns true after completing parsing of at least one request [header]. That
|
|
|
fb5d65b |
- * includes cases where parsing ended with an error (e.g., a huge request).
|
|
|
fb5d65b |
- */
|
|
|
fb5d65b |
-bool
|
|
|
fb5d65b |
-ConnStateData::clientParseRequests()
|
|
|
fb5d65b |
+/// Attempt to parse one or more requests from the input buffer.
|
|
|
fb5d65b |
+/// May close the connection.
|
|
|
fb5d65b |
+void
|
|
|
fb5d65b |
+ConnStateData::parseRequests()
|
|
|
fb5d65b |
{
|
|
|
fb5d65b |
- bool parsed_req = false;
|
|
|
fb5d65b |
-
|
|
|
fb5d65b |
debugs(33, 5, clientConnection << ": attempting to parse");
|
|
|
fb5d65b |
|
|
|
fb5d65b |
// Loop while we have read bytes that are not needed for producing the body
|
|
|
fb5d65b |
@@ -1947,8 +1926,6 @@ ConnStateData::clientParseRequests()
|
|
|
fb5d65b |
|
|
|
fb5d65b |
processParsedRequest(context);
|
|
|
fb5d65b |
|
|
|
fb5d65b |
- parsed_req = true; // XXX: do we really need to parse everything right NOW ?
|
|
|
fb5d65b |
-
|
|
|
fb5d65b |
if (context->mayUseConnection()) {
|
|
|
fb5d65b |
debugs(33, 3, "Not parsing new requests, as this request may need the connection");
|
|
|
fb5d65b |
break;
|
|
|
fb5d65b |
@@ -1961,8 +1938,19 @@ ConnStateData::clientParseRequests()
|
|
|
fb5d65b |
}
|
|
|
fb5d65b |
}
|
|
|
fb5d65b |
|
|
|
fb5d65b |
- /* XXX where to 'finish' the parsing pass? */
|
|
|
fb5d65b |
- return parsed_req;
|
|
|
fb5d65b |
+ debugs(33, 7, "buffered leftovers: " << inBuf.length());
|
|
|
fb5d65b |
+
|
|
|
fb5d65b |
+ if (isOpen() && commIsHalfClosed(clientConnection->fd)) {
|
|
|
fb5d65b |
+ if (pipeline.empty()) {
|
|
|
fb5d65b |
+ // we processed what we could parse, and no more data is coming
|
|
|
fb5d65b |
+ debugs(33, 5, "closing half-closed without parsed requests: " << clientConnection);
|
|
|
fb5d65b |
+ clientConnection->close();
|
|
|
fb5d65b |
+ } else {
|
|
|
fb5d65b |
+ // we parsed what we could, and no more data is coming
|
|
|
fb5d65b |
+ debugs(33, 5, "monitoring half-closed while processing parsed requests: " << clientConnection);
|
|
|
fb5d65b |
+ flags.readMore = false; // may already be false
|
|
|
fb5d65b |
+ }
|
|
|
fb5d65b |
+ }
|
|
|
fb5d65b |
}
|
|
|
fb5d65b |
|
|
|
fb5d65b |
void
|
|
|
fb5d65b |
@@ -1979,18 +1967,7 @@ ConnStateData::afterClientRead()
|
|
|
fb5d65b |
if (pipeline.empty())
|
|
|
fb5d65b |
fd_note(clientConnection->fd, "Reading next request");
|
|
|
fb5d65b |
|
|
|
fb5d65b |
- if (!clientParseRequests()) {
|
|
|
fb5d65b |
- if (!isOpen())
|
|
|
fb5d65b |
- return;
|
|
|
fb5d65b |
- // We may get here if the client half-closed after sending a partial
|
|
|
fb5d65b |
- // request. See doClientRead() and shouldCloseOnEof().
|
|
|
fb5d65b |
- // XXX: This partially duplicates ConnStateData::kick().
|
|
|
fb5d65b |
- if (pipeline.empty() && commIsHalfClosed(clientConnection->fd)) {
|
|
|
fb5d65b |
- debugs(33, 5, clientConnection << ": half-closed connection, no completed request parsed, connection closing.");
|
|
|
fb5d65b |
- clientConnection->close();
|
|
|
fb5d65b |
- return;
|
|
|
fb5d65b |
- }
|
|
|
fb5d65b |
- }
|
|
|
fb5d65b |
+ parseRequests();
|
|
|
fb5d65b |
|
|
|
fb5d65b |
if (!isOpen())
|
|
|
fb5d65b |
return;
|
|
|
fb5d65b |
@@ -3775,7 +3752,7 @@ ConnStateData::notePinnedConnectionBecameIdle(PinnedIdleContext pic)
|
|
|
fb5d65b |
startPinnedConnectionMonitoring();
|
|
|
fb5d65b |
|
|
|
fb5d65b |
if (pipeline.empty())
|
|
|
fb5d65b |
- kick(); // in case clientParseRequests() was blocked by a busy pic.connection
|
|
|
fb5d65b |
+ kick(); // in case parseRequests() was blocked by a busy pic.connection
|
|
|
fb5d65b |
}
|
|
|
fb5d65b |
|
|
|
fb5d65b |
/// Forward future client requests using the given server connection.
|
|
|
fb5d65b |
diff --git a/src/client_side.h b/src/client_side.h
|
|
|
fb5d65b |
index 6027b31..60b99b1 100644
|
|
|
fb5d65b |
--- a/src/client_side.h
|
|
|
fb5d65b |
+++ b/src/client_side.h
|
|
|
fb5d65b |
@@ -98,7 +98,6 @@ public:
|
|
|
fb5d65b |
void doneWithControlMsg() override;
|
|
|
fb5d65b |
|
|
|
fb5d65b |
/// Traffic parsing
|
|
|
fb5d65b |
- bool clientParseRequests();
|
|
|
fb5d65b |
void readNextRequest();
|
|
|
fb5d65b |
|
|
|
fb5d65b |
/// try to make progress on a transaction or read more I/O
|
|
|
fb5d65b |
@@ -443,6 +442,7 @@ private:
|
|
|
fb5d65b |
|
|
|
fb5d65b |
void checkLogging();
|
|
|
fb5d65b |
|
|
|
fb5d65b |
+ void parseRequests();
|
|
|
fb5d65b |
void clientAfterReadingRequests();
|
|
|
fb5d65b |
bool concurrentRequestQueueFilled() const;
|
|
|
fb5d65b |
|
|
|
fb5d65b |
diff --git a/src/tests/stub_client_side.cc b/src/tests/stub_client_side.cc
|
|
|
fb5d65b |
index 8c160e5..f49d5dc 100644
|
|
|
fb5d65b |
--- a/src/tests/stub_client_side.cc
|
|
|
fb5d65b |
+++ b/src/tests/stub_client_side.cc
|
|
|
fb5d65b |
@@ -14,7 +14,7 @@
|
|
|
fb5d65b |
#include "tests/STUB.h"
|
|
|
fb5d65b |
|
|
|
fb5d65b |
#include "client_side.h"
|
|
|
fb5d65b |
-bool ConnStateData::clientParseRequests() STUB_RETVAL(false)
|
|
|
fb5d65b |
+void ConnStateData::parseRequests() STUB
|
|
|
fb5d65b |
void ConnStateData::readNextRequest() STUB
|
|
|
fb5d65b |
bool ConnStateData::isOpen() const STUB_RETVAL(false)
|
|
|
fb5d65b |
void ConnStateData::kick() STUB
|