diff options
Diffstat (limited to 'netwerk/protocol/http')
-rw-r--r-- | netwerk/protocol/http/TunnelUtils.cpp | 67 | ||||
-rw-r--r-- | netwerk/protocol/http/TunnelUtils.h | 11 | ||||
-rw-r--r-- | netwerk/protocol/http/nsHttpConnection.cpp | 21 | ||||
-rw-r--r-- | netwerk/protocol/http/nsHttpConnection.h | 3 |
4 files changed, 71 insertions, 31 deletions
diff --git a/netwerk/protocol/http/TunnelUtils.cpp b/netwerk/protocol/http/TunnelUtils.cpp index 4cc24a07f..6880e0187 100644 --- a/netwerk/protocol/http/TunnelUtils.cpp +++ b/netwerk/protocol/http/TunnelUtils.cpp @@ -23,6 +23,7 @@ #include "nsNetCID.h" #include "nsServiceManagerUtils.h" #include "nsComponentManagerUtils.h" +#include "nsSocketTransport2.h" namespace mozilla { namespace net { @@ -42,6 +43,7 @@ TLSFilterTransaction::TLSFilterTransaction(nsAHttpTransaction *aWrapped, , mSegmentReader(aReader) , mSegmentWriter(aWriter) , mForce(false) + , mReadSegmentReturnValue(NS_OK) , mNudgeCounter(0) { MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread); @@ -130,6 +132,19 @@ TLSFilterTransaction::Close(nsresult aReason) } mTransaction->Close(aReason); mTransaction = nullptr; + + RefPtr<NullHttpTransaction> baseTrans(do_QueryReferent(mWeakTrans)); + SpdyConnectTransaction *trans = baseTrans + ? baseTrans->QuerySpdyConnectTransaction() + : nullptr; + + LOG(("TLSFilterTransaction::Close %p aReason=%" PRIx32 " trans=%p\n", + this, static_cast<uint32_t>(aReason), trans)); + + if (trans) { + trans->Close(aReason); + trans = nullptr; + } } nsresult @@ -140,7 +155,7 @@ TLSFilterTransaction::OnReadSegment(const char *aData, LOG(("TLSFilterTransaction %p OnReadSegment %d (buffered %d)\n", this, aCount, mEncryptedTextUsed)); - mReadSegmentBlocked = false; + mReadSegmentReturnValue = NS_OK; MOZ_ASSERT(mSegmentReader); if (!mSecInfo) { return NS_ERROR_FAILURE; @@ -188,10 +203,12 @@ TLSFilterTransaction::OnReadSegment(const char *aData, return NS_OK; } // mTransaction ReadSegments actually obscures this code, so - // keep it in a member var for this::ReadSegments to insepct. Similar + // keep it in a member var for this::ReadSegments to inspect. Similar // to nsHttpConnection::mSocketOutCondition - mReadSegmentBlocked = (PR_GetError() == PR_WOULD_BLOCK_ERROR); - return mReadSegmentBlocked ? NS_BASE_STREAM_WOULD_BLOCK : NS_ERROR_FAILURE; + PRErrorCode code = PR_GetError(); + mReadSegmentReturnValue = ErrorAccordingToNSPR(code); + + return mReadSegmentReturnValue; } aCount -= written; aData += written; @@ -273,10 +290,18 @@ TLSFilterTransaction::OnWriteSegment(char *aData, mFilterReadCode = NS_OK; int32_t bytesRead = PR_Read(mFD, aData, aCount); if (bytesRead == -1) { - if (PR_GetError() == PR_WOULD_BLOCK_ERROR) { + PRErrorCode code = PR_GetError(); + if (code == PR_WOULD_BLOCK_ERROR) { return NS_BASE_STREAM_WOULD_BLOCK; } - return NS_ERROR_FAILURE; + // If reading from the socket succeeded (NS_SUCCEEDED(mFilterReadCode)), + // but the nss layer encountered an error remember the error. + if (NS_SUCCEEDED(mFilterReadCode)) { + mFilterReadCode = ErrorAccordingToNSPR(code); + LOG(("TLSFilterTransaction::OnWriteSegment %p nss error %" PRIx32 ".\n", + this, static_cast<uint32_t>(mFilterReadCode))); + } + return mFilterReadCode; } *outCountRead = bytesRead; @@ -303,7 +328,7 @@ TLSFilterTransaction::FilterInput(char *aBuf, int32_t aAmount) if (NS_SUCCEEDED(mFilterReadCode) && outCountRead) { LOG(("TLSFilterTransaction::FilterInput rv=%x read=%d input from net " "1 layer stripped, 1 still on\n", mFilterReadCode, outCountRead)); - if (mReadSegmentBlocked) { + if (mReadSegmentReturnValue == NS_BASE_STREAM_WOULD_BLOCK) { mNudgeCounter = 0; } } @@ -325,19 +350,18 @@ TLSFilterTransaction::ReadSegments(nsAHttpSegmentReader *aReader, return NS_ERROR_UNEXPECTED; } - mReadSegmentBlocked = false; + mReadSegmentReturnValue = NS_OK; mSegmentReader = aReader; nsresult rv = mTransaction->ReadSegments(this, aCount, outCountRead); LOG(("TLSFilterTransaction %p called trans->ReadSegments rv=%x %d\n", this, rv, *outCountRead)); - if (NS_SUCCEEDED(rv) && mReadSegmentBlocked) { - rv = NS_BASE_STREAM_WOULD_BLOCK; + if (NS_SUCCEEDED(rv) && (mReadSegmentReturnValue == NS_BASE_STREAM_WOULD_BLOCK)) { LOG(("TLSFilterTransaction %p read segment blocked found rv=%x\n", - this, rv)); + this, static_cast<uint32_t>(rv))); Connection()->ForceSend(); } - return rv; + return NS_SUCCEEDED(rv) ? mReadSegmentReturnValue : rv; } nsresult @@ -442,7 +466,10 @@ TLSFilterTransaction::Notify(nsITimer *timer) if (timer != mTimer) { return NS_ERROR_UNEXPECTED; } - StartTimerCallback(); + nsresult rv = StartTimerCallback(); + if (NS_FAILED(rv)) { + Close(rv); + } return NS_OK; } @@ -456,7 +483,7 @@ TLSFilterTransaction::StartTimerCallback() // This class can be called re-entrantly, so cleanup m* before ->on() RefPtr<NudgeTunnelCallback> cb(mNudgeCallback); mNudgeCallback = nullptr; - cb->OnTunnelNudged(this); + return cb->OnTunnelNudged(this); } return NS_OK; } @@ -675,10 +702,12 @@ TLSFilterTransaction::TakeSubTransactions( } nsresult -TLSFilterTransaction::SetProxiedTransaction(nsAHttpTransaction *aTrans) +TLSFilterTransaction::SetProxiedTransaction(nsAHttpTransaction *aTrans, + nsAHttpTransaction *aSpdyConnectTransaction) { - LOG(("TLSFilterTransaction::SetProxiedTransaction [this=%p] aTrans=%p\n", - this, aTrans)); + LOG(("TLSFilterTransaction::SetProxiedTransaction [this=%p] aTrans=%p, " + "aSpdyConnectTransaction=%p\n", + this, aTrans, aSpdyConnectTransaction)); mTransaction = aTrans; nsCOMPtr<nsIInterfaceRequestor> callbacks; @@ -688,6 +717,8 @@ TLSFilterTransaction::SetProxiedTransaction(nsAHttpTransaction *aTrans) secCtrl->SetNotificationCallbacks(callbacks); } + mWeakTrans = do_GetWeakReference(aSpdyConnectTransaction); + return NS_OK; } @@ -1075,7 +1106,7 @@ SpdyConnectTransaction::MapStreamToHttpConnection(nsISocketTransport *aTransport if (mForcePlainText) { mTunneledConn->ForcePlainText(); } else { - mTunneledConn->SetupSecondaryTLS(); + mTunneledConn->SetupSecondaryTLS(this); mTunneledConn->SetInSpdyTunnel(true); } diff --git a/netwerk/protocol/http/TunnelUtils.h b/netwerk/protocol/http/TunnelUtils.h index 20cfaf7ee..4a003082e 100644 --- a/netwerk/protocol/http/TunnelUtils.h +++ b/netwerk/protocol/http/TunnelUtils.h @@ -93,10 +93,11 @@ class TLSFilterTransaction; class NudgeTunnelCallback : public nsISupports { public: - virtual void OnTunnelNudged(TLSFilterTransaction *) = 0; + virtual nsresult OnTunnelNudged(TLSFilterTransaction *) = 0; }; -#define NS_DECL_NUDGETUNNELCALLBACK void OnTunnelNudged(TLSFilterTransaction *) override; +#define NS_DECL_NUDGETUNNELCALLBACK \ + nsresult OnTunnelNudged(TLSFilterTransaction *) override; class TLSFilterTransaction final : public nsAHttpTransaction @@ -121,7 +122,8 @@ public: nsresult CommitToSegmentSize(uint32_t size, bool forceCommitment) override; nsresult GetTransactionSecurityInfo(nsISupports **) override; nsresult NudgeTunnel(NudgeTunnelCallback *callback); - nsresult SetProxiedTransaction(nsAHttpTransaction *aTrans); + MOZ_MUST_USE nsresult SetProxiedTransaction(nsAHttpTransaction *aTrans, + nsAHttpTransaction *aSpdyConnectTransaction = nullptr); void newIODriver(nsIAsyncInputStream *aSocketIn, nsIAsyncOutputStream *aSocketOut, nsIAsyncInputStream **outSocketIn, @@ -153,6 +155,7 @@ private: private: RefPtr<nsAHttpTransaction> mTransaction; + nsWeakPtr mWeakTrans; // SpdyConnectTransaction * nsCOMPtr<nsISupports> mSecInfo; nsCOMPtr<nsITimer> mTimer; RefPtr<NudgeTunnelCallback> mNudgeCallback; @@ -168,7 +171,7 @@ private: nsresult mFilterReadCode; bool mForce; - bool mReadSegmentBlocked; + nsresult mReadSegmentReturnValue; uint32_t mNudgeCounter; }; diff --git a/netwerk/protocol/http/nsHttpConnection.cpp b/netwerk/protocol/http/nsHttpConnection.cpp index 8ccba76e2..505d849c0 100644 --- a/netwerk/protocol/http/nsHttpConnection.cpp +++ b/netwerk/protocol/http/nsHttpConnection.cpp @@ -535,16 +535,16 @@ npnComplete: return true; } -void +nsresult nsHttpConnection::OnTunnelNudged(TLSFilterTransaction *trans) { MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread); LOG(("nsHttpConnection::OnTunnelNudged %p\n", this)); if (trans != mTLSFilter) { - return; + return NS_OK; } LOG(("nsHttpConnection::OnTunnelNudged %p Calling OnSocketWritable\n", this)); - OnSocketWritable(); + return OnSocketWritable(); } // called on the socket thread @@ -639,7 +639,9 @@ nsHttpConnection::Activate(nsAHttpTransaction *trans, uint32_t caps, int32_t pri } if (mTLSFilter) { - mTLSFilter->SetProxiedTransaction(trans); + RefPtr<NullHttpTransaction> baseTrans(do_QueryReferent(mWeakTrans)); + rv = mTLSFilter->SetProxiedTransaction(trans, baseTrans); + NS_ENSURE_SUCCESS(rv, rv); mTransaction = mTLSFilter; } @@ -1979,7 +1981,7 @@ nsHttpConnection::OnSocketReadable() // negotiation are known (which is determined from the write path). // If the server speaks SPDY it is likely the readable data here is // a spdy settings frame and without NPN it would be misinterpreted - // as HTTP/* + // as HTTP LOG(("nsHttpConnection::OnSocketReadable %p return due to inactive " "tunnel setup but incomplete NPN state\n", this)); @@ -2019,12 +2021,14 @@ nsHttpConnection::OnSocketReadable() } void -nsHttpConnection::SetupSecondaryTLS() +nsHttpConnection::SetupSecondaryTLS(nsAHttpTransaction *aSpdyConnectTransaction) { MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread); MOZ_ASSERT(!mTLSFilter); - LOG(("nsHttpConnection %p SetupSecondaryTLS %s %d\n", - this, mConnInfo->Origin(), mConnInfo->OriginPort())); + LOG(("nsHttpConnection %p SetupSecondaryTLS %s %d " + "aSpdyConnectTransaction=%p\n", + this, mConnInfo->Origin(), mConnInfo->OriginPort(), + aSpdyConnectTransaction)); nsHttpConnectionInfo *ci = nullptr; if (mTransaction) { @@ -2041,6 +2045,7 @@ nsHttpConnection::SetupSecondaryTLS() if (mTransaction) { mTransaction = mTLSFilter; } + mWeakTrans = do_GetWeakReference(aSpdyConnectTransaction); } void diff --git a/netwerk/protocol/http/nsHttpConnection.h b/netwerk/protocol/http/nsHttpConnection.h index 08eea1de2..ce7523eb5 100644 --- a/netwerk/protocol/http/nsHttpConnection.h +++ b/netwerk/protocol/http/nsHttpConnection.h @@ -202,7 +202,7 @@ public: static nsresult MakeConnectString(nsAHttpTransaction *trans, nsHttpRequestHead *request, nsACString &result); - void SetupSecondaryTLS(); + void SetupSecondaryTLS(nsAHttpTransaction *aSpdyConnectTransaction = nullptr); void SetInSpdyTunnel(bool arg); // Check active connections for traffic (or not). SPDY connections send a @@ -281,6 +281,7 @@ private: // transaction is open, otherwise it is null. RefPtr<nsAHttpTransaction> mTransaction; RefPtr<TLSFilterTransaction> mTLSFilter; + nsWeakPtr mWeakTrans; // SpdyConnectTransaction * RefPtr<nsHttpHandler> mHttpHandler; // keep gHttpHandler alive |