Commit 8df4adab authored by Ryan Hamilton's avatar Ryan Hamilton Committed by Commit Bot

Landing Recent QUIC changes until Wed Nov 8 17:27:10 2017 +0000

Flip recent QUIC flags.
https://chromium-review.googlesource.com/c/chromium/src/+/767009


make QuicStream::WriteMemSlices() public.

Merge internal change: 175016870
https://chromium-review.googlesource.com/c/chromium/src/+/767067


In QUIC, rename ScopedPacketBundler to ScopedPacketFlusher. As generator is always in batch mode, generator is flushed only when Flush() is called. No functional change expected.

Merge internal change: 174845352

https: //chromium-review.googlesource.com/c/chromium/src/+/767007
Cq-Include-Trybots: master.tryserver.chromium.android:android_cronet_tester;master.tryserver.chromium.mac:ios-simulator-cronet
Change-Id: I023f08e24946346aaf268c98fb726d0a398f1e7a
Reviewed-on: https://chromium-review.googlesource.com/767031Reviewed-by: default avatarBuck Krasic <ckrasic@chromium.org>
Commit-Queue: Ryan Hamilton <rch@chromium.org>
Cr-Commit-Position: refs/heads/master@{#516105}
parent 8b5968a8
......@@ -172,7 +172,7 @@ void BidirectionalStreamQuicImpl::SendvData(
return;
}
std::unique_ptr<QuicConnection::ScopedPacketBundler> bundler(
std::unique_ptr<QuicConnection::ScopedPacketFlusher> bundler(
session_->CreatePacketBundler(QuicConnection::SEND_ACK_IF_PENDING));
if (!has_sent_headers_) {
DCHECK(!send_request_headers_automatically_);
......
......@@ -335,13 +335,13 @@ void QuicChromiumClientSession::Handle::ResetPromised(
session_->ResetPromised(id, error_code);
}
std::unique_ptr<QuicConnection::ScopedPacketBundler>
std::unique_ptr<QuicConnection::ScopedPacketFlusher>
QuicChromiumClientSession::Handle::CreatePacketBundler(
QuicConnection::AckBundling bundling_mode) {
if (!session_)
return nullptr;
return std::make_unique<QuicConnection::ScopedPacketBundler>(
return std::make_unique<QuicConnection::ScopedPacketFlusher>(
session_->connection(), bundling_mode);
}
......
......@@ -122,7 +122,7 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession
// Returns a new packet bundler while will cause writes to be batched up
// until a packet is full, or the last bundler is destroyed.
std::unique_ptr<QuicConnection::ScopedPacketBundler> CreatePacketBundler(
std::unique_ptr<QuicConnection::ScopedPacketFlusher> CreatePacketBundler(
QuicConnection::AckBundling bundling_mode);
// Populates network error details for this session.
......
......@@ -118,7 +118,7 @@ void QuicChromiumClientStream::Handle::OnError(int error) {
stream_ = nullptr;
// Post a task to invoke the callbacks to ensure that there is no reentrancy.
// A ScopedPacketBundler might cause an error which closes the stream under
// A ScopedPacketFlusher might cause an error which closes the stream under
// the call stack of the owner of the handle.
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
......
......@@ -85,7 +85,7 @@ class AckAlarmDelegate : public QuicAlarm::Delegate {
void OnAlarm() override {
DCHECK(connection_->ack_frame_updated());
QuicConnection::ScopedPacketBundler bundler(connection_,
QuicConnection::ScopedPacketFlusher flusher(connection_,
QuicConnection::SEND_ACK);
}
......@@ -1103,7 +1103,7 @@ QuicConsumedData QuicConnection::SendStreamData(QuicStreamId id,
// packet (a handshake packet from client to server could result in a REJ or a
// SHLO from the server, leading to two different decrypters at the server.)
ScopedRetransmissionScheduler alarm_delayer(this);
ScopedPacketBundler ack_bundler(this, SEND_ACK_IF_PENDING);
ScopedPacketFlusher flusher(this, SEND_ACK_IF_PENDING);
return packet_generator_.ConsumeData(id, write_length, offset, state);
}
......@@ -1111,7 +1111,7 @@ void QuicConnection::SendRstStream(QuicStreamId id,
QuicRstStreamErrorCode error,
QuicStreamOffset bytes_written) {
// Opportunistically bundle an ack with this outgoing packet.
ScopedPacketBundler ack_bundler(this, SEND_ACK_IF_PENDING);
ScopedPacketFlusher flusher(this, SEND_ACK_IF_PENDING);
packet_generator_.AddControlFrame(
QuicFrame(new QuicRstStreamFrame(id, error, bytes_written)));
......@@ -1154,14 +1154,14 @@ void QuicConnection::SendRstStream(QuicStreamId id,
void QuicConnection::SendWindowUpdate(QuicStreamId id,
QuicStreamOffset byte_offset) {
// Opportunistically bundle an ack with this outgoing packet.
ScopedPacketBundler ack_bundler(this, SEND_ACK_IF_PENDING);
ScopedPacketFlusher flusher(this, SEND_ACK_IF_PENDING);
packet_generator_.AddControlFrame(
QuicFrame(new QuicWindowUpdateFrame(id, byte_offset)));
}
void QuicConnection::SendBlocked(QuicStreamId id) {
// Opportunistically bundle an ack with this outgoing packet.
ScopedPacketBundler ack_bundler(this, SEND_ACK_IF_PENDING);
ScopedPacketFlusher flusher(this, SEND_ACK_IF_PENDING);
packet_generator_.AddControlFrame(QuicFrame(new QuicBlockedFrame(id)));
stats_.blocked_frames_sent++;
}
......@@ -1278,7 +1278,7 @@ void QuicConnection::OnCanWrite() {
}
{
ScopedPacketBundler bundler(this, SEND_ACK_IF_QUEUED);
ScopedPacketFlusher flusher(this, SEND_ACK_IF_QUEUED);
visitor_->OnCanWrite();
visitor_->PostProcessAfterData();
}
......@@ -1302,7 +1302,7 @@ void QuicConnection::WriteIfNotBlocked() {
void QuicConnection::WriteAndBundleAcksIfNotBlocked() {
if (!writer_->IsWriteBlocked()) {
ScopedPacketBundler bundler(this, SEND_ACK_IF_QUEUED);
ScopedPacketFlusher flusher(this, SEND_ACK_IF_QUEUED);
OnCanWrite();
}
}
......@@ -1459,7 +1459,7 @@ void QuicConnection::WritePendingRetransmissions() {
// be moved outside of the loop. Also, CanWrite is not checked after the
// generator is flushed.
{
ScopedPacketBundler bundler(this, NO_ACK);
ScopedPacketFlusher flusher(this, NO_ACK);
packet_generator_.FlushAllQueuedFrames();
}
char buffer[kMaxPacketSize];
......@@ -1809,7 +1809,7 @@ void QuicConnection::OnPingTimeout() {
}
void QuicConnection::SendPing() {
ScopedPacketBundler bundler(this, SEND_ACK_IF_QUEUED);
ScopedPacketFlusher flusher(this, SEND_ACK_IF_QUEUED);
packet_generator_.AddControlFrame(QuicFrame(QuicPingFrame()));
// Send PING frame immediately, without checking for congestion window bounds.
packet_generator_.FlushAllQueuedFrames();
......@@ -2000,7 +2000,7 @@ void QuicConnection::SendConnectionClosePacket(QuicErrorCode error,
AckBundling ack_mode) {
QUIC_DLOG(INFO) << ENDPOINT << "Sending connection close packet.";
ClearQueuedPackets();
ScopedPacketBundler ack_bundler(this, ack_mode);
ScopedPacketFlusher flusher(this, ack_mode);
QuicConnectionCloseFrame* frame = new QuicConnectionCloseFrame();
frame->error_code = error;
frame->error_details = details;
......@@ -2058,7 +2058,7 @@ void QuicConnection::SendGoAway(QuicErrorCode error,
<< QuicErrorCodeToString(error) << " (" << error << ")";
// Opportunistically bundle an ack with this outgoing packet.
ScopedPacketBundler ack_bundler(this, SEND_ACK_IF_PENDING);
ScopedPacketFlusher flusher(this, SEND_ACK_IF_PENDING);
packet_generator_.AddControlFrame(
QuicFrame(new QuicGoAwayFrame(error, last_good_stream_id, reason)));
}
......@@ -2219,27 +2219,26 @@ void QuicConnection::MaybeSetMtuAlarm(QuicPacketNumber sent_packet_number) {
}
if (sent_packet_number >= next_mtu_probe_at_) {
// Use an alarm to send the MTU probe to ensure that no ScopedPacketBundlers
// Use an alarm to send the MTU probe to ensure that no ScopedPacketFlushers
// are active.
mtu_discovery_alarm_->Set(clock_->ApproximateNow());
}
}
QuicConnection::ScopedPacketBundler::ScopedPacketBundler(
QuicConnection::ScopedPacketFlusher::ScopedPacketFlusher(
QuicConnection* connection,
AckBundling ack_mode)
: connection_(connection),
already_in_batch_mode_(connection != nullptr &&
connection->packet_generator_.InBatchMode()) {
: connection_(connection), flush_on_delete_(false) {
if (connection_ == nullptr) {
return;
}
// Move generator into batch mode. If caller wants us to include an ack,
// check the delayed-ack timer to see if there's ack info to be sent.
if (!already_in_batch_mode_) {
QUIC_DVLOG(2) << "Entering Batch Mode.";
connection_->packet_generator_.StartBatchOperations();
if (!connection_->packet_generator_.PacketFlusherAttached()) {
flush_on_delete_ = true;
connection->packet_generator_.AttachPacketFlusher();
}
// If caller wants us to include an ack, check the delayed-ack timer to see if
// there's ack info to be sent.
if (ShouldSendAck(ack_mode)) {
QUIC_DVLOG(1) << "Bundling ack with outgoing packet.";
DCHECK(ack_mode == SEND_ACK || connection_->ack_frame_updated() ||
......@@ -2248,7 +2247,7 @@ QuicConnection::ScopedPacketBundler::ScopedPacketBundler(
}
}
bool QuicConnection::ScopedPacketBundler::ShouldSendAck(
bool QuicConnection::ScopedPacketFlusher::ShouldSendAck(
AckBundling ack_mode) const {
switch (ack_mode) {
case SEND_ACK:
......@@ -2266,25 +2265,24 @@ bool QuicConnection::ScopedPacketBundler::ShouldSendAck(
}
}
QuicConnection::ScopedPacketBundler::~ScopedPacketBundler() {
QuicConnection::ScopedPacketFlusher::~ScopedPacketFlusher() {
if (connection_ == nullptr) {
return;
}
// If we changed the generator's batch state, restore original batch state.
if (!already_in_batch_mode_) {
QUIC_DVLOG(2) << "Leaving Batch Mode.";
connection_->packet_generator_.FinishBatchOperations();
if (flush_on_delete_) {
connection_->packet_generator_.Flush();
// Once all transmissions are done, check if there is any outstanding data
// to send and notify the congestion controller if not.
//
// Note that this means that the application limited check will happen as
// soon as the last bundler gets destroyed, which is typically after a
// soon as the last flusher gets destroyed, which is typically after a
// single stream write is finished. This means that if all the data from a
// single write goes through the connection, the application-limited signal
// will fire even if the caller does a write operation immediately after.
// There are two important approaches to remedy this situation:
// (1) Instantiate ScopedPacketBundler before performing multiple subsequent
// (1) Instantiate ScopedPacketFlusher before performing multiple subsequent
// writes, thus deferring this check until all writes are done.
// (2) Write data in chunks sufficiently large so that they cause the
// connection to be limited by the congestion control. Typically, this
......@@ -2295,8 +2293,8 @@ QuicConnection::ScopedPacketBundler::~ScopedPacketBundler() {
// be marked as application-limited.
connection_->CheckIfApplicationLimited();
}
DCHECK_EQ(already_in_batch_mode_,
connection_->packet_generator_.InBatchMode());
DCHECK_EQ(flush_on_delete_,
!connection_->packet_generator_.PacketFlusherAttached());
}
QuicConnection::ScopedRetransmissionScheduler::ScopedRetransmissionScheduler(
......
......@@ -624,26 +624,23 @@ class QUIC_EXPORT_PRIVATE QuicConnection
bool CanWrite(HasRetransmittableData retransmittable);
// Stores current batch state for connection, puts the connection
// into batch mode, and destruction restores the stored batch state.
// While the bundler is in scope, any generated frames are bundled
// as densely as possible into packets. In addition, this bundler
// can be configured to ensure that an ACK frame is included in the
// first packet created, if there's new ack information to be sent.
class QUIC_EXPORT_PRIVATE ScopedPacketBundler {
// When the flusher is out of scope, only the outermost flusher will cause a
// flush of the connection. In addition, this flusher can be configured to
// ensure that an ACK frame is included in the first packet created, if
// there's new ack information to be sent.
class QUIC_EXPORT_PRIVATE ScopedPacketFlusher {
public:
// In addition to all outgoing frames being bundled when the
// bundler is in scope, setting |include_ack| to true ensures that
// an ACK frame is opportunistically bundled with the first
// outgoing packet.
ScopedPacketBundler(QuicConnection* connection, AckBundling send_ack);
~ScopedPacketBundler();
// Setting |include_ack| to true ensures that an ACK frame is
// opportunistically bundled with the first outgoing packet.
ScopedPacketFlusher(QuicConnection* connection, AckBundling ack_mode);
~ScopedPacketFlusher();
private:
bool ShouldSendAck(AckBundling ack_mode) const;
QuicConnection* connection_;
bool already_in_batch_mode_;
// If true, flush connection when this flusher goes out of scope.
bool flush_on_delete_;
};
// Delays setting the retransmission alarm until the scope is exited.
......
......@@ -535,7 +535,7 @@ class TestConnection : public QuicConnection {
size_t total_length,
QuicStreamOffset offset,
StreamSendingState state) {
ScopedPacketBundler bundler(this, NO_ACK);
ScopedPacketFlusher flusher(this, NO_ACK);
producer_.SaveStreamData(id, iov, iov_count, 0u, offset, total_length);
return QuicConnection::SendStreamData(id, total_length, offset, state);
}
......@@ -544,7 +544,7 @@ class TestConnection : public QuicConnection {
QuicStringPiece data,
QuicStreamOffset offset,
StreamSendingState state) {
ScopedPacketBundler bundler(this, NO_ACK);
ScopedPacketFlusher flusher(this, NO_ACK);
if (id != kCryptoStreamId && this->encryption_level() == ENCRYPTION_NONE) {
this->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
}
......@@ -930,7 +930,7 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
void SendAckPacketToPeer() {
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
{
QuicConnection::ScopedPacketBundler bundler(&connection_,
QuicConnection::ScopedPacketFlusher flusher(&connection_,
QuicConnection::NO_ACK);
connection_.SendAck();
}
......@@ -1876,7 +1876,7 @@ TEST_P(QuicConnectionTest, RecordSentTimeBeforePacketSent) {
TEST_P(QuicConnectionTest, FramePacking) {
// Send an ack and two stream frames in 1 packet by queueing them.
{
QuicConnection::ScopedPacketBundler bundler(&connection_,
QuicConnection::ScopedPacketFlusher flusher(&connection_,
QuicConnection::SEND_ACK);
connection_.SendStreamData3();
connection_.SendStreamData5();
......@@ -1905,7 +1905,7 @@ TEST_P(QuicConnectionTest, FramePackingNonCryptoThenCrypto) {
// packets by queueing them.
{
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2);
QuicConnection::ScopedPacketBundler bundler(&connection_,
QuicConnection::ScopedPacketFlusher flusher(&connection_,
QuicConnection::SEND_ACK);
connection_.SendStreamData3();
connection_.SendCryptoStreamData();
......@@ -1925,7 +1925,7 @@ TEST_P(QuicConnectionTest, FramePackingCryptoThenNonCrypto) {
// packets by queueing them.
{
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2);
QuicConnection::ScopedPacketBundler bundler(&connection_,
QuicConnection::ScopedPacketFlusher flusher(&connection_,
QuicConnection::SEND_ACK);
connection_.SendCryptoStreamData();
connection_.SendStreamData3();
......
......@@ -163,7 +163,7 @@ QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_bbr_slower_startup, false)
// Deprecate QuicAckFrame.largest_observed since it is redundant.
QUIC_FLAG(bool,
FLAGS_quic_reloadable_flag_quic_deprecate_largest_observed,
false)
true)
// Fully drain the queue in QUIC BBR at least once per cycle(8 rounds) when
// activated by the BBR3 connection option.
......
......@@ -21,7 +21,7 @@ QuicPacketGenerator::QuicPacketGenerator(QuicConnectionId connection_id,
DelegateInterface* delegate)
: delegate_(delegate),
packet_creator_(connection_id, framer, delegate),
batch_mode_(false),
flusher_attached_(false),
should_send_ack_(false),
should_send_stop_waiting_(false),
random_generator_(random_generator) {}
......@@ -55,8 +55,8 @@ QuicConsumedData QuicPacketGenerator::ConsumeData(QuicStreamId id,
size_t write_length,
QuicStreamOffset offset,
StreamSendingState state) {
QUIC_BUG_IF(!batch_mode_)
<< "Generator is not in batch mode when trying to write stream data.";
QUIC_BUG_IF(!flusher_attached_) << "Packet flusher is not attached when "
"generator tries to write stream data.";
bool has_handshake = (id == kCryptoStreamId);
bool fin = state != NO_FIN;
QUIC_BUG_IF(has_handshake && fin)
......@@ -107,10 +107,6 @@ QuicConsumedData QuicPacketGenerator::ConsumeData(QuicStreamId id,
DCHECK(total_bytes_consumed == write_length ||
(bytes_consumed > 0 && packet_creator_.HasPendingFrames()));
if (!InBatchMode()) {
packet_creator_.Flush();
}
if (total_bytes_consumed == write_length) {
// We're done writing the data. Exit the loop.
// We don't make this a precondition because we could have 0 bytes of data
......@@ -135,7 +131,6 @@ QuicConsumedData QuicPacketGenerator::ConsumeData(QuicStreamId id,
SendQueuedFrames(/*flush=*/true);
}
DCHECK(InBatchMode() || !packet_creator_.HasPendingFrames());
return QuicConsumedData(total_bytes_consumed, fin_consumed);
}
......@@ -222,24 +217,24 @@ void QuicPacketGenerator::SendQueuedFrames(bool flush) {
return;
}
}
if (flush || !InBatchMode()) {
if (flush) {
packet_creator_.Flush();
}
}
bool QuicPacketGenerator::InBatchMode() {
return batch_mode_;
bool QuicPacketGenerator::PacketFlusherAttached() const {
return flusher_attached_;
}
void QuicPacketGenerator::StartBatchOperations() {
batch_mode_ = true;
void QuicPacketGenerator::AttachPacketFlusher() {
flusher_attached_ = true;
}
void QuicPacketGenerator::FinishBatchOperations() {
void QuicPacketGenerator::Flush() {
SendQueuedFrames(/*flush=*/false);
packet_creator_.Flush();
SendRemainingPendingPadding();
batch_mode_ = false;
flusher_attached_ = false;
}
void QuicPacketGenerator::FlushAllQueuedFrames() {
......@@ -260,8 +255,8 @@ bool QuicPacketGenerator::HasPendingFrames() const {
}
bool QuicPacketGenerator::AddNextPendingFrame() {
QUIC_BUG_IF(!batch_mode_)
<< "Generator is not in batch mode when trying to write control frames.";
QUIC_BUG_IF(!flusher_attached_) << "Packet flusher is not attached when "
"generator tries to write control frames.";
if (should_send_ack_) {
should_send_ack_ =
!packet_creator_.AddSavedFrame(delegate_->GetUpdatedAckFrame());
......
......@@ -112,12 +112,12 @@ class QUIC_EXPORT_PRIVATE QuicPacketGenerator {
// Generates an MTU discovery packet of specified size.
void GenerateMtuDiscoveryPacket(QuicByteCount target_mtu);
// Indicates whether batch mode is currently enabled.
bool InBatchMode();
// Disables flushing.
void StartBatchOperations();
// Enables flushing and flushes queued data which can be sent.
void FinishBatchOperations();
// Indicates whether packet flusher is currently attached.
bool PacketFlusherAttached() const;
// Attaches packet flusher.
void AttachPacketFlusher();
// Flushes everything, including all queued frames and pending padding.
void Flush();
// Flushes all queued frames, even frames which are not sendable.
void FlushAllQueuedFrames();
......@@ -210,8 +210,8 @@ class QUIC_EXPORT_PRIVATE QuicPacketGenerator {
QuicPacketCreator packet_creator_;
QuicFrames queued_control_frames_;
// True if batch mode is currently enabled.
bool batch_mode_;
// True if packet flusher is currently attached.
bool flusher_attached_;
// Flags to indicate the need for just-in-time construction of a frame.
bool should_send_ack_;
......
......@@ -162,7 +162,7 @@ class QuicPacketGeneratorTest : public QuicTest {
new NullEncrypter(Perspective::IS_CLIENT));
creator_->set_encryption_level(ENCRYPTION_FORWARD_SECURE);
framer_.set_data_producer(&producer_);
generator_.StartBatchOperations();
generator_.AttachPacketFlusher();
}
~QuicPacketGeneratorTest() override {
......@@ -309,7 +309,7 @@ TEST_F(QuicPacketGeneratorTest, ShouldSendAck_WritableAndShouldFlush) {
.WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
generator_.SetShouldSendAck(false);
generator_.FinishBatchOperations();
generator_.Flush();
EXPECT_FALSE(generator_.HasQueuedFrames());
EXPECT_FALSE(generator_.HasRetransmittableFrames());
......@@ -334,7 +334,7 @@ TEST_F(QuicPacketGeneratorTest, ShouldSendAck_MultipleCalls) {
generator_.SetShouldSendAck(false);
generator_.SetShouldSendAck(false);
generator_.FinishBatchOperations();
generator_.Flush();
}
TEST_F(QuicPacketGeneratorTest, AddControlFrame_NotWritable) {
......@@ -367,13 +367,13 @@ TEST_F(QuicPacketGeneratorTest, AddControlFrame_NotWritableBatchThenFlush) {
generator_.AddControlFrame(QuicFrame(CreateRstStreamFrame()));
EXPECT_TRUE(generator_.HasQueuedFrames());
EXPECT_TRUE(generator_.HasRetransmittableFrames());
generator_.FinishBatchOperations();
generator_.Flush();
EXPECT_TRUE(generator_.HasQueuedFrames());
EXPECT_TRUE(generator_.HasRetransmittableFrames());
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
generator_.StartBatchOperations();
generator_.AttachPacketFlusher();
generator_.FlushAllQueuedFrames();
EXPECT_FALSE(generator_.HasQueuedFrames());
EXPECT_FALSE(generator_.HasRetransmittableFrames());
......@@ -390,7 +390,7 @@ TEST_F(QuicPacketGeneratorTest, AddControlFrame_WritableAndShouldFlush) {
.WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
generator_.AddControlFrame(QuicFrame(CreateRstStreamFrame()));
generator_.FinishBatchOperations();
generator_.Flush();
EXPECT_FALSE(generator_.HasQueuedFrames());
EXPECT_FALSE(generator_.HasRetransmittableFrames());
......@@ -431,7 +431,7 @@ TEST_F(QuicPacketGeneratorTest, ConsumeData_WritableAndShouldFlush) {
MakeIOVector("foo", &iov_);
QuicConsumedData consumed =
generator_.ConsumeData(kHeadersStreamId, &iov_, 1u, iov_.iov_len, 0, FIN);
generator_.FinishBatchOperations();
generator_.Flush();
EXPECT_EQ(3u, consumed.bytes_consumed);
EXPECT_TRUE(consumed.fin_consumed);
EXPECT_FALSE(generator_.HasQueuedFrames());
......@@ -504,7 +504,7 @@ TEST_F(QuicPacketGeneratorTest, ConsumeData_BatchOperations) {
// Now both frames will be flushed out.
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
generator_.FinishBatchOperations();
generator_.Flush();
EXPECT_FALSE(generator_.HasQueuedFrames());
EXPECT_FALSE(generator_.HasRetransmittableFrames());
......@@ -640,7 +640,7 @@ TEST_F(QuicPacketGeneratorTest, ConsumeDataLargeSendAckFalse) {
.WillRepeatedly(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
QuicConsumedData consumed =
generator_.ConsumeData(kHeadersStreamId, &iov_, 1u, iov_.iov_len, 0, FIN);
generator_.FinishBatchOperations();
generator_.Flush();
EXPECT_EQ(10000u, consumed.bytes_consumed);
EXPECT_TRUE(consumed.fin_consumed);
......@@ -676,7 +676,7 @@ TEST_F(QuicPacketGeneratorTest, ConsumeDataLargeSendAckTrue) {
.WillRepeatedly(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
QuicConsumedData consumed =
generator_.ConsumeData(kHeadersStreamId, &iov_, 1u, iov_.iov_len, 0, FIN);
generator_.FinishBatchOperations();
generator_.Flush();
EXPECT_EQ(10000u, consumed.bytes_consumed);
EXPECT_TRUE(consumed.fin_consumed);
......@@ -716,7 +716,7 @@ TEST_F(QuicPacketGeneratorTest, NotWritableThenBatchOperations) {
// All five frames will be flushed out in a single packet.
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
generator_.FinishBatchOperations();
generator_.Flush();
EXPECT_FALSE(generator_.HasQueuedFrames());
EXPECT_FALSE(generator_.HasRetransmittableFrames());
EXPECT_FALSE(generator_.HasPendingStreamFramesOfStream(3));
......@@ -761,7 +761,7 @@ TEST_F(QuicPacketGeneratorTest, NotWritableThenBatchOperations2) {
EXPECT_TRUE(consumed.fin_consumed);
generator_.AddControlFrame(QuicFrame(CreateGoAwayFrame()));
generator_.FinishBatchOperations();
generator_.Flush();
EXPECT_FALSE(generator_.HasQueuedFrames());
EXPECT_FALSE(generator_.HasRetransmittableFrames());
......@@ -845,7 +845,7 @@ TEST_F(QuicPacketGeneratorTest, SetMaxPacketLength_Middle) {
QuicConsumedData consumed =
generator_.ConsumeData(kHeadersStreamId, &iov_, 1u, iov_.iov_len,
/*offset=*/0, NO_FIN);
generator_.FinishBatchOperations();
generator_.Flush();
EXPECT_EQ(data_len, consumed.bytes_consumed);
EXPECT_FALSE(consumed.fin_consumed);
EXPECT_FALSE(generator_.HasQueuedFrames());
......@@ -860,10 +860,10 @@ TEST_F(QuicPacketGeneratorTest, SetMaxPacketLength_Middle) {
// Send a packet after packet size change.
CreateData(data_len);
generator_.StartBatchOperations();
generator_.AttachPacketFlusher();
consumed = generator_.ConsumeData(kHeadersStreamId, &iov_, 1u, iov_.iov_len,
data_len, FIN);
generator_.FinishBatchOperations();
generator_.Flush();
EXPECT_EQ(data_len, consumed.bytes_consumed);
EXPECT_TRUE(consumed.fin_consumed);
EXPECT_FALSE(generator_.HasQueuedFrames());
......@@ -985,7 +985,7 @@ TEST_F(QuicPacketGeneratorTest, GenerateMtuDiscoveryPacket_SurroundedByData) {
QuicConsumedData consumed =
generator_.ConsumeData(kHeadersStreamId, &iov_, 1u, iov_.iov_len,
/*offset=*/0, NO_FIN);
generator_.FinishBatchOperations();
generator_.Flush();
EXPECT_EQ(data_len, consumed.bytes_consumed);
EXPECT_FALSE(consumed.fin_consumed);
EXPECT_FALSE(generator_.HasQueuedFrames());
......@@ -998,10 +998,10 @@ TEST_F(QuicPacketGeneratorTest, GenerateMtuDiscoveryPacket_SurroundedByData) {
// Send data after the MTU probe.
CreateData(data_len);
generator_.StartBatchOperations();
generator_.AttachPacketFlusher();
consumed = generator_.ConsumeData(kHeadersStreamId, &iov_, 1u, iov_.iov_len,
/*offset=*/data_len, FIN);
generator_.FinishBatchOperations();
generator_.Flush();
EXPECT_EQ(data_len, consumed.bytes_consumed);
EXPECT_TRUE(consumed.fin_consumed);
EXPECT_FALSE(generator_.HasQueuedFrames());
......@@ -1047,7 +1047,7 @@ TEST_F(QuicPacketGeneratorTest, DontCrashOnInvalidStopWaiting) {
EXPECT_CALL(delegate_,
OnUnrecoverableError(QUIC_FAILED_TO_SERIALIZE_PACKET, _,
ConnectionCloseSource::FROM_SELF));
EXPECT_QUIC_BUG(generator_.FinishBatchOperations(),
EXPECT_QUIC_BUG(generator_.Flush(),
"packet_number_length 1 is too small "
"for least_unacked_delta: 1001");
}
......@@ -1091,7 +1091,7 @@ TEST_F(QuicPacketGeneratorTest, RandomPaddingAfterFinSingleStreamSinglePacket) {
MakeIOVector(QuicStringPiece(buf, kStreamFramePayloadSize), &iov_);
QuicConsumedData consumed = generator_.ConsumeData(
kDataStreamId, &iov_, 1u, iov_.iov_len, 0, FIN_AND_PADDING);
generator_.FinishBatchOperations();
generator_.Flush();
EXPECT_EQ(kStreamFramePayloadSize, consumed.bytes_consumed);
EXPECT_FALSE(generator_.HasQueuedFrames());
EXPECT_FALSE(generator_.HasRetransmittableFrames());
......@@ -1128,7 +1128,7 @@ TEST_F(QuicPacketGeneratorTest,
MakeIOVector(QuicStringPiece(buf, kStreamFramePayloadSize), &iov_);
QuicConsumedData consumed = generator_.ConsumeData(
kDataStreamId, &iov_, 1u, iov_.iov_len, 0, FIN_AND_PADDING);
generator_.FinishBatchOperations();
generator_.Flush();
EXPECT_EQ(kStreamFramePayloadSize, consumed.bytes_consumed);
EXPECT_FALSE(generator_.HasQueuedFrames());
EXPECT_FALSE(generator_.HasRetransmittableFrames());
......@@ -1182,7 +1182,7 @@ TEST_F(QuicPacketGeneratorTest,
consumed = generator_.ConsumeData(kDataStreamId2, &iov_, 1u, iov_.iov_len, 0,
FIN_AND_PADDING);
EXPECT_EQ(kStreamFramePayloadSize, consumed.bytes_consumed);
generator_.FinishBatchOperations();
generator_.Flush();
EXPECT_FALSE(generator_.HasQueuedFrames());
EXPECT_FALSE(generator_.HasRetransmittableFrames());
......
......@@ -250,7 +250,7 @@ void QuicSession::OnCanWrite() {
return;
}
QuicConnection::ScopedPacketBundler ack_bundler(
QuicConnection::ScopedPacketFlusher flusher(
connection_, QuicConnection::SEND_ACK_IF_QUEUED);
for (size_t i = 0; i < num_writes; ++i) {
if (!(write_blocked_streams_.HasWriteBlockedCryptoOrHeadersStream() ||
......
......@@ -204,6 +204,10 @@ class QUIC_EXPORT_PRIVATE QuicStream : public StreamNotifierInterface {
void OnStreamFrameRetransmitted(const QuicStreamFrame& frame) override;
void OnStreamFrameDiscarded(const QuicStreamFrame& frame) override;
// Same as WritevData except data is provided in reference counted memory so
// that data copy is avoided.
QuicConsumedData WriteMemSlices(QuicMemSliceSpan span, bool fin);