OLD | NEW |
| (Empty) |
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_sent_entropy_manager.h" | |
6 | |
7 #include "base/logging.h" | |
8 #include "net/base/linked_hash_map.h" | |
9 #include "net/quic/quic_flags.h" | |
10 | |
11 using std::make_pair; | |
12 using std::max; | |
13 using std::min; | |
14 | |
15 namespace net { | |
16 | |
17 QuicSentEntropyManager::QuicSentEntropyManager() : map_offset_(1) {} | |
18 | |
19 QuicSentEntropyManager::~QuicSentEntropyManager() {} | |
20 | |
21 QuicPacketEntropyHash QuicSentEntropyManager::GetPacketEntropy( | |
22 QuicPacketNumber packet_number) const { | |
23 return packets_entropy_[packet_number - map_offset_]; | |
24 } | |
25 | |
26 QuicPacketNumber QuicSentEntropyManager::GetLargestPacketWithEntropy() const { | |
27 return map_offset_ + packets_entropy_.size() - 1; | |
28 } | |
29 | |
30 QuicPacketNumber QuicSentEntropyManager::GetSmallestPacketWithEntropy() const { | |
31 return map_offset_; | |
32 } | |
33 | |
34 void QuicSentEntropyManager::UpdateCumulativeEntropy( | |
35 QuicPacketNumber packet_number, | |
36 CumulativeEntropy* cumulative) const { | |
37 while (cumulative->packet_number < packet_number) { | |
38 ++cumulative->packet_number; | |
39 cumulative->entropy ^= GetPacketEntropy(cumulative->packet_number); | |
40 } | |
41 } | |
42 | |
43 void QuicSentEntropyManager::RecordPacketEntropyHash( | |
44 QuicPacketNumber packet_number, | |
45 QuicPacketEntropyHash entropy_hash) { | |
46 if (!packets_entropy_.empty()) { | |
47 // Ensure packets always are recorded in order. | |
48 // Every packet's entropy is recorded, even if it's not sent, so there | |
49 // are not packet number gaps. | |
50 DCHECK_EQ(GetLargestPacketWithEntropy() + 1, packet_number); | |
51 } | |
52 packets_entropy_.push_back(entropy_hash); | |
53 DVLOG(2) << "Recorded packet number " << packet_number | |
54 << " with entropy hash: " << static_cast<int>(entropy_hash); | |
55 } | |
56 | |
57 QuicPacketEntropyHash QuicSentEntropyManager::GetCumulativeEntropy( | |
58 QuicPacketNumber packet_number) { | |
59 DCHECK_LE(last_cumulative_entropy_.packet_number, packet_number); | |
60 DCHECK_GE(GetLargestPacketWithEntropy(), packet_number); | |
61 // First the entropy for largest_observed packet number should be updated. | |
62 UpdateCumulativeEntropy(packet_number, &last_cumulative_entropy_); | |
63 return last_cumulative_entropy_.entropy; | |
64 } | |
65 | |
66 bool QuicSentEntropyManager::IsValidEntropy( | |
67 QuicPacketNumber largest_observed, | |
68 const PacketNumberQueue& missing_packets, | |
69 QuicPacketEntropyHash entropy_hash) { | |
70 DCHECK_GE(largest_observed, last_valid_entropy_.packet_number); | |
71 // Ensure the largest and smallest packet numbers are in range. | |
72 if (largest_observed > GetLargestPacketWithEntropy()) { | |
73 return false; | |
74 } | |
75 if (!missing_packets.Empty() && | |
76 missing_packets.Min() < GetSmallestPacketWithEntropy()) { | |
77 return false; | |
78 } | |
79 // First the entropy for largest_observed packet number should be updated. | |
80 UpdateCumulativeEntropy(largest_observed, &last_valid_entropy_); | |
81 | |
82 // Now XOR out all the missing entropies. | |
83 QuicPacketEntropyHash expected_entropy_hash = last_valid_entropy_.entropy; | |
84 if (FLAGS_quic_use_packet_number_queue_intervals) { | |
85 for (auto itr = missing_packets.begin_intervals(); | |
86 itr != missing_packets.end_intervals(); ++itr) { | |
87 const auto& interval = *itr; | |
88 for (QuicPacketNumber packet_number = interval.min(); | |
89 packet_number < interval.max(); ++packet_number) { | |
90 expected_entropy_hash ^= GetPacketEntropy(packet_number); | |
91 } | |
92 } | |
93 } else { | |
94 for (QuicPacketNumber packet : missing_packets) { | |
95 expected_entropy_hash ^= GetPacketEntropy(packet); | |
96 } | |
97 } | |
98 DLOG_IF(WARNING, entropy_hash != expected_entropy_hash) | |
99 << "Invalid entropy hash: " << static_cast<int>(entropy_hash) | |
100 << " expected entropy hash: " << static_cast<int>(expected_entropy_hash); | |
101 return entropy_hash == expected_entropy_hash; | |
102 } | |
103 | |
104 void QuicSentEntropyManager::ClearEntropyBefore( | |
105 QuicPacketNumber packet_number) { | |
106 // Don't discard entropy before updating the cumulative entropy used to | |
107 // calculate EntropyHash and IsValidEntropy. | |
108 if (last_cumulative_entropy_.packet_number < packet_number) { | |
109 UpdateCumulativeEntropy(packet_number, &last_cumulative_entropy_); | |
110 } | |
111 if (last_valid_entropy_.packet_number < packet_number) { | |
112 UpdateCumulativeEntropy(packet_number, &last_valid_entropy_); | |
113 } | |
114 while (map_offset_ < packet_number) { | |
115 packets_entropy_.pop_front(); | |
116 ++map_offset_; | |
117 } | |
118 DVLOG(2) << "Cleared entropy before: " << packet_number; | |
119 } | |
120 | |
121 } // namespace net | |
OLD | NEW |