Line data Source code
1 : #include "source/common/http/http_server_properties_cache_manager_impl.h" 2 : 3 : #include "envoy/common/key_value_store.h" 4 : #include "envoy/config/common/key_value/v3/config.pb.h" 5 : #include "envoy/config/common/key_value/v3/config.pb.validate.h" 6 : 7 : #include "source/common/config/utility.h" 8 : #include "source/common/http/http_server_properties_cache_impl.h" 9 : #include "source/common/protobuf/protobuf.h" 10 : 11 : #include "absl/container/flat_hash_map.h" 12 : 13 : namespace Envoy { 14 : namespace Http { 15 : 16 : SINGLETON_MANAGER_REGISTRATION(alternate_protocols_cache_manager); 17 : 18 : HttpServerPropertiesCacheManagerImpl::HttpServerPropertiesCacheManagerImpl( 19 : AlternateProtocolsData& data, ThreadLocal::SlotAllocator& tls) 20 131 : : data_(data), slot_(tls) { 21 225 : slot_.set([](Event::Dispatcher& /*dispatcher*/) { return std::make_shared<State>(); }); 22 131 : } 23 : 24 : HttpServerPropertiesCacheSharedPtr HttpServerPropertiesCacheManagerImpl::getCache( 25 : const envoy::config::core::v3::AlternateProtocolsCacheOptions& options, 26 105 : Event::Dispatcher& dispatcher) { 27 105 : const auto& existing_cache = (*slot_).caches_.find(options.name()); 28 105 : if (existing_cache != (*slot_).caches_.end()) { 29 57 : if (!Protobuf::util::MessageDifferencer::Equivalent(options, existing_cache->second.options_)) { 30 0 : IS_ENVOY_BUG(fmt::format( 31 0 : "options specified alternate protocols cache '{}' with different settings" 32 0 : " first '{}' second '{}'", 33 0 : options.name(), existing_cache->second.options_.DebugString(), options.DebugString())); 34 0 : } 35 57 : return existing_cache->second.cache_; 36 57 : } 37 : 38 48 : std::unique_ptr<KeyValueStore> store; 39 48 : if (options.has_key_value_store_config()) { 40 0 : envoy::config::common::key_value::v3::KeyValueStoreConfig kv_config; 41 0 : MessageUtil::anyConvertAndValidate(options.key_value_store_config().typed_config(), kv_config, 42 0 : data_.validation_visitor_); 43 0 : auto& factory = Config::Utility::getAndCheckFactory<KeyValueStoreFactory>(kv_config.config()); 44 0 : store = 45 0 : factory.createStore(kv_config, data_.validation_visitor_, dispatcher, data_.file_system_); 46 0 : } 47 : 48 48 : std::vector<std::string> canonical_suffixes; 49 48 : for (const std::string& suffix : options.canonical_suffixes()) { 50 0 : if (!absl::StartsWith(suffix, ".")) { 51 0 : IS_ENVOY_BUG(absl::StrCat("Suffix does not start with a leading '.': ", suffix)); 52 0 : continue; 53 0 : } 54 0 : canonical_suffixes.push_back(suffix); 55 0 : } 56 : 57 48 : auto new_cache = std::make_shared<HttpServerPropertiesCacheImpl>( 58 48 : dispatcher, std::move(canonical_suffixes), std::move(store), options.max_entries().value()); 59 : 60 48 : for (const envoy::config::core::v3::AlternateProtocolsCacheOptions::AlternateProtocolsCacheEntry& 61 48 : entry : options.prepopulated_entries()) { 62 0 : const HttpServerPropertiesCacheImpl::Origin origin = {"https", entry.hostname(), entry.port()}; 63 0 : std::vector<HttpServerPropertiesCacheImpl::AlternateProtocol> protocol = { 64 0 : {"h3", "", entry.port(), 65 0 : dispatcher.timeSource().monotonicTime() + std::chrono::hours(168)}}; 66 0 : OptRef<const std::vector<HttpServerPropertiesCacheImpl::AlternateProtocol>> existing_protocols = 67 0 : new_cache->findAlternatives(origin); 68 0 : if (!existing_protocols.has_value()) { 69 0 : new_cache->setAlternatives(origin, protocol); 70 0 : } 71 0 : } 72 : 73 48 : (*slot_).caches_.emplace(options.name(), CacheWithOptions{options, new_cache}); 74 48 : return new_cache; 75 105 : } 76 : 77 131 : HttpServerPropertiesCacheManagerSharedPtr HttpServerPropertiesCacheManagerFactoryImpl::get() { 78 131 : return singleton_manager_.getTyped<HttpServerPropertiesCacheManager>( 79 131 : SINGLETON_MANAGER_REGISTERED_NAME(alternate_protocols_cache_manager), 80 131 : [this] { return std::make_shared<HttpServerPropertiesCacheManagerImpl>(data_, tls_); }); 81 131 : } 82 : 83 : } // namespace Http 84 : } // namespace Envoy