#ifndef NET_HTTP_HTTP_SERVER_PROPERTIES_H_
#define NET_HTTP_HTTP_SERVER_PROPERTIES_H_
#include <stddef.h>
#include <stdint.h>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <tuple>
#include <vector>
#include "base/containers/lru_cache.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "base/values.h"
#include "net/base/host_port_pair.h"
#include "net/base/ip_address.h"
#include "net/base/net_export.h"
#include "net/base/network_anonymization_key.h"
#include "net/http/alternative_service.h"
#include "net/http/broken_alternative_services.h"
#include "net/third_party/quiche/src/quiche/quic/core/quic_bandwidth.h"
#include "net/third_party/quiche/src/quiche/quic/core/quic_server_id.h"
#include "net/third_party/quiche/src/quiche/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quiche/spdy/core/spdy_framer.h"
#include "net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/scheme_host_port.h"
namespace base {
class Clock;
class TickClock;
}
namespace net {
class HttpServerPropertiesManager;
class IPAddress;
class NetLog;
struct SSLConfig;
struct NET_EXPORT SupportsQuic {
SupportsQuic() : used_quic(false) {}
SupportsQuic(bool used_quic, const std::string& address)
: used_quic(used_quic), address(address) {}
bool Equals(const SupportsQuic& other) const {
return used_quic == other.used_quic && address == other.address;
}
bool used_quic;
std::string address;
};
struct NET_EXPORT ServerNetworkStats {
ServerNetworkStats() : bandwidth_estimate(quic::QuicBandwidth::Zero()) {}
bool operator==(const ServerNetworkStats& other) const {
return srtt == other.srtt && bandwidth_estimate == other.bandwidth_estimate;
}
bool operator!=(const ServerNetworkStats& other) const {
return !this->operator==(other);
}
base::TimeDelta srtt;
quic::QuicBandwidth bandwidth_estimate;
};
typedef std::vector<AlternativeService> AlternativeServiceVector;
const int kMaxRecentlyBrokenAlternativeServiceEntries = 200;
const int kDefaultMaxQuicServerEntries = 5;
class NET_EXPORT HttpServerProperties
: public BrokenAlternativeServices::Delegate {
public:
static const int kMaxServerInfoEntries = 500;
class NET_EXPORT PrefDelegate {
public:
virtual ~PrefDelegate();
virtual const base::Value::Dict& GetServerProperties() const = 0;
virtual void SetServerProperties(base::Value::Dict dict,
base::OnceClosure callback) = 0;
virtual void WaitForPrefLoad(base::OnceClosure pref_loaded_callback) = 0;
};
struct NET_EXPORT ServerInfo {
ServerInfo();
ServerInfo(const ServerInfo& server_info);
ServerInfo(ServerInfo&& server_info);
~ServerInfo();
bool empty() const;
bool operator==(const ServerInfo& other) const;
absl::optional<bool> supports_spdy;
absl::optional<bool> requires_http11;
absl::optional<AlternativeServiceInfoVector> alternative_services;
absl::optional<ServerNetworkStats> server_network_stats;
};
struct NET_EXPORT ServerInfoMapKey {
ServerInfoMapKey(url::SchemeHostPort server,
const NetworkAnonymizationKey& network_anonymization_key,
bool use_network_anonymization_key);
~ServerInfoMapKey();
bool operator<(const ServerInfoMapKey& other) const;
url::SchemeHostPort server;
NetworkAnonymizationKey network_anonymization_key;
};
class NET_EXPORT ServerInfoMap
: public base::LRUCache<ServerInfoMapKey, ServerInfo> {
public:
ServerInfoMap();
ServerInfoMap(const ServerInfoMap&) = delete;
ServerInfoMap& operator=(const ServerInfoMap&) = delete;
iterator GetOrPut(const ServerInfoMapKey& key);
iterator EraseIfEmpty(iterator server_info_it);
};
struct NET_EXPORT QuicServerInfoMapKey {
QuicServerInfoMapKey(
const quic::QuicServerId& server_id,
const NetworkAnonymizationKey& network_anonymization_key,
bool use_network_anonymization_key);
~QuicServerInfoMapKey();
bool operator<(const QuicServerInfoMapKey& other) const;
bool operator==(const QuicServerInfoMapKey& other) const;
quic::QuicServerId server_id;
NetworkAnonymizationKey network_anonymization_key;
};
typedef base::LRUCache<QuicServerInfoMapKey, std::string> QuicServerInfoMap;
explicit HttpServerProperties(
std::unique_ptr<PrefDelegate> pref_delegate = nullptr,
NetLog* net_log = nullptr,
const base::TickClock* tick_clock = nullptr,
base::Clock* clock = nullptr);
HttpServerProperties(const HttpServerProperties&) = delete;
HttpServerProperties& operator=(const HttpServerProperties&) = delete;
~HttpServerProperties() override;
void Clear(base::OnceClosure callback);
bool SupportsRequestPriority(
const url::SchemeHostPort& server,
const net::NetworkAnonymizationKey& network_anonymization_key);
bool GetSupportsSpdy(
const url::SchemeHostPort& server,
const net::NetworkAnonymizationKey& network_anonymization_key);
void SetSupportsSpdy(
const url::SchemeHostPort& server,
const net::NetworkAnonymizationKey& network_anonymization_key,
bool supports_spdy);
bool RequiresHTTP11(
const url::SchemeHostPort& server,
const net::NetworkAnonymizationKey& network_anonymization_key);
void SetHTTP11Required(
const url::SchemeHostPort& server,
const net::NetworkAnonymizationKey& network_anonymization_key);
void MaybeForceHTTP11(
const url::SchemeHostPort& server,
const net::NetworkAnonymizationKey& network_anonymization_key,
SSLConfig* ssl_config);
AlternativeServiceInfoVector GetAlternativeServiceInfos(
const url::SchemeHostPort& origin,
const net::NetworkAnonymizationKey& network_anonymization_key);
void SetHttp2AlternativeService(
const url::SchemeHostPort& origin,
const NetworkAnonymizationKey& network_anonymization_key,
const AlternativeService& alternative_service,
base::Time expiration);
void SetQuicAlternativeService(
const url::SchemeHostPort& origin,
const NetworkAnonymizationKey& network_anonymization_key,
const AlternativeService& alternative_service,
base::Time expiration,
const quic::ParsedQuicVersionVector& advertised_versions);
void SetAlternativeServices(
const url::SchemeHostPort& origin,
const net::NetworkAnonymizationKey& network_anonymization_key,
const AlternativeServiceInfoVector& alternative_service_info_vector);
void MarkAlternativeServiceBroken(
const AlternativeService& alternative_service,
const net::NetworkAnonymizationKey& network_anonymization_key);
void MarkAlternativeServiceBrokenUntilDefaultNetworkChanges(
const AlternativeService& alternative_service,
const net::NetworkAnonymizationKey& network_anonymization_key);
void MarkAlternativeServiceRecentlyBroken(
const AlternativeService& alternative_service,
const net::NetworkAnonymizationKey& network_anonymization_key);
bool IsAlternativeServiceBroken(
const AlternativeService& alternative_service,
const net::NetworkAnonymizationKey& network_anonymization_key) const;
bool WasAlternativeServiceRecentlyBroken(
const AlternativeService& alternative_service,
const net::NetworkAnonymizationKey& network_anonymization_key);
void ConfirmAlternativeService(
const AlternativeService& alternative_service,
const net::NetworkAnonymizationKey& network_anonymization_key);
void OnDefaultNetworkChanged();
base::Value GetAlternativeServiceInfoAsValue() const;
bool WasLastLocalAddressWhenQuicWorked(const IPAddress& local_address) const;
bool HasLastLocalAddressWhenQuicWorked() const;
void SetLastLocalAddressWhenQuicWorked(
IPAddress last_local_address_when_quic_worked);
void ClearLastLocalAddressWhenQuicWorked();
void SetServerNetworkStats(
const url::SchemeHostPort& server,
const NetworkAnonymizationKey& network_anonymization_key,
ServerNetworkStats stats);
void ClearServerNetworkStats(
const url::SchemeHostPort& server,
const NetworkAnonymizationKey& network_anonymization_key);
const ServerNetworkStats* GetServerNetworkStats(
const url::SchemeHostPort& server,
const NetworkAnonymizationKey& network_anonymization_key);
void SetQuicServerInfo(
const quic::QuicServerId& server_id,
const NetworkAnonymizationKey& network_anonymization_key,
const std::string& server_info);
const std::string* GetQuicServerInfo(
const quic::QuicServerId& server_id,
const NetworkAnonymizationKey& network_anonymization_key);
const QuicServerInfoMap& quic_server_info_map() const;
size_t max_server_configs_stored_in_properties() const;
void SetMaxServerConfigsStoredInProperties(
size_t max_server_configs_stored_in_properties);
void SetBrokenAlternativeServicesDelayParams(
absl::optional<base::TimeDelta> initial_delay,
absl::optional<bool> exponential_backoff_on_initial_delay);
bool IsInitialized() const;
void OnExpireBrokenAlternativeService(
const AlternativeService& expired_alternative_service,
const NetworkAnonymizationKey& network_anonymization_key) override;
static base::TimeDelta GetUpdatePrefsDelayForTesting();
void OnServerInfoLoadedForTesting(
std::unique_ptr<ServerInfoMap> server_info_map) {
OnServerInfoLoaded(std::move(server_info_map));
}
void OnLastLocalAddressWhenQuicWorkedForTesting(
const IPAddress& last_local_address_when_quic_worked) {
OnLastLocalAddressWhenQuicWorkedLoaded(last_local_address_when_quic_worked);
}
void OnQuicServerInfoMapLoadedForTesting(
std::unique_ptr<QuicServerInfoMap> quic_server_info_map) {
OnQuicServerInfoMapLoaded(std::move(quic_server_info_map));
}
void OnBrokenAndRecentlyBrokenAlternativeServicesLoadedForTesting(
std::unique_ptr<BrokenAlternativeServiceList>
broken_alternative_service_list,
std::unique_ptr<RecentlyBrokenAlternativeServices>
recently_broken_alternative_services) {
OnBrokenAndRecentlyBrokenAlternativeServicesLoaded(
std::move(broken_alternative_service_list),
std::move(recently_broken_alternative_services));
}
const std::string* GetCanonicalSuffixForTesting(
const std::string& host) const {
return GetCanonicalSuffix(host);
}
const ServerInfoMap& server_info_map_for_testing() const {
return server_info_map_;
}
const BrokenAlternativeServices& broken_alternative_services_for_testing()
const {
return broken_alternative_services_;
}
const QuicServerInfoMap& quic_server_info_map_for_testing() const {
return quic_server_info_map_;
}
HttpServerPropertiesManager* properties_manager_for_testing() {
return properties_manager_.get();
}
private:
friend class HttpServerPropertiesPeer;
typedef base::flat_map<ServerInfoMapKey, url::SchemeHostPort> CanonicalMap;
typedef base::flat_map<QuicServerInfoMapKey, quic::QuicServerId>
QuicCanonicalMap;
typedef std::vector<std::string> CanonicalSuffixList;
bool GetSupportsSpdyInternal(
url::SchemeHostPort server,
const net::NetworkAnonymizationKey& network_anonymization_key);
void SetSupportsSpdyInternal(
url::SchemeHostPort server,
const net::NetworkAnonymizationKey& network_anonymization_key,
bool supports_spdy);
bool RequiresHTTP11Internal(
url::SchemeHostPort server,
const net::NetworkAnonymizationKey& network_anonymization_key);
void SetHTTP11RequiredInternal(
url::SchemeHostPort server,
const net::NetworkAnonymizationKey& network_anonymization_key);
void MaybeForceHTTP11Internal(
url::SchemeHostPort server,
const net::NetworkAnonymizationKey& network_anonymization_key,
SSLConfig* ssl_config);
AlternativeServiceInfoVector GetAlternativeServiceInfosInternal(
const url::SchemeHostPort& origin,
const net::NetworkAnonymizationKey& network_anonymization_key);
void SetAlternativeServicesInternal(
const url::SchemeHostPort& origin,
const net::NetworkAnonymizationKey& network_anonymization_key,
const AlternativeServiceInfoVector& alternative_service_info_vector);
void SetServerNetworkStatsInternal(
url::SchemeHostPort server,
const NetworkAnonymizationKey& network_anonymization_key,
ServerNetworkStats stats);
void ClearServerNetworkStatsInternal(
url::SchemeHostPort server,
const NetworkAnonymizationKey& network_anonymization_key);
const ServerNetworkStats* GetServerNetworkStatsInternal(
url::SchemeHostPort server,
const NetworkAnonymizationKey& network_anonymization_key);
ServerInfoMapKey CreateServerInfoKey(
const url::SchemeHostPort& server,
const NetworkAnonymizationKey& network_anonymization_key) const;
QuicServerInfoMapKey CreateQuicServerInfoKey(
const quic::QuicServerId& server_id,
const NetworkAnonymizationKey& network_anonymization_key) const;
ServerInfoMap::const_iterator GetIteratorWithAlternativeServiceInfo(
const url::SchemeHostPort& server,
const net::NetworkAnonymizationKey& network_anonymization_key);
CanonicalMap::const_iterator GetCanonicalAltSvcHost(
const url::SchemeHostPort& server,
const net::NetworkAnonymizationKey& network_anonymization_key) const;
QuicCanonicalMap::const_iterator GetCanonicalServerInfoHost(
const QuicServerInfoMapKey& key) const;
void RemoveAltSvcCanonicalHost(
const url::SchemeHostPort& server,
const NetworkAnonymizationKey& network_anonymization_key);
void UpdateCanonicalServerInfoMap(const QuicServerInfoMapKey& key);
const std::string* GetCanonicalSuffix(const std::string& host) const;
void OnPrefsLoaded(std::unique_ptr<ServerInfoMap> server_info_map,
const IPAddress& last_local_address_when_quic_worked,
std::unique_ptr<QuicServerInfoMap> quic_server_info_map,
std::unique_ptr<BrokenAlternativeServiceList>
broken_alternative_service_list,
std::unique_ptr<RecentlyBrokenAlternativeServices>
recently_broken_alternative_services);
void OnServerInfoLoaded(std::unique_ptr<ServerInfoMap> server_info_map);
void OnLastLocalAddressWhenQuicWorkedLoaded(
const IPAddress& last_local_address_when_quic_worked);
void OnQuicServerInfoMapLoaded(
std::unique_ptr<QuicServerInfoMap> quic_server_info_map);
void OnBrokenAndRecentlyBrokenAlternativeServicesLoaded(
std::unique_ptr<BrokenAlternativeServiceList>
broken_alternative_service_list,
std::unique_ptr<RecentlyBrokenAlternativeServices>
recently_broken_alternative_services);
void MaybeQueueWriteProperties();
void WriteProperties(base::OnceClosure callback) const;
raw_ptr<const base::TickClock> tick_clock_;
raw_ptr<base::Clock> clock_;
const bool use_network_anonymization_key_;
bool is_initialized_;
bool queue_write_on_load_ = false;
std::unique_ptr<HttpServerPropertiesManager> properties_manager_;
ServerInfoMap server_info_map_;
BrokenAlternativeServices broken_alternative_services_;
IPAddress last_local_address_when_quic_worked_;
CanonicalMap canonical_alt_svc_map_;
const CanonicalSuffixList canonical_suffixes_;
QuicServerInfoMap quic_server_info_map_;
QuicCanonicalMap canonical_server_info_map_;
size_t max_server_configs_stored_in_properties_;
base::OneShotTimer prefs_update_timer_;
THREAD_CHECKER(thread_checker_);
};
}
#endif