quic_unacked_packet_map.cc revision 03b57e008b61dfcb1fbad3aea950ae0e001748b0
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.
4
5#include "net/quic/quic_unacked_packet_map.h"
6
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"
11
12using std::max;
13
14namespace net {
15
16QuicUnackedPacketMap::QuicUnackedPacketMap()
17    : largest_sent_packet_(0),
18      largest_observed_(0),
19      bytes_in_flight_(0),
20      pending_crypto_packet_count_(0) {
21}
22
23QuicUnackedPacketMap::~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;
30    }
31  }
32}
33
34// TODO(ianswett): Combine this method with OnPacketSent once packets are always
35// sent in order and the connection tracks RetransmittableFrames for longer.
36void 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
43                                  << " vs: "
44                                  << unacked_packets_.rbegin()->first;
45  }
46
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()
53          == IS_HANDSHAKE) {
54    ++pending_crypto_packet_count_;
55  }
56}
57
58void 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);
65
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;
73
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  // Only keep one transmission older than largest observed, because only the
78  // most recent is expected to possibly be a spurious retransmission.
79  if (transmission_info->all_transmissions->size() > 1 &&
80      *(++transmission_info->all_transmissions->begin()) < largest_observed_) {
81    QuicPacketSequenceNumber old_transmission =
82        *transmission_info->all_transmissions->begin();
83    TransmissionInfo* old_transmission_info =
84        FindOrNull(unacked_packets_, old_transmission);
85    // Don't remove old packets if they're still in flight.
86    if (old_transmission_info == NULL || !old_transmission_info->in_flight) {
87      transmission_info->all_transmissions->erase(old_transmission);
88      unacked_packets_.erase(old_transmission);
89    }
90  }
91  unacked_packets_[new_sequence_number] =
92      TransmissionInfo(frames,
93                       new_sequence_number,
94                       transmission_info->sequence_number_length,
95                       transmission_type,
96                       transmission_info->all_transmissions);
97}
98
99void QuicUnackedPacketMap::ClearPreviousRetransmissions(size_t num_to_clear) {
100  UnackedPacketMap::iterator it = unacked_packets_.begin();
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
104    // no point in clearing out any further packets, because they would not
105    // affect the high water mark.
106    if (it->second.in_flight || it->second.retransmittable_frames != NULL) {
107      break;
108    }
109
110    it->second.all_transmissions->erase(sequence_number);
111    LOG_IF(DFATAL, it->second.all_transmissions->empty())
112        << "Previous retransmissions must have a newer transmission.";
113    ++it;
114    unacked_packets_.erase(sequence_number);
115    --num_to_clear;
116  }
117}
118
119bool QuicUnackedPacketMap::HasRetransmittableFrames(
120    QuicPacketSequenceNumber sequence_number) const {
121  const TransmissionInfo* transmission_info =
122      FindOrNull(unacked_packets_, sequence_number);
123  if (transmission_info == NULL) {
124    return false;
125  }
126
127  return transmission_info->retransmittable_frames != NULL;
128}
129
130void QuicUnackedPacketMap::NackPacket(QuicPacketSequenceNumber sequence_number,
131                                      size_t min_nacks) {
132  UnackedPacketMap::iterator it = unacked_packets_.find(sequence_number);
133  if (it == unacked_packets_.end()) {
134    LOG(DFATAL) << "NackPacket called for packet that is not unacked: "
135                << sequence_number;
136    return;
137  }
138
139  it->second.nack_count = max(min_nacks, it->second.nack_count);
140}
141
142void QuicUnackedPacketMap::RemoveRetransmittability(
143    QuicPacketSequenceNumber sequence_number) {
144  UnackedPacketMap::iterator it = unacked_packets_.find(sequence_number);
145  if (it == unacked_packets_.end()) {
146    DVLOG(1) << "packet is not in unacked_packets: " << sequence_number;
147    return;
148  }
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
152  // frames associated with this packet.
153  for (SequenceNumberSet::reverse_iterator it = all_transmissions->rbegin();
154       it != all_transmissions->rend(); ++it) {
155    TransmissionInfo* transmission_info = FindOrNull(unacked_packets_, *it);
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    }
161    MaybeRemoveRetransmittableFrames(transmission_info);
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    }
168  }
169
170  delete all_transmissions;
171}
172
173void QuicUnackedPacketMap::MaybeRemoveRetransmittableFrames(
174    TransmissionInfo* transmission_info) {
175  if (transmission_info->retransmittable_frames != NULL) {
176    if (transmission_info->retransmittable_frames->HasCryptoHandshake()
177            == IS_HANDSHAKE) {
178      --pending_crypto_packet_count_;
179    }
180    delete transmission_info->retransmittable_frames;
181    transmission_info->retransmittable_frames = NULL;
182  }
183}
184
185void QuicUnackedPacketMap::IncreaseLargestObserved(
186    QuicPacketSequenceNumber largest_observed) {
187  DCHECK_LE(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  }
200}
201
202bool QuicUnackedPacketMap::IsPacketUseless(
203    UnackedPacketMap::const_iterator it) const {
204  return it->first <= largest_observed_ &&
205      !it->second.in_flight &&
206      it->second.retransmittable_frames == NULL &&
207      it->second.all_transmissions->size() == 1;
208}
209
210bool QuicUnackedPacketMap::IsUnacked(
211    QuicPacketSequenceNumber sequence_number) const {
212  return ContainsKey(unacked_packets_, sequence_number);
213}
214
215void QuicUnackedPacketMap::RemoveFromInFlight(
216    QuicPacketSequenceNumber sequence_number) {
217  UnackedPacketMap::iterator it = unacked_packets_.find(sequence_number);
218  if (it == unacked_packets_.end()) {
219    LOG(DFATAL) << "RemoveFromFlight called for packet that is not unacked: "
220                << sequence_number;
221    return;
222  }
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);
231  }
232}
233
234bool QuicUnackedPacketMap::HasUnackedPackets() const {
235  return !unacked_packets_.empty();
236}
237
238bool QuicUnackedPacketMap::HasInFlightPackets() const {
239  return bytes_in_flight_ > 0;
240}
241
242const TransmissionInfo& QuicUnackedPacketMap::GetTransmissionInfo(
243    QuicPacketSequenceNumber sequence_number) const {
244  return unacked_packets_.find(sequence_number)->second;
245}
246
247QuicTime QuicUnackedPacketMap::GetLastPacketSentTime() const {
248  UnackedPacketMap::const_reverse_iterator it = unacked_packets_.rbegin();
249  while (it != unacked_packets_.rend()) {
250    if (it->second.in_flight) {
251      LOG_IF(DFATAL, it->second.sent_time == QuicTime::Zero())
252          << "Sent time can never be zero for a packet in flight.";
253      return it->second.sent_time;
254    }
255    ++it;
256  }
257  LOG(DFATAL) << "GetLastPacketSentTime requires in flight packets.";
258  return QuicTime::Zero();
259}
260
261QuicTime QuicUnackedPacketMap::GetFirstInFlightPacketSentTime() const {
262  UnackedPacketMap::const_iterator it = unacked_packets_.begin();
263  while (it != unacked_packets_.end() && !it->second.in_flight) {
264    ++it;
265  }
266  if (it == unacked_packets_.end()) {
267    LOG(DFATAL) << "GetFirstInFlightPacketSentTime requires in flight packets.";
268    return QuicTime::Zero();
269  }
270  return it->second.sent_time;
271}
272
273size_t QuicUnackedPacketMap::GetNumUnackedPackets() const {
274  return unacked_packets_.size();
275}
276
277bool QuicUnackedPacketMap::HasMultipleInFlightPackets() const {
278  size_t num_in_flight = 0;
279  for (UnackedPacketMap::const_reverse_iterator it = unacked_packets_.rbegin();
280       it != unacked_packets_.rend(); ++it) {
281    if (it->second.in_flight) {
282      ++num_in_flight;
283    }
284    if (num_in_flight > 1) {
285      return true;
286    }
287  }
288  return false;
289}
290
291bool QuicUnackedPacketMap::HasPendingCryptoPackets() const {
292  return pending_crypto_packet_count_ > 0;
293}
294
295bool QuicUnackedPacketMap::HasUnackedRetransmittableFrames() const {
296  for (UnackedPacketMap::const_reverse_iterator it =
297           unacked_packets_.rbegin(); it != unacked_packets_.rend(); ++it) {
298    if (it->second.in_flight && it->second.retransmittable_frames) {
299      return true;
300    }
301  }
302  return false;
303}
304
305QuicPacketSequenceNumber
306QuicUnackedPacketMap::GetLeastUnackedSentPacket() const {
307  if (unacked_packets_.empty()) {
308    // If there are no unacked packets, return 0.
309    return 0;
310  }
311
312  return unacked_packets_.begin()->first;
313}
314
315void QuicUnackedPacketMap::SetSent(QuicPacketSequenceNumber sequence_number,
316                                   QuicTime sent_time,
317                                   QuicByteCount bytes_sent,
318                                   bool set_in_flight) {
319  DCHECK_LT(0u, sequence_number);
320  UnackedPacketMap::iterator it = unacked_packets_.find(sequence_number);
321  if (it == unacked_packets_.end()) {
322    LOG(DFATAL) << "OnPacketSent called for packet that is not unacked: "
323                << sequence_number;
324    return;
325  }
326  DCHECK(!it->second.in_flight);
327
328  largest_sent_packet_ = max(sequence_number, largest_sent_packet_);
329  it->second.sent_time = sent_time;
330  if (set_in_flight) {
331    bytes_in_flight_ += bytes_sent;
332    it->second.bytes_sent = bytes_sent;
333    it->second.in_flight = true;
334  }
335}
336
337void QuicUnackedPacketMap::RestoreInFlight(
338    QuicPacketSequenceNumber sequence_number) {
339  DCHECK_LT(0u, sequence_number);
340  UnackedPacketMap::iterator it = unacked_packets_.find(sequence_number);
341  if (it == unacked_packets_.end()) {
342    LOG(DFATAL) << "OnPacketSent called for packet that is not unacked: "
343                << sequence_number;
344    return;
345  }
346  DCHECK(!it->second.in_flight);
347  DCHECK_NE(0u, it->second.bytes_sent);
348  DCHECK(it->second.sent_time.IsInitialized());
349
350  bytes_in_flight_ += it->second.bytes_sent;
351  it->second.in_flight = true;
352}
353
354}  // namespace net
355