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
3 // found in the LICENSE file.
5 #include "net/quic/quic_unacked_packet_map.h"
7 #include "base/logging.h"
8 #include "base/stl_util.h"
9 #include "net/quic/quic_connection_stats.h"
10 #include "net/quic/quic_utils_chromium.h"
16 QuicUnackedPacketMap::QuicUnackedPacketMap()
17 : largest_sent_packet_(0),
20 pending_crypto_packet_count_(0) {
23 QuicUnackedPacketMap::~QuicUnackedPacketMap() {
24 for (UnackedPacketMap::iterator it
= unacked_packets_
.begin();
25 it
!= unacked_packets_
.end(); ++it
) {
26 delete it
->second
.retransmittable_frames
;
27 // Only delete all_transmissions once, for the newest packet.
28 if (it
->first
== *it
->second
.all_transmissions
->rbegin()) {
29 delete it
->second
.all_transmissions
;
34 // TODO(ianswett): Combine this method with OnPacketSent once packets are always
35 // sent in order and the connection tracks RetransmittableFrames for longer.
36 void QuicUnackedPacketMap::AddPacket(
37 const SerializedPacket
& serialized_packet
) {
38 if (!unacked_packets_
.empty()) {
39 bool is_old_packet
= unacked_packets_
.rbegin()->first
>=
40 serialized_packet
.sequence_number
;
41 LOG_IF(DFATAL
, is_old_packet
) << "Old packet serialized: "
42 << serialized_packet
.sequence_number
44 << unacked_packets_
.rbegin()->first
;
47 unacked_packets_
[serialized_packet
.sequence_number
] =
48 TransmissionInfo(serialized_packet
.retransmittable_frames
,
49 serialized_packet
.sequence_number
,
50 serialized_packet
.sequence_number_length
);
51 if (serialized_packet
.retransmittable_frames
!= NULL
&&
52 serialized_packet
.retransmittable_frames
->HasCryptoHandshake()
54 ++pending_crypto_packet_count_
;
58 void QuicUnackedPacketMap::OnRetransmittedPacket(
59 QuicPacketSequenceNumber old_sequence_number
,
60 QuicPacketSequenceNumber new_sequence_number
,
61 TransmissionType transmission_type
) {
62 DCHECK(ContainsKey(unacked_packets_
, old_sequence_number
));
63 DCHECK(unacked_packets_
.empty() ||
64 unacked_packets_
.rbegin()->first
< new_sequence_number
);
66 // TODO(ianswett): Discard and lose the packet lazily instead of immediately.
67 TransmissionInfo
* transmission_info
=
68 FindOrNull(unacked_packets_
, old_sequence_number
);
69 RetransmittableFrames
* frames
= transmission_info
->retransmittable_frames
;
70 LOG_IF(DFATAL
, frames
== NULL
) << "Attempt to retransmit packet with no "
71 << "retransmittable frames: "
72 << old_sequence_number
;
74 // We keep the old packet in the unacked packet list until it, or one of
75 // the retransmissions of it are acked.
76 transmission_info
->retransmittable_frames
= NULL
;
77 unacked_packets_
[new_sequence_number
] =
78 TransmissionInfo(frames
,
80 transmission_info
->sequence_number_length
,
82 transmission_info
->all_transmissions
);
85 void QuicUnackedPacketMap::ClearPreviousRetransmissions(size_t num_to_clear
) {
86 UnackedPacketMap::iterator it
= unacked_packets_
.begin();
87 while (it
!= unacked_packets_
.end() && num_to_clear
> 0) {
88 QuicPacketSequenceNumber sequence_number
= it
->first
;
89 // If this packet is in flight, or has retransmittable data, then there is
90 // no point in clearing out any further packets, because they would not
91 // affect the high water mark.
92 if (it
->second
.in_flight
|| it
->second
.retransmittable_frames
!= NULL
) {
96 it
->second
.all_transmissions
->erase(sequence_number
);
97 LOG_IF(DFATAL
, it
->second
.all_transmissions
->empty())
98 << "Previous retransmissions must have a newer transmission.";
100 unacked_packets_
.erase(sequence_number
);
105 bool QuicUnackedPacketMap::HasRetransmittableFrames(
106 QuicPacketSequenceNumber sequence_number
) const {
107 const TransmissionInfo
* transmission_info
=
108 FindOrNull(unacked_packets_
, sequence_number
);
109 if (transmission_info
== NULL
) {
113 return transmission_info
->retransmittable_frames
!= NULL
;
116 void QuicUnackedPacketMap::NackPacket(QuicPacketSequenceNumber sequence_number
,
118 UnackedPacketMap::iterator it
= unacked_packets_
.find(sequence_number
);
119 if (it
== unacked_packets_
.end()) {
120 LOG(DFATAL
) << "NackPacket called for packet that is not unacked: "
125 it
->second
.nack_count
= max(min_nacks
, it
->second
.nack_count
);
128 void QuicUnackedPacketMap::RemoveRetransmittability(
129 QuicPacketSequenceNumber sequence_number
) {
130 UnackedPacketMap::iterator it
= unacked_packets_
.find(sequence_number
);
131 if (it
== unacked_packets_
.end()) {
132 DVLOG(1) << "packet is not in unacked_packets: " << sequence_number
;
135 SequenceNumberSet
* all_transmissions
= it
->second
.all_transmissions
;
136 // TODO(ianswett): Consider optimizing this for lone packets.
137 // TODO(ianswett): Consider adding a check to ensure there are retransmittable
138 // frames associated with this packet.
139 for (SequenceNumberSet::reverse_iterator it
= all_transmissions
->rbegin();
140 it
!= all_transmissions
->rend(); ++it
) {
141 TransmissionInfo
* transmission_info
= FindOrNull(unacked_packets_
, *it
);
142 if (transmission_info
== NULL
) {
143 LOG(DFATAL
) << "All transmissions in all_transmissions must be present "
144 << "in the unacked packet map.";
147 MaybeRemoveRetransmittableFrames(transmission_info
);
148 if (*it
<= largest_observed_
&& !transmission_info
->in_flight
) {
149 unacked_packets_
.erase(*it
);
151 transmission_info
->all_transmissions
= new SequenceNumberSet();
152 transmission_info
->all_transmissions
->insert(*it
);
156 delete all_transmissions
;
159 void QuicUnackedPacketMap::MaybeRemoveRetransmittableFrames(
160 TransmissionInfo
* transmission_info
) {
161 if (transmission_info
->retransmittable_frames
!= NULL
) {
162 if (transmission_info
->retransmittable_frames
->HasCryptoHandshake()
164 --pending_crypto_packet_count_
;
166 delete transmission_info
->retransmittable_frames
;
167 transmission_info
->retransmittable_frames
= NULL
;
171 void QuicUnackedPacketMap::IncreaseLargestObserved(
172 QuicPacketSequenceNumber largest_observed
) {
173 DCHECK_LT(largest_observed_
, largest_observed
);
174 largest_observed_
= largest_observed
;
175 UnackedPacketMap::iterator it
= unacked_packets_
.begin();
176 while (it
!= unacked_packets_
.end() && it
->first
<= largest_observed_
) {
177 if (!IsPacketUseless(it
)) {
181 delete it
->second
.all_transmissions
;
182 QuicPacketSequenceNumber sequence_number
= it
->first
;
184 unacked_packets_
.erase(sequence_number
);
188 bool QuicUnackedPacketMap::IsPacketUseless(
189 UnackedPacketMap::const_iterator it
) const {
190 return it
->first
<= largest_observed_
&&
191 !it
->second
.in_flight
&&
192 it
->second
.retransmittable_frames
== NULL
&&
193 it
->second
.all_transmissions
->size() == 1;
196 bool QuicUnackedPacketMap::IsUnacked(
197 QuicPacketSequenceNumber sequence_number
) const {
198 return ContainsKey(unacked_packets_
, sequence_number
);
201 void QuicUnackedPacketMap::RemoveFromInFlight(
202 QuicPacketSequenceNumber sequence_number
) {
203 UnackedPacketMap::iterator it
= unacked_packets_
.find(sequence_number
);
204 if (it
== unacked_packets_
.end()) {
205 LOG(DFATAL
) << "RemoveFromFlight called for packet that is not unacked: "
209 if (it
->second
.in_flight
) {
210 LOG_IF(DFATAL
, bytes_in_flight_
< it
->second
.bytes_sent
);
211 bytes_in_flight_
-= it
->second
.bytes_sent
;
212 it
->second
.in_flight
= false;
214 if (IsPacketUseless(it
)) {
215 delete it
->second
.all_transmissions
;
216 unacked_packets_
.erase(it
);
220 bool QuicUnackedPacketMap::HasUnackedPackets() const {
221 return !unacked_packets_
.empty();
224 bool QuicUnackedPacketMap::HasInFlightPackets() const {
225 return bytes_in_flight_
> 0;
228 const TransmissionInfo
& QuicUnackedPacketMap::GetTransmissionInfo(
229 QuicPacketSequenceNumber sequence_number
) const {
230 return unacked_packets_
.find(sequence_number
)->second
;
233 QuicTime
QuicUnackedPacketMap::GetLastPacketSentTime() const {
234 UnackedPacketMap::const_reverse_iterator it
= unacked_packets_
.rbegin();
235 while (it
!= unacked_packets_
.rend()) {
236 if (it
->second
.in_flight
) {
237 LOG_IF(DFATAL
, it
->second
.sent_time
== QuicTime::Zero())
238 << "Sent time can never be zero for a packet in flight.";
239 return it
->second
.sent_time
;
243 LOG(DFATAL
) << "GetLastPacketSentTime requires in flight packets.";
244 return QuicTime::Zero();
247 QuicTime
QuicUnackedPacketMap::GetFirstInFlightPacketSentTime() const {
248 UnackedPacketMap::const_iterator it
= unacked_packets_
.begin();
249 while (it
!= unacked_packets_
.end() && !it
->second
.in_flight
) {
252 if (it
== unacked_packets_
.end()) {
253 LOG(DFATAL
) << "GetFirstInFlightPacketSentTime requires in flight packets.";
254 return QuicTime::Zero();
256 return it
->second
.sent_time
;
259 size_t QuicUnackedPacketMap::GetNumUnackedPackets() const {
260 return unacked_packets_
.size();
263 bool QuicUnackedPacketMap::HasMultipleInFlightPackets() const {
264 size_t num_in_flight
= 0;
265 for (UnackedPacketMap::const_reverse_iterator it
= unacked_packets_
.rbegin();
266 it
!= unacked_packets_
.rend(); ++it
) {
267 if (it
->second
.in_flight
) {
270 if (num_in_flight
> 1) {
277 bool QuicUnackedPacketMap::HasPendingCryptoPackets() const {
278 return pending_crypto_packet_count_
> 0;
281 bool QuicUnackedPacketMap::HasUnackedRetransmittableFrames() const {
282 for (UnackedPacketMap::const_reverse_iterator it
=
283 unacked_packets_
.rbegin(); it
!= unacked_packets_
.rend(); ++it
) {
284 if (it
->second
.in_flight
&& it
->second
.retransmittable_frames
) {
291 QuicPacketSequenceNumber
292 QuicUnackedPacketMap::GetLeastUnackedSentPacket() const {
293 if (unacked_packets_
.empty()) {
294 // If there are no unacked packets, return 0.
298 return unacked_packets_
.begin()->first
;
301 void QuicUnackedPacketMap::SetSent(QuicPacketSequenceNumber sequence_number
,
303 QuicByteCount bytes_sent
,
304 bool set_in_flight
) {
305 DCHECK_LT(0u, sequence_number
);
306 UnackedPacketMap::iterator it
= unacked_packets_
.find(sequence_number
);
307 if (it
== unacked_packets_
.end()) {
308 LOG(DFATAL
) << "OnPacketSent called for packet that is not unacked: "
312 DCHECK(!it
->second
.in_flight
);
314 largest_sent_packet_
= max(sequence_number
, largest_sent_packet_
);
315 it
->second
.sent_time
= sent_time
;
317 bytes_in_flight_
+= bytes_sent
;
318 it
->second
.bytes_sent
= bytes_sent
;
319 it
->second
.in_flight
= true;
323 void QuicUnackedPacketMap::RestoreInFlight(
324 QuicPacketSequenceNumber sequence_number
) {
325 DCHECK_LT(0u, sequence_number
);
326 UnackedPacketMap::iterator it
= unacked_packets_
.find(sequence_number
);
327 if (it
== unacked_packets_
.end()) {
328 LOG(DFATAL
) << "OnPacketSent called for packet that is not unacked: "
332 DCHECK(!it
->second
.in_flight
);
333 DCHECK_NE(0u, it
->second
.bytes_sent
);
334 DCHECK(it
->second
.sent_time
.IsInitialized());
336 bytes_in_flight_
+= it
->second
.bytes_sent
;
337 it
->second
.in_flight
= true;