diff options
author | rtenneti@chromium.org <rtenneti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-06 20:10:12 +0000 |
---|---|---|
committer | rtenneti@chromium.org <rtenneti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-06 20:10:12 +0000 |
commit | 857e9907e393358f0dde0790e18f4247d0a00e51 (patch) | |
tree | 2a58ee00c8a6e36383c18384b1a9d34b14573b9f /net | |
parent | 88744223b0b947f0a2dc065f2070da57c7511f76 (diff) | |
download | chromium_src-857e9907e393358f0dde0790e18f4247d0a00e51.zip chromium_src-857e9907e393358f0dde0790e18f4247d0a00e51.tar.gz chromium_src-857e9907e393358f0dde0790e18f4247d0a00e51.tar.bz2 |
- Add a priority field to QuicCryptoServerConfig configs and used it as
a secondary sort key when there are multiple configs with the same
primary time.
- Fixes to QuicCryptoServerConfig::SetConfigs to allow replacing all
configs including the primary config in one go.
- Change the name of QuicCryptoServerConfig::DefaultConfig to
GenerateConfig.
- Generalize the method of the StrikeRegisterClient interface used to
verify orbits of new configs so that it allows for orbit changes or
strike registers that know about multiple orbits.
Merge internal change: 58556020
R=rch@chromium.org
Review URL: https://codereview.chromium.org/113883003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@243151 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/quic/crypto/crypto_server_config_protobuf.cc | 3 | ||||
-rw-r--r-- | net/quic/crypto/crypto_server_config_protobuf.h | 17 | ||||
-rw-r--r-- | net/quic/crypto/local_strike_register_client.cc | 8 | ||||
-rw-r--r-- | net/quic/crypto/local_strike_register_client.h | 4 | ||||
-rw-r--r-- | net/quic/crypto/local_strike_register_client_test.cc | 12 | ||||
-rw-r--r-- | net/quic/crypto/quic_crypto_server_config.cc | 171 | ||||
-rw-r--r-- | net/quic/crypto/quic_crypto_server_config.h | 11 | ||||
-rw-r--r-- | net/quic/crypto/quic_crypto_server_config_test.cc | 217 | ||||
-rw-r--r-- | net/quic/crypto/strike_register_client.h | 4 |
9 files changed, 312 insertions, 135 deletions
diff --git a/net/quic/crypto/crypto_server_config_protobuf.cc b/net/quic/crypto/crypto_server_config_protobuf.cc index a3418e4..d292f9e9 100644 --- a/net/quic/crypto/crypto_server_config_protobuf.cc +++ b/net/quic/crypto/crypto_server_config_protobuf.cc @@ -10,7 +10,8 @@ namespace net { QuicServerConfigProtobuf::QuicServerConfigProtobuf() - : primary_time_(QuicWallTime::Zero().ToUNIXSeconds()) { + : primary_time_(QuicWallTime::Zero().ToUNIXSeconds()), + priority_(0) { } QuicServerConfigProtobuf::~QuicServerConfigProtobuf() { diff --git a/net/quic/crypto/crypto_server_config_protobuf.h b/net/quic/crypto/crypto_server_config_protobuf.h index 6340ae0..e76ff14 100644 --- a/net/quic/crypto/crypto_server_config_protobuf.h +++ b/net/quic/crypto/crypto_server_config_protobuf.h @@ -85,6 +85,18 @@ class NET_EXPORT_PRIVATE QuicServerConfigProtobuf { primary_time_ = primary_time; } + bool has_priority() const { + return priority_ > 0; + } + + int64 priority() const { + return priority_; + } + + void set_priority(int64 priority) { + priority_ = priority; + } + private: std::vector<PrivateKey*> keys_; @@ -94,6 +106,11 @@ class NET_EXPORT_PRIVATE QuicServerConfigProtobuf { // primary_time_ contains a UNIX epoch seconds value that indicates when this // config should become primary. int64 primary_time_; + + // Relative priority of this config vs other configs with the same + // primary time. For use as a secondary sort key when selecting the + // primary config. + uint64 priority_; }; } // namespace net diff --git a/net/quic/crypto/local_strike_register_client.cc b/net/quic/crypto/local_strike_register_client.cc index c375145..1f78d98 100644 --- a/net/quic/crypto/local_strike_register_client.cc +++ b/net/quic/crypto/local_strike_register_client.cc @@ -21,10 +21,12 @@ LocalStrikeRegisterClient::LocalStrikeRegisterClient( orbit, startup) { } -string LocalStrikeRegisterClient::orbit() { +bool LocalStrikeRegisterClient::IsKnownOrbit(StringPiece orbit) const { base::AutoLock lock(m_); - return string(reinterpret_cast<const char*>(strike_register_.orbit()), - kOrbitSize); + if (orbit.length() != kOrbitSize) { + return false; + } + return memcmp(orbit.data(), strike_register_.orbit(), kOrbitSize) == 0; } void LocalStrikeRegisterClient::VerifyNonceIsValidAndUnique( diff --git a/net/quic/crypto/local_strike_register_client.h b/net/quic/crypto/local_strike_register_client.h index 37020b7..abd610b 100644 --- a/net/quic/crypto/local_strike_register_client.h +++ b/net/quic/crypto/local_strike_register_client.h @@ -25,13 +25,13 @@ class NET_EXPORT_PRIVATE LocalStrikeRegisterClient const uint8 orbit[8], StrikeRegister::StartupType startup); - virtual std::string orbit() OVERRIDE; + virtual bool IsKnownOrbit(base::StringPiece orbit) const OVERRIDE; virtual void VerifyNonceIsValidAndUnique(base::StringPiece nonce, QuicWallTime now, ResultCallback* cb) OVERRIDE; private: - base::Lock m_; + mutable base::Lock m_; StrikeRegister strike_register_; DISALLOW_COPY_AND_ASSIGN(LocalStrikeRegisterClient); diff --git a/net/quic/crypto/local_strike_register_client_test.cc b/net/quic/crypto/local_strike_register_client_test.cc index 0227e92..df80c16 100644 --- a/net/quic/crypto/local_strike_register_client_test.cc +++ b/net/quic/crypto/local_strike_register_client_test.cc @@ -63,15 +63,21 @@ class LocalStrikeRegisterClientTest : public ::testing::Test { }; TEST_F(LocalStrikeRegisterClientTest, CheckOrbit) { - EXPECT_EQ(StringPiece(reinterpret_cast<const char*>(kOrbit), kOrbitSize), - strike_register_->orbit()); + EXPECT_TRUE(strike_register_->IsKnownOrbit( + StringPiece(reinterpret_cast<const char*>(kOrbit), kOrbitSize))); + EXPECT_FALSE(strike_register_->IsKnownOrbit( + StringPiece(reinterpret_cast<const char*>(kOrbit), kOrbitSize - 1))); + EXPECT_FALSE(strike_register_->IsKnownOrbit( + StringPiece(reinterpret_cast<const char*>(kOrbit), kOrbitSize + 1))); + EXPECT_FALSE(strike_register_->IsKnownOrbit( + StringPiece(reinterpret_cast<const char*>(kOrbit) + 1, kOrbitSize))); } TEST_F(LocalStrikeRegisterClientTest, IncorrectNonceLength) { string valid_nonce; uint32 norder = htonl(kCurrentTimeExternalSecs); valid_nonce.assign(reinterpret_cast<const char*>(&norder), sizeof(norder)); - valid_nonce.append(strike_register_->orbit()); + valid_nonce.append(string(reinterpret_cast<const char*>(kOrbit), kOrbitSize)); valid_nonce.append(string(20, '\x17')); // 20 'random' bytes. { diff --git a/net/quic/crypto/quic_crypto_server_config.cc b/net/quic/crypto/quic_crypto_server_config.cc index 3c409e7..2443d72 100644 --- a/net/quic/crypto/quic_crypto_server_config.cc +++ b/net/quic/crypto/quic_crypto_server_config.cc @@ -200,7 +200,7 @@ QuicCryptoServerConfig::~QuicCryptoServerConfig() { } // static -QuicServerConfigProtobuf* QuicCryptoServerConfig::DefaultConfig( +QuicServerConfigProtobuf* QuicCryptoServerConfig::GenerateConfig( QuicRandom* rand, const QuicClock* clock, const ConfigOptions& options) { @@ -331,6 +331,7 @@ CryptoHandshakeMessage* QuicCryptoServerConfig::AddConfig( configs_[config->id] = config; SelectNewPrimaryConfig(now); DCHECK(primary_config_.get()); + DCHECK_EQ(configs_.find(primary_config_->id)->second, primary_config_); } return msg.release(); @@ -341,14 +342,14 @@ CryptoHandshakeMessage* QuicCryptoServerConfig::AddDefaultConfig( const QuicClock* clock, const ConfigOptions& options) { scoped_ptr<QuicServerConfigProtobuf> config( - DefaultConfig(rand, clock, options)); + GenerateConfig(rand, clock, options)); return AddConfig(config.get(), clock->WallNow()); } bool QuicCryptoServerConfig::SetConfigs( const vector<QuicServerConfigProtobuf*>& protobufs, const QuicWallTime now) { - vector<scoped_refptr<Config> > new_configs; + vector<scoped_refptr<Config> > parsed_configs; bool ok = true; for (vector<QuicServerConfigProtobuf*>::const_iterator i = protobufs.begin(); @@ -358,61 +359,57 @@ bool QuicCryptoServerConfig::SetConfigs( ok = false; break; } - new_configs.push_back(config); + + parsed_configs.push_back(config); + } + + if (parsed_configs.empty()) { + LOG(WARNING) << "New config list is empty."; + ok = false; } if (!ok) { LOG(WARNING) << "Rejecting QUIC configs because of above errors"; } else { - base::AutoLock locked(configs_lock_); - typedef ConfigMap::iterator ConfigMapIterator; - vector<ConfigMapIterator> to_delete; - - DCHECK_EQ(protobufs.size(), new_configs.size()); - - // First, look for any configs that have been removed. - for (ConfigMapIterator i = configs_.begin(); - i != configs_.end(); ++i) { - const scoped_refptr<Config> old_config = i->second; - bool found = false; - - for (vector<scoped_refptr<Config> >::const_iterator j = - new_configs.begin(); - j != new_configs.end(); ++j) { - if ((*j)->id == old_config->id) { - found = true; - break; - } - } - - if (!found) { - // We cannot remove the primary config. This has probably happened - // because our source of config information failed for a time and we're - // suddenly seeing a jump in time. No matter - we'll configure a new - // primary config and then we'll be able to delete it next time. - if (!old_config->is_primary) { - to_delete.push_back(i); - } - } - } + VLOG(1) << "Updating configs:"; - for (vector<ConfigMapIterator>::const_iterator i = to_delete.begin(); - i != to_delete.end(); ++i) { - configs_.erase(*i); - } + base::AutoLock locked(configs_lock_); + ConfigMap new_configs; - // Find any configs that need to be added. - for (vector<scoped_refptr<Config> >::const_iterator i = new_configs.begin(); - i != new_configs.end(); ++i) { - const scoped_refptr<Config> new_config = *i; - if (configs_.find(new_config->id) != configs_.end()) { - continue; + for (vector<scoped_refptr<Config> >::const_iterator i = + parsed_configs.begin(); + i != parsed_configs.end(); ++i) { + scoped_refptr<Config> config = *i; + ConfigMap::iterator it = configs_.find(config->id); + if (it != configs_.end()) { + VLOG(1) + << "Keeping scid: " << base::HexEncode( + config->id.data(), config->id.size()) + << " orbit: " << base::HexEncode( + reinterpret_cast<const char *>(config->orbit), kOrbitSize) + << " new primary_time " << config->primary_time.ToUNIXSeconds() + << " old primary_time " << it->second->primary_time.ToUNIXSeconds() + << " new priority " << config->priority + << " old priority " << it->second->priority; + // Update primary_time and priority. + it->second->primary_time = config->primary_time; + it->second->priority = config->priority; + new_configs.insert(*it); + } else { + VLOG(1) << "Adding scid: " << base::HexEncode( + config->id.data(), config->id.size()) + << " orbit: " << base::HexEncode( + reinterpret_cast<const char *>(config->orbit), kOrbitSize) + << " primary_time " << config->primary_time.ToUNIXSeconds() + << " priority " << config->priority; + new_configs.insert(make_pair(config->id, config)); } - - configs_[new_config->id] = new_config; } + configs_.swap(new_configs); SelectNewPrimaryConfig(now); + DCHECK(primary_config_); + DCHECK_EQ(configs_.find(primary_config_->id)->second, primary_config_); } return ok; @@ -424,6 +421,7 @@ void QuicCryptoServerConfig::ValidateClientHello( const QuicClock* clock, ValidateClientHelloResultCallback* done_cb) const { const QuicWallTime now(clock->WallNow()); + ValidateClientHelloResultCallback::Result* result = new ValidateClientHelloResultCallback::Result( client_hello, client_ip, now); @@ -432,13 +430,15 @@ void QuicCryptoServerConfig::ValidateClientHello( { base::AutoLock locked(configs_lock_); - if (!primary_config_) { + if (!primary_config_.get()) { result->error_code = QUIC_CRYPTO_INTERNAL_ERROR; result->error_details = "No configurations loaded"; } else { if (!next_config_promotion_time_.IsZero() && next_config_promotion_time_.IsAfter(now)) { SelectNewPrimaryConfig(now); + DCHECK(primary_config_); + DCHECK(configs_.find(primary_config_->id)->second == primary_config_); } memcpy(primary_orbit, primary_config_->orbit, sizeof(primary_orbit)); @@ -507,6 +507,8 @@ QuicErrorCode QuicCryptoServerConfig::ProcessClientHello( if (!next_config_promotion_time_.IsZero() && next_config_promotion_time_.IsAfter(now)) { SelectNewPrimaryConfig(now); + DCHECK(primary_config_); + DCHECK(configs_.find(primary_config_->id)->second == primary_config_); } primary_config = primary_config_; @@ -709,54 +711,57 @@ QuicErrorCode QuicCryptoServerConfig::ProcessClientHello( bool QuicCryptoServerConfig::ConfigPrimaryTimeLessThan( const scoped_refptr<Config>& a, const scoped_refptr<Config>& b) { - return a->primary_time.IsBefore(b->primary_time); + if (a->primary_time.IsBefore(b->primary_time) || + b->primary_time.IsBefore(a->primary_time)) { + // Primary times differ. + return a->primary_time.IsBefore(b->primary_time); + } else if (a->priority != b->priority) { + // Primary times are equal, sort backwards by priority. + return a->priority < b->priority; + } else { + // Primary times and priorities are equal, sort by config id. + return a->id < b->id; + } } void QuicCryptoServerConfig::SelectNewPrimaryConfig( const QuicWallTime now) const { vector<scoped_refptr<Config> > configs; configs.reserve(configs_.size()); - scoped_refptr<Config> first_config = NULL; for (ConfigMap::const_iterator it = configs_.begin(); it != configs_.end(); ++it) { - const scoped_refptr<Config> config(it->second); - if (!first_config.get()) { - first_config = config; - } - if (config->primary_time.IsZero()) { - continue; - } + // TODO(avd) Exclude expired configs? configs.push_back(it->second); } if (configs.empty()) { - // Tests don't set |primary_time_|. For that case we promote the first - // Config and leave it as primary forever. - if (!primary_config_.get() && first_config.get()) { - primary_config_ = first_config; - primary_config_->is_primary = true; + if (primary_config_.get()) { + LOG(DFATAL) << "No valid QUIC server config. Keeping the current config."; + } else { + LOG(DFATAL) << "No valid QUIC server config."; } return; } std::sort(configs.begin(), configs.end(), ConfigPrimaryTimeLessThan); + Config* best_candidate = configs[0]; + for (size_t i = 0; i < configs.size(); ++i) { const scoped_refptr<Config> config(configs[i]); - if (!config->primary_time.IsAfter(now)) { + if (config->primary_time.IsAfter(best_candidate->primary_time)) { + best_candidate = config; + } continue; } // This is the first config with a primary_time in the future. Thus the // previous Config should be the primary and this one should determine the // next_config_promotion_time_. - scoped_refptr<Config> new_primary; + scoped_refptr<Config> new_primary(best_candidate); if (i == 0) { - // There was no previous Config, so this will have to be primary. - new_primary = config; - // We need the primary_time of the next config. if (configs.size() > 1) { next_config_promotion_time_ = configs[1]->primary_time; @@ -764,7 +769,6 @@ void QuicCryptoServerConfig::SelectNewPrimaryConfig( next_config_promotion_time_ = QuicWallTime::Zero(); } } else { - new_primary = configs[i - 1]; next_config_promotion_time_ = config->primary_time; } @@ -773,18 +777,26 @@ void QuicCryptoServerConfig::SelectNewPrimaryConfig( } primary_config_ = new_primary; new_primary->is_primary = true; + DVLOG(1) << "New primary config. orbit: " + << base::HexEncode( + reinterpret_cast<const char*>(primary_config_->orbit), + kOrbitSize); return; } // All config's primary times are in the past. We should make the most recent - // primary. - scoped_refptr<Config> new_primary = configs[configs.size() - 1]; + // most recent and highest priority candidate primary. + scoped_refptr<Config> new_primary(best_candidate); if (primary_config_.get()) { primary_config_->is_primary = false; } primary_config_ = new_primary; new_primary->is_primary = true; + DVLOG(1) << "New primary config. orbit: " + << base::HexEncode( + reinterpret_cast<const char*>(primary_config_->orbit), + kOrbitSize); next_config_promotion_time_ = QuicWallTime::Zero(); } @@ -976,6 +988,8 @@ QuicCryptoServerConfig::ParseConfigProtobuf( QuicWallTime::FromUNIXSeconds(protobuf->primary_time()); } + config->priority = protobuf->priority(); + StringPiece scid; if (!msg->GetStringPiece(kSCID, &scid)) { LOG(WARNING) << "Server config message is missing SCID"; @@ -1019,14 +1033,12 @@ QuicCryptoServerConfig::ParseConfigProtobuf( strike_register_client = strike_register_client_.get(); } - if (strike_register_client != NULL) { - const string& orbit = strike_register_client->orbit(); - if (0 != memcmp(orbit.data(), config->orbit, kOrbitSize)) { - LOG(WARNING) - << "Server config has different orbit than current config. " - "Switching orbits at run-time is not supported."; - return NULL; - } + if (strike_register_client != NULL && + !strike_register_client->IsKnownOrbit(orbit)) { + LOG(WARNING) + << "Rejecting server config with orbit that the strike register " + "client doesn't know about."; + return NULL; } } @@ -1288,7 +1300,8 @@ bool QuicCryptoServerConfig::ValidateServerNonce(StringPiece token, QuicCryptoServerConfig::Config::Config() : channel_id_enabled(false), is_primary(false), - primary_time(QuicWallTime::Zero()) {} + primary_time(QuicWallTime::Zero()), + priority(0) {} QuicCryptoServerConfig::Config::~Config() { STLDeleteElements(&key_exchanges); } diff --git a/net/quic/crypto/quic_crypto_server_config.h b/net/quic/crypto/quic_crypto_server_config.h index 1f5b2fe..ffe17e6 100644 --- a/net/quic/crypto/quic_crypto_server_config.h +++ b/net/quic/crypto/quic_crypto_server_config.h @@ -101,9 +101,9 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig { // TESTING is a magic parameter for passing to the constructor in tests. static const char TESTING[]; - // DefaultConfig generates a QuicServerConfigProtobuf protobuf suitable for - // using in tests. - static QuicServerConfigProtobuf* DefaultConfig( + // Generates a QuicServerConfigProtobuf protobuf suitable for + // AddConfig and SetConfigs. + static QuicServerConfigProtobuf* GenerateConfig( QuicRandom* rand, const QuicClock* clock, const ConfigOptions& options); @@ -296,6 +296,11 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig { // will not be promoted at a specific time. QuicWallTime primary_time; + // Secondary sort key for use when selecting primary configs and + // there are multiple configs with the same primary time. + // Smaller numbers mean higher priority. + uint64 priority; + private: friend class base::RefCounted<Config>; virtual ~Config(); diff --git a/net/quic/crypto/quic_crypto_server_config_test.cc b/net/quic/crypto/quic_crypto_server_config_test.cc index 94dbac6..c64a0b4 100644 --- a/net/quic/crypto/quic_crypto_server_config_test.cc +++ b/net/quic/crypto/quic_crypto_server_config_test.cc @@ -151,10 +151,10 @@ class QuicCryptoServerConfigPeer { class TestStrikeRegisterClient : public StrikeRegisterClient { public: - TestStrikeRegisterClient(QuicCryptoServerConfig* config, string orbit) - : config_(config), orbit_(orbit), orbit_called_(false) {} + explicit TestStrikeRegisterClient(QuicCryptoServerConfig* config) + : config_(config), is_known_orbit_called_(false) {} - virtual string orbit() OVERRIDE { + virtual bool IsKnownOrbit(StringPiece orbit) const OVERRIDE { // Ensure that the strike register client lock is not held. QuicCryptoServerConfigPeer peer(config_); base::Lock* m = peer.GetStrikeRegisterClientLock(); @@ -163,8 +163,8 @@ class TestStrikeRegisterClient : public StrikeRegisterClient { // m->AssertNotHeld(); base::AutoLock lock(*m); - orbit_called_ = true; - return orbit_; + is_known_orbit_called_ = true; + return true; } virtual void VerifyNonceIsValidAndUnique( @@ -174,12 +174,11 @@ class TestStrikeRegisterClient : public StrikeRegisterClient { LOG(FATAL) << "Not implemented"; } - bool orbit_called() { return orbit_called_; } + bool is_known_orbit_called() { return is_known_orbit_called_; } private: QuicCryptoServerConfig* config_; - string orbit_; - bool orbit_called_; + mutable bool is_known_orbit_called_; }; TEST(QuicCryptoServerConfigTest, ServerConfig) { @@ -197,17 +196,14 @@ TEST(QuicCryptoServerConfigTest, GetOrbitIsCalledWithoutTheStrikeRegisterLock) { QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand); MockClock clock; - const char kOrbit[] = "12345678"; - TestStrikeRegisterClient* strike_register = - new TestStrikeRegisterClient(&server, kOrbit); + new TestStrikeRegisterClient(&server); server.SetStrikeRegisterClient(strike_register); QuicCryptoServerConfig::ConfigOptions options; - options.orbit = kOrbit; scoped_ptr<CryptoHandshakeMessage>( server.AddDefaultConfig(rand, &clock, options)); - EXPECT_TRUE(strike_register->orbit_called()); + EXPECT_TRUE(strike_register->is_known_orbit_called()); } TEST(QuicCryptoServerConfigTest, SourceAddressTokens) { @@ -258,18 +254,23 @@ class CryptoServerConfigsTest : public ::testing::Test { // SetConfigs(NULL); // calls |config_.SetConfigs| with no protobufs. // // // Calls |config_.SetConfigs| with two protobufs: one for a Config with - // // a |primary_time| of 900, and another with a |primary_time| of 1000. + // // a |primary_time| of 900 and priority 1, and another with + // // a |primary_time| of 1000 and priority 2. + // CheckConfigs( - // "id1", 900, - // "id2", 1000, + // "id1", 900, 1, + // "id2", 1000, 2, // NULL); // // If the server config id starts with "INVALID" then the generated protobuf // will be invalid. void SetConfigs(const char* server_config_id1, ...) { + const char kOrbit[] = "12345678"; + va_list ap; va_start(ap, server_config_id1); bool has_invalid = false; + bool is_empty = true; vector<QuicServerConfigProtobuf*> protobufs; bool first = true; @@ -286,13 +287,17 @@ class CryptoServerConfigsTest : public ::testing::Test { break; } + is_empty = false; int primary_time = va_arg(ap, int); + int priority = va_arg(ap, int); QuicCryptoServerConfig::ConfigOptions options; options.id = server_config_id; + options.orbit = kOrbit; QuicServerConfigProtobuf* protobuf( - QuicCryptoServerConfig::DefaultConfig(rand_, &clock_, options)); + QuicCryptoServerConfig::GenerateConfig(rand_, &clock_, options)); protobuf->set_primary_time(primary_time); + protobuf->set_priority(priority); if (string(server_config_id).find("INVALID") == 0) { protobuf->clear_key(); has_invalid = true; @@ -300,7 +305,8 @@ class CryptoServerConfigsTest : public ::testing::Test { protobufs.push_back(protobuf); } - ASSERT_EQ(!has_invalid, config_.SetConfigs(protobufs, clock_.WallNow())); + ASSERT_EQ(!has_invalid && !is_empty, + config_.SetConfigs(protobufs, clock_.WallNow())); STLDeleteElements(&protobufs); } @@ -317,8 +323,8 @@ TEST_F(CryptoServerConfigsTest, NoConfigs) { TEST_F(CryptoServerConfigsTest, MakePrimaryFirst) { // Make sure that "b" is primary even though "a" comes first. - SetConfigs("a", 1100, - "b", 900, + SetConfigs("a", 1100, 1, + "b", 900, 1, NULL); test_peer_.CheckConfigs( "a", false, @@ -328,8 +334,8 @@ TEST_F(CryptoServerConfigsTest, MakePrimaryFirst) { TEST_F(CryptoServerConfigsTest, MakePrimarySecond) { // Make sure that a remains primary after b is added. - SetConfigs("a", 900, - "b", 1100, + SetConfigs("a", 900, 1, + "b", 1100, 1, NULL); test_peer_.CheckConfigs( "a", true, @@ -339,12 +345,17 @@ TEST_F(CryptoServerConfigsTest, MakePrimarySecond) { TEST_F(CryptoServerConfigsTest, Delete) { // Ensure that configs get deleted when removed. - SetConfigs("a", 800, - "b", 900, - "c", 1100, + SetConfigs("a", 800, 1, + "b", 900, 1, + "c", 1100, 1, NULL); - SetConfigs("b", 900, - "c", 1100, + test_peer_.CheckConfigs( + "a", false, + "b", true, + "c", false, + NULL); + SetConfigs("b", 900, 1, + "c", 1100, 1, NULL); test_peer_.CheckConfigs( "b", true, @@ -352,26 +363,148 @@ TEST_F(CryptoServerConfigsTest, Delete) { NULL); } -TEST_F(CryptoServerConfigsTest, DontDeletePrimary) { - // Ensure that the primary config isn't deleted when removed. - SetConfigs("a", 800, - "b", 900, - "c", 1100, +TEST_F(CryptoServerConfigsTest, DeletePrimary) { + // Ensure that deleting the primary config works. + SetConfigs("a", 800, 1, + "b", 900, 1, + "c", 1100, 1, + NULL); + test_peer_.CheckConfigs( + "a", false, + "b", true, + "c", false, + NULL); + SetConfigs("a", 800, 1, + "c", 1100, 1, NULL); - SetConfigs("a", 800, - "c", 1100, + test_peer_.CheckConfigs( + "a", true, + "c", false, + NULL); +} + +TEST_F(CryptoServerConfigsTest, FailIfDeletingAllConfigs) { + // Ensure that configs get deleted when removed. + SetConfigs("a", 800, 1, + "b", 900, 1, NULL); test_peer_.CheckConfigs( "a", false, "b", true, + NULL); + SetConfigs(NULL); + // Config change is rejected, still using old configs. + test_peer_.CheckConfigs( + "a", false, + "b", true, + NULL); +} + +TEST_F(CryptoServerConfigsTest, ChangePrimaryTime) { + // Check that updates to primary time get picked up. + SetConfigs("a", 400, 1, + "b", 800, 1, + "c", 1200, 1, + NULL); + test_peer_.SelectNewPrimaryConfig(500); + test_peer_.CheckConfigs( + "a", true, + "b", false, + "c", false, + NULL); + SetConfigs("a", 1200, 1, + "b", 800, 1, + "c", 400, 1, + NULL); + test_peer_.SelectNewPrimaryConfig(500); + test_peer_.CheckConfigs( + "a", false, + "b", false, + "c", true, + NULL); +} + +TEST_F(CryptoServerConfigsTest, AllConfigsInThePast) { + // Check that the most recent config is selected. + SetConfigs("a", 400, 1, + "b", 800, 1, + "c", 1200, 1, + NULL); + test_peer_.SelectNewPrimaryConfig(1500); + test_peer_.CheckConfigs( + "a", false, + "b", false, + "c", true, + NULL); +} + +TEST_F(CryptoServerConfigsTest, AllConfigsInTheFuture) { + // Check that the first config is selected. + SetConfigs("a", 400, 1, + "b", 800, 1, + "c", 1200, 1, + NULL); + test_peer_.SelectNewPrimaryConfig(100); + test_peer_.CheckConfigs( + "a", true, + "b", false, + "c", false, + NULL); +} + +TEST_F(CryptoServerConfigsTest, SortByPriority) { + // Check that priority is used to decide on a primary config when + // configs have the same primary time. + SetConfigs("a", 900, 1, + "b", 900, 2, + "c", 900, 3, + NULL); + test_peer_.CheckConfigs( + "a", true, + "b", false, + "c", false, + NULL); + test_peer_.SelectNewPrimaryConfig(800); + test_peer_.CheckConfigs( + "a", true, + "b", false, "c", false, NULL); + test_peer_.SelectNewPrimaryConfig(1000); + test_peer_.CheckConfigs( + "a", true, + "b", false, + "c", false, + NULL); + + // Change priorities and expect sort order to change. + SetConfigs("a", 900, 2, + "b", 900, 1, + "c", 900, 0, + NULL); + test_peer_.CheckConfigs( + "a", false, + "b", false, + "c", true, + NULL); + test_peer_.SelectNewPrimaryConfig(800); + test_peer_.CheckConfigs( + "a", false, + "b", false, + "c", true, + NULL); + test_peer_.SelectNewPrimaryConfig(1000); + test_peer_.CheckConfigs( + "a", false, + "b", false, + "c", true, + NULL); } TEST_F(CryptoServerConfigsTest, AdvancePrimary) { // Check that a new primary config is enabled at the right time. - SetConfigs("a", 900, - "b", 1100, + SetConfigs("a", 900, 1, + "b", 1100, 1, NULL); test_peer_.SelectNewPrimaryConfig(1000); test_peer_.CheckConfigs( @@ -387,18 +520,18 @@ TEST_F(CryptoServerConfigsTest, AdvancePrimary) { TEST_F(CryptoServerConfigsTest, InvalidConfigs) { // Ensure that invalid configs don't change anything. - SetConfigs("a", 800, - "b", 900, - "c", 1100, + SetConfigs("a", 800, 1, + "b", 900, 1, + "c", 1100, 1, NULL); test_peer_.CheckConfigs( "a", false, "b", true, "c", false, NULL); - SetConfigs("a", 800, - "c", 1100, - "INVALID1", 1000, + SetConfigs("a", 800, 1, + "c", 1100, 1, + "INVALID1", 1000, 1, NULL); test_peer_.CheckConfigs( "a", false, diff --git a/net/quic/crypto/strike_register_client.h b/net/quic/crypto/strike_register_client.h index 4a27bd7..3555e85 100644 --- a/net/quic/crypto/strike_register_client.h +++ b/net/quic/crypto/strike_register_client.h @@ -38,8 +38,8 @@ class NET_EXPORT_PRIVATE StrikeRegisterClient { StrikeRegisterClient() {} virtual ~StrikeRegisterClient() {} - // Returns the strike server orbit if known, else empty string. - virtual std::string orbit() = 0; + // Returns true iff the strike register knows about the given orbit. + virtual bool IsKnownOrbit(base::StringPiece orbit) const = 0; // Validate a nonce for freshness and uniqueness. // Will invoke cb->Run(ValidateResponse::nonce_is_valid_and_unique()) // once the asynchronous operation is complete. |