| Index: net/quic/quic_sent_entropy_manager.cc
|
| diff --git a/net/quic/quic_sent_entropy_manager.cc b/net/quic/quic_sent_entropy_manager.cc
|
| index 9472a880a52e19e8919d5760d99e292f0ea6b79d..ff19a02c669b457d5a95aef0be82e32ddcc05dc8 100644
|
| --- a/net/quic/quic_sent_entropy_manager.cc
|
| +++ b/net/quic/quic_sent_entropy_manager.cc
|
| @@ -13,11 +13,34 @@ using std::min;
|
|
|
| namespace net {
|
|
|
| -QuicSentEntropyManager::QuicSentEntropyManager()
|
| - : packets_entropy_hash_(0) {}
|
| +QuicSentEntropyManager::QuicSentEntropyManager() : map_offset_(1) {}
|
|
|
| QuicSentEntropyManager::~QuicSentEntropyManager() {}
|
|
|
| +QuicPacketEntropyHash QuicSentEntropyManager::GetPacketEntropy(
|
| + QuicPacketSequenceNumber sequence_number) const {
|
| + return packets_entropy_[sequence_number - map_offset_];
|
| +}
|
| +
|
| +QuicPacketSequenceNumber
|
| +QuicSentEntropyManager::GetLargestPacketWithEntropy() const {
|
| + return map_offset_ + packets_entropy_.size() - 1;
|
| +}
|
| +
|
| +QuicPacketSequenceNumber
|
| +QuicSentEntropyManager::GetSmallestPacketWithEntropy() const {
|
| + return map_offset_;
|
| +}
|
| +
|
| +void QuicSentEntropyManager::UpdateCumulativeEntropy(
|
| + QuicPacketSequenceNumber sequence_number,
|
| + CumulativeEntropy* cumulative) const {
|
| + while (cumulative->sequence_number < sequence_number) {
|
| + ++cumulative->sequence_number;
|
| + cumulative->entropy ^= GetPacketEntropy(cumulative->sequence_number);
|
| + }
|
| +}
|
| +
|
| void QuicSentEntropyManager::RecordPacketEntropyHash(
|
| QuicPacketSequenceNumber sequence_number,
|
| QuicPacketEntropyHash entropy_hash) {
|
| @@ -25,47 +48,43 @@ void QuicSentEntropyManager::RecordPacketEntropyHash(
|
| // Ensure packets always are recorded in order.
|
| // Every packet's entropy is recorded, even if it's not sent, so there
|
| // are not sequence number gaps.
|
| - DCHECK_LT(packets_entropy_.back().first, sequence_number);
|
| + DCHECK_LT(GetLargestPacketWithEntropy(), sequence_number);
|
| }
|
| - packets_entropy_hash_ ^= entropy_hash;
|
| - packets_entropy_.insert(
|
| - make_pair(sequence_number,
|
| - make_pair(entropy_hash, packets_entropy_hash_)));
|
| - DVLOG(2) << "setting cumulative sent entropy hash to: "
|
| - << static_cast<int>(packets_entropy_hash_)
|
| - << " updated with sequence number " << sequence_number
|
| - << " entropy hash: " << static_cast<int>(entropy_hash);
|
| + packets_entropy_.push_back(entropy_hash);
|
| + DVLOG(2) << "Recorded sequence number " << sequence_number
|
| + << " with entropy hash: " << static_cast<int>(entropy_hash);
|
| }
|
|
|
| -QuicPacketEntropyHash QuicSentEntropyManager::EntropyHash(
|
| - QuicPacketSequenceNumber sequence_number) const {
|
| - SentEntropyMap::const_iterator it =
|
| - packets_entropy_.find(sequence_number);
|
| - if (it == packets_entropy_.end()) {
|
| - // Should only happen when we have not received ack for any packet.
|
| - DCHECK_EQ(0u, sequence_number);
|
| - return 0;
|
| - }
|
| - return it->second.second;
|
| +QuicPacketEntropyHash QuicSentEntropyManager::GetCumulativeEntropy(
|
| + QuicPacketSequenceNumber sequence_number) {
|
| + DCHECK_LE(last_cumulative_entropy_.sequence_number, sequence_number);
|
| + DCHECK_GE(GetLargestPacketWithEntropy(), sequence_number);
|
| + // First the entropy for largest_observed sequence number should be updated.
|
| + UpdateCumulativeEntropy(sequence_number, &last_cumulative_entropy_);
|
| + return last_cumulative_entropy_.entropy;
|
| }
|
|
|
| bool QuicSentEntropyManager::IsValidEntropy(
|
| - QuicPacketSequenceNumber sequence_number,
|
| + QuicPacketSequenceNumber largest_observed,
|
| const SequenceNumberSet& missing_packets,
|
| - QuicPacketEntropyHash entropy_hash) const {
|
| - SentEntropyMap::const_iterator entropy_it =
|
| - packets_entropy_.find(sequence_number);
|
| - if (entropy_it == packets_entropy_.end()) {
|
| - DCHECK_EQ(0u, sequence_number);
|
| - // Close connection if something goes wrong.
|
| - return 0 == sequence_number;
|
| + QuicPacketEntropyHash entropy_hash) {
|
| + DCHECK_GE(largest_observed, last_valid_entropy_.sequence_number);
|
| + // Ensure the largest and smallest sequence numbers are in range.
|
| + if (largest_observed > GetLargestPacketWithEntropy()) {
|
| + return false;
|
| + }
|
| + if (!missing_packets.empty() &&
|
| + *missing_packets.begin() < GetSmallestPacketWithEntropy()) {
|
| + return false;
|
| }
|
| - QuicPacketEntropyHash expected_entropy_hash = entropy_it->second.second;
|
| + // First the entropy for largest_observed sequence number should be updated.
|
| + UpdateCumulativeEntropy(largest_observed, &last_valid_entropy_);
|
| +
|
| + // Now XOR out all the missing entropies.
|
| + QuicPacketEntropyHash expected_entropy_hash = last_valid_entropy_.entropy;
|
| for (SequenceNumberSet::const_iterator it = missing_packets.begin();
|
| it != missing_packets.end(); ++it) {
|
| - entropy_it = packets_entropy_.find(*it);
|
| - DCHECK(entropy_it != packets_entropy_.end());
|
| - expected_entropy_hash ^= entropy_it->second.first;
|
| + expected_entropy_hash ^= GetPacketEntropy(*it);
|
| }
|
| DLOG_IF(WARNING, entropy_hash != expected_entropy_hash)
|
| << "Invalid entropy hash: " << static_cast<int>(entropy_hash)
|
| @@ -75,17 +94,19 @@ bool QuicSentEntropyManager::IsValidEntropy(
|
|
|
| void QuicSentEntropyManager::ClearEntropyBefore(
|
| QuicPacketSequenceNumber sequence_number) {
|
| - if (packets_entropy_.empty()) {
|
| - return;
|
| + // Don't discard entropy before updating the cumulative entropy used to
|
| + // calculate EntropyHash and IsValidEntropy.
|
| + if (last_cumulative_entropy_.sequence_number < sequence_number) {
|
| + UpdateCumulativeEntropy(sequence_number, &last_cumulative_entropy_);
|
| + }
|
| + if (last_valid_entropy_.sequence_number < sequence_number) {
|
| + UpdateCumulativeEntropy(sequence_number, &last_valid_entropy_);
|
| }
|
| - SentEntropyMap::iterator it = packets_entropy_.begin();
|
| - while (it->first < sequence_number) {
|
| - packets_entropy_.erase(it);
|
| - it = packets_entropy_.begin();
|
| - DCHECK(it != packets_entropy_.end());
|
| + while (map_offset_ < sequence_number) {
|
| + packets_entropy_.pop_front();
|
| + ++map_offset_;
|
| }
|
| - DVLOG(2) << "Cleared entropy before: "
|
| - << packets_entropy_.begin()->first;
|
| + DVLOG(2) << "Cleared entropy before: " << sequence_number;
|
| }
|
|
|
| } // namespace net
|
|
|