Line data Source code
1 : #include "source/extensions/geoip_providers/maxmind/config.h" 2 : 3 : #include "envoy/extensions/geoip_providers/maxmind/v3/maxmind.pb.h" 4 : #include "envoy/registry/registry.h" 5 : 6 : #include "source/common/common/utility.h" 7 : #include "source/common/protobuf/utility.h" 8 : 9 : #include "geoip_provider.h" 10 : 11 : namespace Envoy { 12 : namespace Extensions { 13 : namespace GeoipProviders { 14 : namespace Maxmind { 15 : 16 : using ConfigProto = envoy::extensions::geoip_providers::maxmind::v3::MaxMindConfig; 17 : 18 : /** 19 : * A singleton that acts as a factory for generating and looking up GeoipProviders. 20 : * When given equivalent provider configs, the singleton returns pointers to the same 21 : * driver/provider. When given different configs, the singleton returns different provider 22 : * instances. 23 : */ 24 : class DriverSingleton : public Envoy::Singleton::Instance { 25 : public: 26 : std::shared_ptr<GeoipProvider> get(std::shared_ptr<DriverSingleton> singleton, 27 : const ConfigProto& proto_config, 28 : const std::string& stat_prefix, 29 0 : Server::Configuration::FactoryContext& context) { 30 0 : std::shared_ptr<GeoipProvider> driver; 31 0 : const uint64_t key = MessageUtil::hash(proto_config); 32 0 : absl::MutexLock lock(&mu_); 33 0 : auto it = drivers_.find(key); 34 0 : if (it != drivers_.end()) { 35 0 : driver = it->second.lock(); 36 0 : } else { 37 0 : const auto& provider_config = 38 0 : std::make_shared<GeoipProviderConfig>(proto_config, stat_prefix, context.scope()); 39 0 : driver = std::make_shared<GeoipProvider>(singleton, provider_config); 40 0 : drivers_[key] = driver; 41 0 : } 42 0 : return driver; 43 0 : } 44 : 45 : private: 46 : absl::Mutex mu_; 47 : // We keep weak_ptr here so the providers can be destroyed if the config is updated to stop using 48 : // that config of the provider. Each provider stores shared_ptrs to this singleton, which keeps 49 : // the singleton from being destroyed unless it's no longer keeping track of any providers. (The 50 : // singleton shared_ptr is *only* held by driver instances.) 51 : absl::flat_hash_map<uint64_t, std::weak_ptr<GeoipProvider>> drivers_ ABSL_GUARDED_BY(mu_); 52 : }; 53 : 54 : SINGLETON_MANAGER_REGISTRATION(maxmind_geolocation_provider_singleton); 55 : 56 2 : MaxmindProviderFactory::MaxmindProviderFactory() : FactoryBase("envoy.geoip_providers.maxmind") {} 57 : 58 : DriverSharedPtr MaxmindProviderFactory::createGeoipProviderDriverTyped( 59 : const ConfigProto& proto_config, const std::string& stat_prefix, 60 0 : Server::Configuration::FactoryContext& context) { 61 0 : std::shared_ptr<DriverSingleton> drivers = 62 0 : context.serverFactoryContext().singletonManager().getTyped<DriverSingleton>( 63 0 : SINGLETON_MANAGER_REGISTERED_NAME(maxmind_geolocation_provider_singleton), 64 0 : [] { return std::make_shared<DriverSingleton>(); }); 65 0 : return drivers->get(drivers, proto_config, stat_prefix, context); 66 0 : } 67 : 68 : /** 69 : * Static registration for the Maxmind provider. @see RegisterFactory. 70 : */ 71 : REGISTER_FACTORY(MaxmindProviderFactory, Geolocation::GeoipProviderFactory); 72 : 73 : } // namespace Maxmind 74 : } // namespace GeoipProviders 75 : } // namespace Extensions 76 : } // namespace Envoy