Index: net/quic/quic_sent_packet_manager.cc |
diff --git a/net/quic/quic_sent_packet_manager.cc b/net/quic/quic_sent_packet_manager.cc |
index 86aba1d74d5c4cfae735fa4829f356daf22861fe..748d6734d6dcc44a4227352075489adcc5aba763 100644 |
--- a/net/quic/quic_sent_packet_manager.cc |
+++ b/net/quic/quic_sent_packet_manager.cc |
@@ -368,11 +368,14 @@ bool QuicSentPacketManager::HasCryptoHandshake( |
QuicSentPacketManager::UnackedPacketMap::iterator |
QuicSentPacketManager::MarkPacketHandled( |
- QuicPacketSequenceNumber sequence_number, ReceivedByPeer received_by_peer) { |
- DCHECK(ContainsKey(unacked_packets_, sequence_number)); |
- |
- // If this packet is pending, remove it and inform the send algorithm. |
+ QuicPacketSequenceNumber sequence_number, |
+ ReceivedByPeer received_by_peer) { |
UnackedPacketMap::iterator it = unacked_packets_.find(sequence_number); |
+ if (it == unacked_packets_.end()) { |
+ LOG(DFATAL) << "Packet is not unacked: " << sequence_number; |
+ return it; |
+ } |
+ // If this packet is pending, remove it and inform the send algorithm. |
if (it->second.pending) { |
size_t bytes_sent = packet_history_map_[sequence_number]->bytes_sent(); |
if (received_by_peer == RECEIVED_BY_PEER) { |
@@ -384,70 +387,56 @@ QuicSentPacketManager::MarkPacketHandled( |
it->second.pending = false; |
} |
- // If this packet has never been retransmitted, then simply drop it. |
- if (it->second.previous_transmissions == NULL) { |
- ++it; |
- DiscardPacket(sequence_number); |
- return it; |
- } |
- |
SequenceNumberSet* previous_transmissions = it->second.previous_transmissions; |
+ if (previous_transmissions == NULL) { |
+ previous_transmissions = new SequenceNumberSet; |
+ previous_transmissions->insert(sequence_number); |
+ } |
DCHECK(!previous_transmissions->empty()); |
SequenceNumberSet::reverse_iterator previous_transmissions_it = |
previous_transmissions->rbegin(); |
QuicPacketSequenceNumber newest_transmission = *previous_transmissions_it; |
- TransmissionInfo* transmission_info = |
- FindOrNull(unacked_packets_, newest_transmission); |
if (newest_transmission != sequence_number) { |
++stats_->packets_spuriously_retransmitted; |
} |
- if (newest_transmission == sequence_number) { |
- DiscardPacket(newest_transmission); |
- } else if (HasCryptoHandshake(*transmission_info)) { |
- // If it's a crypto handshake packet, discard it and all retransmissions, |
- // since they won't be acked now that one has been processed. |
- if (transmission_info->pending) { |
- OnPacketAbandoned(unacked_packets_.find(newest_transmission)); |
- } |
- DiscardPacket(newest_transmission); |
- } else { |
- // If we have received an ack for a previous transmission of a packet, |
- // we want to keep the "new" transmission of the packet unacked, |
- // but prevent the data from being retransmitted. |
- delete transmission_info->retransmittable_frames; |
- transmission_info->retransmittable_frames = NULL; |
- transmission_info->previous_transmissions = NULL; |
- } |
- // Clear out information all previous transmissions unless they're pending. |
- ++previous_transmissions_it; |
+ bool has_cryto_handshake = HasCryptoHandshake( |
+ *FindOrNull(unacked_packets_, newest_transmission)); |
+ if (has_cryto_handshake) { |
+ --pending_crypto_packet_count_; |
+ } |
while (previous_transmissions_it != previous_transmissions->rend()) { |
QuicPacketSequenceNumber previous_transmission = *previous_transmissions_it; |
- ++previous_transmissions_it; |
- // If the packet was TLP retransmitted, the old copy is still pending. |
- // Keep it until it is lost or acked. |
- if (unacked_packets_[previous_transmission].pending) { |
- // Previous transmissions will be deleted, so set it to NULL. |
- unacked_packets_[previous_transmission].previous_transmissions = NULL; |
+ TransmissionInfo* transmission_info = |
+ FindOrNull(unacked_packets_, previous_transmission); |
+ if (transmission_info->retransmittable_frames != NULL) { |
+ // Since some version of this packet has been acked, ensure that |
+ // the data is not retransmitted again. |
+ delete transmission_info->retransmittable_frames; |
+ transmission_info->retransmittable_frames = NULL; |
+ } |
+ if (ContainsKey(pending_retransmissions_, previous_transmission)) { |
+ // Don't bother retransmitting this packet, if it has been |
+ // marked for retransmission. |
+ pending_retransmissions_.erase(previous_transmission); |
+ } |
+ if (has_cryto_handshake) { |
+ // If it's a crypto handshake packet, discard it and all retransmissions, |
+ // since they won't be acked now that one has been processed. |
+ if (transmission_info->pending) { |
+ OnPacketAbandoned(unacked_packets_.find(newest_transmission)); |
+ } |
+ transmission_info->pending = false; |
+ } |
+ if (!transmission_info->pending) { |
+ unacked_packets_.erase(previous_transmission); |
} else { |
- DiscardPacket(previous_transmission); |
+ transmission_info->previous_transmissions = NULL; |
} |
+ ++previous_transmissions_it; |
} |
- |
delete previous_transmissions; |
- if (ContainsKey(pending_retransmissions_, newest_transmission)) { |
- pending_retransmissions_.erase(newest_transmission); |
- if (!unacked_packets_[newest_transmission].pending) { |
- // If the newest transmission has already been marked for retransmission |
- // and has already been abandoned, then we should remove it from |
- // unacked_packets_, as well as cancel the retransmission. |
- DCHECK(ContainsKey(unacked_packets_, newest_transmission)); |
- DCHECK(!unacked_packets_[newest_transmission].previous_transmissions); |
- unacked_packets_.erase(newest_transmission); |
- } |
- } |
- |
UnackedPacketMap::iterator next_unacked = unacked_packets_.begin(); |
while (next_unacked != unacked_packets_.end() && |
next_unacked->first < sequence_number) { |
@@ -456,27 +445,6 @@ QuicSentPacketManager::MarkPacketHandled( |
return next_unacked; |
} |
-void QuicSentPacketManager::DiscardPacket( |
- QuicPacketSequenceNumber sequence_number) { |
- UnackedPacketMap::iterator unacked_it = |
- unacked_packets_.find(sequence_number); |
- DCHECK(unacked_it != unacked_packets_.end()); |
- // Ensure the packet is no longer pending when it's discarded. |
- DCHECK(!unacked_it->second.pending); |
- |
- RetransmittableFrames* retransmittable_frames = |
- unacked_it->second.retransmittable_frames; |
- if (HasCryptoHandshake(unacked_it->second)) { |
- --pending_crypto_packet_count_; |
- } |
- |
- // Delete the retransmittable frames. |
- delete retransmittable_frames; |
- unacked_packets_.erase(unacked_it); |
- pending_retransmissions_.erase(sequence_number); |
- return; |
-} |
- |
bool QuicSentPacketManager::IsUnacked( |
QuicPacketSequenceNumber sequence_number) const { |
return ContainsKey(unacked_packets_, sequence_number); |