OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 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_sent_entropy_manager.h" | 5 #include "net/quic/quic_sent_entropy_manager.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "net/base/linked_hash_map.h" | 8 #include "net/base/linked_hash_map.h" |
9 | 9 |
10 using std::make_pair; | 10 using std::make_pair; |
11 using std::max; | 11 using std::max; |
12 using std::min; | 12 using std::min; |
13 | 13 |
14 namespace net { | 14 namespace net { |
15 | 15 |
16 QuicSentEntropyManager::QuicSentEntropyManager() | 16 QuicSentEntropyManager::QuicSentEntropyManager() : map_offset_(1) {} |
17 : packets_entropy_hash_(0) {} | |
18 | 17 |
19 QuicSentEntropyManager::~QuicSentEntropyManager() {} | 18 QuicSentEntropyManager::~QuicSentEntropyManager() {} |
20 | 19 |
| 20 QuicPacketEntropyHash QuicSentEntropyManager::GetPacketEntropy( |
| 21 QuicPacketSequenceNumber sequence_number) const { |
| 22 return packets_entropy_[sequence_number - map_offset_]; |
| 23 } |
| 24 |
| 25 QuicPacketSequenceNumber |
| 26 QuicSentEntropyManager::GetLargestPacketWithEntropy() const { |
| 27 return map_offset_ + packets_entropy_.size() - 1; |
| 28 } |
| 29 |
| 30 QuicPacketSequenceNumber |
| 31 QuicSentEntropyManager::GetSmallestPacketWithEntropy() const { |
| 32 return map_offset_; |
| 33 } |
| 34 |
| 35 void QuicSentEntropyManager::UpdateCumulativeEntropy( |
| 36 QuicPacketSequenceNumber sequence_number, |
| 37 CumulativeEntropy* cumulative) const { |
| 38 while (cumulative->sequence_number < sequence_number) { |
| 39 ++cumulative->sequence_number; |
| 40 cumulative->entropy ^= GetPacketEntropy(cumulative->sequence_number); |
| 41 } |
| 42 } |
| 43 |
21 void QuicSentEntropyManager::RecordPacketEntropyHash( | 44 void QuicSentEntropyManager::RecordPacketEntropyHash( |
22 QuicPacketSequenceNumber sequence_number, | 45 QuicPacketSequenceNumber sequence_number, |
23 QuicPacketEntropyHash entropy_hash) { | 46 QuicPacketEntropyHash entropy_hash) { |
24 if (!packets_entropy_.empty()) { | 47 if (!packets_entropy_.empty()) { |
25 // Ensure packets always are recorded in order. | 48 // Ensure packets always are recorded in order. |
26 // Every packet's entropy is recorded, even if it's not sent, so there | 49 // Every packet's entropy is recorded, even if it's not sent, so there |
27 // are not sequence number gaps. | 50 // are not sequence number gaps. |
28 DCHECK_LT(packets_entropy_.back().first, sequence_number); | 51 DCHECK_LT(GetLargestPacketWithEntropy(), sequence_number); |
29 } | 52 } |
30 packets_entropy_hash_ ^= entropy_hash; | 53 packets_entropy_.push_back(entropy_hash); |
31 packets_entropy_.insert( | 54 DVLOG(2) << "Recorded sequence number " << sequence_number |
32 make_pair(sequence_number, | 55 << " with entropy hash: " << static_cast<int>(entropy_hash); |
33 make_pair(entropy_hash, packets_entropy_hash_))); | |
34 DVLOG(2) << "setting cumulative sent entropy hash to: " | |
35 << static_cast<int>(packets_entropy_hash_) | |
36 << " updated with sequence number " << sequence_number | |
37 << " entropy hash: " << static_cast<int>(entropy_hash); | |
38 } | 56 } |
39 | 57 |
40 QuicPacketEntropyHash QuicSentEntropyManager::EntropyHash( | 58 QuicPacketEntropyHash QuicSentEntropyManager::GetCumulativeEntropy( |
41 QuicPacketSequenceNumber sequence_number) const { | 59 QuicPacketSequenceNumber sequence_number) { |
42 SentEntropyMap::const_iterator it = | 60 DCHECK_LE(last_cumulative_entropy_.sequence_number, sequence_number); |
43 packets_entropy_.find(sequence_number); | 61 DCHECK_GE(GetLargestPacketWithEntropy(), sequence_number); |
44 if (it == packets_entropy_.end()) { | 62 // First the entropy for largest_observed sequence number should be updated. |
45 // Should only happen when we have not received ack for any packet. | 63 UpdateCumulativeEntropy(sequence_number, &last_cumulative_entropy_); |
46 DCHECK_EQ(0u, sequence_number); | 64 return last_cumulative_entropy_.entropy; |
47 return 0; | |
48 } | |
49 return it->second.second; | |
50 } | 65 } |
51 | 66 |
52 bool QuicSentEntropyManager::IsValidEntropy( | 67 bool QuicSentEntropyManager::IsValidEntropy( |
53 QuicPacketSequenceNumber sequence_number, | 68 QuicPacketSequenceNumber largest_observed, |
54 const SequenceNumberSet& missing_packets, | 69 const SequenceNumberSet& missing_packets, |
55 QuicPacketEntropyHash entropy_hash) const { | 70 QuicPacketEntropyHash entropy_hash) { |
56 SentEntropyMap::const_iterator entropy_it = | 71 DCHECK_GE(largest_observed, last_valid_entropy_.sequence_number); |
57 packets_entropy_.find(sequence_number); | 72 // Ensure the largest and smallest sequence numbers are in range. |
58 if (entropy_it == packets_entropy_.end()) { | 73 if (largest_observed > GetLargestPacketWithEntropy()) { |
59 DCHECK_EQ(0u, sequence_number); | 74 return false; |
60 // Close connection if something goes wrong. | |
61 return 0 == sequence_number; | |
62 } | 75 } |
63 QuicPacketEntropyHash expected_entropy_hash = entropy_it->second.second; | 76 if (!missing_packets.empty() && |
| 77 *missing_packets.begin() < GetSmallestPacketWithEntropy()) { |
| 78 return false; |
| 79 } |
| 80 // First the entropy for largest_observed sequence number should be updated. |
| 81 UpdateCumulativeEntropy(largest_observed, &last_valid_entropy_); |
| 82 |
| 83 // Now XOR out all the missing entropies. |
| 84 QuicPacketEntropyHash expected_entropy_hash = last_valid_entropy_.entropy; |
64 for (SequenceNumberSet::const_iterator it = missing_packets.begin(); | 85 for (SequenceNumberSet::const_iterator it = missing_packets.begin(); |
65 it != missing_packets.end(); ++it) { | 86 it != missing_packets.end(); ++it) { |
66 entropy_it = packets_entropy_.find(*it); | 87 expected_entropy_hash ^= GetPacketEntropy(*it); |
67 DCHECK(entropy_it != packets_entropy_.end()); | |
68 expected_entropy_hash ^= entropy_it->second.first; | |
69 } | 88 } |
70 DLOG_IF(WARNING, entropy_hash != expected_entropy_hash) | 89 DLOG_IF(WARNING, entropy_hash != expected_entropy_hash) |
71 << "Invalid entropy hash: " << static_cast<int>(entropy_hash) | 90 << "Invalid entropy hash: " << static_cast<int>(entropy_hash) |
72 << " expected entropy hash: " << static_cast<int>(expected_entropy_hash); | 91 << " expected entropy hash: " << static_cast<int>(expected_entropy_hash); |
73 return entropy_hash == expected_entropy_hash; | 92 return entropy_hash == expected_entropy_hash; |
74 } | 93 } |
75 | 94 |
76 void QuicSentEntropyManager::ClearEntropyBefore( | 95 void QuicSentEntropyManager::ClearEntropyBefore( |
77 QuicPacketSequenceNumber sequence_number) { | 96 QuicPacketSequenceNumber sequence_number) { |
78 if (packets_entropy_.empty()) { | 97 // Don't discard entropy before updating the cumulative entropy used to |
79 return; | 98 // calculate EntropyHash and IsValidEntropy. |
| 99 if (last_cumulative_entropy_.sequence_number < sequence_number) { |
| 100 UpdateCumulativeEntropy(sequence_number, &last_cumulative_entropy_); |
80 } | 101 } |
81 SentEntropyMap::iterator it = packets_entropy_.begin(); | 102 if (last_valid_entropy_.sequence_number < sequence_number) { |
82 while (it->first < sequence_number) { | 103 UpdateCumulativeEntropy(sequence_number, &last_valid_entropy_); |
83 packets_entropy_.erase(it); | |
84 it = packets_entropy_.begin(); | |
85 DCHECK(it != packets_entropy_.end()); | |
86 } | 104 } |
87 DVLOG(2) << "Cleared entropy before: " | 105 while (map_offset_ < sequence_number) { |
88 << packets_entropy_.begin()->first; | 106 packets_entropy_.pop_front(); |
| 107 ++map_offset_; |
| 108 } |
| 109 DVLOG(2) << "Cleared entropy before: " << sequence_number; |
89 } | 110 } |
90 | 111 |
91 } // namespace net | 112 } // namespace net |
OLD | NEW |