Index: net/quic/quic_connection.cc |
diff --git a/net/quic/quic_connection.cc b/net/quic/quic_connection.cc |
index f1e25d6e24b4989a0fc8062db44263385b8777b9..32c44f44a5e81a6c4e19e23e284d0c07570b0a31 100644 |
--- a/net/quic/quic_connection.cc |
+++ b/net/quic/quic_connection.cc |
@@ -167,6 +167,7 @@ QuicConnection::QuicConnection(QuicGuid guid, |
largest_seen_packet_with_ack_(0), |
pending_version_negotiation_packet_(false), |
received_packet_manager_(kTCP), |
+ ack_queued_(false), |
ack_alarm_(helper->CreateAlarm(new AckAlarm(this))), |
retransmission_alarm_(helper->CreateAlarm(new RetransmissionAlarm(this))), |
send_alarm_(helper->CreateAlarm(new SendAlarm(this))), |
@@ -636,13 +637,7 @@ void QuicConnection::OnPacketComplete() { |
<< last_stream_frames_.size() |
<< " stream frames for " << last_header_.public_header.guid; |
- // Must called before ack processing, because processing acks removes entries |
- // from unacket_packets_, increasing the least_unacked. |
- const bool last_packet_should_instigate_ack = ShouldLastPacketInstigateAck(); |
- |
- // If the incoming packet was missing, send an ack immediately. |
- bool send_ack_immediately = received_packet_manager_.IsMissing( |
- last_header_.packet_sequence_number); |
+ MaybeQueueAck(); |
// Discard the packet if the visitor fails to process the stream frames. |
if (!last_stream_frames_.empty() && |
@@ -680,15 +675,36 @@ void QuicConnection::OnPacketComplete() { |
// If there are new missing packets to report, send an ack immediately. |
if (received_packet_manager_.HasNewMissingPackets()) { |
- send_ack_immediately = true; |
+ ack_queued_ = true; |
+ ack_alarm_->Cancel(); |
} |
- MaybeSendInResponseToPacket(send_ack_immediately, |
- last_packet_should_instigate_ack); |
- |
ClearLastFrames(); |
} |
+void QuicConnection::MaybeQueueAck() { |
+ // If the incoming packet was missing, send an ack immediately. |
+ ack_queued_ = received_packet_manager_.IsMissing( |
+ last_header_.packet_sequence_number); |
+ |
+ // ShouldLastPacketInstigateAck must called before ack processing, because |
+ // processing acks removes entries from unacket_packets_, increasing the |
+ // least_unacked. |
+ if (!ack_queued_ && ShouldLastPacketInstigateAck()) { |
+ if (ack_alarm_->IsSet()) { |
+ ack_queued_ = true; |
+ } else { |
+ ack_alarm_->Set(clock_->ApproximateNow().Add( |
+ sent_packet_manager_.DelayedAckTime())); |
+ DVLOG(1) << "Ack timer set; next packet or timer will trigger ACK."; |
+ } |
+ } |
+ |
+ if (ack_queued_) { |
+ ack_alarm_->Cancel(); |
+ } |
+} |
+ |
void QuicConnection::ClearLastFrames() { |
last_stream_frames_.clear(); |
last_goaway_frames_.clear(); |
@@ -717,9 +733,8 @@ bool QuicConnection::ShouldLastPacketInstigateAck() { |
return true; |
} |
- // If the peer is still waiting for a packet that we are no |
- // longer planning to send, we should send an ack to raise |
- // the high water mark. |
+ // If the peer is still waiting for a packet that we are no longer planning to |
+ // send, send an ack to raise the high water mark. |
if (!last_ack_frames_.empty() && |
!last_ack_frames_.back().received_info.missing_packets.empty()) { |
return sent_packet_manager_.GetLeastUnackedSentPacket() > |
@@ -728,39 +743,26 @@ bool QuicConnection::ShouldLastPacketInstigateAck() { |
return false; |
} |
-void QuicConnection::MaybeSendInResponseToPacket( |
- bool send_ack_immediately, |
- bool last_packet_should_instigate_ack) { |
- // |include_ack| is false since we decide about ack bundling below. |
+void QuicConnection::MaybeSendInResponseToPacket() { |
+ if (!connected_) { |
+ return; |
+ } |
ScopedPacketBundler bundler(this, false); |
- |
- if (last_packet_should_instigate_ack) { |
- // In general, we ack every second packet. When we don't ack the first |
- // packet, we set the delayed ack alarm. Thus, if the ack alarm is set |
- // then we know this is the second packet, and we should send an ack. |
- if (send_ack_immediately || ack_alarm_->IsSet()) { |
- SendAck(); |
- DCHECK(!ack_alarm_->IsSet()); |
- } else { |
- ack_alarm_->Set(clock_->ApproximateNow().Add( |
- sent_packet_manager_.DelayedAckTime())); |
- DVLOG(1) << "Ack timer set; next packet or timer will trigger ACK."; |
- } |
+ if (ack_queued_) { |
+ SendAck(); |
} |
- if (!last_ack_frames_.empty()) { |
- // Now the we have received an ack, we might be able to send packets which |
- // are queued locally, or drain streams which are blocked. |
- QuicTime::Delta delay = sent_packet_manager_.TimeUntilSend( |
- time_of_last_received_packet_, NOT_RETRANSMISSION, |
- HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE); |
- if (delay.IsZero()) { |
- send_alarm_->Cancel(); |
- WriteIfNotBlocked(); |
- } else if (!delay.IsInfinite()) { |
- send_alarm_->Cancel(); |
- send_alarm_->Set(time_of_last_received_packet_.Add(delay)); |
- } |
+ // Now that we have received an ack, we might be able to send packets which |
+ // are queued locally, or drain streams which are blocked. |
+ QuicTime::Delta delay = sent_packet_manager_.TimeUntilSend( |
+ time_of_last_received_packet_, NOT_RETRANSMISSION, |
+ HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE); |
+ if (delay.IsZero()) { |
+ send_alarm_->Cancel(); |
+ WriteIfNotBlocked(); |
+ } else if (!delay.IsInfinite()) { |
+ send_alarm_->Cancel(); |
+ send_alarm_->Set(time_of_last_received_packet_.Add(delay)); |
} |
} |
@@ -873,8 +875,10 @@ void QuicConnection::ProcessUdpPacket(const IPEndPoint& self_address, |
<< last_header_.packet_sequence_number; |
return; |
} |
+ |
MaybeProcessUndecryptablePackets(); |
MaybeProcessRevivedPacket(); |
+ MaybeSendInResponseToPacket(); |
} |
bool QuicConnection::OnCanWrite() { |