quic_received_packet_manager.cc revision bb1529ce867d8845a77ec7cdf3e3003ef1771a40
1// Copyright 2013 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_received_packet_manager.h"
6
7#include "base/logging.h"
8#include "net/base/linked_hash_map.h"
9
10using std::make_pair;
11using std::max;
12using std::min;
13
14namespace net {
15
16QuicReceivedPacketManager::QuicReceivedPacketManager()
17    : packets_entropy_hash_(0),
18      largest_sequence_number_(0),
19      peer_largest_observed_packet_(0),
20      least_packet_awaited_by_peer_(1),
21      peer_least_packet_awaiting_ack_(0),
22      time_largest_observed_(QuicTime::Zero()) {
23  received_info_.largest_observed = 0;
24  received_info_.entropy_hash = 0;
25}
26
27QuicReceivedPacketManager::~QuicReceivedPacketManager() {}
28
29void QuicReceivedPacketManager::RecordPacketReceived(
30    const QuicPacketHeader& header, QuicTime receipt_time) {
31  QuicPacketSequenceNumber sequence_number = header.packet_sequence_number;
32  DCHECK(IsAwaitingPacket(sequence_number));
33
34  InsertMissingPacketsBetween(
35      &received_info_,
36      max(received_info_.largest_observed + 1, peer_least_packet_awaiting_ack_),
37      header.packet_sequence_number);
38
39  if (received_info_.largest_observed > header.packet_sequence_number) {
40    // We've gotten one of the out of order packets - remove it from our
41    // "missing packets" list.
42    DVLOG(1) << "Removing " << sequence_number << " from missing list";
43    received_info_.missing_packets.erase(sequence_number);
44  }
45  if (header.packet_sequence_number > received_info_.largest_observed) {
46    received_info_.largest_observed = header.packet_sequence_number;
47    time_largest_observed_ = receipt_time;
48  }
49  RecordPacketEntropyHash(sequence_number, header.entropy_hash);
50}
51
52bool QuicReceivedPacketManager::IsAwaitingPacket(
53    QuicPacketSequenceNumber sequence_number) {
54  return ::net::IsAwaitingPacket(received_info_, sequence_number);
55}
56
57void QuicReceivedPacketManager::UpdateReceivedPacketInfo(
58    ReceivedPacketInfo* received_info, QuicTime approximate_now) {
59  *received_info = received_info_;
60  received_info->entropy_hash = EntropyHash(received_info_.largest_observed);
61  if (time_largest_observed_ == QuicTime::Zero()) {
62    // We have not received any new higher sequence numbers since we sent our
63    // last ACK.
64    received_info->delta_time_largest_observed = QuicTime::Delta::Infinite();
65  } else {
66    received_info->delta_time_largest_observed =
67        approximate_now.Subtract(time_largest_observed_);
68
69    time_largest_observed_ = QuicTime::Zero();
70  }
71}
72
73void QuicReceivedPacketManager::RecordPacketEntropyHash(
74    QuicPacketSequenceNumber sequence_number,
75    QuicPacketEntropyHash entropy_hash) {
76  if (sequence_number < largest_sequence_number_) {
77    DLOG(INFO) << "Ignoring received packet entropy for sequence_number:"
78               << sequence_number << " less than largest_peer_sequence_number:"
79               << largest_sequence_number_;
80    return;
81  }
82  packets_entropy_.insert(make_pair(sequence_number, entropy_hash));
83  packets_entropy_hash_ ^= entropy_hash;
84  DVLOG(2) << "setting cumulative received entropy hash to: "
85           << static_cast<int>(packets_entropy_hash_)
86           << " updated with sequence number " << sequence_number
87           << " entropy hash: " << static_cast<int>(entropy_hash);
88}
89
90QuicPacketEntropyHash QuicReceivedPacketManager::EntropyHash(
91    QuicPacketSequenceNumber sequence_number) const {
92  DCHECK_LE(sequence_number, received_info_.largest_observed);
93  DCHECK_GE(sequence_number, largest_sequence_number_);
94  if (sequence_number == received_info_.largest_observed) {
95    return packets_entropy_hash_;
96  }
97
98  ReceivedEntropyMap::const_iterator it =
99      packets_entropy_.upper_bound(sequence_number);
100  // When this map is empty we should only query entropy for
101  // |largest_received_sequence_number_|.
102  // TODO(rtenneti): add support for LOG_IF_EVERY_N_SEC to chromium.
103  // LOG_IF_EVERY_N_SEC(WARNING, it != packets_entropy_.end(), 10)
104  LOG_IF(WARNING, it != packets_entropy_.end())
105      << "largest_received: " << received_info_.largest_observed
106      << " sequence_number: " << sequence_number;
107
108  // TODO(satyamshekhar): Make this O(1).
109  QuicPacketEntropyHash hash = packets_entropy_hash_;
110  for (; it != packets_entropy_.end(); ++it) {
111    hash ^= it->second;
112  }
113  return hash;
114}
115
116void QuicReceivedPacketManager::RecalculateEntropyHash(
117    QuicPacketSequenceNumber peer_least_unacked,
118    QuicPacketEntropyHash entropy_hash) {
119  DLOG_IF(WARNING, peer_least_unacked > received_info_.largest_observed)
120      << "Prematurely updating the entropy manager before registering the "
121      << "entropy of the containing packet creates a temporary inconsistency.";
122  if (peer_least_unacked < largest_sequence_number_) {
123    DLOG(INFO) << "Ignoring received peer_least_unacked:" << peer_least_unacked
124               << " less than largest_peer_sequence_number:"
125               << largest_sequence_number_;
126    return;
127  }
128  largest_sequence_number_ = peer_least_unacked;
129  packets_entropy_hash_ = entropy_hash;
130  ReceivedEntropyMap::iterator it =
131      packets_entropy_.lower_bound(peer_least_unacked);
132  // TODO(satyamshekhar): Make this O(1).
133  for (; it != packets_entropy_.end(); ++it) {
134    packets_entropy_hash_ ^= it->second;
135  }
136  // Discard entropies before least unacked.
137  packets_entropy_.erase(
138      packets_entropy_.begin(),
139      packets_entropy_.lower_bound(
140          min(peer_least_unacked, received_info_.largest_observed)));
141}
142
143void QuicReceivedPacketManager::UpdatePacketInformationReceivedByPeer(
144    const QuicAckFrame& incoming_ack) {
145  // ValidateAck should fail if largest_observed ever shrinks.
146  DCHECK_LE(peer_largest_observed_packet_,
147            incoming_ack.received_info.largest_observed);
148  peer_largest_observed_packet_ = incoming_ack.received_info.largest_observed;
149
150  if (incoming_ack.received_info.missing_packets.empty()) {
151    least_packet_awaited_by_peer_ = peer_largest_observed_packet_ + 1;
152  } else {
153    least_packet_awaited_by_peer_ =
154        *(incoming_ack.received_info.missing_packets.begin());
155  }
156}
157
158bool QuicReceivedPacketManager::DontWaitForPacketsBefore(
159    QuicPacketSequenceNumber least_unacked) {
160  size_t missing_packets_count = received_info_.missing_packets.size();
161  received_info_.missing_packets.erase(
162      received_info_.missing_packets.begin(),
163      received_info_.missing_packets.lower_bound(least_unacked));
164  return missing_packets_count != received_info_.missing_packets.size();
165}
166
167void QuicReceivedPacketManager::UpdatePacketInformationSentByPeer(
168    const QuicAckFrame& incoming_ack) {
169  // ValidateAck() should fail if peer_least_packet_awaiting_ack_ shrinks.
170  DCHECK_LE(peer_least_packet_awaiting_ack_,
171            incoming_ack.sent_info.least_unacked);
172  if (incoming_ack.sent_info.least_unacked > peer_least_packet_awaiting_ack_) {
173    bool missed_packets =
174        DontWaitForPacketsBefore(incoming_ack.sent_info.least_unacked);
175    if (missed_packets || incoming_ack.sent_info.least_unacked >
176            received_info_.largest_observed + 1) {
177      DVLOG(1) << "Updating entropy hashed since we missed packets";
178      // There were some missing packets that we won't ever get now. Recalculate
179      // the received entropy hash.
180      RecalculateEntropyHash(incoming_ack.sent_info.least_unacked,
181                             incoming_ack.sent_info.entropy_hash);
182    }
183    peer_least_packet_awaiting_ack_ = incoming_ack.sent_info.least_unacked;
184  }
185  DCHECK(received_info_.missing_packets.empty() ||
186         *received_info_.missing_packets.begin() >=
187             peer_least_packet_awaiting_ack_);
188}
189
190}  // namespace net
191