| 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 bytes_in_flight_(0), | 20 bytes_in_flight_(0), |
| 20 pending_crypto_packet_count_(0) { | 21 pending_crypto_packet_count_(0) { |
| 21 } | 22 } |
| 22 | 23 |
| 23 QuicUnackedPacketMap::~QuicUnackedPacketMap() { | 24 QuicUnackedPacketMap::~QuicUnackedPacketMap() { |
| 25 QuicPacketSequenceNumber index = least_unacked_; |
| 24 for (UnackedPacketMap::iterator it = unacked_packets_.begin(); | 26 for (UnackedPacketMap::iterator it = unacked_packets_.begin(); |
| 25 it != unacked_packets_.end(); ++it) { | 27 it != unacked_packets_.end(); ++it, ++index) { |
| 26 delete it->second.retransmittable_frames; | 28 delete it->retransmittable_frames; |
| 27 // Only delete all_transmissions once, for the newest packet. | 29 // Only delete all_transmissions once, for the newest packet. |
| 28 if (it->first == *it->second.all_transmissions->rbegin()) { | 30 if (index == *it->all_transmissions->rbegin()) { |
| 29 delete it->second.all_transmissions; | 31 delete it->all_transmissions; |
| 30 } | 32 } |
| 31 } | 33 } |
| 32 } | 34 } |
| 33 | 35 |
| 34 // TODO(ianswett): Combine this method with OnPacketSent once packets are always | 36 // TODO(ianswett): Combine this method with OnPacketSent once packets are always |
| 35 // sent in order and the connection tracks RetransmittableFrames for longer. | 37 // sent in order and the connection tracks RetransmittableFrames for longer. |
| 36 void QuicUnackedPacketMap::AddPacket( | 38 void QuicUnackedPacketMap::AddPacket( |
| 37 const SerializedPacket& serialized_packet) { | 39 const SerializedPacket& serialized_packet) { |
| 38 if (!unacked_packets_.empty()) { | 40 DCHECK_EQ(least_unacked_ + unacked_packets_.size(), |
| 39 bool is_old_packet = unacked_packets_.rbegin()->first >= | 41 serialized_packet.sequence_number); |
| 40 serialized_packet.sequence_number; | 42 unacked_packets_.push_back( |
| 41 LOG_IF(DFATAL, is_old_packet) << "Old packet serialized: " | |
| 42 << serialized_packet.sequence_number | |
| 43 << " vs: " | |
| 44 << unacked_packets_.rbegin()->first; | |
| 45 } | |
| 46 | |
| 47 unacked_packets_[serialized_packet.sequence_number] = | |
| 48 TransmissionInfo(serialized_packet.retransmittable_frames, | 43 TransmissionInfo(serialized_packet.retransmittable_frames, |
| 49 serialized_packet.sequence_number, | 44 serialized_packet.sequence_number, |
| 50 serialized_packet.sequence_number_length); | 45 serialized_packet.sequence_number_length)); |
| 51 if (serialized_packet.retransmittable_frames != NULL && | 46 if (serialized_packet.retransmittable_frames != NULL && |
| 52 serialized_packet.retransmittable_frames->HasCryptoHandshake() | 47 serialized_packet.retransmittable_frames->HasCryptoHandshake() |
| 53 == IS_HANDSHAKE) { | 48 == IS_HANDSHAKE) { |
| 54 ++pending_crypto_packet_count_; | 49 ++pending_crypto_packet_count_; |
| 55 } | 50 } |
| 56 } | 51 } |
| 57 | 52 |
| 53 void QuicUnackedPacketMap::RemoveObsoletePackets() { |
| 54 while (!unacked_packets_.empty()) { |
| 55 if (!IsPacketUseless(least_unacked_, unacked_packets_.front())) { |
| 56 break; |
| 57 } |
| 58 delete unacked_packets_.front().all_transmissions; |
| 59 unacked_packets_.pop_front(); |
| 60 ++least_unacked_; |
| 61 } |
| 62 } |
| 63 |
| 58 void QuicUnackedPacketMap::OnRetransmittedPacket( | 64 void QuicUnackedPacketMap::OnRetransmittedPacket( |
| 59 QuicPacketSequenceNumber old_sequence_number, | 65 QuicPacketSequenceNumber old_sequence_number, |
| 60 QuicPacketSequenceNumber new_sequence_number, | 66 QuicPacketSequenceNumber new_sequence_number, |
| 61 TransmissionType transmission_type) { | 67 TransmissionType transmission_type) { |
| 62 DCHECK(ContainsKey(unacked_packets_, old_sequence_number)); | 68 DCHECK_GE(old_sequence_number, least_unacked_); |
| 63 DCHECK(unacked_packets_.empty() || | 69 DCHECK_LT(old_sequence_number, least_unacked_ + unacked_packets_.size()); |
| 64 unacked_packets_.rbegin()->first < new_sequence_number); | 70 DCHECK_EQ(least_unacked_ + unacked_packets_.size(), new_sequence_number); |
| 65 | 71 |
| 66 // TODO(ianswett): Discard and lose the packet lazily instead of immediately. | 72 // TODO(ianswett): Discard and lose the packet lazily instead of immediately. |
| 67 TransmissionInfo* transmission_info = | 73 TransmissionInfo* transmission_info = |
| 68 FindOrNull(unacked_packets_, old_sequence_number); | 74 &unacked_packets_.at(old_sequence_number - least_unacked_); |
| 69 RetransmittableFrames* frames = transmission_info->retransmittable_frames; | 75 RetransmittableFrames* frames = transmission_info->retransmittable_frames; |
| 70 LOG_IF(DFATAL, frames == NULL) << "Attempt to retransmit packet with no " | 76 LOG_IF(DFATAL, frames == NULL) << "Attempt to retransmit packet with no " |
| 71 << "retransmittable frames: " | 77 << "retransmittable frames: " |
| 72 << old_sequence_number; | 78 << old_sequence_number; |
| 73 | 79 |
| 74 // 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 |
| 75 // the retransmissions of it are acked. | 81 // the retransmissions of it are acked. |
| 76 transmission_info->retransmittable_frames = NULL; | 82 transmission_info->retransmittable_frames = NULL; |
| 77 // Only keep one transmission older than largest observed, because only the | 83 // Only keep one transmission older than largest observed, because only the |
| 78 // most recent is expected to possibly be a spurious retransmission. | 84 // most recent is expected to possibly be a spurious retransmission. |
| 79 if (transmission_info->all_transmissions->size() > 1 && | 85 if (transmission_info->all_transmissions->size() > 1 && |
| 80 *(++transmission_info->all_transmissions->begin()) < largest_observed_) { | 86 *(++transmission_info->all_transmissions->begin()) < largest_observed_) { |
| 81 QuicPacketSequenceNumber old_transmission = | 87 QuicPacketSequenceNumber old_transmission = |
| 82 *transmission_info->all_transmissions->begin(); | 88 *transmission_info->all_transmissions->begin(); |
| 83 TransmissionInfo* old_transmission_info = | 89 TransmissionInfo* old_info = |
| 84 FindOrNull(unacked_packets_, old_transmission); | 90 &unacked_packets_[old_transmission - least_unacked_]; |
| 85 // Don't remove old packets if they're still in flight. | 91 // Don't remove old packets if they're still in flight. |
| 86 if (old_transmission_info == NULL || !old_transmission_info->in_flight) { | 92 if (!old_info->in_flight) { |
| 87 transmission_info->all_transmissions->erase(old_transmission); | 93 transmission_info->all_transmissions->erase(old_transmission); |
| 88 unacked_packets_.erase(old_transmission); | 94 // This will cause the packet be removed in RemoveObsoletePackets. |
| 95 old_info->all_transmissions = new SequenceNumberSet(); |
| 96 old_info->all_transmissions->insert(old_transmission); |
| 89 } | 97 } |
| 90 } | 98 } |
| 91 unacked_packets_[new_sequence_number] = | 99 unacked_packets_.push_back( |
| 92 TransmissionInfo(frames, | 100 TransmissionInfo(frames, |
| 93 new_sequence_number, | 101 new_sequence_number, |
| 94 transmission_info->sequence_number_length, | 102 transmission_info->sequence_number_length, |
| 95 transmission_type, | 103 transmission_type, |
| 96 transmission_info->all_transmissions); | 104 transmission_info->all_transmissions)); |
| 97 } | 105 } |
| 98 | 106 |
| 99 void QuicUnackedPacketMap::ClearPreviousRetransmissions(size_t num_to_clear) { | 107 void QuicUnackedPacketMap::ClearPreviousRetransmissions(size_t num_to_clear) { |
| 100 UnackedPacketMap::iterator it = unacked_packets_.begin(); | 108 while (!unacked_packets_.empty() && num_to_clear > 0) { |
| 101 while (it != unacked_packets_.end() && num_to_clear > 0) { | |
| 102 QuicPacketSequenceNumber sequence_number = it->first; | |
| 103 // If this packet is in flight, or has retransmittable data, then there is | 109 // If this packet is in flight, or has retransmittable data, then there is |
| 104 // no point in clearing out any further packets, because they would not | 110 // no point in clearing out any further packets, because they would not |
| 105 // affect the high water mark. | 111 // affect the high water mark. |
| 106 if (it->second.in_flight || it->second.retransmittable_frames != NULL) { | 112 TransmissionInfo* info = &unacked_packets_.front(); |
| 113 if (info->in_flight || info->retransmittable_frames != NULL) { |
| 107 break; | 114 break; |
| 108 } | 115 } |
| 109 | 116 |
| 110 it->second.all_transmissions->erase(sequence_number); | 117 info->all_transmissions->erase(least_unacked_); |
| 111 LOG_IF(DFATAL, it->second.all_transmissions->empty()) | 118 LOG_IF(DFATAL, info->all_transmissions->empty()) |
| 112 << "Previous retransmissions must have a newer transmission."; | 119 << "Previous retransmissions must have a newer transmission."; |
| 113 ++it; | 120 unacked_packets_.pop_front(); |
| 114 unacked_packets_.erase(sequence_number); | 121 ++least_unacked_; |
| 115 --num_to_clear; | 122 --num_to_clear; |
| 116 } | 123 } |
| 117 } | 124 } |
| 118 | 125 |
| 119 bool QuicUnackedPacketMap::HasRetransmittableFrames( | 126 bool QuicUnackedPacketMap::HasRetransmittableFrames( |
| 120 QuicPacketSequenceNumber sequence_number) const { | 127 QuicPacketSequenceNumber sequence_number) const { |
| 121 const TransmissionInfo* transmission_info = | 128 DCHECK_GE(sequence_number, least_unacked_); |
| 122 FindOrNull(unacked_packets_, sequence_number); | 129 DCHECK_LT(sequence_number, least_unacked_ + unacked_packets_.size()); |
| 123 if (transmission_info == NULL) { | 130 return unacked_packets_[ |
| 124 return false; | 131 sequence_number - least_unacked_].retransmittable_frames != NULL; |
| 125 } | |
| 126 | |
| 127 return transmission_info->retransmittable_frames != NULL; | |
| 128 } | 132 } |
| 129 | 133 |
| 130 void QuicUnackedPacketMap::NackPacket(QuicPacketSequenceNumber sequence_number, | 134 void QuicUnackedPacketMap::NackPacket(QuicPacketSequenceNumber sequence_number, |
| 131 size_t min_nacks) { | 135 size_t min_nacks) { |
| 132 UnackedPacketMap::iterator it = unacked_packets_.find(sequence_number); | 136 DCHECK_GE(sequence_number, least_unacked_); |
| 133 if (it == unacked_packets_.end()) { | 137 DCHECK_LT(sequence_number, least_unacked_ + unacked_packets_.size()); |
| 134 LOG(DFATAL) << "NackPacket called for packet that is not unacked: " | 138 unacked_packets_[sequence_number - least_unacked_].nack_count = |
| 135 << sequence_number; | 139 max(min_nacks, |
| 136 return; | 140 unacked_packets_[sequence_number - least_unacked_].nack_count); |
| 137 } | |
| 138 | |
| 139 it->second.nack_count = max(min_nacks, it->second.nack_count); | |
| 140 } | 141 } |
| 141 | 142 |
| 142 void QuicUnackedPacketMap::RemoveRetransmittability( | 143 void QuicUnackedPacketMap::RemoveRetransmittability( |
| 143 QuicPacketSequenceNumber sequence_number) { | 144 QuicPacketSequenceNumber sequence_number) { |
| 144 UnackedPacketMap::iterator it = unacked_packets_.find(sequence_number); | 145 DCHECK_GE(sequence_number, least_unacked_); |
| 145 if (it == unacked_packets_.end()) { | 146 DCHECK_LT(sequence_number, least_unacked_ + unacked_packets_.size()); |
| 146 DVLOG(1) << "packet is not in unacked_packets: " << sequence_number; | 147 TransmissionInfo* info = &unacked_packets_[sequence_number - least_unacked_]; |
| 148 SequenceNumberSet* all_transmissions = info->all_transmissions; |
| 149 if (all_transmissions->size() == 1) { |
| 150 MaybeRemoveRetransmittableFrames(info); |
| 147 return; | 151 return; |
| 148 } | 152 } |
| 149 SequenceNumberSet* all_transmissions = it->second.all_transmissions; | |
| 150 // TODO(ianswett): Consider optimizing this for lone packets. | |
| 151 // TODO(ianswett): Consider adding a check to ensure there are retransmittable | 153 // TODO(ianswett): Consider adding a check to ensure there are retransmittable |
| 152 // frames associated with this packet. | 154 // frames associated with this packet. |
| 153 for (SequenceNumberSet::reverse_iterator it = all_transmissions->rbegin(); | 155 for (SequenceNumberSet::const_iterator it = all_transmissions->begin(); |
| 154 it != all_transmissions->rend(); ++it) { | 156 it != all_transmissions->end(); ++it) { |
| 155 TransmissionInfo* transmission_info = FindOrNull(unacked_packets_, *it); | 157 TransmissionInfo* transmission_info = |
| 156 if (transmission_info == NULL) { | 158 &unacked_packets_[*it - least_unacked_]; |
| 157 LOG(DFATAL) << "All transmissions in all_transmissions must be present " | |
| 158 << "in the unacked packet map."; | |
| 159 continue; | |
| 160 } | |
| 161 MaybeRemoveRetransmittableFrames(transmission_info); | 159 MaybeRemoveRetransmittableFrames(transmission_info); |
| 162 if (*it <= largest_observed_ && !transmission_info->in_flight) { | 160 transmission_info->all_transmissions = new SequenceNumberSet(); |
| 163 unacked_packets_.erase(*it); | 161 transmission_info->all_transmissions->insert(*it); |
| 164 } else { | |
| 165 transmission_info->all_transmissions = new SequenceNumberSet(); | |
| 166 transmission_info->all_transmissions->insert(*it); | |
| 167 } | |
| 168 } | 162 } |
| 169 | |
| 170 delete all_transmissions; | 163 delete all_transmissions; |
| 171 } | 164 } |
| 172 | 165 |
| 173 void QuicUnackedPacketMap::MaybeRemoveRetransmittableFrames( | 166 void QuicUnackedPacketMap::MaybeRemoveRetransmittableFrames( |
| 174 TransmissionInfo* transmission_info) { | 167 TransmissionInfo* transmission_info) { |
| 175 if (transmission_info->retransmittable_frames != NULL) { | 168 if (transmission_info->retransmittable_frames != NULL) { |
| 176 if (transmission_info->retransmittable_frames->HasCryptoHandshake() | 169 if (transmission_info->retransmittable_frames->HasCryptoHandshake() |
| 177 == IS_HANDSHAKE) { | 170 == IS_HANDSHAKE) { |
| 178 --pending_crypto_packet_count_; | 171 --pending_crypto_packet_count_; |
| 179 } | 172 } |
| 180 delete transmission_info->retransmittable_frames; | 173 delete transmission_info->retransmittable_frames; |
| 181 transmission_info->retransmittable_frames = NULL; | 174 transmission_info->retransmittable_frames = NULL; |
| 182 } | 175 } |
| 183 } | 176 } |
| 184 | 177 |
| 185 void QuicUnackedPacketMap::IncreaseLargestObserved( | 178 void QuicUnackedPacketMap::IncreaseLargestObserved( |
| 186 QuicPacketSequenceNumber largest_observed) { | 179 QuicPacketSequenceNumber largest_observed) { |
| 187 DCHECK_LE(largest_observed_, largest_observed); | 180 DCHECK_LE(largest_observed_, largest_observed); |
| 188 largest_observed_ = largest_observed; | 181 largest_observed_ = largest_observed; |
| 189 UnackedPacketMap::iterator it = unacked_packets_.begin(); | |
| 190 while (it != unacked_packets_.end() && it->first <= largest_observed_) { | |
| 191 if (!IsPacketUseless(it)) { | |
| 192 ++it; | |
| 193 continue; | |
| 194 } | |
| 195 delete it->second.all_transmissions; | |
| 196 QuicPacketSequenceNumber sequence_number = it->first; | |
| 197 ++it; | |
| 198 unacked_packets_.erase(sequence_number); | |
| 199 } | |
| 200 } | 182 } |
| 201 | 183 |
| 202 bool QuicUnackedPacketMap::IsPacketUseless( | 184 bool QuicUnackedPacketMap::IsPacketUseless( |
| 203 UnackedPacketMap::const_iterator it) const { | 185 QuicPacketSequenceNumber sequence_number, |
| 204 return it->first <= largest_observed_ && | 186 const TransmissionInfo& info) const { |
| 205 !it->second.in_flight && | 187 return sequence_number <= largest_observed_ && |
| 206 it->second.retransmittable_frames == NULL && | 188 !info.in_flight && |
| 207 it->second.all_transmissions->size() == 1; | 189 info.retransmittable_frames == NULL && |
| 190 info.all_transmissions->size() == 1; |
| 208 } | 191 } |
| 209 | 192 |
| 210 bool QuicUnackedPacketMap::IsUnacked( | 193 bool QuicUnackedPacketMap::IsUnacked( |
| 211 QuicPacketSequenceNumber sequence_number) const { | 194 QuicPacketSequenceNumber sequence_number) const { |
| 212 return ContainsKey(unacked_packets_, sequence_number); | 195 if (sequence_number < least_unacked_ || |
| 196 sequence_number >= least_unacked_ + unacked_packets_.size()) { |
| 197 return false; |
| 198 } |
| 199 return !IsPacketUseless(sequence_number, |
| 200 unacked_packets_[sequence_number - least_unacked_]); |
| 213 } | 201 } |
| 214 | 202 |
| 215 void QuicUnackedPacketMap::RemoveFromInFlight( | 203 void QuicUnackedPacketMap::RemoveFromInFlight( |
| 216 QuicPacketSequenceNumber sequence_number) { | 204 QuicPacketSequenceNumber sequence_number) { |
| 217 UnackedPacketMap::iterator it = unacked_packets_.find(sequence_number); | 205 DCHECK_GE(sequence_number, least_unacked_); |
| 218 if (it == unacked_packets_.end()) { | 206 DCHECK_LT(sequence_number, least_unacked_ + unacked_packets_.size()); |
| 219 LOG(DFATAL) << "RemoveFromFlight called for packet that is not unacked: " | 207 TransmissionInfo* info = &unacked_packets_[sequence_number - least_unacked_]; |
| 220 << sequence_number; | 208 if (info->in_flight) { |
| 221 return; | 209 LOG_IF(DFATAL, bytes_in_flight_ < info->bytes_sent); |
| 222 } | 210 bytes_in_flight_ -= info->bytes_sent; |
| 223 if (it->second.in_flight) { | 211 info->in_flight = false; |
| 224 LOG_IF(DFATAL, bytes_in_flight_ < it->second.bytes_sent); | |
| 225 bytes_in_flight_ -= it->second.bytes_sent; | |
| 226 it->second.in_flight = false; | |
| 227 } | |
| 228 if (IsPacketUseless(it)) { | |
| 229 delete it->second.all_transmissions; | |
| 230 unacked_packets_.erase(it); | |
| 231 } | 212 } |
| 232 } | 213 } |
| 233 | 214 |
| 234 bool QuicUnackedPacketMap::HasUnackedPackets() const { | 215 bool QuicUnackedPacketMap::HasUnackedPackets() const { |
| 235 return !unacked_packets_.empty(); | 216 return !unacked_packets_.empty(); |
| 236 } | 217 } |
| 237 | 218 |
| 238 bool QuicUnackedPacketMap::HasInFlightPackets() const { | 219 bool QuicUnackedPacketMap::HasInFlightPackets() const { |
| 239 return bytes_in_flight_ > 0; | 220 return bytes_in_flight_ > 0; |
| 240 } | 221 } |
| 241 | 222 |
| 242 const TransmissionInfo& QuicUnackedPacketMap::GetTransmissionInfo( | 223 const TransmissionInfo& QuicUnackedPacketMap::GetTransmissionInfo( |
| 243 QuicPacketSequenceNumber sequence_number) const { | 224 QuicPacketSequenceNumber sequence_number) const { |
| 244 return unacked_packets_.find(sequence_number)->second; | 225 return unacked_packets_[sequence_number - least_unacked_]; |
| 245 } | 226 } |
| 246 | 227 |
| 247 QuicTime QuicUnackedPacketMap::GetLastPacketSentTime() const { | 228 QuicTime QuicUnackedPacketMap::GetLastPacketSentTime() const { |
| 248 UnackedPacketMap::const_reverse_iterator it = unacked_packets_.rbegin(); | 229 UnackedPacketMap::const_reverse_iterator it = unacked_packets_.rbegin(); |
| 249 while (it != unacked_packets_.rend()) { | 230 while (it != unacked_packets_.rend()) { |
| 250 if (it->second.in_flight) { | 231 if (it->in_flight) { |
| 251 LOG_IF(DFATAL, it->second.sent_time == QuicTime::Zero()) | 232 LOG_IF(DFATAL, it->sent_time == QuicTime::Zero()) |
| 252 << "Sent time can never be zero for a packet in flight."; | 233 << "Sent time can never be zero for a packet in flight."; |
| 253 return it->second.sent_time; | 234 return it->sent_time; |
| 254 } | 235 } |
| 255 ++it; | 236 ++it; |
| 256 } | 237 } |
| 257 LOG(DFATAL) << "GetLastPacketSentTime requires in flight packets."; | 238 LOG(DFATAL) << "GetLastPacketSentTime requires in flight packets."; |
| 258 return QuicTime::Zero(); | 239 return QuicTime::Zero(); |
| 259 } | 240 } |
| 260 | 241 |
| 261 QuicTime QuicUnackedPacketMap::GetFirstInFlightPacketSentTime() const { | 242 QuicTime QuicUnackedPacketMap::GetFirstInFlightPacketSentTime() const { |
| 262 UnackedPacketMap::const_iterator it = unacked_packets_.begin(); | 243 UnackedPacketMap::const_iterator it = unacked_packets_.begin(); |
| 263 while (it != unacked_packets_.end() && !it->second.in_flight) { | 244 while (it != unacked_packets_.end() && !it->in_flight) { |
| 264 ++it; | 245 ++it; |
| 265 } | 246 } |
| 266 if (it == unacked_packets_.end()) { | 247 if (it == unacked_packets_.end()) { |
| 267 LOG(DFATAL) << "GetFirstInFlightPacketSentTime requires in flight packets."; | 248 LOG(DFATAL) << "GetFirstInFlightPacketSentTime requires in flight packets."; |
| 268 return QuicTime::Zero(); | 249 return QuicTime::Zero(); |
| 269 } | 250 } |
| 270 return it->second.sent_time; | 251 return it->sent_time; |
| 271 } | 252 } |
| 272 | 253 |
| 273 size_t QuicUnackedPacketMap::GetNumUnackedPackets() const { | 254 size_t QuicUnackedPacketMap::GetNumUnackedPacketsDebugOnly() const { |
| 274 return unacked_packets_.size(); | 255 size_t unacked_packet_count = 0; |
| 256 QuicPacketSequenceNumber sequence_number = least_unacked_; |
| 257 for (UnackedPacketMap::const_iterator it = unacked_packets_.begin(); |
| 258 it != unacked_packets_.end(); ++it, ++sequence_number) { |
| 259 if (!IsPacketUseless(sequence_number, *it)) { |
| 260 ++unacked_packet_count; |
| 261 } |
| 262 } |
| 263 return unacked_packet_count; |
| 275 } | 264 } |
| 276 | 265 |
| 277 bool QuicUnackedPacketMap::HasMultipleInFlightPackets() const { | 266 bool QuicUnackedPacketMap::HasMultipleInFlightPackets() const { |
| 278 size_t num_in_flight = 0; | 267 size_t num_in_flight = 0; |
| 279 for (UnackedPacketMap::const_reverse_iterator it = unacked_packets_.rbegin(); | 268 for (UnackedPacketMap::const_reverse_iterator it = unacked_packets_.rbegin(); |
| 280 it != unacked_packets_.rend(); ++it) { | 269 it != unacked_packets_.rend(); ++it) { |
| 281 if (it->second.in_flight) { | 270 if (it->in_flight) { |
| 282 ++num_in_flight; | 271 ++num_in_flight; |
| 283 } | 272 } |
| 284 if (num_in_flight > 1) { | 273 if (num_in_flight > 1) { |
| 285 return true; | 274 return true; |
| 286 } | 275 } |
| 287 } | 276 } |
| 288 return false; | 277 return false; |
| 289 } | 278 } |
| 290 | 279 |
| 291 bool QuicUnackedPacketMap::HasPendingCryptoPackets() const { | 280 bool QuicUnackedPacketMap::HasPendingCryptoPackets() const { |
| 292 return pending_crypto_packet_count_ > 0; | 281 return pending_crypto_packet_count_ > 0; |
| 293 } | 282 } |
| 294 | 283 |
| 295 bool QuicUnackedPacketMap::HasUnackedRetransmittableFrames() const { | 284 bool QuicUnackedPacketMap::HasUnackedRetransmittableFrames() const { |
| 296 for (UnackedPacketMap::const_reverse_iterator it = | 285 for (UnackedPacketMap::const_reverse_iterator it = |
| 297 unacked_packets_.rbegin(); it != unacked_packets_.rend(); ++it) { | 286 unacked_packets_.rbegin(); it != unacked_packets_.rend(); ++it) { |
| 298 if (it->second.in_flight && it->second.retransmittable_frames) { | 287 if (it->in_flight && it->retransmittable_frames) { |
| 299 return true; | 288 return true; |
| 300 } | 289 } |
| 301 } | 290 } |
| 302 return false; | 291 return false; |
| 303 } | 292 } |
| 304 | 293 |
| 305 QuicPacketSequenceNumber | 294 QuicPacketSequenceNumber |
| 306 QuicUnackedPacketMap::GetLeastUnackedSentPacket() const { | 295 QuicUnackedPacketMap::GetLeastUnacked() const { |
| 307 if (unacked_packets_.empty()) { | 296 if (unacked_packets_.empty()) { |
| 308 // If there are no unacked packets, return 0. | 297 // If there are no unacked packets, return 0. |
| 309 return 0; | 298 return 0; |
| 310 } | 299 } |
| 311 | 300 return least_unacked_; |
| 312 return unacked_packets_.begin()->first; | |
| 313 } | 301 } |
| 314 | 302 |
| 315 void QuicUnackedPacketMap::SetSent(QuicPacketSequenceNumber sequence_number, | 303 void QuicUnackedPacketMap::SetSent(QuicPacketSequenceNumber sequence_number, |
| 316 QuicTime sent_time, | 304 QuicTime sent_time, |
| 317 QuicByteCount bytes_sent, | 305 QuicByteCount bytes_sent, |
| 318 bool set_in_flight) { | 306 bool set_in_flight) { |
| 319 DCHECK_LT(0u, sequence_number); | 307 DCHECK_GE(sequence_number, least_unacked_); |
| 320 UnackedPacketMap::iterator it = unacked_packets_.find(sequence_number); | 308 DCHECK_LT(sequence_number, least_unacked_ + unacked_packets_.size()); |
| 321 if (it == unacked_packets_.end()) { | 309 TransmissionInfo* info = &unacked_packets_[sequence_number - least_unacked_]; |
| 322 LOG(DFATAL) << "OnPacketSent called for packet that is not unacked: " | 310 DCHECK(!info->in_flight); |
| 323 << sequence_number; | |
| 324 return; | |
| 325 } | |
| 326 DCHECK(!it->second.in_flight); | |
| 327 | 311 |
| 312 DCHECK_LT(largest_sent_packet_, sequence_number); |
| 328 largest_sent_packet_ = max(sequence_number, largest_sent_packet_); | 313 largest_sent_packet_ = max(sequence_number, largest_sent_packet_); |
| 329 it->second.sent_time = sent_time; | 314 info->sent_time = sent_time; |
| 330 if (set_in_flight) { | 315 if (set_in_flight) { |
| 331 bytes_in_flight_ += bytes_sent; | 316 bytes_in_flight_ += bytes_sent; |
| 332 it->second.bytes_sent = bytes_sent; | 317 info->bytes_sent = bytes_sent; |
| 333 it->second.in_flight = true; | 318 info->in_flight = true; |
| 334 } | 319 } |
| 335 } | 320 } |
| 336 | 321 |
| 337 void QuicUnackedPacketMap::RestoreInFlight( | 322 void QuicUnackedPacketMap::RestoreInFlight( |
| 338 QuicPacketSequenceNumber sequence_number) { | 323 QuicPacketSequenceNumber sequence_number) { |
| 339 DCHECK_LT(0u, sequence_number); | 324 DCHECK_GE(sequence_number, least_unacked_); |
| 340 UnackedPacketMap::iterator it = unacked_packets_.find(sequence_number); | 325 DCHECK_LT(sequence_number, least_unacked_ + unacked_packets_.size()); |
| 341 if (it == unacked_packets_.end()) { | 326 TransmissionInfo* info = &unacked_packets_[sequence_number - least_unacked_]; |
| 342 LOG(DFATAL) << "OnPacketSent called for packet that is not unacked: " | 327 DCHECK(!info->in_flight); |
| 343 << sequence_number; | 328 DCHECK_NE(0u, info->bytes_sent); |
| 344 return; | 329 DCHECK(info->sent_time.IsInitialized()); |
| 345 } | |
| 346 DCHECK(!it->second.in_flight); | |
| 347 DCHECK_NE(0u, it->second.bytes_sent); | |
| 348 DCHECK(it->second.sent_time.IsInitialized()); | |
| 349 | 330 |
| 350 bytes_in_flight_ += it->second.bytes_sent; | 331 bytes_in_flight_ += info->bytes_sent; |
| 351 it->second.in_flight = true; | 332 info->in_flight = true; |
| 352 } | 333 } |
| 353 | 334 |
| 354 } // namespace net | 335 } // namespace net |
| OLD | NEW |