author | Patrick McManus <mcmanus@ducksong.com> |
Fri, 08 Apr 2011 14:37:16 -0400 | |
changeset 67712 | 233dde6c5b44a913639c99f7e4b0c31865b96ad1 |
parent 67711 | e48f48ad28be17759eebde37609b5e60fe8add0a |
child 67713 | 4cadb299e5efac8841181a6547abd4f11cc0e66b |
push id | 1 |
push user | root |
push date | Tue, 26 Apr 2011 22:38:44 +0000 |
treeherder | mozilla-beta@bfdb6e623a36 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | honzab |
bugs | 595316 |
milestone | 2.2a1pre |
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
|
--- a/netwerk/protocol/http/nsAHttpConnection.h +++ b/netwerk/protocol/http/nsAHttpConnection.h @@ -39,16 +39,17 @@ #define nsAHttpConnection_h__ #include "nsISupports.h" class nsAHttpTransaction; class nsHttpRequestHead; class nsHttpResponseHead; class nsHttpConnectionInfo; +class nsHttpConnection; //----------------------------------------------------------------------------- // Abstract base class for a HTTP connection //----------------------------------------------------------------------------- class nsAHttpConnection : public nsISupports { public: @@ -105,24 +106,29 @@ public: // called by a transaction when the transaction reads more from the socket // than it should have (eg. containing part of the next pipelined response). virtual nsresult PushBack(const char *data, PRUint32 length) = 0; // Used by a transaction to manage the state of previous response bodies on // 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 \ nsresult OnHeadersAvailable(nsAHttpTransaction *, nsHttpRequestHead *, nsHttpResponseHead *, PRBool *reset); \ nsresult ResumeSend(); \ nsresult ResumeRecv(); \ void CloseTransaction(nsAHttpTransaction *, nsresult); \ void GetConnectionInfo(nsHttpConnectionInfo **); \ void GetSecurityInfo(nsISupports **); \ PRBool IsPersistent(); \ PRBool IsReused(); \ nsresult PushBack(const char *, PRUint32); \ PRBool LastTransactionExpectedNoContent(); \ - void SetLastTransactionExpectedNoContent(PRBool); + void SetLastTransactionExpectedNoContent(PRBool); \ + nsHttpConnection *TakeHttpConnection(); #endif // nsAHttpConnection_h__
--- a/netwerk/protocol/http/nsAHttpTransaction.h +++ b/netwerk/protocol/http/nsAHttpTransaction.h @@ -40,16 +40,17 @@ #include "nsISupports.h" class nsAHttpConnection; class nsAHttpSegmentReader; class nsAHttpSegmentWriter; class nsIInterfaceRequestor; class nsIEventTarget; +class nsHttpRequestHead; //---------------------------------------------------------------------------- // Abstract base class for a HTTP transaction: // // A transaction is a "sink" for the response data. The connection pushes // data to the transaction by writing to it. The transaction supports // WriteSegments and may refuse to accept data if its buffers are full (its // write function returns NS_BASE_STREAM_WOULD_BLOCK in this case). @@ -81,29 +82,37 @@ public: PRUint32 count, PRUint32 *countRead) = 0; // called to write response data to the transaction. virtual nsresult WriteSegments(nsAHttpSegmentWriter *writer, PRUint32 count, PRUint32 *countWritten) = 0; // 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 \ void SetConnection(nsAHttpConnection *); \ void GetSecurityCallbacks(nsIInterfaceRequestor **, \ nsIEventTarget **); \ void OnTransportStatus(nsresult status, PRUint64 progress); \ PRBool IsDone(); \ nsresult Status(); \ 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 //----------------------------------------------------------------------------- class nsAHttpSegmentReader { public:
--- a/netwerk/protocol/http/nsHttpConnection.cpp +++ b/netwerk/protocol/http/nsHttpConnection.cpp @@ -417,22 +417,17 @@ nsHttpConnection::OnHeadersAvailable(nsA LOG(("ProxyStartSSL failed [rv=%x]\n", rv)); mCompletedSSLConnect = PR_TRUE; rv = mSocketOut->AsyncWait(this, 0, 0, nsnull); // XXX what if this fails -- need to handle this error NS_ASSERTION(NS_SUCCEEDED(rv), "mSocketOut->AsyncWait failed"); } 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<nsHttpTransaction *>(mTransaction.get()); - trans->SetSSLConnectFailed(); + mTransaction->SetSSLConnectFailed(); } } return NS_OK; } PRBool nsHttpConnection::IsReused() @@ -722,29 +717,24 @@ nsHttpConnection::SetupSSLProxyConnect() request.SetMethod(nsHttp::Connect); request.SetVersion(gHttpHandler->HttpVersion()); request.SetRequestURI(buf); request.SetHeader(nsHttp::User_Agent, gHttpHandler->UserAgent()); // 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<nsHttpTransaction *>(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. request.SetHeader(nsHttp::Proxy_Authorization, nsDependentCString(val)); } buf.Truncate(); request.Flatten(buf, PR_FALSE);
--- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp +++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp @@ -871,32 +871,28 @@ nsHttpConnectionMgr::ProcessNewTransacti if (!clone) return NS_ERROR_OUT_OF_MEMORY; ent = new nsConnectionEntry(clone); if (!ent) return NS_ERROR_OUT_OF_MEMORY; 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 GetConnection(ent, trans, &conn); nsresult rv; if (!conn) { LOG((" adding transaction to pending queue [trans=%x pending-count=%u]\n", @@ -1508,16 +1504,29 @@ nsHttpConnectionMgr::nsHalfOpenSocket::G nsCOMPtr<nsIInterfaceRequestor> callbacks; mTransaction->GetSecurityCallbacks(getter_AddRefs(callbacks), nsnull); if (callbacks) return callbacks->GetInterface(iid, result); } 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() { return mConn->LastTransactionExpectedNoContent(); } void nsHttpConnectionMgr::
--- a/netwerk/protocol/http/nsHttpPipeline.cpp +++ b/netwerk/protocol/http/nsHttpPipeline.cpp @@ -298,16 +298,43 @@ nsHttpPipeline::LastTransactionExpectedN void nsHttpPipeline::SetLastTransactionExpectedNoContent(PRBool val) { NS_ABORT_IF_FALSE(mConnection, "no connection"); 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 //----------------------------------------------------------------------------- void nsHttpPipeline::SetConnection(nsAHttpConnection *conn) { LOG(("nsHttpPipeline::SetConnection [this=%x conn=%x]\n", this, conn));
--- a/netwerk/protocol/http/nsHttpTransaction.cpp +++ b/netwerk/protocol/http/nsHttpTransaction.cpp @@ -313,16 +313,28 @@ nsHttpTransaction::TakeResponseHead() return nsnull; } nsHttpResponseHead *head = mResponseHead; mResponseHead = nsnull; return head; } +void +nsHttpTransaction::SetSSLConnectFailed() +{ + mSSLConnectFailed = PR_TRUE; +} + +nsHttpRequestHead * +nsHttpTransaction::RequestHead() +{ + return mRequestHead; +} + //---------------------------------------------------------------------------- // nsHttpTransaction::nsAHttpTransaction //---------------------------------------------------------------------------- void nsHttpTransaction::SetConnection(nsAHttpConnection *conn) { NS_IF_RELEASE(mConnection);
--- a/netwerk/protocol/http/nsHttpTransaction.h +++ b/netwerk/protocol/http/nsHttpTransaction.h @@ -109,32 +109,30 @@ public: nsIEventTarget *consumerTarget, nsIInterfaceRequestor *callbacks, nsITransportEventSink *eventsink, nsIAsyncInputStream **responseBody); // attributes PRUint8 Caps() { return mCaps; } nsHttpConnectionInfo *ConnectionInfo() { return mConnInfo; } - nsHttpRequestHead *RequestHead() { return mRequestHead; } nsHttpResponseHead *ResponseHead() { return mHaveAllHeaders ? mResponseHead : nsnull; } nsISupports *SecurityInfo() { return mSecurityInfo; } nsIInterfaceRequestor *Callbacks() { return mCallbacks; } nsIEventTarget *ConsumerTarget() { return mConsumerTarget; } nsAHttpConnection *Connection() { return mConnection; } // Called to take ownership of the response headers; the transaction // will drop any reference to the response headers after this call. nsHttpResponseHead *TakeResponseHead(); // 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. void SetPriority(PRInt32 priority) { mPriority = priority; } PRInt32 Priority() { return mPriority; } private: nsresult Restart();