bug 528288 - spdy: early configuration of npn negotiation from IsAlive() r=honzab
authorPatrick McManus <mcmanus@ducksong.com>
Fri, 02 Dec 2011 10:28:57 -0500
changeset 82817 0eb13ad19d08be53e991cc03e4d70ec4fd9fb995
parent 82816 0bd45ead1676ae227025ed4dd20181a94ffecff8
child 82818 3f6e6b127b23aa1178c71c8f719c65557c101f01
push id519
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 00:38:35 +0000
treeherdermozilla-beta@788ea1ef610b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewershonzab
bugs528288
milestone11.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
bug 528288 - spdy: early configuration of npn negotiation from IsAlive() r=honzab patch 1
netwerk/protocol/http/nsHttpConnection.cpp
netwerk/protocol/http/nsHttpConnection.h
--- a/netwerk/protocol/http/nsHttpConnection.cpp
+++ b/netwerk/protocol/http/nsHttpConnection.cpp
@@ -81,16 +81,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;
@@ -242,43 +243,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<nsISupports> securityInfo;
-            nsresult rv =
-                mSocketTransport->GetSecurityInfo(getter_AddRefs(securityInfo));
-            NS_ENSURE_SUCCESS(rv, rv);
-            
-            nsCOMPtr<nsISSLSocketControl> ssl =
-                do_QueryInterface(securityInfo, &rv);
-            NS_ENSURE_SUCCESS(rv, rv);
-
-            nsTArray<nsCString> 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;
 
@@ -302,16 +277,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<nsISupports> securityInfo;
+            nsresult rv =
+                mSocketTransport->GetSecurityInfo(getter_AddRefs(securityInfo));
+            if (NS_FAILED(rv))
+                return;
+
+            nsCOMPtr<nsISSLSocketControl> ssl =
+                do_QueryInterface(securityInfo, &rv);
+            if (NS_FAILED(rv))
+                return;
+
+            nsTArray<nsCString> 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,
@@ -430,16 +444,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) {
--- a/netwerk/protocol/http/nsHttpConnection.h
+++ b/netwerk/protocol/http/nsHttpConnection.h
@@ -169,16 +169,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<nsISocketTransport>    mSocketTransport;
     nsCOMPtr<nsIAsyncInputStream>   mSocketIn;
     nsCOMPtr<nsIAsyncOutputStream>  mSocketOut;
@@ -213,15 +214,16 @@ private:
     bool                            mSupportsPipelining;
     bool                            mIsReused;
     bool                            mCompletedProxyConnect;
     bool                            mLastTransactionExpectedNoContent;
     bool                            mIdleMonitoring;
 
     // SPDY related
     bool                            mNPNComplete;
+    bool                            mSetupNPNCalled;
     bool                            mUsingSpdy;
     nsRefPtr<mozilla::net::SpdySession> mSpdySession;
     PRInt32                         mPriority;
     bool                            mReportedSpdy;
 };
 
 #endif // nsHttpConnection_h__