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