Home | History | Annotate | Download | only in quic
      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 
     10 using std::make_pair;
     11 using std::max;
     12 using std::min;
     13 
     14 namespace net {
     15 
     16 QuicSentEntropyManager::QuicSentEntropyManager()
     17     : packets_entropy_hash_(0) {}
     18 
     19 QuicSentEntropyManager::~QuicSentEntropyManager() {}
     20 
     21 void QuicSentEntropyManager::RecordPacketEntropyHash(
     22     QuicPacketSequenceNumber sequence_number,
     23     QuicPacketEntropyHash entropy_hash) {
     24   // TODO(satyamshekhar): Check this logic again when/if we enable packet
     25   // reordering.
     26   packets_entropy_hash_ ^= entropy_hash;
     27   packets_entropy_.insert(
     28       make_pair(sequence_number,
     29                 make_pair(entropy_hash, packets_entropy_hash_)));
     30   DVLOG(2) << "setting cumulative sent entropy hash to: "
     31            << static_cast<int>(packets_entropy_hash_)
     32            << " updated with sequence number " << sequence_number
     33            << " entropy hash: " << static_cast<int>(entropy_hash);
     34 }
     35 
     36 QuicPacketEntropyHash QuicSentEntropyManager::EntropyHash(
     37     QuicPacketSequenceNumber sequence_number) const {
     38   SentEntropyMap::const_iterator it =
     39       packets_entropy_.find(sequence_number);
     40   if (it == packets_entropy_.end()) {
     41     // Should only happen when we have not received ack for any packet.
     42     DCHECK_EQ(0u, sequence_number);
     43     return 0;
     44   }
     45   return it->second.second;
     46 }
     47 
     48 bool QuicSentEntropyManager::IsValidEntropy(
     49     QuicPacketSequenceNumber sequence_number,
     50     const SequenceNumberSet& missing_packets,
     51     QuicPacketEntropyHash entropy_hash) const {
     52   SentEntropyMap::const_iterator entropy_it =
     53       packets_entropy_.find(sequence_number);
     54   if (entropy_it == packets_entropy_.end()) {
     55     DCHECK_EQ(0u, sequence_number);
     56     // Close connection if something goes wrong.
     57     return 0 == sequence_number;
     58   }
     59   QuicPacketEntropyHash expected_entropy_hash = entropy_it->second.second;
     60   for (SequenceNumberSet::const_iterator it = missing_packets.begin();
     61        it != missing_packets.end(); ++it) {
     62     entropy_it = packets_entropy_.find(*it);
     63     DCHECK(entropy_it != packets_entropy_.end());
     64     expected_entropy_hash ^= entropy_it->second.first;
     65   }
     66   DLOG_IF(WARNING, entropy_hash != expected_entropy_hash)
     67       << "Invalid entropy hash: " << static_cast<int>(entropy_hash)
     68       << " expected entropy hash: " << static_cast<int>(expected_entropy_hash);
     69   return entropy_hash == expected_entropy_hash;
     70 }
     71 
     72 void QuicSentEntropyManager::ClearEntropyBefore(
     73     QuicPacketSequenceNumber sequence_number) {
     74   if (packets_entropy_.empty()) {
     75     return;
     76   }
     77   SentEntropyMap::iterator it = packets_entropy_.begin();
     78   while (it->first < sequence_number) {
     79     packets_entropy_.erase(it);
     80     it = packets_entropy_.begin();
     81     DCHECK(it != packets_entropy_.end());
     82   }
     83   DVLOG(2) << "Cleared entropy before: "
     84            << packets_entropy_.begin()->first;
     85 }
     86 
     87 }  // namespace net
     88