Bug 1247205 - dont loop on http2 softerror r=dragana

This commit is contained in:
Patrick McManus 2016-02-13 20:54:24 -05:00
parent b16506b7f1
commit 54be97b2ea
6 changed files with 79 additions and 13 deletions

View File

@ -2259,8 +2259,8 @@ Http2Session::OnTransportStatus(nsITransport* aTransport,
// generated instead.
nsresult
Http2Session::ReadSegments(nsAHttpSegmentReader *reader,
uint32_t count, uint32_t *countRead)
Http2Session::ReadSegmentsAgain(nsAHttpSegmentReader *reader,
uint32_t count, uint32_t *countRead, bool *again)
{
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
@ -2332,6 +2332,8 @@ Http2Session::ReadSegments(nsAHttpSegmentReader *reader,
CleanupStream(stream, rv, CANCEL_ERROR);
if (SoftStreamError(rv)) {
LOG3(("Http2Session::ReadSegments %p soft error override\n", this));
*again = false;
SetWriteCallbacks();
rv = NS_OK;
}
return rv;
@ -2361,6 +2363,14 @@ Http2Session::ReadSegments(nsAHttpSegmentReader *reader,
return rv;
}
nsresult
Http2Session::ReadSegments(nsAHttpSegmentReader *reader,
uint32_t count, uint32_t *countRead)
{
bool again = false;
return ReadSegmentsAgain(reader, count, countRead, &again);
}
nsresult
Http2Session::ReadyToProcessDataFrame(enum internalStateType newState)
{
@ -2428,8 +2438,9 @@ Http2Session::ReadyToProcessDataFrame(enum internalStateType newState)
// data. It always gets full frames if they are part of the stream
nsresult
Http2Session::WriteSegments(nsAHttpSegmentWriter *writer,
uint32_t count, uint32_t *countWritten)
Http2Session::WriteSegmentsAgain(nsAHttpSegmentWriter *writer,
uint32_t count, uint32_t *countWritten,
bool *again)
{
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
@ -2700,6 +2711,8 @@ Http2Session::WriteSegments(nsAHttpSegmentWriter *writer,
MOZ_ASSERT(!mNeedsCleanup || mNeedsCleanup->StreamID() == streamID);
CleanupStream(streamID, NS_OK, CANCEL_ERROR);
mNeedsCleanup = nullptr;
*again = false;
ResumeRecv();
return NS_OK;
}
@ -2813,6 +2826,14 @@ Http2Session::WriteSegments(nsAHttpSegmentWriter *writer,
return rv;
}
nsresult
Http2Session::WriteSegments(nsAHttpSegmentWriter *writer,
uint32_t count, uint32_t *countWritten)
{
bool again = false;
return WriteSegmentsAgain(writer, count, countWritten, &again);
}
nsresult
Http2Session::ProcessConnectedPush(Http2Stream *pushConnectedStream,
nsAHttpSegmentWriter * writer,

View File

@ -232,6 +232,10 @@ public:
bool MaybeReTunnel(nsAHttpTransaction *) override;
bool UseH2Deps() { return mUseH2Deps; }
// overload of nsAHttpTransaction
nsresult ReadSegmentsAgain(nsAHttpSegmentReader *, uint32_t, uint32_t *, bool *) override final;
nsresult WriteSegmentsAgain(nsAHttpSegmentWriter *, uint32_t , uint32_t *, bool *) override final;
private:
// These internal states do not correspond to the states of the HTTP/2 specification

View File

@ -1756,9 +1756,10 @@ SpdySession31::OnTransportStatus(nsITransport* aTransport,
// generated instead.
nsresult
SpdySession31::ReadSegments(nsAHttpSegmentReader *reader,
uint32_t count,
uint32_t *countRead)
SpdySession31::ReadSegmentsAgain(nsAHttpSegmentReader *reader,
uint32_t count,
uint32_t *countRead,
bool *again)
{
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
@ -1826,6 +1827,8 @@ SpdySession31::ReadSegments(nsAHttpSegmentReader *reader,
CleanupStream(stream, rv, RST_CANCEL);
if (SoftStreamError(rv)) {
LOG3(("SpdySession31::ReadSegments %p soft error override\n", this));
*again = false;
SetWriteCallbacks();
rv = NS_OK;
}
return rv;
@ -1855,6 +1858,14 @@ SpdySession31::ReadSegments(nsAHttpSegmentReader *reader,
return rv;
}
nsresult
SpdySession31::ReadSegments(nsAHttpSegmentReader *reader,
uint32_t count, uint32_t *countRead)
{
bool again = false;
return ReadSegmentsAgain(reader, count, countRead, &again);
}
// WriteSegments() is used to read data off the socket. Generally this is
// just the SPDY frame header and from there the appropriate SPDYStream
// is identified from the Stream-ID. The http transaction associated with
@ -1869,9 +1880,10 @@ SpdySession31::ReadSegments(nsAHttpSegmentReader *reader,
// data. It always gets full frames if they are part of the stream
nsresult
SpdySession31::WriteSegments(nsAHttpSegmentWriter *writer,
uint32_t count,
uint32_t *countWritten)
SpdySession31::WriteSegmentsAgain(nsAHttpSegmentWriter *writer,
uint32_t count,
uint32_t *countWritten,
bool *again)
{
typedef nsresult (*Control_FX) (SpdySession31 *self);
static const Control_FX sControlFunctions[] =
@ -2132,6 +2144,8 @@ SpdySession31::WriteSegments(nsAHttpSegmentWriter *writer,
CleanupStream(stream, NS_OK, RST_CANCEL);
MOZ_ASSERT(!mNeedsCleanup || mNeedsCleanup == stream);
mNeedsCleanup = nullptr;
*again = false;
ResumeRecv();
return NS_OK;
}
@ -2234,6 +2248,14 @@ SpdySession31::WriteSegments(nsAHttpSegmentWriter *writer,
return rv;
}
nsresult
SpdySession31::WriteSegments(nsAHttpSegmentWriter *writer,
uint32_t count, uint32_t *countWritten)
{
bool again = false;
return WriteSegmentsAgain(writer, count, countWritten, &again);
}
void
SpdySession31::UpdateLocalStreamWindow(SpdyStream31 *stream,
uint32_t bytes)

View File

@ -198,6 +198,10 @@ public:
bool MaybeReTunnel(nsAHttpTransaction *) override;
// overload of nsAHttpTransaction
nsresult ReadSegmentsAgain(nsAHttpSegmentReader *, uint32_t, uint32_t *, bool *) override final;
nsresult WriteSegmentsAgain(nsAHttpSegmentWriter *, uint32_t , uint32_t *, bool *) override final;
private:
enum stateType {

View File

@ -76,6 +76,20 @@ public:
virtual nsresult WriteSegments(nsAHttpSegmentWriter *writer,
uint32_t count, uint32_t *countWritten) = 0;
// These versions of the functions allow the overloader to specify whether or
// not it is safe to call *Segments() in a loop while they return OK.
// The callee should turn again to false if it is not, otherwise leave untouched
virtual nsresult ReadSegmentsAgain(nsAHttpSegmentReader *reader,
uint32_t count, uint32_t *countRead, bool *again)
{
return ReadSegments(reader, count, countRead);
}
virtual nsresult WriteSegmentsAgain(nsAHttpSegmentWriter *writer,
uint32_t count, uint32_t *countWritten, bool *again)
{
return WriteSegments(writer, count, countWritten);
}
// called to close the transaction
virtual void Close(nsresult reason) = 0;

View File

@ -1595,8 +1595,8 @@ nsHttpConnection::OnSocketWritable()
LOG((" writing transaction request stream\n"));
mProxyConnectInProgress = false;
rv = mTransaction->ReadSegments(this, nsIOService::gDefaultSegmentSize,
&transactionBytes);
rv = mTransaction->ReadSegmentsAgain(this, nsIOService::gDefaultSegmentSize,
&transactionBytes, &again);
mContentBytesWritten += transactionBytes;
}
@ -1766,7 +1766,8 @@ nsHttpConnection::OnSocketReadable()
}
mSocketInCondition = NS_OK;
rv = mTransaction->WriteSegments(this, nsIOService::gDefaultSegmentSize, &n);
rv = mTransaction->
WriteSegmentsAgain(this, nsIOService::gDefaultSegmentSize, &n, &again);
LOG(("nsHttpConnection::OnSocketReadable %p trans->ws rv=%x n=%d socketin=%x\n",
this, rv, n, mSocketInCondition));
if (NS_FAILED(rv)) {