mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2024-11-26 15:26:10 +03:00
189 lines
6.5 KiB
C++
189 lines
6.5 KiB
C++
|
// Copyright 2012 The Chromium Authors
|
||
|
// 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
|