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.