Allow QuicSession::WritevData() to write data at a specified encryption level. gfe-relnote: protected by gfe2_reloadable_flag_quic_writevdata_at_level PiperOrigin-RevId: 297697074 Change-Id: Ib4e5d860f22f506f36db76f4f8ee1c1e406f6a20
diff --git a/common/platform/api/quiche_optional.h b/common/platform/api/quiche_optional.h index 7342714..141c0e4 100644 --- a/common/platform/api/quiche_optional.h +++ b/common/platform/api/quiche_optional.h
@@ -13,6 +13,7 @@ template <typename T> using QuicheOptional = QuicheOptionalImpl<T>; +#define QuicheNullOpt QuicheNullOptImpl } // namespace quiche
diff --git a/quic/core/http/quic_headers_stream_test.cc b/quic/core/http/quic_headers_stream_test.cc index 4337318..9459351 100644 --- a/quic/core/http/quic_headers_stream_test.cc +++ b/quic/core/http/quic_headers_stream_test.cc
@@ -288,7 +288,7 @@ // Write the headers and capture the outgoing data EXPECT_CALL(session_, WritevData(QuicUtils::GetHeadersStreamId( connection_->transport_version()), - _, _, NO_FIN, _)) + _, _, NO_FIN, _, _)) .WillOnce(WithArgs<1>(Invoke(this, &QuicHeadersStreamTest::SaveIov))); QuicSpdySessionPeer::WriteHeadersOnHeadersStream( &session_, stream_id, headers_.Clone(), fin, @@ -412,7 +412,7 @@ // Write the headers and capture the outgoing data EXPECT_CALL(session_, WritevData(QuicUtils::GetHeadersStreamId( connection_->transport_version()), - _, _, NO_FIN, _)) + _, _, NO_FIN, _, _)) .WillOnce(WithArgs<1>(Invoke(this, &QuicHeadersStreamTest::SaveIov))); session_.WritePushPromise(stream_id, promised_stream_id, headers_.Clone()); @@ -827,7 +827,7 @@ TEST_P(QuicHeadersStreamTest, AckSentData) { EXPECT_CALL(session_, WritevData(QuicUtils::GetHeadersStreamId( connection_->transport_version()), - _, _, NO_FIN, _)) + _, _, NO_FIN, _, _)) .WillRepeatedly(Invoke(&session_, &MockQuicSpdySession::ConsumeData)); InSequence s; QuicReferenceCountedPointer<MockAckListener> ack_listener1( @@ -896,7 +896,7 @@ // In this test, a stream frame can contain multiple headers. EXPECT_CALL(session_, WritevData(QuicUtils::GetHeadersStreamId( connection_->transport_version()), - _, _, NO_FIN, _)) + _, _, NO_FIN, _, _)) .WillRepeatedly(Invoke(&session_, &MockQuicSpdySession::ConsumeData)); InSequence s; QuicReferenceCountedPointer<MockAckListener> ack_listener1( @@ -946,7 +946,7 @@ TEST_P(QuicHeadersStreamTest, HeadersGetAckedMultipleTimes) { EXPECT_CALL(session_, WritevData(QuicUtils::GetHeadersStreamId( connection_->transport_version()), - _, _, NO_FIN, _)) + _, _, NO_FIN, _, _)) .WillRepeatedly(Invoke(&session_, &MockQuicSpdySession::ConsumeData)); InSequence s; QuicReferenceCountedPointer<MockAckListener> ack_listener1(
diff --git a/quic/core/http/quic_send_control_stream_test.cc b/quic/core/http/quic_send_control_stream_test.cc index 49c5dea..9e72f23 100644 --- a/quic/core/http/quic_send_control_stream_test.cc +++ b/quic/core/http/quic_send_control_stream_test.cc
@@ -73,7 +73,7 @@ perspective(), SupportedVersions(GetParam().version))), session_(connection_) { - ON_CALL(session_, WritevData(_, _, _, _, _)) + ON_CALL(session_, WritevData(_, _, _, _, _, _)) .WillByDefault(Invoke(&session_, &MockQuicSpdySession::ConsumeData)); } @@ -132,22 +132,22 @@ // A lambda to save and consume stream data when QuicSession::WritevData() is // called. - auto save_write_data = [&writer, this](QuicStreamId /*id*/, - size_t write_length, - QuicStreamOffset offset, - StreamSendingState /*state*/, - bool /*is_retransmission*/) { - send_control_stream_->WriteStreamData(offset, write_length, &writer); - return QuicConsumedData(/* bytes_consumed = */ write_length, - /* fin_consumed = */ false); - }; + auto save_write_data = + [&writer, this](QuicStreamId /*id*/, size_t write_length, + QuicStreamOffset offset, StreamSendingState /*state*/, + bool /*is_retransmission*/, + quiche::QuicheOptional<EncryptionLevel> /*level*/) { + send_control_stream_->WriteStreamData(offset, write_length, &writer); + return QuicConsumedData(/* bytes_consumed = */ write_length, + /* fin_consumed = */ false); + }; - EXPECT_CALL(session_, WritevData(send_control_stream_->id(), 1, _, _, _)) + EXPECT_CALL(session_, WritevData(send_control_stream_->id(), 1, _, _, _, _)) .WillOnce(Invoke(save_write_data)); EXPECT_CALL(session_, WritevData(send_control_stream_->id(), - expected_write_data.size() - 5, _, _, _)) + expected_write_data.size() - 5, _, _, _, _)) .WillOnce(Invoke(save_write_data)); - EXPECT_CALL(session_, WritevData(send_control_stream_->id(), 4, _, _, _)) + EXPECT_CALL(session_, WritevData(send_control_stream_->id(), 4, _, _, _, _)) .WillOnce(Invoke(save_write_data)); send_control_stream_->MaybeSendSettingsFrame(); @@ -159,8 +159,8 @@ Initialize(); testing::InSequence s; - EXPECT_CALL(session_, WritevData(send_control_stream_->id(), 1, _, _, _)); - EXPECT_CALL(session_, WritevData(send_control_stream_->id(), _, _, _, _)) + EXPECT_CALL(session_, WritevData(send_control_stream_->id(), 1, _, _, _, _)); + EXPECT_CALL(session_, WritevData(send_control_stream_->id(), _, _, _, _, _)) .Times(2); send_control_stream_->MaybeSendSettingsFrame(); @@ -176,12 +176,12 @@ // The first write will trigger the control stream to write stream type, a // SETTINGS frame, and a greased frame before the PRIORITY_UPDATE frame. - EXPECT_CALL(session_, WritevData(send_control_stream_->id(), _, _, _, _)) + EXPECT_CALL(session_, WritevData(send_control_stream_->id(), _, _, _, _, _)) .Times(4); PriorityUpdateFrame frame; send_control_stream_->WritePriorityUpdate(frame); - EXPECT_CALL(session_, WritevData(send_control_stream_->id(), _, _, _, _)); + EXPECT_CALL(session_, WritevData(send_control_stream_->id(), _, _, _, _, _)); send_control_stream_->WritePriorityUpdate(frame); }
diff --git a/quic/core/http/quic_spdy_client_session_test.cc b/quic/core/http/quic_spdy_client_session_test.cc index 01e9fd8..a8ddc09 100644 --- a/quic/core/http/quic_spdy_client_session_test.cc +++ b/quic/core/http/quic_spdy_client_session_test.cc
@@ -232,7 +232,7 @@ // Verify that no data may be send on existing streams. char data[] = "hello world"; QuicConsumedData consumed = session_->WritevData( - stream->id(), QUICHE_ARRAYSIZE(data), 0, NO_FIN, false); + stream->id(), QUICHE_ARRAYSIZE(data), 0, NO_FIN, false, QuicheNullOpt); EXPECT_FALSE(consumed.fin_consumed); EXPECT_EQ(0u, consumed.bytes_consumed); }
diff --git a/quic/core/http/quic_spdy_session_test.cc b/quic/core/http/quic_spdy_session_test.cc index bff8bbc..37b559c 100644 --- a/quic/core/http/quic_spdy_session_test.cc +++ b/quic/core/http/quic_spdy_session_test.cc
@@ -267,16 +267,18 @@ return QuicSpdySession::GetOrCreateStream(stream_id); } - QuicConsumedData WritevData(QuicStreamId id, - size_t write_length, - QuicStreamOffset offset, - StreamSendingState state, - bool is_retransmission) override { + QuicConsumedData WritevData( + QuicStreamId id, + size_t write_length, + QuicStreamOffset offset, + StreamSendingState state, + bool is_retransmission, + quiche::QuicheOptional<EncryptionLevel> level) override { bool fin = state != NO_FIN; QuicConsumedData consumed(write_length, fin); if (!writev_consumes_all_data_) { consumed = QuicSession::WritevData(id, write_length, offset, state, - is_retransmission); + is_retransmission, level); } QuicSessionPeer::GetWriteBlockedStreams(this)->UpdateBytesForStream( id, consumed.bytes_consumed); @@ -296,7 +298,8 @@ } MakeIOVector("not empty", &iov); QuicStreamPeer::SendBuffer(stream).SaveStreamData(&iov, 1, 0, 9); - QuicConsumedData consumed = WritevData(stream->id(), 9, 0, FIN, false); + QuicConsumedData consumed = + WritevData(stream->id(), 9, 0, FIN, false, QuicheNullOpt); QuicStreamPeer::SendBuffer(stream).OnStreamDataConsumed( consumed.bytes_consumed); return consumed; @@ -304,7 +307,7 @@ QuicConsumedData SendLargeFakeData(QuicStream* stream, int bytes) { DCHECK(writev_consumes_all_data_); - return WritevData(stream->id(), bytes, 0, FIN, false); + return WritevData(stream->id(), bytes, 0, FIN, false, QuicheNullOpt); } using QuicSession::closed_streams;
diff --git a/quic/core/http/quic_spdy_stream_test.cc b/quic/core/http/quic_spdy_stream_test.cc index c8f9d3a..5b70813 100644 --- a/quic/core/http/quic_spdy_stream_test.cc +++ b/quic/core/http/quic_spdy_stream_test.cc
@@ -202,7 +202,7 @@ &helper_, &alarm_factory_, perspective, SupportedVersions(GetParam())); session_ = std::make_unique<StrictMock<MockQuicSpdySession>>(connection_); session_->Initialize(); - ON_CALL(*session_, WritevData(_, _, _, _, _)) + ON_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillByDefault( Invoke(session_.get(), &MockQuicSpdySession::ConsumeData)); @@ -237,16 +237,17 @@ } auto send_control_stream = QuicSpdySessionPeer::GetSendControlStream(session_.get()); - EXPECT_CALL(*session_, WritevData(send_control_stream->id(), _, _, _, _)) + EXPECT_CALL(*session_, + WritevData(send_control_stream->id(), _, _, _, _, _)) .Times(num_control_stream_writes); auto qpack_decoder_stream = QuicSpdySessionPeer::GetQpackDecoderSendStream(session_.get()); EXPECT_CALL(*session_, - WritevData(qpack_decoder_stream->id(), 1, 0, _, _)); + WritevData(qpack_decoder_stream->id(), 1, 0, _, _, _)); auto qpack_encoder_stream = QuicSpdySessionPeer::GetQpackEncoderSendStream(session_.get()); EXPECT_CALL(*session_, - WritevData(qpack_encoder_stream->id(), 1, 0, _, _)); + WritevData(qpack_encoder_stream->id(), 1, 0, _, _, _)); } static_cast<QuicSession*>(session_.get()) ->SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT); @@ -769,9 +770,9 @@ const uint64_t kHeaderLength = UsesHttp3() ? 2 : 0; if (UsesHttp3()) { - EXPECT_CALL(*session_, WritevData(_, kHeaderLength, _, NO_FIN, _)); + EXPECT_CALL(*session_, WritevData(_, kHeaderLength, _, NO_FIN, _, _)); } - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillOnce(Return(QuicConsumedData(kWindow - kHeaderLength, true))); EXPECT_CALL(*connection_, SendControlFrame(_)); stream_->WriteOrBufferBody(body, false); @@ -1047,7 +1048,7 @@ EXPECT_CALL(*connection_, SendBlocked(GetNthClientInitiatedBidirectionalId(0))) .Times(0); - EXPECT_CALL(*session_, WritevData(_, 0, _, FIN, _)); + EXPECT_CALL(*session_, WritevData(_, 0, _, FIN, _, _)); stream_->WriteOrBufferBody(body, fin); } @@ -1290,7 +1291,7 @@ // In this case, TestStream::WriteHeadersImpl() does not prevent writes. // Four writes on the request stream: HEADERS frame header and payload both // for headers and trailers. - EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _)).Times(4); + EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _, _)).Times(4); } // Write the initial headers, without a FIN. @@ -1314,13 +1315,13 @@ // Four writes on the request stream: HEADERS frame header and payload both // for headers and trailers. - EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _)).Times(4); + EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _, _)).Times(4); // No PRIORITY_UPDATE frames on the control stream, // because the stream has default priority. auto send_control_stream = QuicSpdySessionPeer::GetSendControlStream(session_.get()); - EXPECT_CALL(*session_, WritevData(send_control_stream->id(), _, _, _, _)) + EXPECT_CALL(*session_, WritevData(send_control_stream->id(), _, _, _, _, _)) .Times(0); // Write the initial headers, without a FIN. @@ -1343,14 +1344,14 @@ InitializeWithPerspective(kShouldProcessData, Perspective::IS_CLIENT); // Two writes on the request stream: HEADERS frame header and payload. - EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _)).Times(2); + EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _, _)).Times(2); EXPECT_CALL(*stream_, WriteHeadersMock(false)); stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/false, nullptr); // PRIORITY_UPDATE frame on the control stream. auto send_control_stream = QuicSpdySessionPeer::GetSendControlStream(session_.get()); - EXPECT_CALL(*session_, WritevData(send_control_stream->id(), _, _, _, _)); + EXPECT_CALL(*session_, WritevData(send_control_stream->id(), _, _, _, _, _)); stream_->SetPriority(spdy::SpdyStreamPrecedence(kV3HighestPriority)); } @@ -1365,14 +1366,14 @@ // is called, before HEADERS frame is sent. auto send_control_stream = QuicSpdySessionPeer::GetSendControlStream(session_.get()); - EXPECT_CALL(*session_, WritevData(send_control_stream->id(), _, _, _, _)); + EXPECT_CALL(*session_, WritevData(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_->id(), _, _, _, _)).Times(2); + EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _, _)).Times(2); EXPECT_CALL(*stream_, WriteHeadersMock(true)); stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/true, nullptr); } @@ -1385,7 +1386,7 @@ if (UsesHttp3()) { // In this case, TestStream::WriteHeadersImpl() does not prevent writes. // HEADERS frame header and payload on the request stream. - EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _)).Times(2); + EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _, _)).Times(2); } // Write the initial headers. @@ -1393,7 +1394,7 @@ stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/false, nullptr); // Write non-zero body data to force a non-zero final offset. - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(AtLeast(1)); + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(AtLeast(1)); std::string body(1024, 'x'); // 1 kB QuicByteCount header_length = 0; if (UsesHttp3()) { @@ -1428,7 +1429,7 @@ // Expect data being written on the stream. In addition to that, headers are // also written on the stream in case of IETF QUIC. - EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _)) + EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _, _)) .Times(AtLeast(1)); // Write the initial headers. @@ -1467,9 +1468,9 @@ // Write non-zero body data, but only consume partially, ensuring queueing. const int kBodySize = 1 * 1024; // 1 kB if (UsesHttp3()) { - EXPECT_CALL(*session_, WritevData(_, 3, _, NO_FIN, _)); + EXPECT_CALL(*session_, WritevData(_, 3, _, NO_FIN, _, _)); } - EXPECT_CALL(*session_, WritevData(_, kBodySize, _, NO_FIN, _)) + EXPECT_CALL(*session_, WritevData(_, kBodySize, _, NO_FIN, _, _)) .WillOnce(Return(QuicConsumedData(kBodySize - 1, false))); stream_->WriteOrBufferBody(std::string(kBodySize, 'x'), false); EXPECT_EQ(1u, stream_->BufferedDataBytes()); @@ -1482,7 +1483,7 @@ EXPECT_FALSE(stream_->write_side_closed()); // Writing the queued bytes will close the write side of the stream. - EXPECT_CALL(*session_, WritevData(_, 1, _, NO_FIN, _)); + EXPECT_CALL(*session_, WritevData(_, 1, _, NO_FIN, _, _)); stream_->OnCanWrite(); EXPECT_TRUE(stream_->write_side_closed()); } @@ -1520,7 +1521,7 @@ const char kBody2[] = "Test2"; Initialize(kShouldProcessData); - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(AtLeast(1)); + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(AtLeast(1)); testing::InSequence s; QuicReferenceCountedPointer<MockAckListener> ack_listener1( new MockAckListener()); @@ -1566,7 +1567,7 @@ TEST_P(QuicSpdyStreamTest, StreamBecomesZombieWithWriteThatCloses) { Initialize(kShouldProcessData); - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(AtLeast(1)); + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(AtLeast(1)); QuicStreamPeer::CloseReadSide(stream_); // This write causes stream to be closed. stream_->WriteOrBufferBody("Test1", true); @@ -1588,9 +1589,9 @@ Initialize(kShouldProcessData); if (UsesHttp3()) { - EXPECT_CALL(*session_, WritevData(_, 2, _, NO_FIN, _)); + EXPECT_CALL(*session_, WritevData(_, 2, _, NO_FIN, _, _)); } - EXPECT_CALL(*session_, WritevData(_, 4, _, FIN, _)); + EXPECT_CALL(*session_, WritevData(_, 4, _, FIN, _, _)); stream_->WriteOrBufferBody("data", true); stream_->OnPriorityFrame(spdy::SpdyStreamPrecedence(kV3HighestPriority)); EXPECT_EQ(spdy::SpdyStreamPrecedence(kV3HighestPriority), @@ -1627,7 +1628,7 @@ QuicReferenceCountedPointer<MockAckListener> mock_ack_listener( new StrictMock<MockAckListener>); stream_->set_ack_listener(mock_ack_listener); - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(AtLeast(1)); + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(AtLeast(1)); // Stream is not waiting for acks initially. EXPECT_FALSE(stream_->IsWaitingForAcks()); EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size()); @@ -1681,7 +1682,7 @@ QuicReferenceCountedPointer<MockAckListener> mock_ack_listener( new StrictMock<MockAckListener>); stream_->set_ack_listener(mock_ack_listener); - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(AtLeast(1)); + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(AtLeast(1)); // Send [0, 27) and fin. stream_->WriteOrBufferData("FooAndBar", false, nullptr); stream_->WriteOrBufferData("FooAndBar", false, nullptr); @@ -1749,7 +1750,7 @@ std::string body = "Test1"; std::string body2(100, 'x'); - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(AtLeast(1)); + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(AtLeast(1)); stream_->WriteOrBufferBody(body, false); stream_->WriteOrBufferBody(body2, true); @@ -1802,7 +1803,7 @@ helper_.GetStreamSendBufferAllocator(), 1024); QuicMemSliceStorage storage2(&body2_iov, 1, helper_.GetStreamSendBufferAllocator(), 1024); - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(AtLeast(1)); + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(AtLeast(1)); stream_->WriteBodySlices(storage.ToSpan(), false); stream_->WriteBodySlices(storage2.ToSpan(), true); @@ -1832,7 +1833,7 @@ std::string body1 = "Test1"; std::string body2(100, 'x'); - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(AtLeast(1)); + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(AtLeast(1)); stream_->WriteOrBufferBody(body1, false); stream_->WriteOrBufferBody(body2, true); @@ -2022,7 +2023,7 @@ QuicSpdySessionPeer::GetQpackDecoderSendStream(session_.get()); // The stream byte will be written in the first byte. - EXPECT_CALL(*session_, WritevData(decoder_send_stream->id(), _, _, _, _)); + EXPECT_CALL(*session_, WritevData(decoder_send_stream->id(), _, _, _, _, _)); // Deliver dynamic table entry to decoder. session_->qpack_decoder()->OnInsertWithoutNameReference("foo", "bar"); @@ -2044,7 +2045,7 @@ headers.length(), data)); EXPECT_EQ(kDataFramePayload, stream_->data()); - EXPECT_CALL(*session_, WritevData(decoder_send_stream->id(), _, _, _, _)); + EXPECT_CALL(*session_, WritevData(decoder_send_stream->id(), _, _, _, _, _)); // Deliver second dynamic table entry to decoder. session_->qpack_decoder()->OnInsertWithoutNameReference("trailing", "foobar"); @@ -2085,7 +2086,7 @@ QuicSpdySessionPeer::GetQpackDecoderSendStream(session_.get()); // The stream byte will be written in the first byte. - EXPECT_CALL(*session_, WritevData(decoder_send_stream->id(), _, _, _, _)); + EXPECT_CALL(*session_, WritevData(decoder_send_stream->id(), _, _, _, _, _)); // Deliver dynamic table entry to decoder. session_->qpack_decoder()->OnInsertWithoutNameReference("foo", "bar"); EXPECT_TRUE(stream_->headers_decompressed()); @@ -2110,7 +2111,7 @@ // Decoding is blocked because dynamic table entry has not been received yet. EXPECT_FALSE(stream_->trailers_decompressed()); - EXPECT_CALL(*session_, WritevData(decoder_send_stream->id(), _, _, _, _)); + EXPECT_CALL(*session_, WritevData(decoder_send_stream->id(), _, _, _, _, _)); // Deliver second dynamic table entry to decoder. session_->qpack_decoder()->OnInsertWithoutNameReference("trailing", "foobar"); EXPECT_TRUE(stream_->trailers_decompressed()); @@ -2204,7 +2205,7 @@ QuicSpdySessionPeer::GetQpackDecoderSendStream(session_.get()); // The stream byte will be written in the first byte. - EXPECT_CALL(*session_, WritevData(decoder_send_stream->id(), _, _, _, _)); + EXPECT_CALL(*session_, WritevData(decoder_send_stream->id(), _, _, _, _, _)); // Deliver dynamic table entry to decoder. session_->qpack_decoder()->OnInsertWithoutNameReference("foo", "bar"); EXPECT_TRUE(stream_->headers_decompressed()); @@ -2633,7 +2634,7 @@ auto qpack_decoder_stream = QuicSpdySessionPeer::GetQpackDecoderSendStream(session_.get()); - EXPECT_CALL(*session_, WritevData(qpack_decoder_stream->id(), 1, 1, _, _)); + EXPECT_CALL(*session_, WritevData(qpack_decoder_stream->id(), 1, 1, _, _, _)); EXPECT_CALL(*session_, SendRstStream(stream_->id(), QUIC_STREAM_CANCELLED, 0)); @@ -2651,7 +2652,7 @@ auto qpack_decoder_stream = QuicSpdySessionPeer::GetQpackDecoderSendStream(session_.get()); - EXPECT_CALL(*session_, WritevData(qpack_decoder_stream->id(), 1, 1, _, _)); + EXPECT_CALL(*session_, WritevData(qpack_decoder_stream->id(), 1, 1, _, _, _)); stream_->OnStreamReset(QuicRstStreamFrame( kInvalidControlFrameId, stream_->id(), QUIC_STREAM_CANCELLED, 0));
diff --git a/quic/core/qpack/qpack_send_stream_test.cc b/quic/core/qpack/qpack_send_stream_test.cc index e3fcc15..d6a4df7 100644 --- a/quic/core/qpack/qpack_send_stream_test.cc +++ b/quic/core/qpack/qpack_send_stream_test.cc
@@ -76,7 +76,7 @@ qpack_send_stream_ = QuicSpdySessionPeer::GetQpackDecoderSendStream(&session_); - ON_CALL(session_, WritevData(_, _, _, _, _)) + ON_CALL(session_, WritevData(_, _, _, _, _, _)) .WillByDefault(Invoke(&session_, &MockQuicSpdySession::ConsumeData)); } @@ -96,13 +96,13 @@ TEST_P(QpackSendStreamTest, WriteStreamTypeOnlyFirstTime) { std::string data = "data"; - EXPECT_CALL(session_, WritevData(_, 1, _, _, _)); - EXPECT_CALL(session_, WritevData(_, data.length(), _, _, _)); + EXPECT_CALL(session_, WritevData(_, 1, _, _, _, _)); + EXPECT_CALL(session_, WritevData(_, data.length(), _, _, _, _)); qpack_send_stream_->WriteStreamData(quiche::QuicheStringPiece(data)); - EXPECT_CALL(session_, WritevData(_, data.length(), _, _, _)); + EXPECT_CALL(session_, WritevData(_, data.length(), _, _, _, _)); qpack_send_stream_->WriteStreamData(quiche::QuicheStringPiece(data)); - EXPECT_CALL(session_, WritevData(_, _, _, _, _)).Times(0); + EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)).Times(0); qpack_send_stream_->MaybeSendStreamType(); }
diff --git a/quic/core/quic_crypto_stream.cc b/quic/core/quic_crypto_stream.cc index bf0106c..86603a9 100644 --- a/quic/core/quic_crypto_stream.cc +++ b/quic/core/quic_crypto_stream.cc
@@ -10,10 +10,12 @@ #include "net/third_party/quiche/src/quic/core/crypto/crypto_utils.h" #include "net/third_party/quiche/src/quic/core/quic_connection.h" #include "net/third_party/quiche/src/quic/core/quic_session.h" +#include "net/third_party/quiche/src/quic/core/quic_types.h" #include "net/third_party/quiche/src/quic/core/quic_utils.h" #include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h" #include "net/third_party/quiche/src/quic/platform/api/quic_flags.h" #include "net/third_party/quiche/src/quic/platform/api/quic_logging.h" +#include "net/third_party/quiche/src/common/platform/api/quiche_optional.h" #include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h" namespace quic { @@ -36,7 +38,8 @@ substreams_{{{this, ENCRYPTION_INITIAL}, {this, ENCRYPTION_HANDSHAKE}, {this, ENCRYPTION_ZERO_RTT}, - {this, ENCRYPTION_FORWARD_SECURE}}} { + {this, ENCRYPTION_FORWARD_SECURE}}}, + writevdata_at_level_(GetQuicReloadableFlag(quic_writevdata_at_level)) { // The crypto stream is exempt from connection level flow control. DisableConnectionFlowControlForThisStream(); } @@ -282,25 +285,32 @@ pending.offset = retransmission.begin()->min(); pending.length = retransmission.begin()->max() - retransmission.begin()->min(); - EncryptionLevel current_encryption_level = - session()->connection()->encryption_level(); - // Set appropriate encryption level. - session()->connection()->SetDefaultEncryptionLevel( - retransmission_encryption_level); - QuicConsumedData consumed = - stream_delegate()->WritevData(id(), pending.length, pending.offset, - NO_FIN, /*is_retransmission*/ true); - QUIC_DVLOG(1) << ENDPOINT << "stream " << id() - << " tries to retransmit stream data [" << pending.offset - << ", " << pending.offset + pending.length - << ") with encryption level: " - << retransmission_encryption_level - << ", consumed: " << consumed; - OnStreamFrameRetransmitted(pending.offset, consumed.bytes_consumed, - consumed.fin_consumed); - // Restore encryption level. - session()->connection()->SetDefaultEncryptionLevel( - current_encryption_level); + QuicConsumedData consumed(0, false); + if (!writevdata_at_level_) { + EncryptionLevel current_encryption_level = + session()->connection()->encryption_level(); + // Set appropriate encryption level. + session()->connection()->SetDefaultEncryptionLevel( + retransmission_encryption_level); + consumed = stream_delegate()->WritevData( + id(), pending.length, pending.offset, NO_FIN, + /*is_retransmission*/ true, QuicheNullOpt); + QUIC_DVLOG(1) << ENDPOINT << "stream " << id() + << " tries to retransmit stream data [" << pending.offset + << ", " << pending.offset + pending.length + << ") with encryption level: " + << retransmission_encryption_level + << ", consumed: " << consumed; + OnStreamFrameRetransmitted(pending.offset, consumed.bytes_consumed, + consumed.fin_consumed); + // Restore encryption level. + session()->connection()->SetDefaultEncryptionLevel( + current_encryption_level); + } else { + QUIC_RELOADABLE_FLAG_COUNT_N(quic_writevdata_at_level, 1, 2); + consumed = RetransmitStreamDataAtLevel(pending.offset, pending.length, + retransmission_encryption_level); + } if (consumed.bytes_consumed < pending.length) { // The connection is write blocked. break; @@ -328,22 +338,29 @@ for (const auto& interval : retransmission) { QuicStreamOffset retransmission_offset = interval.min(); QuicByteCount retransmission_length = interval.max() - interval.min(); - // Set appropriate encryption level. - session()->connection()->SetDefaultEncryptionLevel(send_encryption_level); - QuicConsumedData consumed = stream_delegate()->WritevData( - id(), retransmission_length, retransmission_offset, NO_FIN, - /*is_retransmission*/ true); - QUIC_DVLOG(1) << ENDPOINT << "stream " << id() - << " is forced to retransmit stream data [" - << retransmission_offset << ", " - << retransmission_offset + retransmission_length - << "), with encryption level: " << send_encryption_level - << ", consumed: " << consumed; - OnStreamFrameRetransmitted(retransmission_offset, consumed.bytes_consumed, - consumed.fin_consumed); - // Restore encryption level. - session()->connection()->SetDefaultEncryptionLevel( - current_encryption_level); + QuicConsumedData consumed(0, false); + if (!writevdata_at_level_) { + // Set appropriate encryption level. + session()->connection()->SetDefaultEncryptionLevel(send_encryption_level); + consumed = stream_delegate()->WritevData( + id(), retransmission_length, retransmission_offset, NO_FIN, + /*is_retransmission*/ true, QuicheNullOpt); + QUIC_DVLOG(1) << ENDPOINT << "stream " << id() + << " is forced to retransmit stream data [" + << retransmission_offset << ", " + << retransmission_offset + retransmission_length + << "), with encryption level: " << send_encryption_level + << ", consumed: " << consumed; + OnStreamFrameRetransmitted(retransmission_offset, consumed.bytes_consumed, + consumed.fin_consumed); + // Restore encryption level. + session()->connection()->SetDefaultEncryptionLevel( + current_encryption_level); + } else { + QUIC_RELOADABLE_FLAG_COUNT_N(quic_writevdata_at_level, 2, 2); + consumed = RetransmitStreamDataAtLevel( + retransmission_offset, retransmission_length, send_encryption_level); + } if (consumed.bytes_consumed < retransmission_length) { // The connection is write blocked. return false; @@ -353,6 +370,26 @@ return true; } +QuicConsumedData QuicCryptoStream::RetransmitStreamDataAtLevel( + QuicStreamOffset retransmission_offset, + QuicByteCount retransmission_length, + EncryptionLevel encryption_level) { + DCHECK(writevdata_at_level_); + const auto consumed = stream_delegate()->WritevData( + id(), retransmission_length, retransmission_offset, NO_FIN, + /*is_retransmission*/ true, encryption_level); + QUIC_DVLOG(1) << ENDPOINT << "stream " << id() + << " is forced to retransmit stream data [" + << retransmission_offset << ", " + << retransmission_offset + retransmission_length + << "), with encryption level: " << encryption_level + << ", consumed: " << consumed; + OnStreamFrameRetransmitted(retransmission_offset, consumed.bytes_consumed, + consumed.fin_consumed); + + return consumed; +} + uint64_t QuicCryptoStream::crypto_bytes_read() const { if (!QuicVersionUsesCryptoFrames(session()->transport_version())) { return stream_bytes_read();
diff --git a/quic/core/quic_crypto_stream.h b/quic/core/quic_crypto_stream.h index ecd3201..d07a4e7 100644 --- a/quic/core/quic_crypto_stream.h +++ b/quic/core/quic_crypto_stream.h
@@ -14,6 +14,7 @@ #include "net/third_party/quiche/src/quic/core/quic_config.h" #include "net/third_party/quiche/src/quic/core/quic_packets.h" #include "net/third_party/quiche/src/quic/core/quic_stream.h" +#include "net/third_party/quiche/src/quic/core/quic_types.h" #include "net/third_party/quiche/src/quic/platform/api/quic_export.h" #include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h" @@ -120,6 +121,12 @@ QuicByteCount data_length, bool fin) override; + // Sends stream retransmission data at |encryption_level|. + QuicConsumedData RetransmitStreamDataAtLevel( + QuicStreamOffset retransmission_offset, + QuicByteCount retransmission_length, + EncryptionLevel encryption_level); + // Returns the number of bytes of handshake data that have been received from // the peer in either CRYPTO or STREAM frames. uint64_t crypto_bytes_read() const; @@ -186,6 +193,9 @@ // Keeps state for data sent/received in CRYPTO frames at each encryption // level. std::array<CryptoSubstream, NUM_ENCRYPTION_LEVELS> substreams_; + + // Latched value of gfe2_reloadable_flag_quic_writevdata_at_level. + const bool writevdata_at_level_; }; } // namespace quic
diff --git a/quic/core/quic_crypto_stream_test.cc b/quic/core/quic_crypto_stream_test.cc index 2006e47..e3ba21c 100644 --- a/quic/core/quic_crypto_stream_test.cc +++ b/quic/core/quic_crypto_stream_test.cc
@@ -158,7 +158,7 @@ EXPECT_CALL( session_, WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()), - 1350, 0, _, _)) + 1350, 0, _, _, _)) .WillOnce(Invoke(&session_, &MockQuicSpdySession::ConsumeData)); stream_->WriteOrBufferData(data, false, nullptr); // Send [1350, 2700) in ENCRYPTION_ZERO_RTT. @@ -167,7 +167,7 @@ EXPECT_CALL( session_, WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()), - 1350, 1350, _, _)) + 1350, 1350, _, _, _)) .WillOnce(Invoke(&session_, &MockQuicSpdySession::ConsumeData)); stream_->WriteOrBufferData(data, false, nullptr); connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE); @@ -181,19 +181,19 @@ EXPECT_CALL( session_, WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()), - 1000, 0, _, _)) + 1000, 0, _, _, _)) .WillOnce(Invoke(&session_, &MockQuicSpdySession::ConsumeData)); // Verify [1200, 2000) are sent in [1200, 1350) and [1350, 2000) because of // they are in different encryption levels. EXPECT_CALL( session_, WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()), - 150, 1200, _, _)) + 150, 1200, _, _, _)) .WillOnce(Invoke(&session_, &MockQuicSpdySession::ConsumeData)); EXPECT_CALL( session_, WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()), - 650, 1350, _, _)) + 650, 1350, _, _, _)) .WillOnce(Invoke(&session_, &MockQuicSpdySession::ConsumeData)); stream_->OnCanWrite(); EXPECT_FALSE(stream_->HasPendingRetransmission()); @@ -263,7 +263,7 @@ EXPECT_CALL( session_, WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()), - 1350, 0, _, _)) + 1350, 0, _, _, _)) .WillOnce(Invoke(&session_, &MockQuicSpdySession::ConsumeData)); stream_->WriteOrBufferData(data, false, nullptr); // Send [1350, 2700) in ENCRYPTION_ZERO_RTT. @@ -272,7 +272,7 @@ EXPECT_CALL( session_, WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()), - 1350, 1350, _, _)) + 1350, 1350, _, _, _)) .WillOnce(Invoke(&session_, &MockQuicSpdySession::ConsumeData)); stream_->WriteOrBufferData(data, false, nullptr); @@ -347,7 +347,7 @@ EXPECT_CALL( session_, WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()), - 1350, 0, _, _)) + 1350, 0, _, _, _)) .WillOnce(Invoke(&session_, &MockQuicSpdySession::ConsumeData)); stream_->WriteOrBufferData(data, false, nullptr); // Send [1350, 2700) in ENCRYPTION_ZERO_RTT. @@ -356,7 +356,7 @@ EXPECT_CALL( session_, WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()), - 1350, 1350, _, _)) + 1350, 1350, _, _, _)) .WillOnce(Invoke(&session_, &MockQuicSpdySession::ConsumeData)); stream_->WriteOrBufferData(data, false, nullptr); connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE); @@ -372,11 +372,11 @@ EXPECT_CALL( session_, WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()), - 650, 1350, _, _)) + 650, 1350, _, _, _)) .WillOnce(InvokeWithoutArgs([this]() { return session_.ConsumeData( QuicUtils::GetCryptoStreamId(connection_->transport_version()), 150, - 1350, NO_FIN, 1350); + 1350, NO_FIN, 1350, QuicheNullOpt); })); EXPECT_FALSE(stream_->RetransmitStreamData(1350, 1350, false)); @@ -387,18 +387,18 @@ EXPECT_CALL( session_, WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()), - 650, 1350, _, _)) + 650, 1350, _, _, _)) .WillOnce(Invoke(&session_, &MockQuicSpdySession::ConsumeData)); EXPECT_CALL( session_, WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()), - 200, 2500, _, _)) + 200, 2500, _, _, _)) .WillOnce(Invoke(&session_, &MockQuicSpdySession::ConsumeData)); EXPECT_TRUE(stream_->RetransmitStreamData(1350, 1350, false)); // Verify connection's encryption level has restored. EXPECT_EQ(ENCRYPTION_FORWARD_SECURE, connection_->encryption_level()); - EXPECT_CALL(session_, WritevData(_, _, _, _, _)).Times(0); + EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)).Times(0); // Force to send an empty frame. EXPECT_TRUE(stream_->RetransmitStreamData(0, 0, false)); } @@ -470,7 +470,7 @@ EXPECT_CALL( session_, WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()), - 1350, 0, _, _)) + 1350, 0, _, _, _)) .WillOnce(testing::Return(QuicConsumedData(0, false))); stream_->WriteOrBufferData(data, false, nullptr); EXPECT_FALSE(stream_->IsWaitingForAcks()); @@ -481,7 +481,7 @@ EXPECT_CALL( session_, WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()), - 1350, 0, _, _)) + 1350, 0, _, _, _)) .WillOnce(Invoke(&session_, &MockQuicSpdySession::ConsumeData)); stream_->OnCanWrite(); EXPECT_TRUE(stream_->IsWaitingForAcks());
diff --git a/quic/core/quic_session.cc b/quic/core/quic_session.cc index c7890d7..1cc1d90 100644 --- a/quic/core/quic_session.cc +++ b/quic/core/quic_session.cc
@@ -732,11 +732,13 @@ connection_->ProcessUdpPacket(self_address, peer_address, packet); } -QuicConsumedData QuicSession::WritevData(QuicStreamId id, - size_t write_length, - QuicStreamOffset offset, - StreamSendingState state, - bool is_retransmission) { +QuicConsumedData QuicSession::WritevData( + QuicStreamId id, + size_t write_length, + QuicStreamOffset offset, + StreamSendingState state, + bool is_retransmission, + quiche::QuicheOptional<EncryptionLevel> level) { DCHECK(connection_->connected()) << ENDPOINT << "Try to write stream data when connection is closed."; if (!IsEncryptionEstablished() && @@ -746,12 +748,23 @@ return QuicConsumedData(0, false); } + const auto current_level = connection()->encryption_level(); + if (level.has_value()) { + connection()->SetDefaultEncryptionLevel(level.value()); + } + QuicConsumedData data = connection_->SendStreamData(id, write_length, offset, state); if (!is_retransmission) { // This is new stream data. write_blocked_streams_.UpdateBytesForStream(id, data.bytes_consumed); } + + // Restore the encryption level. + if (level.has_value()) { + connection()->SetDefaultEncryptionLevel(current_level); + } + return data; }
diff --git a/quic/core/quic_session.h b/quic/core/quic_session.h index beb6763..4549878 100644 --- a/quic/core/quic_session.h +++ b/quic/core/quic_session.h
@@ -268,11 +268,13 @@ // indicating if the fin bit was consumed. This does not indicate the data // has been sent on the wire: it may have been turned into a packet and queued // if the socket was unexpectedly blocked. - QuicConsumedData WritevData(QuicStreamId id, - size_t write_length, - QuicStreamOffset offset, - StreamSendingState state, - bool is_retransmission) override; + QuicConsumedData WritevData( + QuicStreamId id, + size_t write_length, + QuicStreamOffset offset, + StreamSendingState state, + bool is_retransmission, + quiche::QuicheOptional<EncryptionLevel> level) override; // Called by the QuicCryptoStream when a handshake message is sent. virtual void OnCryptoHandshakeMessageSent(
diff --git a/quic/core/quic_session_test.cc b/quic/core/quic_session_test.cc index d9ecbae..93c3a9b 100644 --- a/quic/core/quic_session_test.cc +++ b/quic/core/quic_session_test.cc
@@ -36,6 +36,7 @@ #include "net/third_party/quiche/src/quic/test_tools/quic_stream_send_buffer_peer.h" #include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h" #include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h" +#include "net/third_party/quiche/src/common/platform/api/quiche_optional.h" #include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h" #include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h" @@ -261,16 +262,18 @@ return GetNumActiveStreams() > 0; } - QuicConsumedData WritevData(QuicStreamId id, - size_t write_length, - QuicStreamOffset offset, - StreamSendingState state, - bool is_retransmission) override { + QuicConsumedData WritevData( + QuicStreamId id, + size_t write_length, + QuicStreamOffset offset, + StreamSendingState state, + bool is_retransmission, + quiche::QuicheOptional<EncryptionLevel> level) override { bool fin = state != NO_FIN; QuicConsumedData consumed(write_length, fin); if (!writev_consumes_all_data_) { consumed = QuicSession::WritevData(id, write_length, offset, state, - is_retransmission); + is_retransmission, level); } QuicSessionPeer::GetWriteBlockedStreams(this)->UpdateBytesForStream( id, consumed.bytes_consumed); @@ -292,8 +295,8 @@ } MakeIOVector("not empty", &iov); QuicStreamPeer::SendBuffer(stream).SaveStreamData(&iov, 1, 0, 9); - QuicConsumedData consumed = - WritevData(stream->id(), 9, 0, FIN, /*is_retransmission*/ false); + QuicConsumedData consumed = WritevData( + stream->id(), 9, 0, FIN, /*is_retransmission*/ false, QuicheNullOpt); QuicStreamPeer::SendBuffer(stream).OnStreamDataConsumed( consumed.bytes_consumed); return consumed; @@ -310,7 +313,7 @@ QuicConsumedData SendLargeFakeData(QuicStream* stream, int bytes) { DCHECK(writev_consumes_all_data_); return WritevData(stream->id(), bytes, 0, FIN, - /*is_retransmission*/ false); + /*is_retransmission*/ false, QuicheNullOpt); } bool UsesPendingStreams() const override { return uses_pending_streams_; }
diff --git a/quic/core/quic_stream.cc b/quic/core/quic_stream.cc index ca33a0c..d952cc0 100644 --- a/quic/core/quic_stream.cc +++ b/quic/core/quic_stream.cc
@@ -15,6 +15,7 @@ #include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h" #include "net/third_party/quiche/src/quic/platform/api/quic_flags.h" #include "net/third_party/quiche/src/quic/platform/api/quic_logging.h" +#include "net/third_party/quiche/src/common/platform/api/quiche_optional.h" #include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h" #include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h" @@ -932,7 +933,8 @@ stream_bytes_written()); consumed = stream_delegate_->WritevData( id_, retransmission_length, retransmission_offset, - can_bundle_fin ? FIN : NO_FIN, /*is_retransmission*/ true); + can_bundle_fin ? FIN : NO_FIN, /*is_retransmission*/ true, + QuicheNullOpt); QUIC_DVLOG(1) << ENDPOINT << "stream " << id_ << " is forced to retransmit stream data [" << retransmission_offset << ", " @@ -953,8 +955,9 @@ if (retransmit_fin) { QUIC_DVLOG(1) << ENDPOINT << "stream " << id_ << " retransmits fin only frame."; - consumed = stream_delegate_->WritevData(id_, 0, stream_bytes_written(), FIN, - /*is_retransmission*/ true); + consumed = + stream_delegate_->WritevData(id_, 0, stream_bytes_written(), FIN, + /*is_retransmission*/ true, QuicheNullOpt); if (!consumed.fin_consumed) { return false; } @@ -1024,9 +1027,9 @@ if (fin && add_random_padding_after_fin_) { state = FIN_AND_PADDING; } - QuicConsumedData consumed_data = - stream_delegate_->WritevData(id(), write_length, stream_bytes_written(), - state, /*is_retransmission*/ false); + QuicConsumedData consumed_data = stream_delegate_->WritevData( + id(), write_length, stream_bytes_written(), state, + /*is_retransmission*/ false, QuicheNullOpt); OnStreamDataConsumed(consumed_data.bytes_consumed); @@ -1100,8 +1103,9 @@ if (!send_buffer_.HasPendingRetransmission()) { QUIC_DVLOG(1) << ENDPOINT << "stream " << id_ << " retransmits fin only frame."; - consumed = stream_delegate_->WritevData(id_, 0, stream_bytes_written(), - FIN, /*is_retransmission*/ true); + consumed = stream_delegate_->WritevData( + id_, 0, stream_bytes_written(), FIN, + /*is_retransmission*/ true, QuicheNullOpt); fin_lost_ = !consumed.fin_consumed; if (fin_lost_) { // Connection is write blocked. @@ -1116,7 +1120,7 @@ (pending.offset + pending.length == stream_bytes_written()); consumed = stream_delegate_->WritevData( id_, pending.length, pending.offset, can_bundle_fin ? FIN : NO_FIN, - /*is_retransmission*/ true); + /*is_retransmission*/ true, QuicheNullOpt); QUIC_DVLOG(1) << ENDPOINT << "stream " << id_ << " tries to retransmit stream data [" << pending.offset << ", " << pending.offset + pending.length
diff --git a/quic/core/quic_stream_test.cc b/quic/core/quic_stream_test.cc index c7e650b..4055b4c 100644 --- a/quic/core/quic_stream_test.cc +++ b/quic/core/quic_stream_test.cc
@@ -31,6 +31,7 @@ #include "net/third_party/quiche/src/quic/test_tools/quic_stream_sequencer_peer.h" #include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h" #include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h" +#include "net/third_party/quiche/src/common/platform/api/quiche_optional.h" #include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h" using testing::_; @@ -122,11 +123,13 @@ write_blocked_list_->HasWriteBlockedDataStreams(); } - QuicConsumedData CloseStreamOnWriteError(QuicStreamId id, - size_t /*write_length*/, - QuicStreamOffset /*offset*/, - StreamSendingState /*state*/, - QuicByteCount /*bytes_written*/) { + QuicConsumedData CloseStreamOnWriteError( + QuicStreamId id, + size_t /*write_length*/, + QuicStreamOffset /*offset*/, + StreamSendingState /*state*/, + QuicByteCount /*bytes_written*/, + quiche::QuicheOptional<EncryptionLevel> /*level*/) { session_->CloseStream(id); return QuicConsumedData(1, false); } @@ -277,7 +280,7 @@ VARIABLE_LENGTH_INTEGER_LENGTH_0, 0u); connection_->SetMaxPacketLength(length); - EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _)) .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData)); stream_->WriteOrBufferData(kData1, false, nullptr); EXPECT_FALSE(HasWriteBlockedStreams()); @@ -299,9 +302,10 @@ // Write some data and no fin. If we consume some but not all of the data, // we should be write blocked a not all the data was consumed. - EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _)) .WillOnce(InvokeWithoutArgs([this]() { - return session_->ConsumeData(stream_->id(), 1u, 0u, NO_FIN, false); + return session_->ConsumeData(stream_->id(), 1u, 0u, NO_FIN, false, + QuicheNullOpt); })); stream_->WriteOrBufferData(quiche::QuicheStringPiece(kData1, 2), false, nullptr); @@ -317,9 +321,10 @@ // we should be write blocked because the fin was not consumed. // (This should never actually happen as the fin should be sent out with the // last data) - EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _)) .WillOnce(InvokeWithoutArgs([this]() { - return session_->ConsumeData(stream_->id(), 2u, 0u, NO_FIN, false); + return session_->ConsumeData(stream_->id(), 2u, 0u, NO_FIN, false, + QuicheNullOpt); })); stream_->WriteOrBufferData(quiche::QuicheStringPiece(kData1, 2), true, nullptr); @@ -332,7 +337,7 @@ // Write no data and a fin. If we consume nothing we should be write blocked, // as the fin was not consumed. - EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _)) .WillOnce(Return(QuicConsumedData(0, false))); stream_->WriteOrBufferData(quiche::QuicheStringPiece(), true, nullptr); ASSERT_EQ(1u, write_blocked_list_->NumBlockedStreams()); @@ -344,7 +349,7 @@ // Write some data and no fin. However, while writing the data // close the stream and verify that MarkConnectionLevelWriteBlocked does not // crash with an unknown stream. - EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _)) .WillOnce(Invoke(this, &QuicStreamTest::CloseStreamOnWriteError)); stream_->WriteOrBufferData(quiche::QuicheStringPiece(kData1, 2), false, nullptr); @@ -364,10 +369,10 @@ VARIABLE_LENGTH_INTEGER_LENGTH_0, 0u); connection_->SetMaxPacketLength(length); - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillOnce(InvokeWithoutArgs([this]() { return session_->ConsumeData(stream_->id(), kDataLen - 1, 0u, NO_FIN, - false); + false, QuicheNullOpt); })); stream_->WriteOrBufferData(kData1, false, nullptr); @@ -380,20 +385,20 @@ EXPECT_EQ(10u, stream_->BufferedDataBytes()); // Make sure we get the tail of the first write followed by the bytes_consumed InSequence s; - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillOnce(InvokeWithoutArgs([this]() { return session_->ConsumeData(stream_->id(), kDataLen - 1, kDataLen - 1, - NO_FIN, false); + NO_FIN, false, QuicheNullOpt); })); EXPECT_CALL(*stream_, OnCanWriteNewData()); stream_->OnCanWrite(); EXPECT_TRUE(session_->HasUnackedStreamData()); // And finally the end of the bytes_consumed. - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillOnce(InvokeWithoutArgs([this]() { return session_->ConsumeData(stream_->id(), 2u, 2 * kDataLen - 2, - NO_FIN, false); + NO_FIN, false, QuicheNullOpt); })); EXPECT_CALL(*stream_, OnCanWriteNewData()); stream_->OnCanWrite(); @@ -405,7 +410,7 @@ std::string data("aaaaa"); QuicStreamPeer::SetStreamBytesWritten(kMaxStreamLength - data.length(), stream_); - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData)); stream_->WriteOrBufferData(data, false, nullptr); EXPECT_TRUE(session_->HasUnackedStreamData()); @@ -437,9 +442,10 @@ EXPECT_FALSE(rst_sent()); // Write some data, with no FIN. - EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _)) .WillOnce(InvokeWithoutArgs([this]() { - return session_->ConsumeData(stream_->id(), 1u, 0u, NO_FIN, false); + return session_->ConsumeData(stream_->id(), 1u, 0u, NO_FIN, false, + QuicheNullOpt); })); stream_->WriteOrBufferData(quiche::QuicheStringPiece(kData1, 1), false, nullptr); @@ -465,9 +471,10 @@ EXPECT_FALSE(rst_sent()); // Write some data, with FIN. - EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _)) .WillOnce(InvokeWithoutArgs([this]() { - return session_->ConsumeData(stream_->id(), 1u, 0u, FIN, false); + return session_->ConsumeData(stream_->id(), 1u, 0u, FIN, false, + QuicheNullOpt); })); stream_->WriteOrBufferData(quiche::QuicheStringPiece(kData1, 1), true, nullptr); @@ -730,9 +737,10 @@ EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams()); // Outgoing data with FIN. - EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _)) .WillOnce(InvokeWithoutArgs([this]() { - return session_->ConsumeData(stream_->id(), 2u, 0u, FIN, false); + return session_->ConsumeData(stream_->id(), 2u, 0u, FIN, false, + QuicheNullOpt); })); stream_->WriteOrBufferData(quiche::QuicheStringPiece(kData1, 2), true, nullptr); @@ -748,9 +756,10 @@ Initialize(); // Outgoing data with FIN. - EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _)) .WillOnce(InvokeWithoutArgs([this]() { - return session_->ConsumeData(stream_->id(), 2u, 0u, FIN, false); + return session_->ConsumeData(stream_->id(), 2u, 0u, FIN, false, + QuicheNullOpt); })); stream_->WriteOrBufferData(quiche::QuicheStringPiece(kData1, 2), true, nullptr); @@ -777,7 +786,7 @@ Initialize(); EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0); - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillRepeatedly(Invoke(session_.get(), &MockQuicSession::ConsumeData)); // Receive data for the request. @@ -799,7 +808,7 @@ TEST_P(QuicStreamTest, StreamWaitsForAcks) { Initialize(); - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillRepeatedly(Invoke(session_.get(), &MockQuicSession::ConsumeData)); // Stream is not waiting for acks initially. EXPECT_FALSE(stream_->IsWaitingForAcks()); @@ -856,7 +865,7 @@ TEST_P(QuicStreamTest, StreamDataGetAckedOutOfOrder) { Initialize(); - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillRepeatedly(Invoke(session_.get(), &MockQuicSession::ConsumeData)); // Send data. stream_->WriteOrBufferData(kData1, false, nullptr); @@ -898,7 +907,7 @@ TEST_P(QuicStreamTest, CancelStream) { Initialize(); - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillRepeatedly(Invoke(session_.get(), &MockQuicSession::ConsumeData)); EXPECT_FALSE(stream_->IsWaitingForAcks()); EXPECT_FALSE(session_->HasUnackedStreamData()); @@ -940,7 +949,7 @@ } Initialize(); - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillRepeatedly(Invoke(session_.get(), &MockQuicSession::ConsumeData)); EXPECT_FALSE(stream_->IsWaitingForAcks()); EXPECT_FALSE(session_->HasUnackedStreamData()); @@ -966,7 +975,7 @@ TEST_P(QuicStreamTest, RstFrameReceivedStreamFinishSending) { Initialize(); - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillRepeatedly(Invoke(session_.get(), &MockQuicSession::ConsumeData)); EXPECT_FALSE(stream_->IsWaitingForAcks()); EXPECT_FALSE(session_->HasUnackedStreamData()); @@ -989,7 +998,7 @@ TEST_P(QuicStreamTest, ConnectionClosed) { Initialize(); - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillRepeatedly(Invoke(session_.get(), &MockQuicSession::ConsumeData)); EXPECT_FALSE(stream_->IsWaitingForAcks()); EXPECT_FALSE(session_->HasUnackedStreamData()); @@ -1024,9 +1033,10 @@ EXPECT_TRUE(stream_->CanWriteNewData()); // Testing WriteOrBufferData. - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillOnce(InvokeWithoutArgs([this]() { - return session_->ConsumeData(stream_->id(), 100u, 0u, NO_FIN, false); + return session_->ConsumeData(stream_->id(), 100u, 0u, NO_FIN, false, + QuicheNullOpt); })); stream_->WriteOrBufferData(data, false, nullptr); stream_->WriteOrBufferData(data, false, nullptr); @@ -1036,9 +1046,10 @@ // Verify all data is saved. EXPECT_EQ(3 * data.length() - 100, stream_->BufferedDataBytes()); - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillOnce(InvokeWithoutArgs([this]() { - return session_->ConsumeData(stream_->id(), 100, 100u, NO_FIN, false); + return session_->ConsumeData(stream_->id(), 100, 100u, NO_FIN, false, + QuicheNullOpt); })); // Buffered data size > threshold, do not ask upper layer for more data. EXPECT_CALL(*stream_, OnCanWriteNewData()).Times(0); @@ -1049,10 +1060,10 @@ // Send buffered data to make buffered data size < threshold. size_t data_to_write = 3 * data.length() - 200 - GetQuicFlag(FLAGS_quic_buffered_data_threshold) + 1; - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillOnce(InvokeWithoutArgs([this, data_to_write]() { return session_->ConsumeData(stream_->id(), data_to_write, 200u, NO_FIN, - false); + false, QuicheNullOpt); })); // Buffered data size < threshold, ask upper layer for more data. EXPECT_CALL(*stream_, OnCanWriteNewData()).Times(1); @@ -1063,7 +1074,7 @@ EXPECT_TRUE(stream_->CanWriteNewData()); // Flush all buffered data. - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData)); EXPECT_CALL(*stream_, OnCanWriteNewData()).Times(1); stream_->OnCanWrite(); @@ -1072,7 +1083,7 @@ EXPECT_TRUE(stream_->CanWriteNewData()); // Testing Writev. - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillOnce(Return(QuicConsumedData(0, false))); struct iovec iov = {const_cast<char*>(data.data()), data.length()}; QuicMemSliceStorage storage( @@ -1087,7 +1098,7 @@ EXPECT_EQ(data.length(), stream_->BufferedDataBytes()); EXPECT_FALSE(stream_->CanWriteNewData()); - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(0); + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(0); QuicMemSliceStorage storage2( &iov, 1, session_->connection()->helper()->GetStreamSendBufferAllocator(), 1024); @@ -1099,10 +1110,10 @@ data_to_write = data.length() - GetQuicFlag(FLAGS_quic_buffered_data_threshold) + 1; - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillOnce(InvokeWithoutArgs([this, data_to_write]() { return session_->ConsumeData(stream_->id(), data_to_write, 0u, NO_FIN, - false); + false, QuicheNullOpt); })); EXPECT_CALL(*stream_, OnCanWriteNewData()).Times(1); @@ -1112,7 +1123,7 @@ stream_->BufferedDataBytes()); EXPECT_TRUE(stream_->CanWriteNewData()); - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(0); + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(0); // All data can be consumed as buffered data is below upper limit. QuicMemSliceStorage storage3( &iov, 1, session_->connection()->helper()->GetStreamSendBufferAllocator(), @@ -1130,7 +1141,7 @@ std::string data("aaaaa"); QuicStreamPeer::SetStreamBytesWritten(kMaxStreamLength - data.length(), stream_); - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData)); struct iovec iov = {const_cast<char*>(data.data()), 5u}; QuicMemSliceStorage storage( @@ -1161,9 +1172,10 @@ QuicMemSliceSpan span1 = vector1.span(); QuicMemSliceSpan span2 = vector2.span(); - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillOnce(InvokeWithoutArgs([this]() { - return session_->ConsumeData(stream_->id(), 100u, 0u, NO_FIN, false); + return session_->ConsumeData(stream_->id(), 100u, 0u, NO_FIN, false, + QuicheNullOpt); })); // There is no buffered data before, all data should be consumed. QuicConsumedData consumed = stream_->WriteMemSlices(span1, false); @@ -1172,7 +1184,7 @@ EXPECT_EQ(2 * QUICHE_ARRAYSIZE(data) - 100, stream_->BufferedDataBytes()); EXPECT_FALSE(stream_->fin_buffered()); - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(0); + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(0); // No Data can be consumed as buffered data is beyond upper limit. consumed = stream_->WriteMemSlices(span2, true); EXPECT_EQ(0u, consumed.bytes_consumed); @@ -1182,10 +1194,10 @@ size_t data_to_write = 2 * QUICHE_ARRAYSIZE(data) - 100 - GetQuicFlag(FLAGS_quic_buffered_data_threshold) + 1; - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillOnce(InvokeWithoutArgs([this, data_to_write]() { return session_->ConsumeData(stream_->id(), data_to_write, 100u, NO_FIN, - false); + false, QuicheNullOpt); })); EXPECT_CALL(*stream_, OnCanWriteNewData()).Times(1); stream_->OnCanWrite(); @@ -1193,7 +1205,7 @@ GetQuicFlag(FLAGS_quic_buffered_data_threshold) - 1), stream_->BufferedDataBytes()); // Try to write slices2 again. - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(0); + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(0); consumed = stream_->WriteMemSlices(span2, true); EXPECT_EQ(2048u, consumed.bytes_consumed); EXPECT_TRUE(consumed.fin_consumed); @@ -1203,7 +1215,7 @@ EXPECT_TRUE(stream_->fin_buffered()); // Flush all buffered data. - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData)); stream_->OnCanWrite(); EXPECT_CALL(*stream_, OnCanWriteNewData()).Times(0); @@ -1219,9 +1231,10 @@ buffers.push_back(std::make_pair(data, QUICHE_ARRAYSIZE(data))); QuicTestMemSliceVector vector1(buffers); QuicMemSliceSpan span1 = vector1.span(); - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillOnce(InvokeWithoutArgs([this]() { - return session_->ConsumeData(stream_->id(), 5u, 0u, NO_FIN, false); + return session_->ConsumeData(stream_->id(), 5u, 0u, NO_FIN, false, + QuicheNullOpt); })); // There is no buffered data before, all data should be consumed. QuicConsumedData consumed = stream_->WriteMemSlices(span1, false); @@ -1238,7 +1251,7 @@ TEST_P(QuicStreamTest, StreamDataGetAckedMultipleTimes) { Initialize(); - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillRepeatedly(Invoke(session_.get(), &MockQuicSession::ConsumeData)); EXPECT_FALSE(stream_->IsWaitingForAcks()); EXPECT_FALSE(session_->HasUnackedStreamData()); @@ -1305,14 +1318,14 @@ Initialize(); // Send [0, 9). - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData)); stream_->WriteOrBufferData(kData1, false, nullptr); EXPECT_FALSE(stream_->HasBufferedData()); EXPECT_TRUE(stream_->IsStreamFrameOutstanding(0, 9, false)); // Try to send [9, 27), but connection is blocked. - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillOnce(Return(QuicConsumedData(0, false))); stream_->WriteOrBufferData(kData2, false, nullptr); stream_->WriteOrBufferData(kData2, false, nullptr); @@ -1323,7 +1336,7 @@ // transmitted. stream_->OnStreamFrameLost(0, 9, false); EXPECT_TRUE(stream_->HasPendingRetransmission()); - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData)); EXPECT_CALL(*stream_, OnCanWriteNewData()).Times(1); stream_->OnCanWrite(); @@ -1331,13 +1344,13 @@ EXPECT_TRUE(stream_->HasBufferedData()); // This OnCanWrite causes [9, 27) to be sent. - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData)); stream_->OnCanWrite(); EXPECT_FALSE(stream_->HasBufferedData()); // Send a fin only frame. - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData)); stream_->WriteOrBufferData("", true, nullptr); @@ -1356,9 +1369,10 @@ EXPECT_TRUE(stream_->HasPendingRetransmission()); // This OnCanWrite causes [18, 27) and fin to be retransmitted. Verify fin can // be bundled with data. - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillOnce(InvokeWithoutArgs([this]() { - return session_->ConsumeData(stream_->id(), 9u, 18u, FIN, false); + return session_->ConsumeData(stream_->id(), 9u, 18u, FIN, false, + QuicheNullOpt); })); stream_->OnCanWrite(); EXPECT_FALSE(stream_->HasPendingRetransmission()); @@ -1373,7 +1387,7 @@ Initialize(); // Send [0, 18) and fin. - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillRepeatedly(Invoke(session_.get(), &MockQuicSession::ConsumeData)); stream_->WriteOrBufferData(kData1, false, nullptr); stream_->WriteOrBufferData(kData2, true, nullptr); @@ -1385,11 +1399,12 @@ // Retransmit lost data. Verify [0, 9) and fin are retransmitted in two // frames. InSequence s; - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillOnce(InvokeWithoutArgs([this]() { - return session_->ConsumeData(stream_->id(), 9u, 0u, NO_FIN, false); + return session_->ConsumeData(stream_->id(), 9u, 0u, NO_FIN, false, + QuicheNullOpt); })); - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillOnce(Return(QuicConsumedData(0, true))); stream_->OnCanWrite(); } @@ -1408,7 +1423,7 @@ session_.get(), BIDIRECTIONAL); session_->ActivateStream(QuicWrapUnique(stream)); - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillRepeatedly(Invoke(session_.get(), &MockQuicSession::ConsumeData)); EXPECT_CALL(*connection_, SendControlFrame(_)) .WillOnce(Invoke(&ClearControlFrame)); @@ -1442,7 +1457,7 @@ session_->ActivateStream(QuicWrapUnique(stream)); std::string data(100, '.'); - EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) + EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillRepeatedly(Invoke(session_.get(), &MockQuicSession::ConsumeData)); EXPECT_CALL(*connection_, SendControlFrame(_)) .WillOnce(Invoke(&ClearControlFrame)); @@ -1462,7 +1477,7 @@ InSequence s; // Send [0, 18) with fin. - EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _)) + EXPECT_CALL(*session_, WritevData(stream_->id(), _, _, _, _, _)) .Times(2) .WillRepeatedly(Invoke(session_.get(), &MockQuicSession::ConsumeData)); stream_->WriteOrBufferData(kData1, false, nullptr); @@ -1473,23 +1488,24 @@ QuicTime::Zero(), &newly_acked_length); EXPECT_EQ(3u, newly_acked_length); // Retransmit [0, 18) with fin, and only [0, 8) is consumed. - EXPECT_CALL(*session_, WritevData(stream_->id(), 10, 0, NO_FIN, _)) + EXPECT_CALL(*session_, WritevData(stream_->id(), 10, 0, NO_FIN, _, _)) .WillOnce(InvokeWithoutArgs([this]() { - return session_->ConsumeData(stream_->id(), 8, 0u, NO_FIN, false); + return session_->ConsumeData(stream_->id(), 8, 0u, NO_FIN, false, + QuicheNullOpt); })); EXPECT_FALSE(stream_->RetransmitStreamData(0, 18, true)); // Retransmit [0, 18) with fin, and all is consumed. - EXPECT_CALL(*session_, WritevData(stream_->id(), 10, 0, NO_FIN, _)) + EXPECT_CALL(*session_, WritevData(stream_->id(), 10, 0, NO_FIN, _, _)) .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData)); - EXPECT_CALL(*session_, WritevData(stream_->id(), 5, 13, FIN, _)) + EXPECT_CALL(*session_, WritevData(stream_->id(), 5, 13, FIN, _, _)) .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData)); EXPECT_TRUE(stream_->RetransmitStreamData(0, 18, true)); // Retransmit [0, 8) with fin, and all is consumed. - EXPECT_CALL(*session_, WritevData(stream_->id(), 8, 0, NO_FIN, _)) + EXPECT_CALL(*session_, WritevData(stream_->id(), 8, 0, NO_FIN, _, _)) .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData)); - EXPECT_CALL(*session_, WritevData(stream_->id(), 0, 18, FIN, _)) + EXPECT_CALL(*session_, WritevData(stream_->id(), 0, 18, FIN, _, _)) .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData)); EXPECT_TRUE(stream_->RetransmitStreamData(0, 8, true)); } @@ -1497,7 +1513,7 @@ TEST_P(QuicStreamTest, ResetStreamOnTtlExpiresRetransmitLostData) { Initialize(); - EXPECT_CALL(*session_, WritevData(stream_->id(), 200, 0, FIN, _)) + EXPECT_CALL(*session_, WritevData(stream_->id(), 200, 0, FIN, _, _)) .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData)); std::string body(200, 'a'); stream_->WriteOrBufferData(body, true, nullptr); @@ -1506,7 +1522,7 @@ QuicTime::Delta ttl = QuicTime::Delta::FromSeconds(1); ASSERT_TRUE(stream_->MaybeSetTtl(ttl)); // Verify data gets retransmitted because TTL does not expire. - EXPECT_CALL(*session_, WritevData(stream_->id(), 100, 0, NO_FIN, _)) + EXPECT_CALL(*session_, WritevData(stream_->id(), 100, 0, NO_FIN, _, _)) .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData)); EXPECT_TRUE(stream_->RetransmitStreamData(0, 100, false)); stream_->OnStreamFrameLost(100, 100, true); @@ -1521,7 +1537,7 @@ TEST_P(QuicStreamTest, ResetStreamOnTtlExpiresEarlyRetransmitData) { Initialize(); - EXPECT_CALL(*session_, WritevData(stream_->id(), 200, 0, FIN, _)) + EXPECT_CALL(*session_, WritevData(stream_->id(), 200, 0, FIN, _, _)) .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData)); std::string body(200, 'a'); stream_->WriteOrBufferData(body, true, nullptr);
diff --git a/quic/core/stream_delegate_interface.h b/quic/core/stream_delegate_interface.h index 2443a74..898baa5 100644 --- a/quic/core/stream_delegate_interface.h +++ b/quic/core/stream_delegate_interface.h
@@ -7,6 +7,7 @@ #include <cstddef> #include "net/third_party/quiche/src/quic/core/quic_types.h" +#include "net/third_party/quiche/src/common/platform/api/quiche_optional.h" #include "net/third_party/quiche/src/spdy/core/spdy_protocol.h" namespace quic { @@ -20,12 +21,15 @@ // Called when the stream has encountered errors that it can't handle. virtual void OnStreamError(QuicErrorCode error_code, std::string error_details) = 0; - // Called when the stream needs to write data. - virtual QuicConsumedData WritevData(QuicStreamId id, - size_t write_length, - QuicStreamOffset offset, - StreamSendingState state, - bool is_retransmission) = 0; + // Called when the stream needs to write data. If |level| is present, the data + // will be written at the specified |level|. + virtual QuicConsumedData WritevData( + QuicStreamId id, + size_t write_length, + QuicStreamOffset offset, + StreamSendingState state, + bool is_retransmission, + quiche::QuicheOptional<EncryptionLevel> level) = 0; // Called on stream creation. virtual void RegisterStreamPriority( QuicStreamId id,
diff --git a/quic/qbone/qbone_stream_test.cc b/quic/qbone/qbone_stream_test.cc index 06dbd34..df25f6b 100644 --- a/quic/qbone/qbone_stream_test.cc +++ b/quic/qbone/qbone_stream_test.cc
@@ -40,11 +40,13 @@ ~MockQuicSession() override {} // Writes outgoing data from QuicStream to a string. - QuicConsumedData WritevData(QuicStreamId id, - size_t write_length, - QuicStreamOffset offset, - StreamSendingState state, - bool is_retransmission) override { + QuicConsumedData WritevData( + QuicStreamId id, + size_t write_length, + QuicStreamOffset offset, + StreamSendingState state, + bool is_retransmission, + quiche::QuicheOptional<EncryptionLevel> level) override { if (!writable_) { return QuicConsumedData(0, false); }
diff --git a/quic/quartc/quartc_stream_test.cc b/quic/quartc/quartc_stream_test.cc index fd4c578..d0a527c 100644 --- a/quic/quartc/quartc_stream_test.cc +++ b/quic/quartc/quartc_stream_test.cc
@@ -77,11 +77,13 @@ ~MockQuicSession() override {} // Writes outgoing data from QuicStream to a string. - QuicConsumedData WritevData(QuicStreamId id, - size_t write_length, - QuicStreamOffset offset, - StreamSendingState state, - bool /*is_retransmission*/) override { + QuicConsumedData WritevData( + QuicStreamId id, + size_t write_length, + QuicStreamOffset offset, + StreamSendingState state, + bool /*is_retransmission*/, + quiche::QuicheOptional<EncryptionLevel> /*level*/) override { if (!writable_) { return QuicConsumedData(0, false); }
diff --git a/quic/quic_transport/quic_transport_stream_test.cc b/quic/quic_transport/quic_transport_stream_test.cc index 9fce821..31e01a0 100644 --- a/quic/quic_transport/quic_transport_stream_test.cc +++ b/quic/quic_transport/quic_transport_stream_test.cc
@@ -141,7 +141,7 @@ EXPECT_CALL(interface_, IsSessionReady()).WillRepeatedly(Return(true)); ASSERT_TRUE(stream_->CanWrite()); - EXPECT_CALL(session_, WritevData(stream_->id(), _, _, _, _)) + EXPECT_CALL(session_, WritevData(stream_->id(), _, _, _, _, _)) .WillOnce(Return(QuicConsumedData(0, /*fin_consumed=*/true))); EXPECT_TRUE(stream_->SendFin()); EXPECT_FALSE(stream_->CanWrite());
diff --git a/quic/test_tools/quic_test_utils.cc b/quic/test_tools/quic_test_utils.cc index 6ba98de..680b16c 100644 --- a/quic/test_tools/quic_test_utils.cc +++ b/quic/test_tools/quic_test_utils.cc
@@ -557,7 +557,7 @@ if (create_mock_crypto_stream) { crypto_stream_ = std::make_unique<MockQuicCryptoStream>(this); } - ON_CALL(*this, WritevData(_, _, _, _, _)) + ON_CALL(*this, WritevData(_, _, _, _, _, _)) .WillByDefault(testing::Return(QuicConsumedData(0, false))); } @@ -577,11 +577,13 @@ crypto_stream_.reset(crypto_stream); } -QuicConsumedData MockQuicSession::ConsumeData(QuicStreamId id, - size_t write_length, - QuicStreamOffset offset, - StreamSendingState state, - bool /*is_retransmission*/) { +QuicConsumedData MockQuicSession::ConsumeData( + QuicStreamId id, + size_t write_length, + QuicStreamOffset offset, + StreamSendingState state, + bool /*is_retransmission*/, + quiche::QuicheOptional<EncryptionLevel> /*level*/) { if (write_length > 0) { auto buf = std::make_unique<char[]>(write_length); QuicStream* stream = GetOrCreateStream(id); @@ -629,7 +631,7 @@ crypto_stream_ = std::make_unique<MockQuicCryptoStream>(this); } - ON_CALL(*this, WritevData(_, _, _, _, _)) + ON_CALL(*this, WritevData(_, _, _, _, _, _)) .WillByDefault(testing::Return(QuicConsumedData(0, false))); } @@ -649,11 +651,13 @@ crypto_stream_.reset(crypto_stream); } -QuicConsumedData MockQuicSpdySession::ConsumeData(QuicStreamId id, - size_t write_length, - QuicStreamOffset offset, - StreamSendingState state, - bool /*is_retransmission*/) { +QuicConsumedData MockQuicSpdySession::ConsumeData( + QuicStreamId id, + size_t write_length, + QuicStreamOffset offset, + StreamSendingState state, + bool /*is_retransmission*/, + quiche::QuicheOptional<EncryptionLevel> /*level*/) { if (write_length > 0) { auto buf = std::make_unique<char[]>(write_length); QuicStream* stream = GetOrCreateStream(id);
diff --git a/quic/test_tools/quic_test_utils.h b/quic/test_tools/quic_test_utils.h index 7a95250..7440c4d 100644 --- a/quic/test_tools/quic_test_utils.h +++ b/quic/test_tools/quic_test_utils.h
@@ -633,12 +633,13 @@ MOCK_METHOD1(ShouldCreateIncomingStream2, bool(QuicStreamId id)); MOCK_METHOD0(ShouldCreateOutgoingBidirectionalStream, bool()); MOCK_METHOD0(ShouldCreateOutgoingUnidirectionalStream, bool()); - MOCK_METHOD5(WritevData, + MOCK_METHOD6(WritevData, QuicConsumedData(QuicStreamId id, size_t write_length, QuicStreamOffset offset, StreamSendingState state, - bool is_retransmission)); + bool is_retransmission, + quiche::QuicheOptional<EncryptionLevel> level)); MOCK_METHOD3(SendRstStream, void(QuicStreamId stream_id, @@ -668,7 +669,8 @@ size_t write_length, QuicStreamOffset offset, StreamSendingState state, - bool is_retransmission); + bool is_retransmission, + quiche::QuicheOptional<EncryptionLevel> level); void ReallySendRstStream(QuicStreamId id, QuicRstStreamErrorCode error, @@ -732,12 +734,13 @@ MOCK_METHOD1(ShouldCreateIncomingStream, bool(QuicStreamId id)); MOCK_METHOD0(ShouldCreateOutgoingBidirectionalStream, bool()); MOCK_METHOD0(ShouldCreateOutgoingUnidirectionalStream, bool()); - MOCK_METHOD5(WritevData, + MOCK_METHOD6(WritevData, QuicConsumedData(QuicStreamId id, size_t write_length, QuicStreamOffset offset, StreamSendingState state, - bool is_retransmission)); + bool is_retransmission, + quiche::QuicheOptional<EncryptionLevel> level)); MOCK_METHOD3(SendRstStream, void(QuicStreamId stream_id, @@ -784,7 +787,8 @@ size_t write_length, QuicStreamOffset offset, StreamSendingState state, - bool is_retransmission); + bool is_retransmission, + quiche::QuicheOptional<EncryptionLevel> level); using QuicSession::ActivateStream;
diff --git a/quic/tools/quic_simple_server_stream_test.cc b/quic/tools/quic_simple_server_stream_test.cc index 880d3aa..1c71af1 100644 --- a/quic/tools/quic_simple_server_stream_test.cc +++ b/quic/tools/quic_simple_server_stream_test.cc
@@ -10,6 +10,7 @@ #include "net/third_party/quiche/src/quic/core/http/http_encoder.h" #include "net/third_party/quiche/src/quic/core/http/spdy_utils.h" +#include "net/third_party/quiche/src/quic/core/quic_types.h" #include "net/third_party/quiche/src/quic/core/quic_utils.h" #include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h" #include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h" @@ -25,6 +26,7 @@ #include "net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.h" #include "net/third_party/quiche/src/quic/tools/quic_simple_server_session.h" #include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h" +#include "net/third_party/quiche/src/common/platform/api/quiche_optional.h" #include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h" using testing::_; @@ -109,7 +111,7 @@ QuicSessionPeer::SetMaxOpenIncomingStreams(this, kMaxStreamsForTest); QuicSessionPeer::SetMaxOpenOutgoingStreams(this, kMaxStreamsForTest); } - ON_CALL(*this, WritevData(_, _, _, _, _)) + ON_CALL(*this, WritevData(_, _, _, _, _, _)) .WillByDefault(Invoke(this, &MockQuicSimpleServerSession::ConsumeData)); } @@ -122,12 +124,13 @@ void(const QuicConnectionCloseFrame& frame, ConnectionCloseSource source)); MOCK_METHOD1(CreateIncomingStream, QuicSpdyStream*(QuicStreamId id)); - MOCK_METHOD5(WritevData, + MOCK_METHOD6(WritevData, QuicConsumedData(QuicStreamId id, size_t write_length, QuicStreamOffset offset, StreamSendingState state, - bool is_retransmission)); + bool is_retransmission, + quiche::QuicheOptional<EncryptionLevel> level)); MOCK_METHOD4(OnStreamHeaderList, void(QuicStreamId stream_id, bool fin, @@ -163,11 +166,13 @@ MOCK_METHOD1(OnStopSendingReceived, void(const QuicStopSendingFrame& frame)); - QuicConsumedData ConsumeData(QuicStreamId id, - size_t write_length, - QuicStreamOffset offset, - StreamSendingState state, - bool /*is_retransmission*/) { + QuicConsumedData ConsumeData( + QuicStreamId id, + size_t write_length, + QuicStreamOffset offset, + StreamSendingState state, + bool /*is_retransmission*/, + quiche::QuicheOptional<EncryptionLevel> /*level*/) { if (write_length > 0) { auto buf = std::make_unique<char[]>(write_length); QuicStream* stream = GetOrCreateStream(id); @@ -273,7 +278,7 @@ ::testing::PrintToStringParamName()); TEST_P(QuicSimpleServerStreamTest, TestFraming) { - EXPECT_CALL(session_, WritevData(_, _, _, _, _)) + EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)) .WillRepeatedly( Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData)); stream_->OnStreamHeaderList(false, kFakeFrameLen, header_list_); @@ -291,7 +296,7 @@ } TEST_P(QuicSimpleServerStreamTest, TestFramingOnePacket) { - EXPECT_CALL(session_, WritevData(_, _, _, _, _)) + EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)) .WillRepeatedly( Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData)); @@ -310,7 +315,7 @@ } TEST_P(QuicSimpleServerStreamTest, SendQuicRstStreamNoErrorInStopReading) { - EXPECT_CALL(session_, WritevData(_, _, _, _, _)) + EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)) .WillRepeatedly( Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData)); @@ -331,9 +336,10 @@ // We'll automatically write out an error (headers + body) EXPECT_CALL(*stream_, WriteHeadersMock(false)); if (UsesHttp3()) { - EXPECT_CALL(session_, WritevData(_, kDataFrameHeaderLength, _, NO_FIN, _)); + EXPECT_CALL(session_, + WritevData(_, kDataFrameHeaderLength, _, NO_FIN, _, _)); } - EXPECT_CALL(session_, WritevData(_, kErrorLength, _, FIN, _)); + EXPECT_CALL(session_, WritevData(_, kErrorLength, _, FIN, _, _)); EXPECT_CALL(session_, SendRstStream(_, QUIC_STREAM_NO_ERROR, _)).Times(0); @@ -382,9 +388,9 @@ InSequence s; EXPECT_CALL(*stream_, WriteHeadersMock(false)); if (UsesHttp3()) { - EXPECT_CALL(session_, WritevData(_, header_length, _, NO_FIN, _)); + EXPECT_CALL(session_, WritevData(_, header_length, _, NO_FIN, _, _)); } - EXPECT_CALL(session_, WritevData(_, kErrorLength, _, FIN, _)); + EXPECT_CALL(session_, WritevData(_, kErrorLength, _, FIN, _, _)); stream_->DoSendResponse(); EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_)); @@ -415,9 +421,9 @@ InSequence s; EXPECT_CALL(*stream_, WriteHeadersMock(false)); if (UsesHttp3()) { - EXPECT_CALL(session_, WritevData(_, header_length, _, NO_FIN, _)); + EXPECT_CALL(session_, WritevData(_, header_length, _, NO_FIN, _, _)); } - EXPECT_CALL(session_, WritevData(_, kErrorLength, _, FIN, _)); + EXPECT_CALL(session_, WritevData(_, kErrorLength, _, FIN, _, _)); stream_->DoSendResponse(); EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_)); @@ -475,9 +481,9 @@ InSequence s; EXPECT_CALL(*stream_, WriteHeadersMock(false)); if (UsesHttp3()) { - EXPECT_CALL(session_, WritevData(_, header_length, _, NO_FIN, _)); + EXPECT_CALL(session_, WritevData(_, header_length, _, NO_FIN, _, _)); } - EXPECT_CALL(session_, WritevData(_, body.length(), _, FIN, _)); + EXPECT_CALL(session_, WritevData(_, body.length(), _, FIN, _, _)); stream_->DoSendResponse(); EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_)); @@ -517,9 +523,9 @@ _, _)); EXPECT_CALL(*stream_, WriteHeadersMock(false)); if (UsesHttp3()) { - EXPECT_CALL(session_, WritevData(_, header_length, _, NO_FIN, _)); + EXPECT_CALL(session_, WritevData(_, header_length, _, NO_FIN, _, _)); } - EXPECT_CALL(session_, WritevData(_, body.length(), _, FIN, _)); + EXPECT_CALL(session_, WritevData(_, body.length(), _, FIN, _, _)); stream_->DoSendResponse(); EXPECT_EQ(*request_headers, session_.original_request_headers_); } @@ -574,10 +580,10 @@ if (UsesHttp3()) { EXPECT_CALL(session_, WritevData(kServerInitiatedStreamId, header_length, _, - NO_FIN, _)); + NO_FIN, _, _)); } EXPECT_CALL(session_, - WritevData(kServerInitiatedStreamId, kBody.size(), _, FIN, _)); + WritevData(kServerInitiatedStreamId, kBody.size(), _, FIN, _, _)); server_initiated_stream->PushResponse(std::move(headers)); EXPECT_EQ(kPath, server_initiated_stream->GetHeader(":path")); EXPECT_EQ("GET", server_initiated_stream->GetHeader(":method")); @@ -591,9 +597,10 @@ InSequence s; EXPECT_CALL(*stream_, WriteHeadersMock(false)); if (UsesHttp3()) { - EXPECT_CALL(session_, WritevData(_, kDataFrameHeaderLength, _, NO_FIN, _)); + EXPECT_CALL(session_, + WritevData(_, kDataFrameHeaderLength, _, NO_FIN, _, _)); } - EXPECT_CALL(session_, WritevData(_, kErrorLength, _, FIN, _)); + EXPECT_CALL(session_, WritevData(_, kErrorLength, _, FIN, _, _)); stream_->DoSendErrorResponse(); EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_)); @@ -609,7 +616,7 @@ quiche::QuicheStringPiece("11\00012", 5)); EXPECT_CALL(*stream_, WriteHeadersMock(false)); - EXPECT_CALL(session_, WritevData(_, _, _, _, _)) + EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)) .WillRepeatedly( Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData)); stream_->OnStreamHeaderList(true, kFakeFrameLen, header_list_); @@ -628,7 +635,7 @@ quiche::QuicheStringPiece("\00012", 3)); EXPECT_CALL(*stream_, WriteHeadersMock(false)); - EXPECT_CALL(session_, WritevData(_, _, _, _, _)) + EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)) .WillRepeatedly( Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData)); stream_->OnStreamHeaderList(true, kFakeFrameLen, header_list_); @@ -664,7 +671,7 @@ // assumption on their number or size. auto* qpack_decoder_stream = QuicSpdySessionPeer::GetQpackDecoderSendStream(&session_); - EXPECT_CALL(session_, WritevData(qpack_decoder_stream->id(), _, _, _, _)) + EXPECT_CALL(session_, WritevData(qpack_decoder_stream->id(), _, _, _, _, _)) .Times(AnyNumber()); } EXPECT_CALL(session_, SendRstStream(_, QUIC_RST_ACKNOWLEDGEMENT, _)).Times(1);