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/port_suggester.h" 6 7 #include "base/logging.h" 8 #include "net/base/host_port_pair.h" 9 10 namespace net { 11 12 PortSuggester::PortSuggester(const HostPortPair& server, uint64 seed) 13 : call_count_(0), 14 previous_suggestion_(-1) { 15 unsigned char hash_bytes[base::kSHA1Length]; 16 base::SHA1HashBytes( 17 reinterpret_cast<const unsigned char*>(server.host().data()), 18 server.host().length(), hash_bytes); 19 COMPILE_ASSERT(sizeof(seed_) < sizeof(hash_bytes), seed_larger_than_hash); 20 memcpy(&seed_, hash_bytes, sizeof(seed_)); 21 seed_ ^= seed ^ server.port(); 22 } 23 24 int PortSuggester::SuggestPort(int min, int max) { 25 // Sometimes our suggestion can't be used, so we ensure that if additional 26 // calls are made, then each call (probably) provides a new suggestion. 27 if (++call_count_ > 1) { 28 // Evolve the seed. 29 unsigned char hash_bytes[base::kSHA1Length]; 30 base::SHA1HashBytes(reinterpret_cast<const unsigned char *>(&seed_), 31 sizeof(seed_), hash_bytes); 32 memcpy(&seed_, hash_bytes, sizeof(seed_)); 33 } 34 DCHECK_LE(min, max); 35 DCHECK_GT(min, 0); 36 int range = max - min + 1; 37 // Ports (and hence the extent of the |range|) are generally under 2^16, so 38 // the tiny non-uniformity in the pseudo-random distribution is not 39 // significant. 40 previous_suggestion_ = static_cast<int>(seed_ % range) + min; 41 return previous_suggestion_; 42 } 43 44 int PortSuggester::previous_suggestion() const { 45 DCHECK_LT(0u, call_count_); 46 return previous_suggestion_; 47 } 48 49 } // namespace net 50