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

Unified Diff: net/quic/quic_connection.cc

Issue 16256017: Land Recent QUIC changes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix for Android DEBUG builds with DEATH_TEST Created 7 years, 6 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
Index: net/quic/quic_connection.cc
diff --git a/net/quic/quic_connection.cc b/net/quic/quic_connection.cc
index 0698dd354dc3d2bf142c53a3ff0c430a5cb81a86..9932032f0ac3b2b868dc9c615c9f08e6e8caa499 100644
--- a/net/quic/quic_connection.cc
+++ b/net/quic/quic_connection.cc
@@ -125,7 +125,7 @@ QuicConnection::~QuicConnection() {
it != queued_packets_.end(); ++it) {
delete it->packet;
}
- LOG(ERROR) << "Quic connection " << write_blocked_;
+ DLOG(INFO) << ENDPOINT << "write_blocked: " << write_blocked_;
}
bool QuicConnection::SelectMutualVersion(
@@ -242,6 +242,7 @@ void QuicConnection::OnVersionNegotiationPacket(
if (!SelectMutualVersion(packet.versions)) {
SendConnectionCloseWithDetails(QUIC_INVALID_VERSION,
"no common version found");
+ return;
}
version_negotiation_state_ = NEGOTIATED_VERSION;
@@ -361,19 +362,18 @@ bool QuicConnection::OnAckFrame(const QuicAckFrame& incoming_ack) {
congestion_manager_.OnIncomingAckFrame(incoming_ack,
time_of_last_received_packet_);
- // Now the we have received an ack, we might be able to send queued packets.
- if (!queued_packets_.empty()) {
- QuicTime::Delta delay = congestion_manager_.TimeUntilSend(
- time_of_last_received_packet_, NOT_RETRANSMISSION,
- HAS_RETRANSMITTABLE_DATA);
- if (delay.IsZero()) {
- helper_->UnregisterSendAlarmIfRegistered();
- if (!write_blocked_) {
- OnCanWrite();
- }
- } else if (!delay.IsInfinite()) {
- helper_->SetSendAlarm(time_of_last_received_packet_.Add(delay));
+ // 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 = congestion_manager_.TimeUntilSend(
+ time_of_last_received_packet_, NOT_RETRANSMISSION,
+ HAS_RETRANSMITTABLE_DATA);
+ if (delay.IsZero()) {
+ helper_->UnregisterSendAlarmIfRegistered();
+ if (!write_blocked_) {
+ OnCanWrite();
}
+ } else if (!delay.IsInfinite()) {
+ helper_->SetSendAlarm(time_of_last_received_packet_.Add(delay));
}
return connected_;
}
@@ -461,24 +461,8 @@ bool QuicConnection::ValidateAckFrame(const QuicAckFrame& incoming_ack) {
return true;
}
-void QuicConnection::UpdatePacketInformationReceivedByPeer(
- const QuicAckFrame& incoming_ack) {
- SequenceNumberSet acked_packets;
-
- // ValidateAck should fail if largest_observed ever shrinks.
- DCHECK_LE(peer_largest_observed_packet_,
- incoming_ack.received_info.largest_observed);
- peer_largest_observed_packet_ = incoming_ack.received_info.largest_observed;
-
- if (incoming_ack.received_info.missing_packets.empty()) {
- least_packet_awaited_by_peer_ = peer_largest_observed_packet_ + 1;
- } else {
- least_packet_awaited_by_peer_ =
- *(incoming_ack.received_info.missing_packets.begin());
- }
-
- entropy_manager_.ClearSentEntropyBefore(least_packet_awaited_by_peer_ - 1);
-
+void QuicConnection::HandleAckForSentPackets(const QuicAckFrame& incoming_ack,
+ SequenceNumberSet* acked_packets) {
int retransmitted_packets = 0;
// Go through the packets we have not received an ack for and see if this
// incoming_ack shows they've been seen by the peer.
@@ -492,11 +476,9 @@ void QuicConnection::UpdatePacketInformationReceivedByPeer(
if (!IsAwaitingPacket(incoming_ack.received_info, sequence_number)) {
// Packet was acked, so remove it from our unacked packet list.
DVLOG(1) << ENDPOINT <<"Got an ack for packet " << sequence_number;
- acked_packets.insert(sequence_number);
+ acked_packets->insert(sequence_number);
delete unacked;
- UnackedPacketMap::iterator it_tmp = it;
- ++it;
- unacked_packets_.erase(it_tmp);
+ unacked_packets_.erase(it++);
retransmission_map_.erase(sequence_number);
} else {
// This is a packet which we planned on retransmitting and has not been
@@ -522,6 +504,48 @@ void QuicConnection::UpdatePacketInformationReceivedByPeer(
}
}
}
+}
+
+void QuicConnection::HandleAckForSentFecPackets(
+ const QuicAckFrame& incoming_ack, SequenceNumberSet* acked_packets) {
+ UnackedPacketMap::iterator it = unacked_fec_packets_.begin();
+ while (it != unacked_fec_packets_.end()) {
+ QuicPacketSequenceNumber sequence_number = it->first;
+ if (sequence_number > peer_largest_observed_packet_) {
+ break;
+ }
+ if (!IsAwaitingPacket(incoming_ack.received_info, sequence_number)) {
+ DVLOG(1) << ENDPOINT << "Got an ack for fec packet: " << sequence_number;
+ acked_packets->insert(sequence_number);
+ unacked_fec_packets_.erase(it++);
+ } else {
+ DVLOG(1) << ENDPOINT << "Still missing ack for fec packet: "
+ << sequence_number;
+ ++it;
+ }
+ }
+}
+
+void QuicConnection::UpdatePacketInformationReceivedByPeer(
+ const QuicAckFrame& incoming_ack) {
+ // ValidateAck should fail if largest_observed ever shrinks.
+ DCHECK_LE(peer_largest_observed_packet_,
+ incoming_ack.received_info.largest_observed);
+ peer_largest_observed_packet_ = incoming_ack.received_info.largest_observed;
+
+ if (incoming_ack.received_info.missing_packets.empty()) {
+ least_packet_awaited_by_peer_ = peer_largest_observed_packet_ + 1;
+ } else {
+ least_packet_awaited_by_peer_ =
+ *(incoming_ack.received_info.missing_packets.begin());
+ }
+
+ entropy_manager_.ClearSentEntropyBefore(least_packet_awaited_by_peer_ - 1);
+
+ SequenceNumberSet acked_packets;
+ HandleAckForSentPackets(incoming_ack, &acked_packets);
+ HandleAckForSentFecPackets(incoming_ack, &acked_packets);
+
if (acked_packets.size() > 0) {
visitor_->OnAck(acked_packets);
}
@@ -725,7 +749,7 @@ void QuicConnection::ProcessUdpPacket(const IPEndPoint& self_address,
self_address_ = self_address;
}
- if (!(peer_address == peer_address_) && (self_address == self_address_)) {
+ if (!(peer_address == peer_address_ && self_address == self_address_)) {
address_migrating_ = true;
}
@@ -960,7 +984,7 @@ bool QuicConnection::IsRetransmission(
it->second.number_retransmissions > 0;
}
-void QuicConnection::MaybeSetupRetransmission(
+void QuicConnection::SetupRetransmission(
QuicPacketSequenceNumber sequence_number) {
RetransmissionMap::iterator it = retransmission_map_.find(sequence_number);
if (it == retransmission_map_.end()) {
@@ -973,9 +997,11 @@ void QuicConnection::MaybeSetupRetransmission(
congestion_manager_.GetRetransmissionDelay(
unacked_packets_.size(),
retransmission_info.number_retransmissions);
- retransmission_info.scheduled_time =
- clock_->ApproximateNow().Add(retransmission_delay);
- retransmission_timeouts_.push(retransmission_info);
+
+ retransmission_timeouts_.push(RetransmissionTime(
+ sequence_number,
+ clock_->ApproximateNow().Add(retransmission_delay),
+ false));
// Do not set the retransmisson alarm if we're already handling the
// retransmission alarm because the retransmission alarm will be reset when
@@ -987,6 +1013,18 @@ void QuicConnection::MaybeSetupRetransmission(
// SendStreamData().
}
+void QuicConnection::SetupAbandonFecTimer(
+ QuicPacketSequenceNumber sequence_number) {
+ DCHECK(ContainsKey(unacked_fec_packets_, sequence_number));
+ QuicTime::Delta retransmission_delay =
+ QuicTime::Delta::FromMilliseconds(
+ congestion_manager_.DefaultRetransmissionTime().ToMilliseconds() * 3);
+ retransmission_timeouts_.push(RetransmissionTime(
+ sequence_number,
+ clock_->ApproximateNow().Add(retransmission_delay),
+ true));
+}
+
void QuicConnection::DropPacket(QuicPacketSequenceNumber sequence_number) {
UnackedPacketMap::iterator unacked_it =
unacked_packets_.find(sequence_number);
@@ -1077,7 +1115,11 @@ bool QuicConnection::WritePacket(EncryptionLevel level,
// Set the retransmit alarm only when we have sent the packet to the client
// and not when it goes to the pending queue, otherwise we will end up adding
// an entry to retransmission_timeout_ every time we attempt a write.
- MaybeSetupRetransmission(sequence_number);
+ if (retransmittable == HAS_RETRANSMITTABLE_DATA) {
+ SetupRetransmission(sequence_number);
+ } else if (packet->is_fec_packet()) {
+ SetupAbandonFecTimer(sequence_number);
+ }
congestion_manager_.SentPacket(sequence_number, now, packet->length(),
retransmission);
@@ -1111,6 +1153,10 @@ bool QuicConnection::OnSerializedPacket(
retransmission_map_.insert(
make_pair(serialized_packet.sequence_number,
RetransmissionInfo(serialized_packet.sequence_number)));
+ } else if (serialized_packet.packet->is_fec_packet()) {
+ unacked_fec_packets_.insert(make_pair(
+ serialized_packet.sequence_number,
+ serialized_packet.retransmittable_frames));
}
return SendOrQueuePacket(encryption_level_,
serialized_packet.sequence_number,
@@ -1180,6 +1226,17 @@ void QuicConnection::SendAck() {
packet_generator_.SetShouldSendAck(send_feedback);
}
+void QuicConnection::MaybeAbandonFecPacket(
+ QuicPacketSequenceNumber sequence_number) {
+ if (!ContainsKey(unacked_fec_packets_, sequence_number)) {
+ DVLOG(2) << ENDPOINT << "no need to abandon fec packet: "
+ << sequence_number << "; it's already acked'";
+ return;
+ }
+ congestion_manager_.AbandoningPacket(sequence_number);
+ // TODO(satyashekhar): Should this decrease the congestion window?
+}
+
QuicTime QuicConnection::OnRetransmissionTimeout() {
// This guards against registering the alarm later than we should.
//
@@ -1192,19 +1249,24 @@ QuicTime QuicConnection::OnRetransmissionTimeout() {
for (size_t i = 0; i < max_packets_per_retransmission_alarm_ &&
!retransmission_timeouts_.empty(); ++i) {
- RetransmissionInfo retransmission_info = retransmission_timeouts_.top();
- DCHECK(retransmission_info.scheduled_time.IsInitialized());
- if (retransmission_info.scheduled_time > clock_->ApproximateNow()) {
+ RetransmissionTime retransmission_time = retransmission_timeouts_.top();
+ DCHECK(retransmission_time.scheduled_time.IsInitialized());
+ if (retransmission_time.scheduled_time > clock_->ApproximateNow()) {
break;
}
retransmission_timeouts_.pop();
- if (!MaybeRetransmitPacketForRTO(retransmission_info.sequence_number)) {
+
+ if (retransmission_time.for_fec) {
+ MaybeAbandonFecPacket(retransmission_time.sequence_number);
+ continue;
+ } else if (
+ !MaybeRetransmitPacketForRTO(retransmission_time.sequence_number)) {
DLOG(INFO) << ENDPOINT << "MaybeRetransmitPacketForRTO failed: "
<< "adding an extra delay for "
- << retransmission_info.sequence_number;
- retransmission_info.scheduled_time = clock_->ApproximateNow().Add(
+ << retransmission_time.sequence_number;
+ retransmission_time.scheduled_time = clock_->ApproximateNow().Add(
congestion_manager_.DefaultRetransmissionTime());
- retransmission_timeouts_.push(retransmission_info);
+ retransmission_timeouts_.push(retransmission_time);
}
}
@@ -1377,21 +1439,21 @@ bool QuicConnection::HasQueuedData() const {
}
void QuicConnection::SetIdleNetworkTimeout(QuicTime::Delta timeout) {
- // if (timeout < idle_network_timeout_) {
+ if (timeout < idle_network_timeout_) {
idle_network_timeout_ = timeout;
CheckForTimeout();
- // } else {
- // idle_network_timeout_ = timeout;
- // }
+ } else {
+ idle_network_timeout_ = timeout;
+ }
}
void QuicConnection::SetOverallConnectionTimeout(QuicTime::Delta timeout) {
- // if (timeout < overall_connection_timeout_) {
+ if (timeout < overall_connection_timeout_) {
overall_connection_timeout_ = timeout;
CheckForTimeout();
- // } else {
- // overall_connection_timeout_ = timeout;
- // }
+ } else {
+ overall_connection_timeout_ = timeout;
+ }
}
bool QuicConnection::CheckForTimeout() {
@@ -1399,6 +1461,9 @@ bool QuicConnection::CheckForTimeout() {
QuicTime time_of_last_packet = std::max(time_of_last_received_packet_,
time_of_last_sent_packet_);
+ // |delta| can be < 0 as |now| is approximate time but |time_of_last_packet|
+ // is accurate time. However, this should not change the behavior of
+ // timeout handling.
QuicTime::Delta delta = now.Subtract(time_of_last_packet);
DVLOG(1) << ENDPOINT << "last packet "
<< time_of_last_packet.ToDebuggingValue()

Powered by Google App Engine
This is Rietveld 408576698