1558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// Copyright 2013 The Chromium Authors. All rights reserved. 2558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 3558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// found in the LICENSE file. 4558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 5558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "net/quic/quic_sent_entropy_manager.h" 6558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 7558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "base/logging.h" 8558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "net/base/linked_hash_map.h" 9558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 10558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochusing std::make_pair; 11558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochusing std::max; 12558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochusing std::min; 13558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 14558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochnamespace net { 15558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 1603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)QuicSentEntropyManager::QuicSentEntropyManager() : map_offset_(1) {} 17558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 18558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochQuicSentEntropyManager::~QuicSentEntropyManager() {} 19558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 2003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)QuicPacketEntropyHash QuicSentEntropyManager::GetPacketEntropy( 2103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) QuicPacketSequenceNumber sequence_number) const { 2203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return packets_entropy_[sequence_number - map_offset_]; 2303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 2403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 2503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)QuicPacketSequenceNumber 2603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)QuicSentEntropyManager::GetLargestPacketWithEntropy() const { 2703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return map_offset_ + packets_entropy_.size() - 1; 2803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 2903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 3003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)QuicPacketSequenceNumber 3103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)QuicSentEntropyManager::GetSmallestPacketWithEntropy() const { 3203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return map_offset_; 3303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 3403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 3503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void QuicSentEntropyManager::UpdateCumulativeEntropy( 3603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) QuicPacketSequenceNumber sequence_number, 3703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) CumulativeEntropy* cumulative) const { 3803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) while (cumulative->sequence_number < sequence_number) { 3903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ++cumulative->sequence_number; 4003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) cumulative->entropy ^= GetPacketEntropy(cumulative->sequence_number); 4103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 4203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 4303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 44558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochvoid QuicSentEntropyManager::RecordPacketEntropyHash( 45558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch QuicPacketSequenceNumber sequence_number, 46558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch QuicPacketEntropyHash entropy_hash) { 4703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!packets_entropy_.empty()) { 4803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Ensure packets always are recorded in order. 4903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Every packet's entropy is recorded, even if it's not sent, so there 5003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // are not sequence number gaps. 511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK_EQ(GetLargestPacketWithEntropy() + 1, sequence_number); 5203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 5303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) packets_entropy_.push_back(entropy_hash); 5403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DVLOG(2) << "Recorded sequence number " << sequence_number 5503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) << " with entropy hash: " << static_cast<int>(entropy_hash); 56558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch} 57558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 5803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)QuicPacketEntropyHash QuicSentEntropyManager::GetCumulativeEntropy( 5903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) QuicPacketSequenceNumber sequence_number) { 6003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK_LE(last_cumulative_entropy_.sequence_number, sequence_number); 6103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK_GE(GetLargestPacketWithEntropy(), sequence_number); 6203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // First the entropy for largest_observed sequence number should be updated. 6303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) UpdateCumulativeEntropy(sequence_number, &last_cumulative_entropy_); 6403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return last_cumulative_entropy_.entropy; 65558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch} 66558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 67558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochbool QuicSentEntropyManager::IsValidEntropy( 6803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) QuicPacketSequenceNumber largest_observed, 69558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch const SequenceNumberSet& missing_packets, 7003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) QuicPacketEntropyHash entropy_hash) { 7103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK_GE(largest_observed, last_valid_entropy_.sequence_number); 7203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Ensure the largest and smallest sequence numbers are in range. 7303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (largest_observed > GetLargestPacketWithEntropy()) { 7403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 7503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 7603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!missing_packets.empty() && 7703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) *missing_packets.begin() < GetSmallestPacketWithEntropy()) { 7803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 79558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 8003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // First the entropy for largest_observed sequence number should be updated. 8103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) UpdateCumulativeEntropy(largest_observed, &last_valid_entropy_); 8203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 8303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Now XOR out all the missing entropies. 8403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) QuicPacketEntropyHash expected_entropy_hash = last_valid_entropy_.entropy; 85558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch for (SequenceNumberSet::const_iterator it = missing_packets.begin(); 86558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch it != missing_packets.end(); ++it) { 8703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) expected_entropy_hash ^= GetPacketEntropy(*it); 88558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 89558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch DLOG_IF(WARNING, entropy_hash != expected_entropy_hash) 90558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch << "Invalid entropy hash: " << static_cast<int>(entropy_hash) 91558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch << " expected entropy hash: " << static_cast<int>(expected_entropy_hash); 92558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch return entropy_hash == expected_entropy_hash; 93558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch} 94558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 95558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochvoid QuicSentEntropyManager::ClearEntropyBefore( 96558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch QuicPacketSequenceNumber sequence_number) { 9703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Don't discard entropy before updating the cumulative entropy used to 9803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // calculate EntropyHash and IsValidEntropy. 9903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (last_cumulative_entropy_.sequence_number < sequence_number) { 10003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) UpdateCumulativeEntropy(sequence_number, &last_cumulative_entropy_); 10103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 10203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (last_valid_entropy_.sequence_number < sequence_number) { 10303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) UpdateCumulativeEntropy(sequence_number, &last_valid_entropy_); 104558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 10503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) while (map_offset_ < sequence_number) { 10603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) packets_entropy_.pop_front(); 10703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ++map_offset_; 108558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 10903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DVLOG(2) << "Cleared entropy before: " << sequence_number; 110558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch} 111558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 112558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch} // namespace net 113