Sent PRIORITY_UPDATE frame when priority changes.
gfe-relnote: n/a, change to QUIC v99-only code. Protected by existing disabled gfe2_reloadable_flag_quic_enable_version_99.
PiperOrigin-RevId: 292458752
Change-Id: I210de2980d1e79d9654ea16fd20ab663200fb2ed
diff --git a/quic/core/http/quic_spdy_stream.h b/quic/core/http/quic_spdy_stream.h
index 437e0bf..c75a268 100644
--- a/quic/core/http/quic_spdy_stream.h
+++ b/quic/core/http/quic_spdy_stream.h
@@ -229,7 +229,7 @@
// Send PRIORITY_UPDATE frame and update |last_sent_urgency_| if
// |last_sent_urgency_| is different from current priority.
- void MaybeSendPriorityUpdateFrame();
+ void MaybeSendPriorityUpdateFrame() override;
protected:
// Called when the received headers are too large. By default this will
diff --git a/quic/core/http/quic_spdy_stream_test.cc b/quic/core/http/quic_spdy_stream_test.cc
index decba06..5d0a162 100644
--- a/quic/core/http/quic_spdy_stream_test.cc
+++ b/quic/core/http/quic_spdy_stream_test.cc
@@ -1372,6 +1372,54 @@
EXPECT_TRUE(stream_->fin_sent());
}
+TEST_P(QuicSpdyStreamTest, ChangePriority) {
+ if (!UsesHttp3()) {
+ return;
+ }
+
+ InitializeWithPerspective(kShouldProcessData, Perspective::IS_CLIENT);
+
+ // Two writes on the request stream: HEADERS frame header and payload.
+ EXPECT_CALL(*session_, WritevData(stream_, stream_->id(), _, _, _)).Times(2);
+ EXPECT_CALL(*stream_, WriteHeadersMock(false));
+ // PRIORITY_UPDATE frame on the control stream.
+ auto send_control_stream =
+ QuicSpdySessionPeer::GetSendControlStream(session_.get());
+ EXPECT_CALL(*session_, WritevData(send_control_stream,
+ send_control_stream->id(), _, _, _));
+ stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/false, nullptr);
+ testing::Mock::VerifyAndClearExpectations(session_.get());
+
+ // Another PRIORITY_UPDATE frame.
+ EXPECT_CALL(*session_, WritevData(send_control_stream,
+ send_control_stream->id(), _, _, _));
+ stream_->SetPriority(spdy::SpdyStreamPrecedence(kV3HighestPriority));
+}
+
+TEST_P(QuicSpdyStreamTest, ChangePriorityBeforeWritingHeaders) {
+ if (!UsesHttp3()) {
+ return;
+ }
+
+ InitializeWithPerspective(kShouldProcessData, Perspective::IS_CLIENT);
+
+ // PRIORITY_UPDATE frame sent on the control stream as soon as SetPriority()
+ // is called, before HEADERS frame is sent.
+ auto send_control_stream =
+ QuicSpdySessionPeer::GetSendControlStream(session_.get());
+ EXPECT_CALL(*session_, WritevData(send_control_stream,
+ send_control_stream->id(), _, _, _));
+
+ stream_->SetPriority(spdy::SpdyStreamPrecedence(kV3HighestPriority));
+ testing::Mock::VerifyAndClearExpectations(session_.get());
+
+ // Two writes on the request stream: HEADERS frame header and payload.
+ // PRIORITY_UPDATE frame is not sent this time, because one is already sent.
+ EXPECT_CALL(*session_, WritevData(stream_, stream_->id(), _, _, _)).Times(2);
+ EXPECT_CALL(*stream_, WriteHeadersMock(true));
+ stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/true, nullptr);
+}
+
// Test that when writing trailers, the trailers that are actually sent to the
// peer contain the final offset field indicating last byte of data.
TEST_P(QuicSpdyStreamTest, WritingTrailersFinalOffset) {
diff --git a/quic/core/quic_stream.cc b/quic/core/quic_stream.cc
index a440a13..bcdf0d9 100644
--- a/quic/core/quic_stream.cc
+++ b/quic/core/quic_stream.cc
@@ -562,6 +562,9 @@
void QuicStream::SetPriority(const spdy::SpdyStreamPrecedence& precedence) {
precedence_ = precedence;
+
+ MaybeSendPriorityUpdateFrame();
+
session_->UpdateStreamPriority(id(), precedence);
}
diff --git a/quic/core/quic_stream.h b/quic/core/quic_stream.h
index 42bdb5c..bd680f6 100644
--- a/quic/core/quic_stream.h
+++ b/quic/core/quic_stream.h
@@ -179,8 +179,14 @@
const spdy::SpdyStreamPrecedence& precedence() const;
- // Sets priority_ to priority. This should only be called before bytes are
- // written to the server.
+ // Send PRIORITY_UPDATE frame if application protocol supports it.
+ virtual void MaybeSendPriorityUpdateFrame() {}
+
+ // Sets |priority_| to priority. This should only be called before bytes are
+ // written to the server. For a server stream, this is called when a
+ // PRIORITY_UPDATE frame is received. This calls
+ // MaybeSendPriorityUpdateFrame(), which for a client stream might send a
+ // PRIORITY_UPDATE frame.
void SetPriority(const spdy::SpdyStreamPrecedence& precedence);
// Returns true if this stream is still waiting for acks of sent data.