Commit 2890796e authored by Matt Menke's avatar Matt Menke Committed by Commit Bot

Remove BrokenAlternativeServices's dependency on HttpServerProperties.

Previously, http_server_properties_impl.h included on
broken_alternative_services.h which included http_server_properties.h.

Since HttpServerPropertiesImpl is the only implementation of
HttpServerProperties, I want to merge the two files, but that would
result in a circular dependency due to the aforementioned dependency.

This CL moves the alternative services-related members of
http_server_properties.h into alternative_services.h, which
broken_alternatives_services.h now depends on.

Bug: 984996
Change-Id: Ibb037219662ea0c3eab534c1bf9b7c0f3ef4c32c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1724752
Commit-Queue: Matt Menke <mmenke@chromium.org>
Reviewed-by: default avatarZhongyi Shi <zhongyi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#683635}
parent 4c285f86
......@@ -744,6 +744,8 @@ component("net") {
"filter/source_stream.cc",
"filter/source_stream.h",
"filter/source_stream_type_list.h",
"http/alternative_service.cc",
"http/alternative_service.h",
"http/bidirectional_stream.cc",
"http/bidirectional_stream.h",
"http/bidirectional_stream_impl.cc",
......
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/http/alternative_service.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/stringprintf.h"
namespace net {
namespace {
enum AlternativeProxyUsage {
// Alternative Proxy was used without racing a normal connection.
ALTERNATIVE_PROXY_USAGE_NO_RACE = 0,
// Alternative Proxy was used by winning a race with a normal connection.
ALTERNATIVE_PROXY_USAGE_WON_RACE = 1,
// Alternative Proxy was not used by losing a race with a normal connection.
ALTERNATIVE_PROXY_USAGE_LOST_RACE = 2,
// Maximum value for the enum.
ALTERNATIVE_PROXY_USAGE_MAX,
};
AlternativeProxyUsage ConvertProtocolUsageToProxyUsage(
AlternateProtocolUsage usage) {
switch (usage) {
case ALTERNATE_PROTOCOL_USAGE_NO_RACE:
return ALTERNATIVE_PROXY_USAGE_NO_RACE;
case ALTERNATE_PROTOCOL_USAGE_WON_RACE:
return ALTERNATIVE_PROXY_USAGE_WON_RACE;
case ALTERNATE_PROTOCOL_USAGE_LOST_RACE:
return ALTERNATIVE_PROXY_USAGE_LOST_RACE;
default:
NOTREACHED();
return ALTERNATIVE_PROXY_USAGE_MAX;
}
}
} // anonymous namespace
void HistogramAlternateProtocolUsage(AlternateProtocolUsage usage,
bool proxy_server_used) {
if (proxy_server_used) {
DCHECK_LE(usage, ALTERNATE_PROTOCOL_USAGE_LOST_RACE);
UMA_HISTOGRAM_ENUMERATION("Net.QuicAlternativeProxy.Usage",
ConvertProtocolUsageToProxyUsage(usage),
ALTERNATIVE_PROXY_USAGE_MAX);
} else {
UMA_HISTOGRAM_ENUMERATION("Net.AlternateProtocolUsage", usage,
ALTERNATE_PROTOCOL_USAGE_MAX);
}
}
void HistogramBrokenAlternateProtocolLocation(
BrokenAlternateProtocolLocation location) {
UMA_HISTOGRAM_ENUMERATION("Net.AlternateProtocolBrokenLocation", location,
BROKEN_ALTERNATE_PROTOCOL_LOCATION_MAX);
}
bool IsAlternateProtocolValid(NextProto protocol) {
switch (protocol) {
case kProtoUnknown:
return false;
case kProtoHTTP11:
return false;
case kProtoHTTP2:
return true;
case kProtoQUIC:
return true;
}
NOTREACHED();
return false;
}
// static
AlternativeServiceInfo
AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
const AlternativeService& alternative_service,
base::Time expiration) {
DCHECK_EQ(alternative_service.protocol, kProtoHTTP2);
return AlternativeServiceInfo(alternative_service, expiration,
quic::ParsedQuicVersionVector());
}
// static
AlternativeServiceInfo AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
const AlternativeService& alternative_service,
base::Time expiration,
const quic::ParsedQuicVersionVector& advertised_versions) {
DCHECK_EQ(alternative_service.protocol, kProtoQUIC);
return AlternativeServiceInfo(alternative_service, expiration,
advertised_versions);
}
AlternativeServiceInfo::AlternativeServiceInfo() : alternative_service_() {}
AlternativeServiceInfo::~AlternativeServiceInfo() = default;
AlternativeServiceInfo::AlternativeServiceInfo(
const AlternativeService& alternative_service,
base::Time expiration,
const quic::ParsedQuicVersionVector& advertised_versions)
: alternative_service_(alternative_service), expiration_(expiration) {
if (alternative_service_.protocol == kProtoQUIC) {
advertised_versions_ = advertised_versions;
std::sort(advertised_versions_.begin(), advertised_versions_.end(),
TransportVersionLessThan);
}
}
AlternativeServiceInfo::AlternativeServiceInfo(
const AlternativeServiceInfo& alternative_service_info) = default;
AlternativeServiceInfo& AlternativeServiceInfo::operator=(
const AlternativeServiceInfo& alternative_service_info) = default;
std::string AlternativeService::ToString() const {
return base::StringPrintf("%s %s:%d", NextProtoToString(protocol),
host.c_str(), port);
}
std::string AlternativeServiceInfo::ToString() const {
base::Time::Exploded exploded;
expiration_.LocalExplode(&exploded);
return base::StringPrintf(
"%s, expires %04d-%02d-%02d %02d:%02d:%02d",
alternative_service_.ToString().c_str(), exploded.year, exploded.month,
exploded.day_of_month, exploded.hour, exploded.minute, exploded.second);
}
// static
bool AlternativeServiceInfo::TransportVersionLessThan(
const quic::ParsedQuicVersion& lhs,
const quic::ParsedQuicVersion& rhs) {
return lhs.transport_version < rhs.transport_version;
}
std::ostream& operator<<(std::ostream& os,
const AlternativeService& alternative_service) {
os << alternative_service.ToString();
return os;
}
} // namespace net
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NET_HTTP_ALTERNATIVE_SERVICE_H_
#define NET_HTTP_ALTERNATIVE_SERVICE_H_
#include <stdint.h>
#include <algorithm>
#include <ostream>
#include <string>
#include "base/time/time.h"
#include "net/base/host_port_pair.h"
#include "net/base/net_export.h"
#include "net/socket/next_proto.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
namespace net {
enum AlternateProtocolUsage {
// Alternate Protocol was used without racing a normal connection.
ALTERNATE_PROTOCOL_USAGE_NO_RACE = 0,
// Alternate Protocol was used by winning a race with a normal connection.
ALTERNATE_PROTOCOL_USAGE_WON_RACE = 1,
// Alternate Protocol was not used by losing a race with a normal connection.
ALTERNATE_PROTOCOL_USAGE_LOST_RACE = 2,
// Alternate Protocol was not used because no Alternate-Protocol information
// was available when the request was issued, but an Alternate-Protocol header
// was present in the response.
ALTERNATE_PROTOCOL_USAGE_MAPPING_MISSING = 3,
// Alternate Protocol was not used because it was marked broken.
ALTERNATE_PROTOCOL_USAGE_BROKEN = 4,
// Maximum value for the enum.
ALTERNATE_PROTOCOL_USAGE_MAX,
};
// Log a histogram to reflect |usage|.
NET_EXPORT void HistogramAlternateProtocolUsage(AlternateProtocolUsage usage,
bool proxy_server_used);
enum BrokenAlternateProtocolLocation {
BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_JOB = 0,
BROKEN_ALTERNATE_PROTOCOL_LOCATION_QUIC_STREAM_FACTORY = 1,
BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_JOB_ALT = 2,
BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_JOB_MAIN = 3,
BROKEN_ALTERNATE_PROTOCOL_LOCATION_QUIC_HTTP_STREAM = 4,
BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_NETWORK_TRANSACTION = 5,
BROKEN_ALTERNATE_PROTOCOL_LOCATION_MAX,
};
// Log a histogram to reflect |location|.
NET_EXPORT void HistogramBrokenAlternateProtocolLocation(
BrokenAlternateProtocolLocation location);
NET_EXPORT bool IsAlternateProtocolValid(NextProto protocol);
// (protocol, host, port) triple as defined in
// https://tools.ietf.org/id/draft-ietf-httpbis-alt-svc-06.html
//
// TODO(mmenke): Seems like most of this stuff should be de-inlined.
struct NET_EXPORT AlternativeService {
AlternativeService() : protocol(kProtoUnknown), host(), port(0) {}
AlternativeService(NextProto protocol, const std::string& host, uint16_t port)
: protocol(protocol), host(host), port(port) {}
AlternativeService(NextProto protocol, const HostPortPair& host_port_pair)
: protocol(protocol),
host(host_port_pair.host()),
port(host_port_pair.port()) {}
AlternativeService(const AlternativeService& alternative_service) = default;
AlternativeService& operator=(const AlternativeService& alternative_service) =
default;
HostPortPair host_port_pair() const { return HostPortPair(host, port); }
bool operator==(const AlternativeService& other) const {
return protocol == other.protocol && host == other.host &&
port == other.port;
}
bool operator!=(const AlternativeService& other) const {
return !this->operator==(other);
}
bool operator<(const AlternativeService& other) const {
return std::tie(protocol, host, port) <
std::tie(other.protocol, other.host, other.port);
}
// Output format: "protocol host:port", e.g. "h2 www.google.com:1234".
std::string ToString() const;
NextProto protocol;
std::string host;
uint16_t port;
};
NET_EXPORT_PRIVATE std::ostream& operator<<(
std::ostream& os,
const AlternativeService& alternative_service);
struct AlternativeServiceHash {
size_t operator()(const net::AlternativeService& entry) const {
return entry.protocol ^ std::hash<std::string>()(entry.host) ^ entry.port;
}
};
class NET_EXPORT_PRIVATE AlternativeServiceInfo {
public:
static AlternativeServiceInfo CreateHttp2AlternativeServiceInfo(
const AlternativeService& alternative_service,
base::Time expiration);
static AlternativeServiceInfo CreateQuicAlternativeServiceInfo(
const AlternativeService& alternative_service,
base::Time expiration,
const quic::ParsedQuicVersionVector& advertised_versions);
AlternativeServiceInfo();
~AlternativeServiceInfo();
AlternativeServiceInfo(
const AlternativeServiceInfo& alternative_service_info);
AlternativeServiceInfo& operator=(
const AlternativeServiceInfo& alternative_service_info);
bool operator==(const AlternativeServiceInfo& other) const {
return alternative_service_ == other.alternative_service() &&
expiration_ == other.expiration() &&
advertised_versions_ == other.advertised_versions();
}
bool operator!=(const AlternativeServiceInfo& other) const {
return !this->operator==(other);
}
std::string ToString() const;
void set_alternative_service(const AlternativeService& alternative_service) {
alternative_service_ = alternative_service;
}
void set_protocol(const NextProto& protocol) {
alternative_service_.protocol = protocol;
}
void set_host(const std::string& host) { alternative_service_.host = host; }
void set_port(uint16_t port) { alternative_service_.port = port; }
void set_expiration(const base::Time& expiration) {
expiration_ = expiration;
}
void set_advertised_versions(
const quic::ParsedQuicVersionVector& advertised_versions) {
if (alternative_service_.protocol != kProtoQUIC)
return;
advertised_versions_ = advertised_versions;
std::sort(advertised_versions_.begin(), advertised_versions_.end(),
TransportVersionLessThan);
}
const AlternativeService& alternative_service() const {
return alternative_service_;
}
NextProto protocol() const { return alternative_service_.protocol; }
HostPortPair host_port_pair() const {
return alternative_service_.host_port_pair();
}
base::Time expiration() const { return expiration_; }
const quic::ParsedQuicVersionVector& advertised_versions() const {
return advertised_versions_;
}
private:
AlternativeServiceInfo(
const AlternativeService& alternative_service,
base::Time expiration,
const quic::ParsedQuicVersionVector& advertised_versions);
static bool TransportVersionLessThan(const quic::ParsedQuicVersion& lhs,
const quic::ParsedQuicVersion& rhs);
AlternativeService alternative_service_;
base::Time expiration_;
// Lists all the QUIC versions that are advertised by the server and supported
// by Chrome. If empty, defaults to versions used by the current instance of
// the netstack.
// This list MUST be sorted in ascending order.
quic::ParsedQuicVersionVector advertised_versions_;
};
} // namespace net
#endif // NET_HTTP_ALTERNATIVE_SERVICE_H_
......@@ -32,9 +32,13 @@ base::TimeDelta ComputeBrokenAlternativeServiceExpirationDelay(
} // namespace
BrokenAlternativeServices::BrokenAlternativeServices(
int max_recently_broken_alternative_service_entries,
Delegate* delegate,
const base::TickClock* clock)
: delegate_(delegate), clock_(clock) {
: delegate_(delegate),
clock_(clock),
recently_broken_alternative_services_(
max_recently_broken_alternative_service_entries) {
DCHECK(delegate_);
DCHECK(clock_);
}
......
......@@ -9,9 +9,11 @@
#include <set>
#include <unordered_map>
#include "base/containers/mru_cache.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "net/http/http_server_properties.h"
#include "net/http/alternative_service.h"
namespace base {
class TickClock;
......@@ -19,12 +21,28 @@ class TickClock;
namespace net {
// Stores broken alternative services and when their brokenness expires.
typedef std::list<std::pair<AlternativeService, base::TimeTicks>>
BrokenAlternativeServiceList;
// Stores how many times an alternative service has been marked broken.
class RecentlyBrokenAlternativeServices
: public base::MRUCache<AlternativeService, int> {
public:
RecentlyBrokenAlternativeServices(
int max_recently_broken_alternative_service_entries)
: base::MRUCache<AlternativeService, int>(
max_recently_broken_alternative_service_entries) {}
};
// This class tracks HTTP alternative services that have been marked as broken.
// The brokenness of an alt-svc will expire after some time according to an
// exponential back-off formula: each time an alt-svc is marked broken, the
// expiration delay will be some constant multiple of its previous expiration
// delay. This prevents broken alt-svcs from being retried too often by the
// network stack.
//
// Intended solely for use by HttpServerProperties.
class NET_EXPORT_PRIVATE BrokenAlternativeServices {
public:
// Delegate to be used by owner so it can be notified when the brokenness of
......@@ -42,7 +60,9 @@ class NET_EXPORT_PRIVATE BrokenAlternativeServices {
// |clock| is used for setting expiration times and scheduling the
// expiration of broken alternative services. It must not be null.
// |delegate| and |clock| are both unowned and must outlive this.
BrokenAlternativeServices(Delegate* delegate, const base::TickClock* clock);
BrokenAlternativeServices(int max_recently_broken_alternative_service_entries,
Delegate* delegate,
const base::TickClock* clock);
BrokenAlternativeServices(const BrokenAlternativeServices&) = delete;
void operator=(const BrokenAlternativeServices&) = delete;
......
......@@ -26,7 +26,7 @@ class BrokenAlternativeServicesTest
: test_task_runner_(new base::TestMockTimeTaskRunner()),
test_task_runner_context_(test_task_runner_),
broken_services_clock_(test_task_runner_->GetMockTickClock()),
broken_services_(this, broken_services_clock_) {}
broken_services_(50, this, broken_services_clock_) {}
// BrokenAlternativeServices::Delegate implementation
void OnExpireBrokenAlternativeService(
......@@ -640,7 +640,7 @@ TEST_F(BrokenAlternativeServicesTest, SetBrokenAlternativeServices) {
{alternative_service1, broken_services_clock_->NowTicks() + delay1});
std::unique_ptr<RecentlyBrokenAlternativeServices> recently_broken_map =
std::make_unique<RecentlyBrokenAlternativeServices>();
std::make_unique<RecentlyBrokenAlternativeServices>(10);
recently_broken_map->Put(alternative_service1, 1);
recently_broken_map->Put(alternative_service2, 2);
......@@ -701,7 +701,7 @@ TEST_F(BrokenAlternativeServicesTest,
broken_services_clock_->NowTicks() + base::TimeDelta::FromMinutes(1)});
std::unique_ptr<RecentlyBrokenAlternativeServices> recently_broken_map =
std::make_unique<RecentlyBrokenAlternativeServices>();
std::make_unique<RecentlyBrokenAlternativeServices>(10);
recently_broken_map->Put(alternative_service1, 1);
recently_broken_map->Put(alternative_service3, 1);
......@@ -822,7 +822,7 @@ TEST_F(BrokenAlternativeServicesTest, Clear) {
broken_services_clock_->NowTicks() + base::TimeDelta::FromMinutes(1)});
std::unique_ptr<RecentlyBrokenAlternativeServices> recently_broken_map =
std::make_unique<RecentlyBrokenAlternativeServices>();
std::make_unique<RecentlyBrokenAlternativeServices>(10);
recently_broken_map->Put(alternative_service2, 2);
broken_services_.SetBrokenAndRecentlyBrokenAlternativeServices(
......
......@@ -4,150 +4,11 @@
#include "net/http/http_server_properties.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/stringprintf.h"
#include "net/http/http_network_session.h"
#include "net/socket/ssl_client_socket.h"
#include "net/ssl/ssl_config.h"
namespace net {
namespace {
enum AlternativeProxyUsage {
// Alternative Proxy was used without racing a normal connection.
ALTERNATIVE_PROXY_USAGE_NO_RACE = 0,
// Alternative Proxy was used by winning a race with a normal connection.
ALTERNATIVE_PROXY_USAGE_WON_RACE = 1,
// Alternative Proxy was not used by losing a race with a normal connection.
ALTERNATIVE_PROXY_USAGE_LOST_RACE = 2,
// Maximum value for the enum.
ALTERNATIVE_PROXY_USAGE_MAX,
};
AlternativeProxyUsage ConvertProtocolUsageToProxyUsage(
AlternateProtocolUsage usage) {
switch (usage) {
case ALTERNATE_PROTOCOL_USAGE_NO_RACE:
return ALTERNATIVE_PROXY_USAGE_NO_RACE;
case ALTERNATE_PROTOCOL_USAGE_WON_RACE:
return ALTERNATIVE_PROXY_USAGE_WON_RACE;
case ALTERNATE_PROTOCOL_USAGE_LOST_RACE:
return ALTERNATIVE_PROXY_USAGE_LOST_RACE;
default:
NOTREACHED();
return ALTERNATIVE_PROXY_USAGE_MAX;
}
}
} // anonymous namespace
const char kAlternativeServiceHeader[] = "Alt-Svc";
void HistogramAlternateProtocolUsage(AlternateProtocolUsage usage,
bool proxy_server_used) {
if (proxy_server_used) {
DCHECK_LE(usage, ALTERNATE_PROTOCOL_USAGE_LOST_RACE);
UMA_HISTOGRAM_ENUMERATION("Net.QuicAlternativeProxy.Usage",
ConvertProtocolUsageToProxyUsage(usage),
ALTERNATIVE_PROXY_USAGE_MAX);
} else {
UMA_HISTOGRAM_ENUMERATION("Net.AlternateProtocolUsage", usage,
ALTERNATE_PROTOCOL_USAGE_MAX);
}
}
void HistogramBrokenAlternateProtocolLocation(
BrokenAlternateProtocolLocation location){
UMA_HISTOGRAM_ENUMERATION("Net.AlternateProtocolBrokenLocation", location,
BROKEN_ALTERNATE_PROTOCOL_LOCATION_MAX);
}
bool IsAlternateProtocolValid(NextProto protocol) {
switch (protocol) {
case kProtoUnknown:
return false;
case kProtoHTTP11:
return false;
case kProtoHTTP2:
return true;
case kProtoQUIC:
return true;
}
NOTREACHED();
return false;
}
// static
AlternativeServiceInfo
AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
const AlternativeService& alternative_service,
base::Time expiration) {
DCHECK_EQ(alternative_service.protocol, kProtoHTTP2);
return AlternativeServiceInfo(alternative_service, expiration,
quic::ParsedQuicVersionVector());
}
// static
AlternativeServiceInfo AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
const AlternativeService& alternative_service,
base::Time expiration,
const quic::ParsedQuicVersionVector& advertised_versions) {
DCHECK_EQ(alternative_service.protocol, kProtoQUIC);
return AlternativeServiceInfo(alternative_service, expiration,
advertised_versions);
}
AlternativeServiceInfo::AlternativeServiceInfo() : alternative_service_() {}
AlternativeServiceInfo::~AlternativeServiceInfo() = default;
AlternativeServiceInfo::AlternativeServiceInfo(
const AlternativeService& alternative_service,
base::Time expiration,
const quic::ParsedQuicVersionVector& advertised_versions)
: alternative_service_(alternative_service), expiration_(expiration) {
if (alternative_service_.protocol == kProtoQUIC) {
advertised_versions_ = advertised_versions;
std::sort(advertised_versions_.begin(), advertised_versions_.end(),
TransportVersionLessThan);
}
}
AlternativeServiceInfo::AlternativeServiceInfo(
const AlternativeServiceInfo& alternative_service_info) = default;
AlternativeServiceInfo& AlternativeServiceInfo::operator=(
const AlternativeServiceInfo& alternative_service_info) = default;
std::string AlternativeService::ToString() const {
return base::StringPrintf("%s %s:%d", NextProtoToString(protocol),
host.c_str(), port);
}
std::string AlternativeServiceInfo::ToString() const {
base::Time::Exploded exploded;
expiration_.LocalExplode(&exploded);
return base::StringPrintf(
"%s, expires %04d-%02d-%02d %02d:%02d:%02d",
alternative_service_.ToString().c_str(), exploded.year, exploded.month,
exploded.day_of_month, exploded.hour, exploded.minute, exploded.second);
}
// static
bool AlternativeServiceInfo::TransportVersionLessThan(
const quic::ParsedQuicVersion& lhs,
const quic::ParsedQuicVersion& rhs) {
return lhs.transport_version < rhs.transport_version;
}
std::ostream& operator<<(std::ostream& os,
const AlternativeService& alternative_service) {
os << alternative_service.ToString();
return os;
}
// static
void HttpServerProperties::ForceHTTP11(SSLConfig* ssl_config) {
ssl_config->alpn_protos.clear();
......
......@@ -5,10 +5,7 @@
#ifndef NET_HTTP_HTTP_SERVER_PROPERTIES_H_
#define NET_HTTP_HTTP_SERVER_PROPERTIES_H_
#include <stdint.h>
#include <map>
#include <ostream>
#include <string>
#include <tuple>
#include <vector>
......@@ -17,9 +14,8 @@
#include "base/containers/mru_cache.h"
#include "base/macros.h"
#include "base/time/time.h"
#include "net/base/host_port_pair.h"
#include "net/base/net_export.h"
#include "net/socket/next_proto.h"
#include "net/http/alternative_service.h"
#include "net/third_party/quiche/src/quic/core/quic_bandwidth.h"
#include "net/third_party/quiche/src/quic/core/quic_server_id.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
......@@ -33,190 +29,10 @@ class Value;
namespace net {
class HostPortPair;
class IPAddress;
struct SSLConfig;
enum AlternateProtocolUsage {
// Alternate Protocol was used without racing a normal connection.
ALTERNATE_PROTOCOL_USAGE_NO_RACE = 0,
// Alternate Protocol was used by winning a race with a normal connection.
ALTERNATE_PROTOCOL_USAGE_WON_RACE = 1,
// Alternate Protocol was not used by losing a race with a normal connection.
ALTERNATE_PROTOCOL_USAGE_LOST_RACE = 2,
// Alternate Protocol was not used because no Alternate-Protocol information
// was available when the request was issued, but an Alternate-Protocol header
// was present in the response.
ALTERNATE_PROTOCOL_USAGE_MAPPING_MISSING = 3,
// Alternate Protocol was not used because it was marked broken.
ALTERNATE_PROTOCOL_USAGE_BROKEN = 4,
// Maximum value for the enum.
ALTERNATE_PROTOCOL_USAGE_MAX,
};
// Log a histogram to reflect |usage|.
NET_EXPORT void HistogramAlternateProtocolUsage(AlternateProtocolUsage usage,
bool proxy_server_used);
enum BrokenAlternateProtocolLocation {
BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_JOB = 0,
BROKEN_ALTERNATE_PROTOCOL_LOCATION_QUIC_STREAM_FACTORY = 1,
BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_JOB_ALT = 2,
BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_JOB_MAIN = 3,
BROKEN_ALTERNATE_PROTOCOL_LOCATION_QUIC_HTTP_STREAM = 4,
BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_NETWORK_TRANSACTION = 5,
BROKEN_ALTERNATE_PROTOCOL_LOCATION_MAX,
};
// Log a histogram to reflect |location|.
NET_EXPORT void HistogramBrokenAlternateProtocolLocation(
BrokenAlternateProtocolLocation location);
NET_EXPORT bool IsAlternateProtocolValid(NextProto protocol);
// (protocol, host, port) triple as defined in
// https://tools.ietf.org/id/draft-ietf-httpbis-alt-svc-06.html
struct NET_EXPORT AlternativeService {
AlternativeService() : protocol(kProtoUnknown), host(), port(0) {}
AlternativeService(NextProto protocol, const std::string& host, uint16_t port)
: protocol(protocol), host(host), port(port) {}
AlternativeService(NextProto protocol, const HostPortPair& host_port_pair)
: protocol(protocol),
host(host_port_pair.host()),
port(host_port_pair.port()) {}
AlternativeService(const AlternativeService& alternative_service) = default;
AlternativeService& operator=(const AlternativeService& alternative_service) =
default;
HostPortPair host_port_pair() const { return HostPortPair(host, port); }
bool operator==(const AlternativeService& other) const {
return protocol == other.protocol && host == other.host &&
port == other.port;
}
bool operator!=(const AlternativeService& other) const {
return !this->operator==(other);
}
bool operator<(const AlternativeService& other) const {
return std::tie(protocol, host, port) <
std::tie(other.protocol, other.host, other.port);
}
// Output format: "protocol host:port", e.g. "h2 www.google.com:1234".
std::string ToString() const;
NextProto protocol;
std::string host;
uint16_t port;
};
NET_EXPORT_PRIVATE std::ostream& operator<<(
std::ostream& os,
const AlternativeService& alternative_service);
struct AlternativeServiceHash {
size_t operator()(const net::AlternativeService& entry) const {
return entry.protocol ^ std::hash<std::string>()(entry.host) ^ entry.port;
}
};
class NET_EXPORT_PRIVATE AlternativeServiceInfo {
public:
static AlternativeServiceInfo CreateHttp2AlternativeServiceInfo(
const AlternativeService& alternative_service,
base::Time expiration);
static AlternativeServiceInfo CreateQuicAlternativeServiceInfo(
const AlternativeService& alternative_service,
base::Time expiration,
const quic::ParsedQuicVersionVector& advertised_versions);
AlternativeServiceInfo();
~AlternativeServiceInfo();
AlternativeServiceInfo(
const AlternativeServiceInfo& alternative_service_info);
AlternativeServiceInfo& operator=(
const AlternativeServiceInfo& alternative_service_info);
bool operator==(const AlternativeServiceInfo& other) const {
return alternative_service_ == other.alternative_service() &&
expiration_ == other.expiration() &&
advertised_versions_ == other.advertised_versions();
}
bool operator!=(const AlternativeServiceInfo& other) const {
return !this->operator==(other);
}
std::string ToString() const;
void set_alternative_service(const AlternativeService& alternative_service) {
alternative_service_ = alternative_service;
}
void set_protocol(const NextProto& protocol) {
alternative_service_.protocol = protocol;
}
void set_host(const std::string& host) { alternative_service_.host = host; }
void set_port(uint16_t port) { alternative_service_.port = port; }
void set_expiration(const base::Time& expiration) {
expiration_ = expiration;
}
void set_advertised_versions(
const quic::ParsedQuicVersionVector& advertised_versions) {
if (alternative_service_.protocol != kProtoQUIC)
return;
advertised_versions_ = advertised_versions;
std::sort(advertised_versions_.begin(), advertised_versions_.end(),
TransportVersionLessThan);
}
const AlternativeService& alternative_service() const {
return alternative_service_;
}
NextProto protocol() const { return alternative_service_.protocol; }
HostPortPair host_port_pair() const {
return alternative_service_.host_port_pair();
}
base::Time expiration() const { return expiration_; }
const quic::ParsedQuicVersionVector& advertised_versions() const {
return advertised_versions_;
}
private:
AlternativeServiceInfo(
const AlternativeService& alternative_service,
base::Time expiration,
const quic::ParsedQuicVersionVector& advertised_versions);
static bool TransportVersionLessThan(const quic::ParsedQuicVersion& lhs,
const quic::ParsedQuicVersion& rhs);
AlternativeService alternative_service_;
base::Time expiration_;
// Lists all the QUIC versions that are advertised by the server and supported
// by Chrome. If empty, defaults to versions used by the current instance of
// the netstack.
// This list MUST be sorted in ascending order.
quic::ParsedQuicVersionVector advertised_versions_;
};
struct NET_EXPORT SupportsQuic {
SupportsQuic() : used_quic(false) {}
SupportsQuic(bool used_quic, const std::string& address)
......@@ -249,10 +65,6 @@ struct NET_EXPORT ServerNetworkStats {
typedef std::vector<AlternativeService> AlternativeServiceVector;
typedef std::vector<AlternativeServiceInfo> AlternativeServiceInfoVector;
// Stores broken alternative services and when their brokenness expires.
typedef std::list<std::pair<AlternativeService, base::TimeTicks>>
BrokenAlternativeServiceList;
// Store at most 300 MRU SupportsSpdyServerHostPortPairs in memory and disk.
const int kMaxSupportsSpdyServerEntries = 300;
......@@ -263,6 +75,8 @@ const int kMaxAlternateProtocolEntries = 200;
const int kMaxServerNetworkStatsEntries = 200;
// Store at most 200 MRU RecentlyBrokenAlternativeServices in memory and disk.
// This ideally would be with the other constants in HttpServerProperties, but
// has to go here instead of prevent a circular dependency.
const int kMaxRecentlyBrokenAlternativeServiceEntries = 200;
// Store at most 5 MRU QUIC servers by default. This is mainly used by cronet.
......@@ -292,21 +106,10 @@ class ServerNetworkStatsMap
kMaxServerNetworkStatsEntries) {}
};
// Stores how many times an alternative service has been marked broken.
class RecentlyBrokenAlternativeServices
: public base::MRUCache<AlternativeService, int> {
public:
RecentlyBrokenAlternativeServices()
: base::MRUCache<AlternativeService, int>(
kMaxRecentlyBrokenAlternativeServiceEntries) {}
};
// Max number of quic servers to store is not hardcoded and can be set.
// Because of this, QuicServerInfoMap will not be a subclass of MRUCache.
typedef base::MRUCache<quic::QuicServerId, std::string> QuicServerInfoMap;
extern const char kAlternativeServiceHeader[];
// The interface for setting/retrieving the HTTP server properties.
// Currently, this class manages servers':
// * HTTP/2 support;
......
......@@ -50,7 +50,9 @@ HttpServerPropertiesImpl::HttpServerPropertiesImpl(
net_log,
tick_clock_)
: nullptr),
broken_alternative_services_(this, tick_clock_),
broken_alternative_services_(kMaxRecentlyBrokenAlternativeServiceEntries,
this,
tick_clock_),
canonical_suffixes_({".ggpht.com", ".c.youtube.com", ".googlevideo.com",
".googleusercontent.com"}),
quic_server_info_map_(kDefaultMaxQuicServerEntries),
......
......@@ -218,7 +218,8 @@ void HttpServerPropertiesManager::ReadPrefs(
*broken_alternative_service_list =
std::make_unique<BrokenAlternativeServiceList>();
*recently_broken_alternative_services =
std::make_unique<RecentlyBrokenAlternativeServices>();
std::make_unique<RecentlyBrokenAlternativeServices>(
kMaxRecentlyBrokenAlternativeServiceEntries);
// Iterate list in reverse-MRU order
for (auto it = broken_alt_svc_list->end();
......
......@@ -15,6 +15,8 @@
#include "base/sequence_checker.h"
#include "net/base/host_port_pair.h"
#include "net/base/net_export.h"
#include "net/http/alternative_service.h"
#include "net/http/broken_alternative_services.h"
#include "net/http/http_server_properties.h"
#include "net/log/net_log_with_source.h"
......
......@@ -40,6 +40,10 @@
namespace net {
namespace {
const char kAlternativeServiceHeader[] = "Alt-Svc";
} // namespace
HttpStreamFactory::HttpStreamFactory(HttpNetworkSession* session)
: session_(session), job_factory_(std::make_unique<JobFactory>()) {}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment