diff --git a/netwerk/protocol/http/nsAHttpConnection.h b/netwerk/protocol/http/nsAHttpConnection.h index 43e8beebc89e..68b707e52a89 100644 --- a/netwerk/protocol/http/nsAHttpConnection.h +++ b/netwerk/protocol/http/nsAHttpConnection.h @@ -44,6 +44,7 @@ class nsAHttpTransaction; class nsHttpRequestHead; class nsHttpResponseHead; class nsHttpConnectionInfo; +class nsHttpConnection; //----------------------------------------------------------------------------- // Abstract base class for a HTTP connection @@ -110,6 +111,10 @@ public: // the same connection and work around buggy servers. virtual PRBool LastTransactionExpectedNoContent() = 0; virtual void SetLastTransactionExpectedNoContent(PRBool) = 0; + + // Transfer the base http connection object along with a + // reference to it to the caller. + virtual nsHttpConnection *TakeHttpConnection() = 0; }; #define NS_DECL_NSAHTTPCONNECTION \ @@ -123,6 +128,7 @@ public: PRBool IsReused(); \ nsresult PushBack(const char *, PRUint32); \ PRBool LastTransactionExpectedNoContent(); \ - void SetLastTransactionExpectedNoContent(PRBool); + void SetLastTransactionExpectedNoContent(PRBool); \ + nsHttpConnection *TakeHttpConnection(); #endif // nsAHttpConnection_h__ diff --git a/netwerk/protocol/http/nsAHttpTransaction.h b/netwerk/protocol/http/nsAHttpTransaction.h index 8c11c62c88b5..a965e7e67ef2 100644 --- a/netwerk/protocol/http/nsAHttpTransaction.h +++ b/netwerk/protocol/http/nsAHttpTransaction.h @@ -45,6 +45,7 @@ class nsAHttpSegmentReader; class nsAHttpSegmentWriter; class nsIInterfaceRequestor; class nsIEventTarget; +class nsHttpRequestHead; //---------------------------------------------------------------------------- // Abstract base class for a HTTP transaction: @@ -86,6 +87,12 @@ public: // called to close the transaction virtual void Close(nsresult reason) = 0; + + // called to indicate a failure at the SSL setup level + virtual void SetSSLConnectFailed() = 0; + + // called to retrieve the request headers of the transaction + virtual nsHttpRequestHead *RequestHead() = 0; }; #define NS_DECL_NSAHTTPTRANSACTION \ @@ -98,7 +105,9 @@ public: PRUint32 Available(); \ nsresult ReadSegments(nsAHttpSegmentReader *, PRUint32, PRUint32 *); \ nsresult WriteSegments(nsAHttpSegmentWriter *, PRUint32, PRUint32 *); \ - void Close(nsresult reason); + void Close(nsresult reason); \ + void SetSSLConnectFailed(); \ + nsHttpRequestHead *RequestHead(); //----------------------------------------------------------------------------- // nsAHttpSegmentReader diff --git a/netwerk/protocol/http/nsHttpConnection.cpp b/netwerk/protocol/http/nsHttpConnection.cpp index 47e1a07c4918..1e0da4c4fcf7 100644 --- a/netwerk/protocol/http/nsHttpConnection.cpp +++ b/netwerk/protocol/http/nsHttpConnection.cpp @@ -422,12 +422,7 @@ nsHttpConnection::OnHeadersAvailable(nsAHttpTransaction *trans, } else { LOG(("SSL proxy CONNECT failed!\n")); - // NOTE: this cast is valid since this connection cannot be - // processing a transaction pipeline until after the first HTTP/1.1 - // response. - nsHttpTransaction *trans = - static_cast(mTransaction.get()); - trans->SetSSLConnectFailed(); + mTransaction->SetSSLConnectFailed(); } } @@ -727,19 +722,14 @@ nsHttpConnection::SetupSSLProxyConnect() // send this header for backwards compatibility. request.SetHeader(nsHttp::Proxy_Connection, NS_LITERAL_CSTRING("keep-alive")); - // NOTE: this cast is valid since this connection cannot be processing a - // transaction pipeline until after the first HTTP/1.1 response. - nsHttpTransaction *trans = - static_cast(mTransaction.get()); - - val = trans->RequestHead()->PeekHeader(nsHttp::Host); + val = mTransaction->RequestHead()->PeekHeader(nsHttp::Host); if (val) { // all HTTP/1.1 requests must include a Host header (even though it // may seem redundant in this case; see bug 82388). request.SetHeader(nsHttp::Host, nsDependentCString(val)); } - val = trans->RequestHead()->PeekHeader(nsHttp::Proxy_Authorization); + val = mTransaction->RequestHead()->PeekHeader(nsHttp::Proxy_Authorization); if (val) { // we don't know for sure if this authorization is intended for the // SSL proxy, so we add it just in case. diff --git a/netwerk/protocol/http/nsHttpConnectionMgr.cpp b/netwerk/protocol/http/nsHttpConnectionMgr.cpp index d233907596c3..13f63f5392dd 100644 --- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp +++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp @@ -876,22 +876,18 @@ nsHttpConnectionMgr::ProcessNewTransaction(nsHttpTransaction *trans) mCT.Put(&key, ent); } - nsHttpConnection *conn; + // Check if the transaction already has a sticky reference to a connection. + // If so, then we can just use it directly by transferring its reference + // to the new connection var instead of calling GetConnection() to search + // for an available one. - // check if the transaction already has a sticky reference to a connection. - // if so, then we can just use it directly. XXX check if alive?? - // XXX add a TakeConnection method or something to make this clearer! - nsConnectionHandle *handle = (nsConnectionHandle *) trans->Connection(); - if (handle) { + nsAHttpConnection *wrappedConnection = trans->Connection(); + nsHttpConnection *conn; + conn = wrappedConnection ? wrappedConnection->TakeHttpConnection() : nsnull; + + if (conn) { NS_ASSERTION(caps & NS_HTTP_STICKY_CONNECTION, "unexpected caps"); - NS_ASSERTION(handle->mConn, "no connection"); - // steal reference from connection handle. - // XXX prevent SetConnection(nsnull) from calling ReclaimConnection - conn = handle->mConn; - handle->mConn = nsnull; - - // destroy connection handle. trans->SetConnection(nsnull); } else @@ -1513,6 +1509,19 @@ nsHttpConnectionMgr::nsHalfOpenSocket::GetInterface(const nsIID &iid, return NS_ERROR_NO_INTERFACE; } + +nsHttpConnection * +nsHttpConnectionMgr::nsConnectionHandle::TakeHttpConnection() +{ + // return our connection object to the caller and clear it internally + // do not drop our reference - the caller now owns it. + + NS_ASSERTION(mConn, "no connection"); + nsHttpConnection *conn = mConn; + mConn = nsnull; + return conn; +} + PRBool nsHttpConnectionMgr::nsConnectionHandle::LastTransactionExpectedNoContent() { diff --git a/netwerk/protocol/http/nsHttpPipeline.cpp b/netwerk/protocol/http/nsHttpPipeline.cpp index 88630d030aa5..9ea0408554b7 100644 --- a/netwerk/protocol/http/nsHttpPipeline.cpp +++ b/netwerk/protocol/http/nsHttpPipeline.cpp @@ -303,6 +303,33 @@ nsHttpPipeline::SetLastTransactionExpectedNoContent(PRBool val) mConnection->SetLastTransactionExpectedNoContent(val); } +nsHttpConnection * +nsHttpPipeline::TakeHttpConnection() +{ + if (mConnection) + return mConnection->TakeHttpConnection(); + return nsnull; +} + +void +nsHttpPipeline::SetSSLConnectFailed() +{ + nsAHttpTransaction *trans = Request(0); + + if (trans) + trans->SetSSLConnectFailed(); +} + +nsHttpRequestHead * +nsHttpPipeline::RequestHead() +{ + nsAHttpTransaction *trans = Request(0); + + if (trans) + return trans->RequestHead(); + return nsnull; +} + //----------------------------------------------------------------------------- // nsHttpPipeline::nsAHttpConnection //----------------------------------------------------------------------------- diff --git a/netwerk/protocol/http/nsHttpTransaction.cpp b/netwerk/protocol/http/nsHttpTransaction.cpp index d2349c0a79ae..6f0260bc3ee9 100644 --- a/netwerk/protocol/http/nsHttpTransaction.cpp +++ b/netwerk/protocol/http/nsHttpTransaction.cpp @@ -318,6 +318,18 @@ nsHttpTransaction::TakeResponseHead() return head; } +void +nsHttpTransaction::SetSSLConnectFailed() +{ + mSSLConnectFailed = PR_TRUE; +} + +nsHttpRequestHead * +nsHttpTransaction::RequestHead() +{ + return mRequestHead; +} + //---------------------------------------------------------------------------- // nsHttpTransaction::nsAHttpTransaction //---------------------------------------------------------------------------- diff --git a/netwerk/protocol/http/nsHttpTransaction.h b/netwerk/protocol/http/nsHttpTransaction.h index f6177d0b7f3e..527428847444 100644 --- a/netwerk/protocol/http/nsHttpTransaction.h +++ b/netwerk/protocol/http/nsHttpTransaction.h @@ -114,7 +114,6 @@ public: // attributes PRUint8 Caps() { return mCaps; } nsHttpConnectionInfo *ConnectionInfo() { return mConnInfo; } - nsHttpRequestHead *RequestHead() { return mRequestHead; } nsHttpResponseHead *ResponseHead() { return mHaveAllHeaders ? mResponseHead : nsnull; } nsISupports *SecurityInfo() { return mSecurityInfo; } @@ -129,7 +128,6 @@ public: // Called to find out if the transaction generated a complete response. PRBool ResponseIsComplete() { return mResponseIsComplete; } - void SetSSLConnectFailed() { mSSLConnectFailed = PR_TRUE; } PRBool SSLConnectFailed() { return mSSLConnectFailed; } // These methods may only be used by the connection manager.