Return proper error if the nss layer encounters an error on the http tunnel.

master
Fedor 2019-05-20 09:01:21 +03:00
parent 8c75e181ea
commit eecf3a3830
3 changed files with 30 additions and 26 deletions

View File

@ -43,6 +43,7 @@ TLSFilterTransaction::TLSFilterTransaction(nsAHttpTransaction *aWrapped,
, mSegmentReader(aReader) , mSegmentReader(aReader)
, mSegmentWriter(aWriter) , mSegmentWriter(aWriter)
, mForce(false) , mForce(false)
, mReadSegmentReturnValue(NS_OK)
, mNudgeCounter(0) , mNudgeCounter(0)
{ {
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread); MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
@ -154,7 +155,7 @@ TLSFilterTransaction::OnReadSegment(const char *aData,
LOG(("TLSFilterTransaction %p OnReadSegment %d (buffered %d)\n", LOG(("TLSFilterTransaction %p OnReadSegment %d (buffered %d)\n",
this, aCount, mEncryptedTextUsed)); this, aCount, mEncryptedTextUsed));
mReadSegmentBlocked = false; mReadSegmentReturnValue = NS_OK;
MOZ_ASSERT(mSegmentReader); MOZ_ASSERT(mSegmentReader);
if (!mSecInfo) { if (!mSecInfo) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
@ -202,17 +203,12 @@ TLSFilterTransaction::OnReadSegment(const char *aData,
return NS_OK; return NS_OK;
} }
// 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 inspect. Similar
// to nsHttpConnection::mSocketOutCondition // to nsHttpConnection::mSocketOutCondition
PRErrorCode code = PR_GetError(); PRErrorCode code = PR_GetError();
mReadSegmentBlocked = (code == PR_WOULD_BLOCK_ERROR); mReadSegmentReturnValue = ErrorAccordingToNSPR(code);
if (mReadSegmentBlocked) {
return NS_BASE_STREAM_WOULD_BLOCK;
}
nsresult rv = ErrorAccordingToNSPR(code); return mReadSegmentReturnValue;
Close(rv);
return rv;
} }
aCount -= written; aCount -= written;
aData += written; aData += written;
@ -298,9 +294,14 @@ TLSFilterTransaction::OnWriteSegment(char *aData,
if (code == PR_WOULD_BLOCK_ERROR) { if (code == PR_WOULD_BLOCK_ERROR) {
return NS_BASE_STREAM_WOULD_BLOCK; return NS_BASE_STREAM_WOULD_BLOCK;
} }
nsresult rv = ErrorAccordingToNSPR(code); // If reading from the socket succeeded (NS_SUCCEEDED(mFilterReadCode)),
Close(rv); // but the nss layer encountered an error remember the error.
return rv; 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; *outCountRead = bytesRead;
@ -327,7 +328,7 @@ TLSFilterTransaction::FilterInput(char *aBuf, int32_t aAmount)
if (NS_SUCCEEDED(mFilterReadCode) && outCountRead) { if (NS_SUCCEEDED(mFilterReadCode) && outCountRead) {
LOG(("TLSFilterTransaction::FilterInput rv=%x read=%d input from net " LOG(("TLSFilterTransaction::FilterInput rv=%x read=%d input from net "
"1 layer stripped, 1 still on\n", mFilterReadCode, outCountRead)); "1 layer stripped, 1 still on\n", mFilterReadCode, outCountRead));
if (mReadSegmentBlocked) { if (mReadSegmentReturnValue == NS_BASE_STREAM_WOULD_BLOCK) {
mNudgeCounter = 0; mNudgeCounter = 0;
} }
} }
@ -349,19 +350,18 @@ TLSFilterTransaction::ReadSegments(nsAHttpSegmentReader *aReader,
return NS_ERROR_UNEXPECTED; return NS_ERROR_UNEXPECTED;
} }
mReadSegmentBlocked = false; mReadSegmentReturnValue = NS_OK;
mSegmentReader = aReader; mSegmentReader = aReader;
nsresult rv = mTransaction->ReadSegments(this, aCount, outCountRead); nsresult rv = mTransaction->ReadSegments(this, aCount, outCountRead);
LOG(("TLSFilterTransaction %p called trans->ReadSegments rv=%x %d\n", LOG(("TLSFilterTransaction %p called trans->ReadSegments rv=%x %d\n",
this, rv, *outCountRead)); this, rv, *outCountRead));
if (NS_SUCCEEDED(rv) && mReadSegmentBlocked) { if (NS_SUCCEEDED(rv) && (mReadSegmentReturnValue == NS_BASE_STREAM_WOULD_BLOCK)) {
rv = NS_BASE_STREAM_WOULD_BLOCK;
LOG(("TLSFilterTransaction %p read segment blocked found rv=%x\n", LOG(("TLSFilterTransaction %p read segment blocked found rv=%x\n",
this, rv)); this, static_cast<uint32_t>(rv)));
Connection()->ForceSend(); Connection()->ForceSend();
} }
return rv; return NS_SUCCEEDED(rv) ? mReadSegmentReturnValue : rv;
} }
nsresult nsresult
@ -466,7 +466,10 @@ TLSFilterTransaction::Notify(nsITimer *timer)
if (timer != mTimer) { if (timer != mTimer) {
return NS_ERROR_UNEXPECTED; return NS_ERROR_UNEXPECTED;
} }
StartTimerCallback(); nsresult rv = StartTimerCallback();
if (NS_FAILED(rv)) {
Close(rv);
}
return NS_OK; return NS_OK;
} }
@ -480,7 +483,7 @@ TLSFilterTransaction::StartTimerCallback()
// This class can be called re-entrantly, so cleanup m* before ->on() // This class can be called re-entrantly, so cleanup m* before ->on()
RefPtr<NudgeTunnelCallback> cb(mNudgeCallback); RefPtr<NudgeTunnelCallback> cb(mNudgeCallback);
mNudgeCallback = nullptr; mNudgeCallback = nullptr;
cb->OnTunnelNudged(this); return cb->OnTunnelNudged(this);
} }
return NS_OK; return NS_OK;
} }

View File

@ -93,10 +93,11 @@ class TLSFilterTransaction;
class NudgeTunnelCallback : public nsISupports class NudgeTunnelCallback : public nsISupports
{ {
public: 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 class TLSFilterTransaction final
: public nsAHttpTransaction : public nsAHttpTransaction
@ -170,7 +171,7 @@ private:
nsresult mFilterReadCode; nsresult mFilterReadCode;
bool mForce; bool mForce;
bool mReadSegmentBlocked; nsresult mReadSegmentReturnValue;
uint32_t mNudgeCounter; uint32_t mNudgeCounter;
}; };

View File

@ -535,16 +535,16 @@ npnComplete:
return true; return true;
} }
void nsresult
nsHttpConnection::OnTunnelNudged(TLSFilterTransaction *trans) nsHttpConnection::OnTunnelNudged(TLSFilterTransaction *trans)
{ {
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread); MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
LOG(("nsHttpConnection::OnTunnelNudged %p\n", this)); LOG(("nsHttpConnection::OnTunnelNudged %p\n", this));
if (trans != mTLSFilter) { if (trans != mTLSFilter) {
return; return NS_OK;
} }
LOG(("nsHttpConnection::OnTunnelNudged %p Calling OnSocketWritable\n", this)); LOG(("nsHttpConnection::OnTunnelNudged %p Calling OnSocketWritable\n", this));
OnSocketWritable(); return OnSocketWritable();
} }
// called on the socket thread // called on the socket thread