Index: net/quic/core/quic_connection.cc |
diff --git a/net/quic/core/quic_connection.cc b/net/quic/core/quic_connection.cc |
index add7d673302b4dc795154abb96051a2ab4293be0..e205e31dd9359785c64ff85a70181837844ef71e 100644 |
--- a/net/quic/core/quic_connection.cc |
+++ b/net/quic/core/quic_connection.cc |
@@ -2306,6 +2306,28 @@ QuicConnection::ScopedPacketBundler::~ScopedPacketBundler() { |
if (!already_in_batch_mode_) { |
DVLOG(2) << "Leaving Batch Mode."; |
connection_->packet_generator_.FinishBatchOperations(); |
+ |
+ // 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 |
+ // 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 |
+ // 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 |
+ // would mean writing chunks larger than the product of the current |
+ // pacing rate and the pacer granularity. So, for instance, if the |
+ // pacing rate of the connection is 1 Gbps, and the pacer granularity is |
+ // 1 ms, the caller should send at least 125k bytes in order to not |
+ // be marked as application-limited. |
+ if (FLAGS_quic_enable_app_limited_check) { |
+ connection_->CheckIfApplicationLimited(); |
+ } |
} |
DCHECK_EQ(already_in_batch_mode_, |
connection_->packet_generator_.InBatchMode()); |
@@ -2522,4 +2544,12 @@ const QuicTime::Delta QuicConnection::DelayedAckTime() { |
min(kMaxDelayedAckTimeMs, kMinRetransmissionTimeMs / 2)); |
} |
+void QuicConnection::CheckIfApplicationLimited() { |
+ if (queued_packets_.empty() && |
+ !sent_packet_manager_->HasPendingRetransmissions() && |
+ !visitor_->WillingAndAbleToWrite()) { |
+ sent_packet_manager_->OnApplicationLimited(); |
+ } |
+} |
+ |
} // namespace net |