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