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