Close the transaction if PR_Read/PR_Write failed.

When PR_Read/PR_White returns -1, we have to use ErrorAccordingToNSPR
to get the error code.
We need to close the transaction if a real error happens.
This commit is contained in:
wolfbeast 2019-03-22 18:41:22 +01:00 • committed by Roy Tam
commit ad188bf3c0
4 changed files with 51 additions and 15 deletions

View file

@ -23,6 +23,7 @@
#include "nsNetCID.h" #include "nsNetCID.h"
#include "nsServiceManagerUtils.h" #include "nsServiceManagerUtils.h"
#include "nsComponentManagerUtils.h" #include "nsComponentManagerUtils.h"
#include "nsSocketTransport2.h"
namespace mozilla { namespace mozilla {
namespace net { namespace net {
@ -130,6 +131,19 @@ TLSFilterTransaction::Close(nsresult aReason)
} }
mTransaction->Close(aReason); mTransaction->Close(aReason);
mTransaction = nullptr; 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 nsresult
@ -190,8 +204,15 @@ TLSFilterTransaction::OnReadSegment(const char *aData,
// mTransaction ReadSegments actually obscures this code, so // 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 insepct. Similar
// to nsHttpConnection::mSocketOutCondition // to nsHttpConnection::mSocketOutCondition
mReadSegmentBlocked = (PR_GetError() == PR_WOULD_BLOCK_ERROR); PRErrorCode code = PR_GetError();
return mReadSegmentBlocked ? NS_BASE_STREAM_WOULD_BLOCK : NS_ERROR_FAILURE; mReadSegmentBlocked = (code == PR_WOULD_BLOCK_ERROR);
if (mReadSegmentBlocked) {
return NS_BASE_STREAM_WOULD_BLOCK;
}
nsresult rv = ErrorAccordingToNSPR(code);
Close(rv);
return rv;
} }
aCount -= written; aCount -= written;
aData += written; aData += written;
@ -273,10 +294,13 @@ TLSFilterTransaction::OnWriteSegment(char *aData,
mFilterReadCode = NS_OK; mFilterReadCode = NS_OK;
int32_t bytesRead = PR_Read(mFD, aData, aCount); int32_t bytesRead = PR_Read(mFD, aData, aCount);
if (bytesRead == -1) { 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_BASE_STREAM_WOULD_BLOCK;
} }
return NS_ERROR_FAILURE; nsresult rv = ErrorAccordingToNSPR(code);
Close(rv);
return rv;
} }
*outCountRead = bytesRead; *outCountRead = bytesRead;
@ -675,10 +699,12 @@ TLSFilterTransaction::TakeSubTransactions(
} }
nsresult nsresult
TLSFilterTransaction::SetProxiedTransaction(nsAHttpTransaction *aTrans) TLSFilterTransaction::SetProxiedTransaction(nsAHttpTransaction *aTrans,
nsAHttpTransaction *aSpdyConnectTransaction)
{ {
LOG(("TLSFilterTransaction::SetProxiedTransaction [this=%p] aTrans=%p\n", LOG(("TLSFilterTransaction::SetProxiedTransaction [this=%p] aTrans=%p, "
this, aTrans)); "aSpdyConnectTransaction=%p\n",
this, aTrans, aSpdyConnectTransaction));
mTransaction = aTrans; mTransaction = aTrans;
nsCOMPtr<nsIInterfaceRequestor> callbacks; nsCOMPtr<nsIInterfaceRequestor> callbacks;
@ -688,6 +714,8 @@ TLSFilterTransaction::SetProxiedTransaction(nsAHttpTransaction *aTrans)
secCtrl->SetNotificationCallbacks(callbacks); secCtrl->SetNotificationCallbacks(callbacks);
} }
mWeakTrans = do_GetWeakReference(aSpdyConnectTransaction);
return NS_OK; return NS_OK;
} }
@ -1075,7 +1103,7 @@ SpdyConnectTransaction::MapStreamToHttpConnection(nsISocketTransport *aTransport
if (mForcePlainText) { if (mForcePlainText) {
mTunneledConn->ForcePlainText(); mTunneledConn->ForcePlainText();
} else { } else {
mTunneledConn->SetupSecondaryTLS(); mTunneledConn->SetupSecondaryTLS(this);
mTunneledConn->SetInSpdyTunnel(true); mTunneledConn->SetInSpdyTunnel(true);
} }

View file

@ -121,7 +121,8 @@ public:
nsresult CommitToSegmentSize(uint32_t size, bool forceCommitment) override; nsresult CommitToSegmentSize(uint32_t size, bool forceCommitment) override;
nsresult GetTransactionSecurityInfo(nsISupports **) override; nsresult GetTransactionSecurityInfo(nsISupports **) override;
nsresult NudgeTunnel(NudgeTunnelCallback *callback); nsresult NudgeTunnel(NudgeTunnelCallback *callback);
nsresult SetProxiedTransaction(nsAHttpTransaction *aTrans); MOZ_MUST_USE nsresult SetProxiedTransaction(nsAHttpTransaction *aTrans,
nsAHttpTransaction *aSpdyConnectTransaction = nullptr);
void newIODriver(nsIAsyncInputStream *aSocketIn, void newIODriver(nsIAsyncInputStream *aSocketIn,
nsIAsyncOutputStream *aSocketOut, nsIAsyncOutputStream *aSocketOut,
nsIAsyncInputStream **outSocketIn, nsIAsyncInputStream **outSocketIn,
@ -153,6 +154,7 @@ private:
private: private:
RefPtr<nsAHttpTransaction> mTransaction; RefPtr<nsAHttpTransaction> mTransaction;
nsWeakPtr mWeakTrans; // SpdyConnectTransaction *
nsCOMPtr<nsISupports> mSecInfo; nsCOMPtr<nsISupports> mSecInfo;
nsCOMPtr<nsITimer> mTimer; nsCOMPtr<nsITimer> mTimer;
RefPtr<NudgeTunnelCallback> mNudgeCallback; RefPtr<NudgeTunnelCallback> mNudgeCallback;

View file

@ -639,7 +639,9 @@ nsHttpConnection::Activate(nsAHttpTransaction *trans, uint32_t caps, int32_t pri
} }
if (mTLSFilter) { if (mTLSFilter) {
mTLSFilter->SetProxiedTransaction(trans); RefPtr<NullHttpTransaction> baseTrans(do_QueryReferent(mWeakTrans));
rv = mTLSFilter->SetProxiedTransaction(trans, baseTrans);
NS_ENSURE_SUCCESS(rv, rv);
mTransaction = mTLSFilter; mTransaction = mTLSFilter;
} }
@ -1979,7 +1981,7 @@ nsHttpConnection::OnSocketReadable()
// negotiation are known (which is determined from the write path). // negotiation are known (which is determined from the write path).
// If the server speaks SPDY it is likely the readable data here is // If the server speaks SPDY it is likely the readable data here is
// a spdy settings frame and without NPN it would be misinterpreted // a spdy settings frame and without NPN it would be misinterpreted
// as HTTP/* // as HTTP
LOG(("nsHttpConnection::OnSocketReadable %p return due to inactive " LOG(("nsHttpConnection::OnSocketReadable %p return due to inactive "
"tunnel setup but incomplete NPN state\n", this)); "tunnel setup but incomplete NPN state\n", this));
@ -2019,12 +2021,14 @@ nsHttpConnection::OnSocketReadable()
} }
void void
nsHttpConnection::SetupSecondaryTLS() nsHttpConnection::SetupSecondaryTLS(nsAHttpTransaction *aSpdyConnectTransaction)
{ {
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread); MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
MOZ_ASSERT(!mTLSFilter); MOZ_ASSERT(!mTLSFilter);
LOG(("nsHttpConnection %p SetupSecondaryTLS %s %d\n", LOG(("nsHttpConnection %p SetupSecondaryTLS %s %d "
this, mConnInfo->Origin(), mConnInfo->OriginPort())); "aSpdyConnectTransaction=%p\n",
this, mConnInfo->Origin(), mConnInfo->OriginPort(),
aSpdyConnectTransaction));
nsHttpConnectionInfo *ci = nullptr; nsHttpConnectionInfo *ci = nullptr;
if (mTransaction) { if (mTransaction) {
@ -2041,6 +2045,7 @@ nsHttpConnection::SetupSecondaryTLS()
if (mTransaction) { if (mTransaction) {
mTransaction = mTLSFilter; mTransaction = mTLSFilter;
} }
mWeakTrans = do_GetWeakReference(aSpdyConnectTransaction);
} }
void void

View file

@ -202,7 +202,7 @@ public:
static nsresult MakeConnectString(nsAHttpTransaction *trans, static nsresult MakeConnectString(nsAHttpTransaction *trans,
nsHttpRequestHead *request, nsHttpRequestHead *request,
nsACString &result); nsACString &result);
void SetupSecondaryTLS(); void SetupSecondaryTLS(nsAHttpTransaction *aSpdyConnectTransaction = nullptr);
void SetInSpdyTunnel(bool arg); void SetInSpdyTunnel(bool arg);
// Check active connections for traffic (or not). SPDY connections send a // Check active connections for traffic (or not). SPDY connections send a
@ -281,6 +281,7 @@ private:
// transaction is open, otherwise it is null. // transaction is open, otherwise it is null.
RefPtr<nsAHttpTransaction> mTransaction; RefPtr<nsAHttpTransaction> mTransaction;
RefPtr<TLSFilterTransaction> mTLSFilter; RefPtr<TLSFilterTransaction> mTLSFilter;
nsWeakPtr mWeakTrans; // SpdyConnectTransaction *
RefPtr<nsHttpHandler> mHttpHandler; // keep gHttpHandler alive RefPtr<nsHttpHandler> mHttpHandler; // keep gHttpHandler alive