// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "net/quic/quic_sent_entropy_manager.h" #include "base/logging.h" #include "net/base/linked_hash_map.h" using std::make_pair; using std::max; using std::min; namespace net { QuicSentEntropyManager::QuicSentEntropyManager() : packets_entropy_hash_(0) {} QuicSentEntropyManager::~QuicSentEntropyManager() {} void QuicSentEntropyManager::RecordPacketEntropyHash( QuicPacketSequenceNumber sequence_number, QuicPacketEntropyHash entropy_hash) { // TODO(satyamshekhar): Check this logic again when/if we enable packet // reordering. 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); } 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; } bool QuicSentEntropyManager::IsValidEntropy( QuicPacketSequenceNumber sequence_number, 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 expected_entropy_hash = entropy_it->second.second; 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; } DLOG_IF(WARNING, entropy_hash != expected_entropy_hash) << "Invalid entropy hash: " << static_cast<int>(entropy_hash) << " expected entropy hash: " << static_cast<int>(expected_entropy_hash); return entropy_hash == expected_entropy_hash; } void QuicSentEntropyManager::ClearEntropyBefore( QuicPacketSequenceNumber sequence_number) { if (packets_entropy_.empty()) { return; } SentEntropyMap::iterator it = packets_entropy_.begin(); while (it->first < sequence_number) { packets_entropy_.erase(it); it = packets_entropy_.begin(); DCHECK(it != packets_entropy_.end()); } DVLOG(2) << "Cleared entropy before: " << packets_entropy_.begin()->first; } } // namespace net