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 (it->all_transmissions != NULL && | 30 if (it->all_transmissions != nullptr && |
31 index == *it->all_transmissions->rbegin()) { | 31 index == *it->all_transmissions->rbegin()) { |
32 delete it->all_transmissions; | 32 delete it->all_transmissions; |
33 } | 33 } |
34 } | 34 } |
35 } | 35 } |
36 | 36 |
37 // TODO(ianswett): Combine this method with OnPacketSent once packets are always | 37 // TODO(ianswett): Combine this method with OnPacketSent once packets are always |
38 // sent in order and the connection tracks RetransmittableFrames for longer. | 38 // sent in order and the connection tracks RetransmittableFrames for longer. |
39 void QuicUnackedPacketMap::AddPacket( | 39 void QuicUnackedPacketMap::AddPacket( |
40 const SerializedPacket& serialized_packet) { | 40 const SerializedPacket& serialized_packet) { |
41 DCHECK_GE(serialized_packet.sequence_number, | 41 DCHECK_GE(serialized_packet.sequence_number, |
42 least_unacked_ + unacked_packets_.size()); | 42 least_unacked_ + unacked_packets_.size()); |
43 while (least_unacked_ + unacked_packets_.size() < | 43 while (least_unacked_ + unacked_packets_.size() < |
44 serialized_packet.sequence_number) { | 44 serialized_packet.sequence_number) { |
45 unacked_packets_.push_back(TransmissionInfo()); | 45 unacked_packets_.push_back(TransmissionInfo()); |
46 unacked_packets_.back().is_unackable = true; | 46 unacked_packets_.back().is_unackable = true; |
47 } | 47 } |
48 unacked_packets_.push_back( | 48 unacked_packets_.push_back( |
49 TransmissionInfo(serialized_packet.retransmittable_frames, | 49 TransmissionInfo(serialized_packet.retransmittable_frames, |
50 serialized_packet.sequence_number_length)); | 50 serialized_packet.sequence_number_length)); |
51 if (serialized_packet.retransmittable_frames != NULL && | 51 if (serialized_packet.retransmittable_frames != nullptr && |
52 serialized_packet.retransmittable_frames->HasCryptoHandshake() | 52 serialized_packet.retransmittable_frames->HasCryptoHandshake() == |
53 == IS_HANDSHAKE) { | 53 IS_HANDSHAKE) { |
54 ++pending_crypto_packet_count_; | 54 ++pending_crypto_packet_count_; |
55 } | 55 } |
56 } | 56 } |
57 | 57 |
58 void QuicUnackedPacketMap::RemoveObsoletePackets() { | 58 void QuicUnackedPacketMap::RemoveObsoletePackets() { |
59 while (!unacked_packets_.empty()) { | 59 while (!unacked_packets_.empty()) { |
60 if (!IsPacketRemovable(least_unacked_, unacked_packets_.front())) { | 60 if (!IsPacketRemovable(least_unacked_, unacked_packets_.front())) { |
61 break; | 61 break; |
62 } | 62 } |
63 unacked_packets_.pop_front(); | 63 unacked_packets_.pop_front(); |
(...skipping 10 matching lines...) Expand all Loading... |
74 DCHECK_GE(new_sequence_number, least_unacked_ + unacked_packets_.size()); | 74 DCHECK_GE(new_sequence_number, least_unacked_ + unacked_packets_.size()); |
75 while (least_unacked_ + unacked_packets_.size() < new_sequence_number) { | 75 while (least_unacked_ + unacked_packets_.size() < new_sequence_number) { |
76 unacked_packets_.push_back(TransmissionInfo()); | 76 unacked_packets_.push_back(TransmissionInfo()); |
77 unacked_packets_.back().is_unackable = true; | 77 unacked_packets_.back().is_unackable = true; |
78 } | 78 } |
79 | 79 |
80 // TODO(ianswett): Discard and lose the packet lazily instead of immediately. | 80 // TODO(ianswett): Discard and lose the packet lazily instead of immediately. |
81 TransmissionInfo* transmission_info = | 81 TransmissionInfo* transmission_info = |
82 &unacked_packets_.at(old_sequence_number - least_unacked_); | 82 &unacked_packets_.at(old_sequence_number - least_unacked_); |
83 RetransmittableFrames* frames = transmission_info->retransmittable_frames; | 83 RetransmittableFrames* frames = transmission_info->retransmittable_frames; |
84 LOG_IF(DFATAL, frames == NULL) << "Attempt to retransmit packet with no " | 84 LOG_IF(DFATAL, frames == nullptr) |
85 << "retransmittable frames: " | 85 << "Attempt to retransmit packet with no " |
86 << old_sequence_number; | 86 << "retransmittable frames: " << old_sequence_number; |
87 | 87 |
88 // We keep the old packet in the unacked packet list until it, or one of | 88 // We keep the old packet in the unacked packet list until it, or one of |
89 // the retransmissions of it are acked. | 89 // the retransmissions of it are acked. |
90 transmission_info->retransmittable_frames = NULL; | 90 transmission_info->retransmittable_frames = nullptr; |
91 // Only keep one transmission older than largest observed, because only the | 91 // Only keep one transmission older than largest observed, because only the |
92 // most recent is expected to possibly be a spurious retransmission. | 92 // most recent is expected to possibly be a spurious retransmission. |
93 while (transmission_info->all_transmissions != NULL && | 93 while (transmission_info->all_transmissions != nullptr && |
94 transmission_info->all_transmissions->size() > 1 && | 94 transmission_info->all_transmissions->size() > 1 && |
95 *(++transmission_info->all_transmissions->begin()) | 95 *(++transmission_info->all_transmissions->begin()) < |
96 < largest_observed_) { | 96 largest_observed_) { |
97 QuicPacketSequenceNumber old_transmission = | 97 QuicPacketSequenceNumber old_transmission = |
98 *transmission_info->all_transmissions->begin(); | 98 *transmission_info->all_transmissions->begin(); |
99 TransmissionInfo* old_info = | 99 TransmissionInfo* old_info = |
100 &unacked_packets_[old_transmission - least_unacked_]; | 100 &unacked_packets_[old_transmission - least_unacked_]; |
101 // Don't remove old packets if they're still in flight. | 101 // Don't remove old packets if they're still in flight. |
102 if (old_info->in_flight) { | 102 if (old_info->in_flight) { |
103 break; | 103 break; |
104 } | 104 } |
105 old_info->all_transmissions->pop_front(); | 105 old_info->all_transmissions->pop_front(); |
106 // This will cause the packet be removed in RemoveObsoletePackets. | 106 // This will cause the packet be removed in RemoveObsoletePackets. |
107 old_info->all_transmissions = NULL; | 107 old_info->all_transmissions = nullptr; |
108 } | 108 } |
109 // Don't link old transmissions to new ones when version or | 109 // Don't link old transmissions to new ones when version or |
110 // encryption changes. | 110 // encryption changes. |
111 if (transmission_type == ALL_INITIAL_RETRANSMISSION || | 111 if (transmission_type == ALL_INITIAL_RETRANSMISSION || |
112 transmission_type == ALL_UNACKED_RETRANSMISSION) { | 112 transmission_type == ALL_UNACKED_RETRANSMISSION) { |
113 RemoveAckability(transmission_info); | 113 RemoveAckability(transmission_info); |
114 } else { | 114 } else { |
115 if (transmission_info->all_transmissions == NULL) { | 115 if (transmission_info->all_transmissions == nullptr) { |
116 transmission_info->all_transmissions = new SequenceNumberList(); | 116 transmission_info->all_transmissions = new SequenceNumberList(); |
117 transmission_info->all_transmissions->push_back(old_sequence_number); | 117 transmission_info->all_transmissions->push_back(old_sequence_number); |
118 } | 118 } |
119 transmission_info->all_transmissions->push_back(new_sequence_number); | 119 transmission_info->all_transmissions->push_back(new_sequence_number); |
120 } | 120 } |
121 unacked_packets_.push_back( | 121 unacked_packets_.push_back( |
122 TransmissionInfo(frames, | 122 TransmissionInfo(frames, |
123 transmission_info->sequence_number_length, | 123 transmission_info->sequence_number_length, |
124 transmission_type, | 124 transmission_type, |
125 transmission_info->all_transmissions)); | 125 transmission_info->all_transmissions)); |
126 RemoveObsoletePackets(); | 126 RemoveObsoletePackets(); |
127 } | 127 } |
128 | 128 |
129 void QuicUnackedPacketMap::ClearAllPreviousRetransmissions() { | 129 void QuicUnackedPacketMap::ClearAllPreviousRetransmissions() { |
130 while (!unacked_packets_.empty() && least_unacked_ < largest_observed_) { | 130 while (!unacked_packets_.empty() && least_unacked_ < largest_observed_) { |
131 // If this packet is in flight, or has retransmittable data, then there is | 131 // If this packet is in flight, or has retransmittable data, then there is |
132 // no point in clearing out any further packets, because they would not | 132 // no point in clearing out any further packets, because they would not |
133 // affect the high water mark. | 133 // affect the high water mark. |
134 TransmissionInfo* info = &unacked_packets_.front(); | 134 TransmissionInfo* info = &unacked_packets_.front(); |
135 if (info->in_flight || info->retransmittable_frames != NULL) { | 135 if (info->in_flight || info->retransmittable_frames != nullptr) { |
136 break; | 136 break; |
137 } | 137 } |
138 | 138 |
139 if (info->all_transmissions != NULL) { | 139 if (info->all_transmissions != nullptr) { |
140 if (info->all_transmissions->size() < 2) { | 140 if (info->all_transmissions->size() < 2) { |
141 LOG(DFATAL) << "all_transmissions must be NULL or have multiple " | 141 LOG(DFATAL) << "all_transmissions must be nullptr or have multiple " |
142 << "elements. size:" << info->all_transmissions->size(); | 142 << "elements. size:" << info->all_transmissions->size(); |
143 delete info->all_transmissions; | 143 delete info->all_transmissions; |
144 } else { | 144 } else { |
145 info->all_transmissions->pop_front(); | 145 info->all_transmissions->pop_front(); |
146 if (info->all_transmissions->size() == 1) { | 146 if (info->all_transmissions->size() == 1) { |
147 // Set the newer transmission's 'all_transmissions' entry to NULL. | 147 // Set the newer transmission's 'all_transmissions' entry to nullptr. |
148 QuicPacketSequenceNumber new_transmission = | 148 QuicPacketSequenceNumber new_transmission = |
149 info->all_transmissions->front(); | 149 info->all_transmissions->front(); |
150 TransmissionInfo* new_info = | 150 TransmissionInfo* new_info = |
151 &unacked_packets_.at(new_transmission - least_unacked_); | 151 &unacked_packets_.at(new_transmission - least_unacked_); |
152 delete new_info->all_transmissions; | 152 delete new_info->all_transmissions; |
153 new_info->all_transmissions = NULL; | 153 new_info->all_transmissions = nullptr; |
154 } | 154 } |
155 } | 155 } |
156 } | 156 } |
157 unacked_packets_.pop_front(); | 157 unacked_packets_.pop_front(); |
158 ++least_unacked_; | 158 ++least_unacked_; |
159 } | 159 } |
160 } | 160 } |
161 | 161 |
162 bool QuicUnackedPacketMap::HasRetransmittableFrames( | 162 bool QuicUnackedPacketMap::HasRetransmittableFrames( |
163 QuicPacketSequenceNumber sequence_number) const { | 163 QuicPacketSequenceNumber sequence_number) const { |
164 DCHECK_GE(sequence_number, least_unacked_); | 164 DCHECK_GE(sequence_number, least_unacked_); |
165 DCHECK_LT(sequence_number, least_unacked_ + unacked_packets_.size()); | 165 DCHECK_LT(sequence_number, least_unacked_ + unacked_packets_.size()); |
166 return unacked_packets_[ | 166 return unacked_packets_[sequence_number - least_unacked_] |
167 sequence_number - least_unacked_].retransmittable_frames != NULL; | 167 .retransmittable_frames != nullptr; |
168 } | 168 } |
169 | 169 |
170 void QuicUnackedPacketMap::NackPacket(QuicPacketSequenceNumber sequence_number, | 170 void QuicUnackedPacketMap::NackPacket(QuicPacketSequenceNumber sequence_number, |
171 size_t min_nacks) { | 171 size_t min_nacks) { |
172 DCHECK_GE(sequence_number, least_unacked_); | 172 DCHECK_GE(sequence_number, least_unacked_); |
173 DCHECK_LT(sequence_number, least_unacked_ + unacked_packets_.size()); | 173 DCHECK_LT(sequence_number, least_unacked_ + unacked_packets_.size()); |
174 unacked_packets_[sequence_number - least_unacked_].nack_count = | 174 unacked_packets_[sequence_number - least_unacked_].nack_count = |
175 max(min_nacks, | 175 max(min_nacks, |
176 unacked_packets_[sequence_number - least_unacked_].nack_count); | 176 unacked_packets_[sequence_number - least_unacked_].nack_count); |
177 } | 177 } |
178 | 178 |
179 void QuicUnackedPacketMap::RemoveRetransmittability( | 179 void QuicUnackedPacketMap::RemoveRetransmittability( |
180 QuicPacketSequenceNumber sequence_number) { | 180 QuicPacketSequenceNumber sequence_number) { |
181 DCHECK_GE(sequence_number, least_unacked_); | 181 DCHECK_GE(sequence_number, least_unacked_); |
182 DCHECK_LT(sequence_number, least_unacked_ + unacked_packets_.size()); | 182 DCHECK_LT(sequence_number, least_unacked_ + unacked_packets_.size()); |
183 TransmissionInfo* info = &unacked_packets_[sequence_number - least_unacked_]; | 183 TransmissionInfo* info = &unacked_packets_[sequence_number - least_unacked_]; |
184 SequenceNumberList* all_transmissions = info->all_transmissions; | 184 SequenceNumberList* all_transmissions = info->all_transmissions; |
185 if (all_transmissions == NULL) { | 185 if (all_transmissions == nullptr) { |
186 MaybeRemoveRetransmittableFrames(info); | 186 MaybeRemoveRetransmittableFrames(info); |
187 return; | 187 return; |
188 } | 188 } |
189 // TODO(ianswett): Consider adding a check to ensure there are retransmittable | 189 // TODO(ianswett): Consider adding a check to ensure there are retransmittable |
190 // frames associated with this packet. | 190 // frames associated with this packet. |
191 for (SequenceNumberList::const_iterator it = all_transmissions->begin(); | 191 for (SequenceNumberList::const_iterator it = all_transmissions->begin(); |
192 it != all_transmissions->end(); ++it) { | 192 it != all_transmissions->end(); ++it) { |
193 TransmissionInfo* transmission_info = | 193 TransmissionInfo* transmission_info = |
194 &unacked_packets_[*it - least_unacked_]; | 194 &unacked_packets_[*it - least_unacked_]; |
195 MaybeRemoveRetransmittableFrames(transmission_info); | 195 MaybeRemoveRetransmittableFrames(transmission_info); |
196 transmission_info->all_transmissions = NULL; | 196 transmission_info->all_transmissions = nullptr; |
197 } | 197 } |
198 delete all_transmissions; | 198 delete all_transmissions; |
199 } | 199 } |
200 | 200 |
201 void QuicUnackedPacketMap::RemoveAckability(TransmissionInfo* info) { | 201 void QuicUnackedPacketMap::RemoveAckability(TransmissionInfo* info) { |
202 DCHECK(info->retransmittable_frames == NULL); | 202 DCHECK(info->retransmittable_frames == nullptr); |
203 info->is_unackable = true; | 203 info->is_unackable = true; |
204 SequenceNumberList* all_transmissions = info->all_transmissions; | 204 SequenceNumberList* all_transmissions = info->all_transmissions; |
205 if (all_transmissions == NULL) { | 205 if (all_transmissions == nullptr) { |
206 return; | 206 return; |
207 } | 207 } |
208 for (SequenceNumberList::const_iterator it = all_transmissions->begin(); | 208 for (SequenceNumberList::const_iterator it = all_transmissions->begin(); |
209 it != all_transmissions->end(); ++it) { | 209 it != all_transmissions->end(); ++it) { |
210 TransmissionInfo* transmission_info = | 210 TransmissionInfo* transmission_info = |
211 &unacked_packets_[*it - least_unacked_]; | 211 &unacked_packets_[*it - least_unacked_]; |
212 transmission_info->all_transmissions = NULL; | 212 transmission_info->all_transmissions = nullptr; |
213 transmission_info->is_unackable = true; | 213 transmission_info->is_unackable = true; |
214 } | 214 } |
215 delete all_transmissions; | 215 delete all_transmissions; |
216 } | 216 } |
217 | 217 |
218 void QuicUnackedPacketMap::MaybeRemoveRetransmittableFrames( | 218 void QuicUnackedPacketMap::MaybeRemoveRetransmittableFrames( |
219 TransmissionInfo* transmission_info) { | 219 TransmissionInfo* transmission_info) { |
220 if (transmission_info->retransmittable_frames != NULL) { | 220 if (transmission_info->retransmittable_frames != nullptr) { |
221 if (transmission_info->retransmittable_frames->HasCryptoHandshake() | 221 if (transmission_info->retransmittable_frames->HasCryptoHandshake() |
222 == IS_HANDSHAKE) { | 222 == IS_HANDSHAKE) { |
223 --pending_crypto_packet_count_; | 223 --pending_crypto_packet_count_; |
224 } | 224 } |
225 delete transmission_info->retransmittable_frames; | 225 delete transmission_info->retransmittable_frames; |
226 transmission_info->retransmittable_frames = NULL; | 226 transmission_info->retransmittable_frames = nullptr; |
227 } | 227 } |
228 } | 228 } |
229 | 229 |
230 void QuicUnackedPacketMap::IncreaseLargestObserved( | 230 void QuicUnackedPacketMap::IncreaseLargestObserved( |
231 QuicPacketSequenceNumber largest_observed) { | 231 QuicPacketSequenceNumber largest_observed) { |
232 DCHECK_LE(largest_observed_, largest_observed); | 232 DCHECK_LE(largest_observed_, largest_observed); |
233 largest_observed_ = largest_observed; | 233 largest_observed_ = largest_observed; |
234 } | 234 } |
235 | 235 |
236 bool QuicUnackedPacketMap::IsPacketUseless( | 236 bool QuicUnackedPacketMap::IsPacketUseless( |
237 QuicPacketSequenceNumber sequence_number, | 237 QuicPacketSequenceNumber sequence_number, |
238 const TransmissionInfo& info) const { | 238 const TransmissionInfo& info) const { |
239 return (info.is_unackable || sequence_number <= largest_observed_) && | 239 return (info.is_unackable || sequence_number <= largest_observed_) && |
240 !info.in_flight && | 240 !info.in_flight && info.retransmittable_frames == nullptr && |
241 info.retransmittable_frames == NULL && | 241 info.all_transmissions == nullptr; |
242 info.all_transmissions == NULL; | |
243 } | 242 } |
244 | 243 |
245 bool QuicUnackedPacketMap::IsPacketRemovable( | 244 bool QuicUnackedPacketMap::IsPacketRemovable( |
246 QuicPacketSequenceNumber sequence_number, | 245 QuicPacketSequenceNumber sequence_number, |
247 const TransmissionInfo& info) const { | 246 const TransmissionInfo& info) const { |
248 return (info.is_unackable || | 247 return (info.is_unackable || sequence_number <= largest_observed_ || |
249 sequence_number <= largest_observed_ || | |
250 unacked_packets_.size() > kMaxTcpCongestionWindow) && | 248 unacked_packets_.size() > kMaxTcpCongestionWindow) && |
251 !info.in_flight && | 249 !info.in_flight && info.retransmittable_frames == nullptr && |
252 info.retransmittable_frames == NULL && | 250 info.all_transmissions == nullptr; |
253 info.all_transmissions == NULL; | |
254 } | 251 } |
255 | 252 |
256 bool QuicUnackedPacketMap::IsUnacked( | 253 bool QuicUnackedPacketMap::IsUnacked( |
257 QuicPacketSequenceNumber sequence_number) const { | 254 QuicPacketSequenceNumber sequence_number) const { |
258 if (sequence_number < least_unacked_ || | 255 if (sequence_number < least_unacked_ || |
259 sequence_number >= least_unacked_ + unacked_packets_.size()) { | 256 sequence_number >= least_unacked_ + unacked_packets_.size()) { |
260 return false; | 257 return false; |
261 } | 258 } |
262 return !IsPacketUseless(sequence_number, | 259 return !IsPacketUseless(sequence_number, |
263 unacked_packets_[sequence_number - least_unacked_]); | 260 unacked_packets_[sequence_number - least_unacked_]); |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
385 TransmissionInfo* info = &unacked_packets_[sequence_number - least_unacked_]; | 382 TransmissionInfo* info = &unacked_packets_[sequence_number - least_unacked_]; |
386 DCHECK(!info->in_flight); | 383 DCHECK(!info->in_flight); |
387 DCHECK_NE(0u, info->bytes_sent); | 384 DCHECK_NE(0u, info->bytes_sent); |
388 DCHECK(info->sent_time.IsInitialized()); | 385 DCHECK(info->sent_time.IsInitialized()); |
389 | 386 |
390 bytes_in_flight_ += info->bytes_sent; | 387 bytes_in_flight_ += info->bytes_sent; |
391 info->in_flight = true; | 388 info->in_flight = true; |
392 } | 389 } |
393 | 390 |
394 } // namespace net | 391 } // namespace net |
OLD | NEW |