| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/quic/quic_unacked_packet_map.h" | 5 #include "net/quic/quic_unacked_packet_map.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/stl_util.h" | 8 #include "base/stl_util.h" |
| 9 #include "net/quic/quic_connection_stats.h" | 9 #include "net/quic/quic_connection_stats.h" |
| 10 #include "net/quic/quic_utils_chromium.h" | 10 #include "net/quic/quic_utils_chromium.h" |
| 11 | 11 |
| 12 using std::max; | 12 using std::max; |
| 13 | 13 |
| 14 namespace net { | 14 namespace net { |
| 15 | 15 |
| 16 QuicUnackedPacketMap::QuicUnackedPacketMap() | 16 QuicUnackedPacketMap::QuicUnackedPacketMap() |
| 17 : largest_sent_packet_(0), | 17 : largest_sent_packet_(0), |
| 18 largest_observed_(0), | 18 largest_observed_(0), |
| 19 least_unacked_(1), | 19 least_unacked_(1), |
| 20 bytes_in_flight_(0), | 20 bytes_in_flight_(0), |
| 21 pending_crypto_packet_count_(0) { | 21 pending_crypto_packet_count_(0) { |
| 22 } | 22 } |
| 23 | 23 |
| 24 QuicUnackedPacketMap::~QuicUnackedPacketMap() { | 24 QuicUnackedPacketMap::~QuicUnackedPacketMap() { |
| 25 QuicPacketSequenceNumber index = least_unacked_; | 25 QuicPacketSequenceNumber index = least_unacked_; |
| 26 for (UnackedPacketMap::iterator it = unacked_packets_.begin(); | 26 for (UnackedPacketMap::iterator it = unacked_packets_.begin(); |
| 27 it != unacked_packets_.end(); ++it, ++index) { | 27 it != unacked_packets_.end(); ++it, ++index) { |
| 28 delete it->retransmittable_frames; | 28 delete it->retransmittable_frames; |
| 29 // Only delete all_transmissions once, for the newest packet. | 29 // Only delete all_transmissions once, for the newest packet. |
| 30 if (index == *it->all_transmissions->rbegin()) { | 30 if (it->all_transmissions != NULL && |
| 31 index == *it->all_transmissions->rbegin()) { |
| 31 delete it->all_transmissions; | 32 delete it->all_transmissions; |
| 32 } | 33 } |
| 33 } | 34 } |
| 34 } | 35 } |
| 35 | 36 |
| 36 // TODO(ianswett): Combine this method with OnPacketSent once packets are always | 37 // TODO(ianswett): Combine this method with OnPacketSent once packets are always |
| 37 // sent in order and the connection tracks RetransmittableFrames for longer. | 38 // sent in order and the connection tracks RetransmittableFrames for longer. |
| 38 void QuicUnackedPacketMap::AddPacket( | 39 void QuicUnackedPacketMap::AddPacket( |
| 39 const SerializedPacket& serialized_packet) { | 40 const SerializedPacket& serialized_packet) { |
| 40 DCHECK_EQ(least_unacked_ + unacked_packets_.size(), | 41 DCHECK_EQ(least_unacked_ + unacked_packets_.size(), |
| 41 serialized_packet.sequence_number); | 42 serialized_packet.sequence_number); |
| 42 unacked_packets_.push_back( | 43 unacked_packets_.push_back( |
| 43 TransmissionInfo(serialized_packet.retransmittable_frames, | 44 TransmissionInfo(serialized_packet.retransmittable_frames, |
| 44 serialized_packet.sequence_number, | |
| 45 serialized_packet.sequence_number_length)); | 45 serialized_packet.sequence_number_length)); |
| 46 if (serialized_packet.retransmittable_frames != NULL && | 46 if (serialized_packet.retransmittable_frames != NULL && |
| 47 serialized_packet.retransmittable_frames->HasCryptoHandshake() | 47 serialized_packet.retransmittable_frames->HasCryptoHandshake() |
| 48 == IS_HANDSHAKE) { | 48 == IS_HANDSHAKE) { |
| 49 ++pending_crypto_packet_count_; | 49 ++pending_crypto_packet_count_; |
| 50 } | 50 } |
| 51 } | 51 } |
| 52 | 52 |
| 53 void QuicUnackedPacketMap::RemoveObsoletePackets() { | 53 void QuicUnackedPacketMap::RemoveObsoletePackets() { |
| 54 while (!unacked_packets_.empty()) { | 54 while (!unacked_packets_.empty()) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 75 RetransmittableFrames* frames = transmission_info->retransmittable_frames; | 75 RetransmittableFrames* frames = transmission_info->retransmittable_frames; |
| 76 LOG_IF(DFATAL, frames == NULL) << "Attempt to retransmit packet with no " | 76 LOG_IF(DFATAL, frames == NULL) << "Attempt to retransmit packet with no " |
| 77 << "retransmittable frames: " | 77 << "retransmittable frames: " |
| 78 << old_sequence_number; | 78 << old_sequence_number; |
| 79 | 79 |
| 80 // We keep the old packet in the unacked packet list until it, or one of | 80 // We keep the old packet in the unacked packet list until it, or one of |
| 81 // the retransmissions of it are acked. | 81 // the retransmissions of it are acked. |
| 82 transmission_info->retransmittable_frames = NULL; | 82 transmission_info->retransmittable_frames = NULL; |
| 83 // Only keep one transmission older than largest observed, because only the | 83 // Only keep one transmission older than largest observed, because only the |
| 84 // most recent is expected to possibly be a spurious retransmission. | 84 // most recent is expected to possibly be a spurious retransmission. |
| 85 if (transmission_info->all_transmissions->size() > 1 && | 85 if (transmission_info->all_transmissions != NULL && |
| 86 *(++transmission_info->all_transmissions->begin()) < largest_observed_) { | 86 *(++transmission_info->all_transmissions->begin()) < largest_observed_) { |
| 87 QuicPacketSequenceNumber old_transmission = | 87 QuicPacketSequenceNumber old_transmission = |
| 88 *transmission_info->all_transmissions->begin(); | 88 *transmission_info->all_transmissions->begin(); |
| 89 TransmissionInfo* old_info = | 89 TransmissionInfo* old_info = |
| 90 &unacked_packets_[old_transmission - least_unacked_]; | 90 &unacked_packets_[old_transmission - least_unacked_]; |
| 91 // Don't remove old packets if they're still in flight. | 91 // Don't remove old packets if they're still in flight. |
| 92 if (!old_info->in_flight) { | 92 if (!old_info->in_flight) { |
| 93 transmission_info->all_transmissions->erase(old_transmission); | 93 old_info->all_transmissions->pop_front(); |
| 94 // This will cause the packet be removed in RemoveObsoletePackets. | 94 // This will cause the packet be removed in RemoveObsoletePackets. |
| 95 old_info->all_transmissions = new SequenceNumberSet(); | 95 old_info->all_transmissions = NULL; |
| 96 old_info->all_transmissions->insert(old_transmission); | |
| 97 } | 96 } |
| 98 } | 97 } |
| 98 if (transmission_info->all_transmissions == NULL) { |
| 99 transmission_info->all_transmissions = new SequenceNumberList(); |
| 100 transmission_info->all_transmissions->push_back(old_sequence_number); |
| 101 } |
| 102 transmission_info->all_transmissions->push_back(new_sequence_number); |
| 99 unacked_packets_.push_back( | 103 unacked_packets_.push_back( |
| 100 TransmissionInfo(frames, | 104 TransmissionInfo(frames, |
| 101 new_sequence_number, | |
| 102 transmission_info->sequence_number_length, | 105 transmission_info->sequence_number_length, |
| 103 transmission_type, | 106 transmission_type, |
| 104 transmission_info->all_transmissions)); | 107 transmission_info->all_transmissions)); |
| 105 } | 108 } |
| 106 | 109 |
| 107 void QuicUnackedPacketMap::ClearPreviousRetransmissions(size_t num_to_clear) { | 110 void QuicUnackedPacketMap::ClearPreviousRetransmissions(size_t num_to_clear) { |
| 108 while (!unacked_packets_.empty() && num_to_clear > 0) { | 111 while (!unacked_packets_.empty() && num_to_clear > 0) { |
| 109 // If this packet is in flight, or has retransmittable data, then there is | 112 // If this packet is in flight, or has retransmittable data, then there is |
| 110 // no point in clearing out any further packets, because they would not | 113 // no point in clearing out any further packets, because they would not |
| 111 // affect the high water mark. | 114 // affect the high water mark. |
| 112 TransmissionInfo* info = &unacked_packets_.front(); | 115 TransmissionInfo* info = &unacked_packets_.front(); |
| 113 if (info->in_flight || info->retransmittable_frames != NULL) { | 116 if (info->in_flight || info->retransmittable_frames != NULL) { |
| 114 break; | 117 break; |
| 115 } | 118 } |
| 116 | 119 |
| 117 info->all_transmissions->erase(least_unacked_); | 120 info->all_transmissions->pop_front(); |
| 118 LOG_IF(DFATAL, info->all_transmissions->empty()) | 121 LOG_IF(DFATAL, info->all_transmissions->empty()) |
| 119 << "Previous retransmissions must have a newer transmission."; | 122 << "Previous retransmissions must have a newer transmission."; |
| 120 unacked_packets_.pop_front(); | 123 unacked_packets_.pop_front(); |
| 121 ++least_unacked_; | 124 ++least_unacked_; |
| 122 --num_to_clear; | 125 --num_to_clear; |
| 123 } | 126 } |
| 124 } | 127 } |
| 125 | 128 |
| 126 bool QuicUnackedPacketMap::HasRetransmittableFrames( | 129 bool QuicUnackedPacketMap::HasRetransmittableFrames( |
| 127 QuicPacketSequenceNumber sequence_number) const { | 130 QuicPacketSequenceNumber sequence_number) const { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 138 unacked_packets_[sequence_number - least_unacked_].nack_count = | 141 unacked_packets_[sequence_number - least_unacked_].nack_count = |
| 139 max(min_nacks, | 142 max(min_nacks, |
| 140 unacked_packets_[sequence_number - least_unacked_].nack_count); | 143 unacked_packets_[sequence_number - least_unacked_].nack_count); |
| 141 } | 144 } |
| 142 | 145 |
| 143 void QuicUnackedPacketMap::RemoveRetransmittability( | 146 void QuicUnackedPacketMap::RemoveRetransmittability( |
| 144 QuicPacketSequenceNumber sequence_number) { | 147 QuicPacketSequenceNumber sequence_number) { |
| 145 DCHECK_GE(sequence_number, least_unacked_); | 148 DCHECK_GE(sequence_number, least_unacked_); |
| 146 DCHECK_LT(sequence_number, least_unacked_ + unacked_packets_.size()); | 149 DCHECK_LT(sequence_number, least_unacked_ + unacked_packets_.size()); |
| 147 TransmissionInfo* info = &unacked_packets_[sequence_number - least_unacked_]; | 150 TransmissionInfo* info = &unacked_packets_[sequence_number - least_unacked_]; |
| 148 SequenceNumberSet* all_transmissions = info->all_transmissions; | 151 SequenceNumberList* all_transmissions = info->all_transmissions; |
| 149 if (all_transmissions->size() == 1) { | 152 if (all_transmissions == NULL) { |
| 150 MaybeRemoveRetransmittableFrames(info); | 153 MaybeRemoveRetransmittableFrames(info); |
| 151 return; | 154 return; |
| 152 } | 155 } |
| 153 // TODO(ianswett): Consider adding a check to ensure there are retransmittable | 156 // TODO(ianswett): Consider adding a check to ensure there are retransmittable |
| 154 // frames associated with this packet. | 157 // frames associated with this packet. |
| 155 for (SequenceNumberSet::const_iterator it = all_transmissions->begin(); | 158 for (SequenceNumberList::const_iterator it = all_transmissions->begin(); |
| 156 it != all_transmissions->end(); ++it) { | 159 it != all_transmissions->end(); ++it) { |
| 157 TransmissionInfo* transmission_info = | 160 TransmissionInfo* transmission_info = |
| 158 &unacked_packets_[*it - least_unacked_]; | 161 &unacked_packets_[*it - least_unacked_]; |
| 159 MaybeRemoveRetransmittableFrames(transmission_info); | 162 MaybeRemoveRetransmittableFrames(transmission_info); |
| 160 transmission_info->all_transmissions = new SequenceNumberSet(); | 163 transmission_info->all_transmissions = NULL; |
| 161 transmission_info->all_transmissions->insert(*it); | |
| 162 } | 164 } |
| 163 delete all_transmissions; | 165 delete all_transmissions; |
| 164 } | 166 } |
| 165 | 167 |
| 166 void QuicUnackedPacketMap::MaybeRemoveRetransmittableFrames( | 168 void QuicUnackedPacketMap::MaybeRemoveRetransmittableFrames( |
| 167 TransmissionInfo* transmission_info) { | 169 TransmissionInfo* transmission_info) { |
| 168 if (transmission_info->retransmittable_frames != NULL) { | 170 if (transmission_info->retransmittable_frames != NULL) { |
| 169 if (transmission_info->retransmittable_frames->HasCryptoHandshake() | 171 if (transmission_info->retransmittable_frames->HasCryptoHandshake() |
| 170 == IS_HANDSHAKE) { | 172 == IS_HANDSHAKE) { |
| 171 --pending_crypto_packet_count_; | 173 --pending_crypto_packet_count_; |
| 172 } | 174 } |
| 173 delete transmission_info->retransmittable_frames; | 175 delete transmission_info->retransmittable_frames; |
| 174 transmission_info->retransmittable_frames = NULL; | 176 transmission_info->retransmittable_frames = NULL; |
| 175 } | 177 } |
| 176 } | 178 } |
| 177 | 179 |
| 178 void QuicUnackedPacketMap::IncreaseLargestObserved( | 180 void QuicUnackedPacketMap::IncreaseLargestObserved( |
| 179 QuicPacketSequenceNumber largest_observed) { | 181 QuicPacketSequenceNumber largest_observed) { |
| 180 DCHECK_LE(largest_observed_, largest_observed); | 182 DCHECK_LE(largest_observed_, largest_observed); |
| 181 largest_observed_ = largest_observed; | 183 largest_observed_ = largest_observed; |
| 182 } | 184 } |
| 183 | 185 |
| 184 bool QuicUnackedPacketMap::IsPacketUseless( | 186 bool QuicUnackedPacketMap::IsPacketUseless( |
| 185 QuicPacketSequenceNumber sequence_number, | 187 QuicPacketSequenceNumber sequence_number, |
| 186 const TransmissionInfo& info) const { | 188 const TransmissionInfo& info) const { |
| 187 return sequence_number <= largest_observed_ && | 189 return sequence_number <= largest_observed_ && |
| 188 !info.in_flight && | 190 !info.in_flight && |
| 189 info.retransmittable_frames == NULL && | 191 info.retransmittable_frames == NULL && |
| 190 info.all_transmissions->size() == 1; | 192 info.all_transmissions == NULL; |
| 191 } | 193 } |
| 192 | 194 |
| 193 bool QuicUnackedPacketMap::IsUnacked( | 195 bool QuicUnackedPacketMap::IsUnacked( |
| 194 QuicPacketSequenceNumber sequence_number) const { | 196 QuicPacketSequenceNumber sequence_number) const { |
| 195 if (sequence_number < least_unacked_ || | 197 if (sequence_number < least_unacked_ || |
| 196 sequence_number >= least_unacked_ + unacked_packets_.size()) { | 198 sequence_number >= least_unacked_ + unacked_packets_.size()) { |
| 197 return false; | 199 return false; |
| 198 } | 200 } |
| 199 return !IsPacketUseless(sequence_number, | 201 return !IsPacketUseless(sequence_number, |
| 200 unacked_packets_[sequence_number - least_unacked_]); | 202 unacked_packets_[sequence_number - least_unacked_]); |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 326 TransmissionInfo* info = &unacked_packets_[sequence_number - least_unacked_]; | 328 TransmissionInfo* info = &unacked_packets_[sequence_number - least_unacked_]; |
| 327 DCHECK(!info->in_flight); | 329 DCHECK(!info->in_flight); |
| 328 DCHECK_NE(0u, info->bytes_sent); | 330 DCHECK_NE(0u, info->bytes_sent); |
| 329 DCHECK(info->sent_time.IsInitialized()); | 331 DCHECK(info->sent_time.IsInitialized()); |
| 330 | 332 |
| 331 bytes_in_flight_ += info->bytes_sent; | 333 bytes_in_flight_ += info->bytes_sent; |
| 332 info->in_flight = true; | 334 info->in_flight = true; |
| 333 } | 335 } |
| 334 | 336 |
| 335 } // namespace net | 337 } // namespace net |
| OLD | NEW |