From 59d7c13750002ad963edef8fa8c8470939b97ef7 Mon Sep 17 00:00:00 2001 From: Dragana Damjanovic Date: Wed, 4 Mar 2020 01:18:25 +0000 Subject: [PATCH] Bug 1619813 - If transaction has data to write but is blocked on http3's max_stream_data put them in an array to wait for a DataWritable event. r=agrover Differential Revision: https://phabricator.services.mozilla.com/D65246 --HG-- extra : moz-landing-system : lando --- netwerk/protocol/http/Http3Session.cpp | 28 +++++++++++++++++++------- netwerk/protocol/http/Http3Session.h | 1 + 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/netwerk/protocol/http/Http3Session.cpp b/netwerk/protocol/http/Http3Session.cpp index 7fe7dbc3b360..c707a02c9e02 100644 --- a/netwerk/protocol/http/Http3Session.cpp +++ b/netwerk/protocol/http/Http3Session.cpp @@ -240,10 +240,8 @@ nsresult Http3Session::ProcessEvents(uint32_t count, uint32_t* countWritten, } RefPtr stream = mStreamIdHash.Get(id); + MOZ_ASSERT(stream); if (!stream) { - // This is an old event. This may happen because we store events in - // neqo_glue. - // TODO: maybe change neqo interface to return only one event. LOG( ("Http3Session::ProcessEvents - stream not found " "stream_id=0x%" PRIx64 " [this=%p].", @@ -292,6 +290,18 @@ nsresult Http3Session::ProcessEvents(uint32_t count, uint32_t* countWritten, } break; } + case Http3Event::Tag::DataWritable: + MOZ_ASSERT(mState == CONNECTED); + LOG(("Http3Session::ProcessEvents - DataWritable")); + if (mReadyForWriteButBlocked.RemoveElement( + event.data_writable.stream_id)) { + RefPtr stream = + mStreamIdHash.Get(event.data_writable.stream_id); + if (stream) { + mReadyForWrite.Push(stream); + } + } + break; case Http3Event::Tag::Reset: LOG(("Http3Session::ProcessEvents - Reset")); ResetRecvd(event.reset.stream_id, event.reset.error); @@ -534,6 +544,7 @@ static void RemoveStreamFromQueue(Http3Stream* aStream, nsDeque& queue) { void Http3Session::RemoveStreamFromQueues(Http3Stream* aStream) { RemoveStreamFromQueue(aStream, mReadyForWrite); RemoveStreamFromQueue(aStream, mQueuedStreams); + mReadyForWriteButBlocked.RemoveElement(aStream->StreamId()); } // This is called by Http3Stream::OnReadSegment. @@ -725,9 +736,11 @@ nsresult Http3Session::ReadSegmentsAgain(nsAHttpSegmentReader* reader, LOG3(("Http3Session::ReadSegmentsAgain %p returns error code 0x%" PRIx32, this, static_cast(rv))); if (rv == NS_BASE_STREAM_WOULD_BLOCK) { - // TODO handle NS_BASE_STREAM_WOULD_BLOCK, i.e. handle block on - // max_stream_data - rv = NS_OK; + // The stream is blocked on max_stream_data. + MOZ_ASSERT(!mReadyForWriteButBlocked.Contains(stream->StreamId())); + if (!mReadyForWriteButBlocked.Contains(stream->StreamId())) { + mReadyForWriteButBlocked.AppendElement(stream->StreamId()); + } } else if (ASpdySession::SoftStreamError(rv)) { CloseStream(stream, rv); LOG3(("Http3Session::ReadSegments %p soft error override\n", this)); @@ -1066,7 +1079,8 @@ void Http3Session::TransactionHasDataToWrite(nsAHttpTransaction* caller) { LOG3(("Http3Session::TransactionHasDataToWrite %p ID is 0x%" PRIx64, this, stream->StreamId())); - if (!IsClosing()) { + MOZ_ASSERT(!mReadyForWriteButBlocked.Contains(stream->StreamId())); + if (!IsClosing() && !mReadyForWriteButBlocked.Contains(stream->StreamId())) { mReadyForWrite.Push(stream); Unused << mConnection->ResumeSend(); } else { diff --git a/netwerk/protocol/http/Http3Session.h b/netwerk/protocol/http/Http3Session.h index 819fab5c3fd1..4d867e8a75ca 100644 --- a/netwerk/protocol/http/Http3Session.h +++ b/netwerk/protocol/http/Http3Session.h @@ -143,6 +143,7 @@ class Http3Session final : public nsAHttpTransaction, mStreamTransactionHash; nsDeque mReadyForWrite; + nsTArray mReadyForWriteButBlocked; nsDeque mQueuedStreams; enum State { INITIALIZING, CONNECTED, CLOSING, CLOSED } mState;