Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(570)

Unified Diff: net/quic/quic_connection.cc

Issue 146033003: Land Recent QUIC Changes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix compile error Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/quic/quic_connection.h ('k') | net/quic/quic_connection_test.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/quic/quic_connection.cc
diff --git a/net/quic/quic_connection.cc b/net/quic/quic_connection.cc
index f1e25d6e24b4989a0fc8062db44263385b8777b9..737fee4d2c94610cee37c76a2bf41043de1ac34e 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,61 +743,57 @@ 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));
}
}
void QuicConnection::SendVersionNegotiationPacket() {
+ // TODO(alyssar): implement zero server state negotiation.
+ pending_version_negotiation_packet_ = true;
+ if (writer_->IsWriteBlocked()) {
+ visitor_->OnWriteBlocked();
+ return;
+ }
scoped_ptr<QuicEncryptedPacket> version_packet(
packet_creator_.SerializeVersionNegotiationPacket(
framer_.supported_versions()));
- // TODO(satyamshekhar): implement zero server state negotiation.
- WriteResult result =
- writer_->WritePacket(version_packet->data(), version_packet->length(),
- self_address().address(), peer_address(), this);
- if (result.status == WRITE_STATUS_OK ||
- (result.status == WRITE_STATUS_BLOCKED &&
- writer_->IsWriteBlockedDataBuffered())) {
- pending_version_negotiation_packet_ = false;
- return;
- }
+ WriteResult result = writer_->WritePacket(
+ version_packet->data(), version_packet->length(),
+ self_address().address(), peer_address());
+
if (result.status == WRITE_STATUS_ERROR) {
// We can't send an error as the socket is presumably borked.
CloseConnection(QUIC_PACKET_WRITE_ERROR, false);
+ return;
}
- pending_version_negotiation_packet_ = true;
+ if (result.status == WRITE_STATUS_BLOCKED) {
+ visitor_->OnWriteBlocked();
+ if (writer_->IsWriteBlockedDataBuffered()) {
+ pending_version_negotiation_packet_ = false;
+ }
+ return;
+ }
+
+ pending_version_negotiation_packet_ = false;
}
QuicConsumedData QuicConnection::SendStreamData(
@@ -873,8 +884,10 @@ void QuicConnection::ProcessUdpPacket(const IPEndPoint& self_address,
<< last_header_.packet_sequence_number;
return;
}
+
MaybeProcessUndecryptablePackets();
MaybeProcessRevivedPacket();
+ MaybeSendInResponseToPacket();
}
bool QuicConnection::OnCanWrite() {
@@ -1027,6 +1040,7 @@ bool QuicConnection::CanWrite(TransmissionType transmission_type,
HasRetransmittableData retransmittable,
IsHandshake handshake) {
if (writer_->IsWriteBlocked()) {
+ visitor_->OnWriteBlocked();
return false;
}
@@ -1107,6 +1121,7 @@ bool QuicConnection::WritePacket(EncryptionLevel level,
// This assures we won't try to write *forced* packets when blocked.
// Return true to stop processing.
if (writer_->IsWriteBlocked()) {
+ visitor_->OnWriteBlocked();
return true;
}
}
@@ -1141,7 +1156,7 @@ bool QuicConnection::WritePacket(EncryptionLevel level,
WriteResult result =
writer_->WritePacket(encrypted->data(), encrypted->length(),
- self_address().address(), peer_address(), this);
+ self_address().address(), peer_address());
if (result.error_code == ERR_IO_PENDING) {
DCHECK_EQ(WRITE_STATUS_BLOCKED, result.status);
}
@@ -1150,6 +1165,7 @@ bool QuicConnection::WritePacket(EncryptionLevel level,
debug_visitor_->OnPacketSent(sequence_number, level, *encrypted, result);
}
if (result.status == WRITE_STATUS_BLOCKED) {
+ visitor_->OnWriteBlocked();
// If the socket buffers the the data, then the packet should not
// be queued and sent again, which would result in an unnecessary
// duplicate packet being sent. The helper must call OnPacketSent
@@ -1195,25 +1211,12 @@ bool QuicConnection::ShouldDiscardPacket(
return true;
}
- if (retransmittable == HAS_RETRANSMITTABLE_DATA) {
- if (sent_packet_manager_.IsPreviousTransmission(sequence_number)) {
- // If somehow we have already retransmitted this packet *before*
- // we actually send it for the first time (I think this is probably
- // impossible in the real world), then don't bother sending it.
- // We don't want to call DiscardUnackedPacket because in this case
- // the peer has not yet ACK'd the data. We need the subsequent
- // retransmission to be sent.
- DVLOG(1) << ENDPOINT << "Dropping packet: " << sequence_number
- << " since it has already been retransmitted.";
- return true;
- }
-
- if (!sent_packet_manager_.HasRetransmittableFrames(sequence_number)) {
- DVLOG(1) << ENDPOINT << "Dropping packet: " << sequence_number
- << " since a previous transmission has been acked.";
- sent_packet_manager_.DiscardUnackedPacket(sequence_number);
- return true;
- }
+ if (retransmittable == HAS_RETRANSMITTABLE_DATA &&
+ !sent_packet_manager_.HasRetransmittableFrames(sequence_number)) {
+ DVLOG(1) << ENDPOINT << "Dropping packet: " << sequence_number
+ << " since a previous transmission has been acked.";
+ sent_packet_manager_.DiscardUnackedPacket(sequence_number);
+ return true;
}
return false;
« no previous file with comments | « net/quic/quic_connection.h ('k') | net/quic/quic_connection_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698