123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- // 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/check_op.h"
- #include "base/metrics/histogram_macros.h"
- #include "base/metrics/histogram_macros_local.h"
- #include "base/notreached.h"
- #include "base/strings/stringprintf.h"
- #include "net/base/port_util.h"
- #include "net/third_party/quiche/src/quiche/quic/core/http/spdy_utils.h"
- namespace net {
- void HistogramAlternateProtocolUsage(AlternateProtocolUsage usage,
- bool is_google_host) {
- UMA_HISTOGRAM_ENUMERATION("Net.AlternateProtocolUsage", usage,
- ALTERNATE_PROTOCOL_USAGE_MAX);
- if (is_google_host) {
- UMA_HISTOGRAM_ENUMERATION("Net.AlternateProtocolUsageGoogle", 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;
- }
- bool IsProtocolEnabled(NextProto protocol,
- bool is_http2_enabled,
- bool is_quic_enabled) {
- switch (protocol) {
- case kProtoUnknown:
- NOTREACHED();
- return false;
- case kProtoHTTP11:
- return true;
- case kProtoHTTP2:
- return is_http2_enabled;
- case kProtoQUIC:
- return is_quic_enabled;
- }
- 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;
- }
- }
- 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;
- }
- AlternativeServiceInfoVector ProcessAlternativeServices(
- const spdy::SpdyAltSvcWireFormat::AlternativeServiceVector&
- alternative_service_vector,
- bool is_http2_enabled,
- bool is_quic_enabled,
- const quic::ParsedQuicVersionVector& supported_quic_versions) {
- // Convert spdy::SpdyAltSvcWireFormat::AlternativeService entries
- // to net::AlternativeServiceInfo.
- AlternativeServiceInfoVector alternative_service_info_vector;
- for (const spdy::SpdyAltSvcWireFormat::AlternativeService&
- alternative_service_entry : alternative_service_vector) {
- if (!IsPortValid(alternative_service_entry.port))
- continue;
- NextProto protocol =
- NextProtoFromString(alternative_service_entry.protocol_id);
- quic::ParsedQuicVersionVector advertised_versions;
- if (protocol == kProtoQUIC) {
- continue; // Ignore legacy QUIC alt-svc advertisements.
- } else if (!IsAlternateProtocolValid(protocol)) {
- quic::ParsedQuicVersion version =
- quic::SpdyUtils::ExtractQuicVersionFromAltSvcEntry(
- alternative_service_entry, supported_quic_versions);
- if (version == quic::ParsedQuicVersion::Unsupported()) {
- continue;
- }
- protocol = kProtoQUIC;
- advertised_versions = {version};
- }
- if (!IsAlternateProtocolValid(protocol) ||
- !IsProtocolEnabled(protocol, is_http2_enabled, is_quic_enabled)) {
- continue;
- }
- AlternativeService alternative_service(protocol,
- alternative_service_entry.host,
- alternative_service_entry.port);
- base::Time expiration =
- base::Time::Now() +
- base::Seconds(alternative_service_entry.max_age_seconds);
- AlternativeServiceInfo alternative_service_info;
- if (protocol == kProtoQUIC) {
- alternative_service_info =
- AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
- alternative_service, expiration, advertised_versions);
- } else {
- alternative_service_info =
- AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
- alternative_service, expiration);
- }
- alternative_service_info_vector.push_back(alternative_service_info);
- }
- return alternative_service_info_vector;
- }
- } // namespace net
|