# HG changeset patch # Parent 356dc060e86692447af69a8e8c66a31b006497ab # User Patrick McManus bug 528288 - spdy: early configuration of npn negotiation from IsAlive() r=honzab patch 1 diff --git a/netwerk/protocol/http/nsHttpConnection.cpp b/netwerk/protocol/http/nsHttpConnection.cpp --- a/netwerk/protocol/http/nsHttpConnection.cpp +++ b/netwerk/protocol/http/nsHttpConnection.cpp @@ -83,16 +83,17 @@ nsHttpConnection::nsHttpConnection() , mKeepAlive(true) // assume to keep-alive by default , mKeepAliveMask(true) , mSupportsPipelining(false) // assume low-grade server , mIsReused(false) , mCompletedProxyConnect(false) , mLastTransactionExpectedNoContent(false) , mIdleMonitoring(false) , mNPNComplete(false) + , mSetupNPNCalled(false) , mUsingSpdy(false) , mPriority(nsISupportsPriority::PRIORITY_NORMAL) , mReportedSpdy(false) { LOG(("Creating nsHttpConnection @%x\n", this)); // grab a reference to the handler to ensure that it doesn't go away. nsHttpHandler *handler = gHttpHandler; @@ -260,43 +261,17 @@ nsHttpConnection::Activate(nsAHttpTransa getter_AddRefs(callbackTarget)); if (callbacks != mCallbacks) { mCallbacks.swap(callbacks); if (callbacks) NS_ProxyRelease(mCallbackTarget, callbacks); mCallbackTarget = callbackTarget; } - // Setup NPN Negotiation if necessary (only for SPDY) - if (!mNPNComplete) { - - mNPNComplete = true; - - if (mConnInfo->UsingSSL() && - !(caps & NS_HTTP_DISALLOW_SPDY) && - gHttpHandler->IsSpdyEnabled()) { - LOG(("nsHttpConnection::Init Setting up SPDY Negotiation")); - nsCOMPtr securityInfo; - nsresult rv = - mSocketTransport->GetSecurityInfo(getter_AddRefs(securityInfo)); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr ssl = - do_QueryInterface(securityInfo, &rv); - NS_ENSURE_SUCCESS(rv, rv); - - nsTArray protocolArray; - protocolArray.AppendElement(NS_LITERAL_CSTRING("spdy/2")); - protocolArray.AppendElement(NS_LITERAL_CSTRING("http/1.1")); - if (NS_SUCCEEDED(ssl->SetNPNList(protocolArray))) { - LOG(("nsHttpConnection::Init Setting up SPDY Negotiation OK")); - mNPNComplete = false; - } - } - } + SetupNPN(caps); // only for spdy // take ownership of the transaction mTransaction = trans; NS_ABORT_IF_FALSE(!mIdleMonitoring, "Activating a connection with an Idle Monitor"); mIdleMonitoring = false; @@ -320,16 +295,55 @@ nsHttpConnection::Activate(nsAHttpTransa failed_activation: if (NS_FAILED(rv)) { mTransaction = nsnull; } return rv; } +void +nsHttpConnection::SetupNPN(PRUint8 caps) +{ + if (mSetupNPNCalled) /* do only once */ + return; + mSetupNPNCalled = true; + + // Setup NPN Negotiation if necessary (only for SPDY) + if (!mNPNComplete) { + + mNPNComplete = true; + + if (mConnInfo->UsingSSL() && + !(caps & NS_HTTP_DISALLOW_SPDY) && + gHttpHandler->IsSpdyEnabled()) { + LOG(("nsHttpConnection::Init Setting up SPDY Negotiation")); + nsCOMPtr securityInfo; + nsresult rv = + mSocketTransport->GetSecurityInfo(getter_AddRefs(securityInfo)); + if (NS_FAILED(rv)) + return; + + nsCOMPtr ssl = + do_QueryInterface(securityInfo, &rv); + if (NS_FAILED(rv)) + return; + + nsTArray protocolArray; + protocolArray.AppendElement(NS_LITERAL_CSTRING("spdy/2")); + protocolArray.AppendElement(NS_LITERAL_CSTRING("http/1.1")); + if (NS_SUCCEEDED(ssl->SetNPNList(protocolArray))) { + LOG(("nsHttpConnection::Init Setting up SPDY Negotiation OK")); + mNPNComplete = false; + } + } + } +} + + nsresult nsHttpConnection::AddTransaction(nsAHttpTransaction *httpTransaction, PRInt32 priority) { LOG(("nsHttpConnection::AddTransaction for SPDY")); NS_ABORT_IF_FALSE(PR_GetCurrentThread() == gSocketThread, "wrong thread"); NS_ABORT_IF_FALSE(mSpdySession && mUsingSpdy, @@ -448,16 +462,20 @@ PRUint32 nsHttpConnection::TimeToLive() } bool nsHttpConnection::IsAlive() { if (!mSocketTransport) return false; + // SocketTransport::IsAlive can run the SSL state machine, so make sure + // the NPN options are set before that happens. + SetupNPN(0); + bool alive; nsresult rv = mSocketTransport->IsAlive(&alive); if (NS_FAILED(rv)) alive = false; //#define TEST_RESTART_LOGIC #ifdef TEST_RESTART_LOGIC if (!alive) { diff --git a/netwerk/protocol/http/nsHttpConnection.h b/netwerk/protocol/http/nsHttpConnection.h --- a/netwerk/protocol/http/nsHttpConnection.h +++ b/netwerk/protocol/http/nsHttpConnection.h @@ -168,16 +168,17 @@ private: nsresult SetupProxyConnect(); bool IsAlive(); bool SupportsPipelining(nsHttpResponseHead *); // Makes certain the SSL handshake is complete and NPN negotiation // has had a chance to happen bool EnsureNPNComplete(); + void SetupNPN(PRUint8 caps); // Directly Add a transaction to an active connection for SPDY nsresult AddTransaction(nsAHttpTransaction *, PRInt32); private: nsCOMPtr mSocketTransport; nsCOMPtr mSocketIn; nsCOMPtr mSocketOut; @@ -212,15 +213,16 @@ private: bool mSupportsPipelining; bool mIsReused; bool mCompletedProxyConnect; bool mLastTransactionExpectedNoContent; bool mIdleMonitoring; // SPDY related bool mNPNComplete; + bool mSetupNPNCalled; bool mUsingSpdy; nsRefPtr mSpdySession; PRInt32 mPriority; bool mReportedSpdy; }; #endif // nsHttpConnection_h__