bug 665885 respect keepalive: "max=" attribute r=honzab

This commit is contained in:
Patrick McManus 2012-03-22 19:39:31 -04:00
parent 8d78fbf9c8
commit a034a9d50a
2 changed files with 46 additions and 4 deletions

View File

@ -86,6 +86,7 @@ nsHttpConnection::nsHttpConnection()
, mIdleMonitoring(false) , mIdleMonitoring(false)
, mProxyConnectInProgress(false) , mProxyConnectInProgress(false)
, mHttp1xTransactionCount(0) , mHttp1xTransactionCount(0)
, mRemainingConnectionUses(0xffffffff)
, mClassification(nsAHttpTransaction::CLASS_GENERAL) , mClassification(nsAHttpTransaction::CLASS_GENERAL)
, mNPNComplete(false) , mNPNComplete(false)
, mSetupNPNCalled(false) , mSetupNPNCalled(false)
@ -537,9 +538,28 @@ nsHttpConnection::DontReuse()
mSpdySession->DontReuse(); mSpdySession->DontReuse();
} }
// Checked by the Connection Manager before scheduling a pipelined transaction
bool
nsHttpConnection::SupportsPipelining()
{
if (mTransaction &&
mTransaction->PipelineDepth() >= mRemainingConnectionUses) {
LOG(("nsHttpConnection::SupportsPipelining this=%p deny pipeline "
"because current depth %d exceeds max remaining uses %d\n",
this, mTransaction->PipelineDepth(), mRemainingConnectionUses));
return false;
}
return mSupportsPipelining && IsKeepAlive();
}
bool bool
nsHttpConnection::CanReuse() nsHttpConnection::CanReuse()
{ {
if ((mTransaction ? mTransaction->PipelineDepth() : 0) >=
mRemainingConnectionUses) {
return false;
}
bool canReuse; bool canReuse;
if (mSpdySession) if (mSpdySession)
@ -737,9 +757,13 @@ nsHttpConnection::OnHeadersAvailable(nsAHttpTransaction *trans,
// HTTP/1.1 connections are by default persistent // HTTP/1.1 connections are by default persistent
if (val && !PL_strcasecmp(val, "close")) { if (val && !PL_strcasecmp(val, "close")) {
mKeepAlive = false; mKeepAlive = false;
// persistent connections are required for pipelining to work
gHttpHandler->ConnMgr()->PipelineFeedbackInfo( // persistent connections are required for pipelining to work - if
mConnInfo, nsHttpConnectionMgr::BadExplicitClose, this, 0); // this close was not pre-announced then generate the negative
// BadExplicitClose feedback
if (mRemainingConnectionUses > 1)
gHttpHandler->ConnMgr()->PipelineFeedbackInfo(
mConnInfo, nsHttpConnectionMgr::BadExplicitClose, this, 0);
} }
else { else {
mKeepAlive = true; mKeepAlive = true;
@ -787,6 +811,7 @@ nsHttpConnection::OnHeadersAvailable(nsAHttpTransaction *trans,
// a "keep-alive" connection is by definition capable of being reused, and // a "keep-alive" connection is by definition capable of being reused, and
// we only care about being able to reuse it once. if a timeout is not // we only care about being able to reuse it once. if a timeout is not
// specified then we use our advertized timeout value. // specified then we use our advertized timeout value.
bool foundKeepAliveMax = false;
if (mKeepAlive) { if (mKeepAlive) {
val = responseHead->PeekHeader(nsHttp::Keep_Alive); val = responseHead->PeekHeader(nsHttp::Keep_Alive);
@ -796,6 +821,15 @@ nsHttpConnection::OnHeadersAvailable(nsAHttpTransaction *trans,
mIdleTimeout = PR_SecondsToInterval((PRUint32) atoi(cp + 8)); mIdleTimeout = PR_SecondsToInterval((PRUint32) atoi(cp + 8));
else else
mIdleTimeout = gHttpHandler->SpdyTimeout(); mIdleTimeout = gHttpHandler->SpdyTimeout();
cp = PL_strcasestr(val, "max=");
if (cp) {
int val = atoi(cp + 4);
if (val > 0) {
foundKeepAliveMax = true;
mRemainingConnectionUses = static_cast<PRUint32>(val);
}
}
} }
else { else {
mIdleTimeout = gHttpHandler->SpdyTimeout(); mIdleTimeout = gHttpHandler->SpdyTimeout();
@ -805,6 +839,9 @@ nsHttpConnection::OnHeadersAvailable(nsAHttpTransaction *trans,
this, PR_IntervalToSeconds(mIdleTimeout))); this, PR_IntervalToSeconds(mIdleTimeout)));
} }
if (!foundKeepAliveMax && mRemainingConnectionUses && !mUsingSpdy)
--mRemainingConnectionUses;
if (!mProxyConnectStream) if (!mProxyConnectStream)
HandleAlternateProtocol(responseHead); HandleAlternateProtocol(responseHead);

View File

@ -106,7 +106,7 @@ public:
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// XXX document when these are ok to call // XXX document when these are ok to call
bool SupportsPipelining() { return mSupportsPipelining && IsKeepAlive(); } bool SupportsPipelining();
bool IsKeepAlive() { return mUsingSpdy || bool IsKeepAlive() { return mUsingSpdy ||
(mKeepAliveMask && mKeepAlive); } (mKeepAliveMask && mKeepAlive); }
bool CanReuse(); // can this connection be reused? bool CanReuse(); // can this connection be reused?
@ -250,6 +250,11 @@ private:
// excludes spdy transactions. // excludes spdy transactions.
PRUint32 mHttp1xTransactionCount; PRUint32 mHttp1xTransactionCount;
// Keep-Alive: max="mRemainingConnectionUses" provides the number of future
// transactions (including the current one) that the server expects to allow
// on this persistent connection.
PRUint32 mRemainingConnectionUses;
nsAHttpTransaction::Classifier mClassification; nsAHttpTransaction::Classifier mClassification;
// SPDY related // SPDY related