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;