xref: /aosp_15_r20/external/cronet/net/http/alternative_service.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "net/http/alternative_service.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include "base/check_op.h"
8*6777b538SAndroid Build Coastguard Worker #include "base/metrics/histogram_macros.h"
9*6777b538SAndroid Build Coastguard Worker #include "base/metrics/histogram_macros_local.h"
10*6777b538SAndroid Build Coastguard Worker #include "base/notreached.h"
11*6777b538SAndroid Build Coastguard Worker #include "base/strings/stringprintf.h"
12*6777b538SAndroid Build Coastguard Worker #include "net/base/port_util.h"
13*6777b538SAndroid Build Coastguard Worker #include "net/third_party/quiche/src/quiche/quic/core/http/spdy_utils.h"
14*6777b538SAndroid Build Coastguard Worker 
15*6777b538SAndroid Build Coastguard Worker namespace net {
16*6777b538SAndroid Build Coastguard Worker 
HistogramAlternateProtocolUsage(AlternateProtocolUsage usage,bool is_google_host)17*6777b538SAndroid Build Coastguard Worker void HistogramAlternateProtocolUsage(AlternateProtocolUsage usage,
18*6777b538SAndroid Build Coastguard Worker                                      bool is_google_host) {
19*6777b538SAndroid Build Coastguard Worker     UMA_HISTOGRAM_ENUMERATION("Net.AlternateProtocolUsage", usage,
20*6777b538SAndroid Build Coastguard Worker                               ALTERNATE_PROTOCOL_USAGE_MAX);
21*6777b538SAndroid Build Coastguard Worker     if (is_google_host) {
22*6777b538SAndroid Build Coastguard Worker       UMA_HISTOGRAM_ENUMERATION("Net.AlternateProtocolUsageGoogle", usage,
23*6777b538SAndroid Build Coastguard Worker                                 ALTERNATE_PROTOCOL_USAGE_MAX);
24*6777b538SAndroid Build Coastguard Worker     }
25*6777b538SAndroid Build Coastguard Worker }
26*6777b538SAndroid Build Coastguard Worker 
HistogramBrokenAlternateProtocolLocation(BrokenAlternateProtocolLocation location)27*6777b538SAndroid Build Coastguard Worker void HistogramBrokenAlternateProtocolLocation(
28*6777b538SAndroid Build Coastguard Worker     BrokenAlternateProtocolLocation location) {
29*6777b538SAndroid Build Coastguard Worker   UMA_HISTOGRAM_ENUMERATION("Net.AlternateProtocolBrokenLocation", location,
30*6777b538SAndroid Build Coastguard Worker                             BROKEN_ALTERNATE_PROTOCOL_LOCATION_MAX);
31*6777b538SAndroid Build Coastguard Worker }
32*6777b538SAndroid Build Coastguard Worker 
IsAlternateProtocolValid(NextProto protocol)33*6777b538SAndroid Build Coastguard Worker bool IsAlternateProtocolValid(NextProto protocol) {
34*6777b538SAndroid Build Coastguard Worker   switch (protocol) {
35*6777b538SAndroid Build Coastguard Worker     case kProtoUnknown:
36*6777b538SAndroid Build Coastguard Worker       return false;
37*6777b538SAndroid Build Coastguard Worker     case kProtoHTTP11:
38*6777b538SAndroid Build Coastguard Worker       return false;
39*6777b538SAndroid Build Coastguard Worker     case kProtoHTTP2:
40*6777b538SAndroid Build Coastguard Worker       return true;
41*6777b538SAndroid Build Coastguard Worker     case kProtoQUIC:
42*6777b538SAndroid Build Coastguard Worker       return true;
43*6777b538SAndroid Build Coastguard Worker   }
44*6777b538SAndroid Build Coastguard Worker   NOTREACHED();
45*6777b538SAndroid Build Coastguard Worker   return false;
46*6777b538SAndroid Build Coastguard Worker }
47*6777b538SAndroid Build Coastguard Worker 
IsProtocolEnabled(NextProto protocol,bool is_http2_enabled,bool is_quic_enabled)48*6777b538SAndroid Build Coastguard Worker bool IsProtocolEnabled(NextProto protocol,
49*6777b538SAndroid Build Coastguard Worker                        bool is_http2_enabled,
50*6777b538SAndroid Build Coastguard Worker                        bool is_quic_enabled) {
51*6777b538SAndroid Build Coastguard Worker   switch (protocol) {
52*6777b538SAndroid Build Coastguard Worker     case kProtoUnknown:
53*6777b538SAndroid Build Coastguard Worker       NOTREACHED();
54*6777b538SAndroid Build Coastguard Worker       return false;
55*6777b538SAndroid Build Coastguard Worker     case kProtoHTTP11:
56*6777b538SAndroid Build Coastguard Worker       return true;
57*6777b538SAndroid Build Coastguard Worker     case kProtoHTTP2:
58*6777b538SAndroid Build Coastguard Worker       return is_http2_enabled;
59*6777b538SAndroid Build Coastguard Worker     case kProtoQUIC:
60*6777b538SAndroid Build Coastguard Worker       return is_quic_enabled;
61*6777b538SAndroid Build Coastguard Worker   }
62*6777b538SAndroid Build Coastguard Worker   NOTREACHED();
63*6777b538SAndroid Build Coastguard Worker   return false;
64*6777b538SAndroid Build Coastguard Worker }
65*6777b538SAndroid Build Coastguard Worker 
66*6777b538SAndroid Build Coastguard Worker // static
67*6777b538SAndroid Build Coastguard Worker AlternativeServiceInfo
CreateHttp2AlternativeServiceInfo(const AlternativeService & alternative_service,base::Time expiration)68*6777b538SAndroid Build Coastguard Worker AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
69*6777b538SAndroid Build Coastguard Worker     const AlternativeService& alternative_service,
70*6777b538SAndroid Build Coastguard Worker     base::Time expiration) {
71*6777b538SAndroid Build Coastguard Worker   DCHECK_EQ(alternative_service.protocol, kProtoHTTP2);
72*6777b538SAndroid Build Coastguard Worker   return AlternativeServiceInfo(alternative_service, expiration,
73*6777b538SAndroid Build Coastguard Worker                                 quic::ParsedQuicVersionVector());
74*6777b538SAndroid Build Coastguard Worker }
75*6777b538SAndroid Build Coastguard Worker 
76*6777b538SAndroid Build Coastguard Worker // static
CreateQuicAlternativeServiceInfo(const AlternativeService & alternative_service,base::Time expiration,const quic::ParsedQuicVersionVector & advertised_versions)77*6777b538SAndroid Build Coastguard Worker AlternativeServiceInfo AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
78*6777b538SAndroid Build Coastguard Worker     const AlternativeService& alternative_service,
79*6777b538SAndroid Build Coastguard Worker     base::Time expiration,
80*6777b538SAndroid Build Coastguard Worker     const quic::ParsedQuicVersionVector& advertised_versions) {
81*6777b538SAndroid Build Coastguard Worker   DCHECK_EQ(alternative_service.protocol, kProtoQUIC);
82*6777b538SAndroid Build Coastguard Worker   return AlternativeServiceInfo(alternative_service, expiration,
83*6777b538SAndroid Build Coastguard Worker                                 advertised_versions);
84*6777b538SAndroid Build Coastguard Worker }
85*6777b538SAndroid Build Coastguard Worker 
AlternativeServiceInfo()86*6777b538SAndroid Build Coastguard Worker AlternativeServiceInfo::AlternativeServiceInfo() : alternative_service_() {}
87*6777b538SAndroid Build Coastguard Worker 
88*6777b538SAndroid Build Coastguard Worker AlternativeServiceInfo::~AlternativeServiceInfo() = default;
89*6777b538SAndroid Build Coastguard Worker 
AlternativeServiceInfo(const AlternativeService & alternative_service,base::Time expiration,const quic::ParsedQuicVersionVector & advertised_versions)90*6777b538SAndroid Build Coastguard Worker AlternativeServiceInfo::AlternativeServiceInfo(
91*6777b538SAndroid Build Coastguard Worker     const AlternativeService& alternative_service,
92*6777b538SAndroid Build Coastguard Worker     base::Time expiration,
93*6777b538SAndroid Build Coastguard Worker     const quic::ParsedQuicVersionVector& advertised_versions)
94*6777b538SAndroid Build Coastguard Worker     : alternative_service_(alternative_service), expiration_(expiration) {
95*6777b538SAndroid Build Coastguard Worker   if (alternative_service_.protocol == kProtoQUIC) {
96*6777b538SAndroid Build Coastguard Worker     advertised_versions_ = advertised_versions;
97*6777b538SAndroid Build Coastguard Worker   }
98*6777b538SAndroid Build Coastguard Worker }
99*6777b538SAndroid Build Coastguard Worker 
100*6777b538SAndroid Build Coastguard Worker AlternativeServiceInfo::AlternativeServiceInfo(
101*6777b538SAndroid Build Coastguard Worker     const AlternativeServiceInfo& alternative_service_info) = default;
102*6777b538SAndroid Build Coastguard Worker 
103*6777b538SAndroid Build Coastguard Worker AlternativeServiceInfo& AlternativeServiceInfo::operator=(
104*6777b538SAndroid Build Coastguard Worker     const AlternativeServiceInfo& alternative_service_info) = default;
105*6777b538SAndroid Build Coastguard Worker 
ToString() const106*6777b538SAndroid Build Coastguard Worker std::string AlternativeService::ToString() const {
107*6777b538SAndroid Build Coastguard Worker   return base::StringPrintf("%s %s:%d", NextProtoToString(protocol),
108*6777b538SAndroid Build Coastguard Worker                             host.c_str(), port);
109*6777b538SAndroid Build Coastguard Worker }
110*6777b538SAndroid Build Coastguard Worker 
ToString() const111*6777b538SAndroid Build Coastguard Worker std::string AlternativeServiceInfo::ToString() const {
112*6777b538SAndroid Build Coastguard Worker   // NOTE: Cannot use `base::UnlocalizedTimeFormatWithPattern()` since
113*6777b538SAndroid Build Coastguard Worker   // `net/DEPS` disallows `base/i18n`.
114*6777b538SAndroid Build Coastguard Worker   base::Time::Exploded exploded;
115*6777b538SAndroid Build Coastguard Worker   expiration_.LocalExplode(&exploded);
116*6777b538SAndroid Build Coastguard Worker   return base::StringPrintf(
117*6777b538SAndroid Build Coastguard Worker       "%s, expires %04d-%02d-%02d %02d:%02d:%02d",
118*6777b538SAndroid Build Coastguard Worker       alternative_service_.ToString().c_str(), exploded.year, exploded.month,
119*6777b538SAndroid Build Coastguard Worker       exploded.day_of_month, exploded.hour, exploded.minute, exploded.second);
120*6777b538SAndroid Build Coastguard Worker }
121*6777b538SAndroid Build Coastguard Worker 
122*6777b538SAndroid Build Coastguard Worker // static
TransportVersionLessThan(const quic::ParsedQuicVersion & lhs,const quic::ParsedQuicVersion & rhs)123*6777b538SAndroid Build Coastguard Worker bool AlternativeServiceInfo::TransportVersionLessThan(
124*6777b538SAndroid Build Coastguard Worker     const quic::ParsedQuicVersion& lhs,
125*6777b538SAndroid Build Coastguard Worker     const quic::ParsedQuicVersion& rhs) {
126*6777b538SAndroid Build Coastguard Worker   return lhs.transport_version < rhs.transport_version;
127*6777b538SAndroid Build Coastguard Worker }
128*6777b538SAndroid Build Coastguard Worker 
operator <<(std::ostream & os,const AlternativeService & alternative_service)129*6777b538SAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os,
130*6777b538SAndroid Build Coastguard Worker                          const AlternativeService& alternative_service) {
131*6777b538SAndroid Build Coastguard Worker   os << alternative_service.ToString();
132*6777b538SAndroid Build Coastguard Worker   return os;
133*6777b538SAndroid Build Coastguard Worker }
134*6777b538SAndroid Build Coastguard Worker 
ProcessAlternativeServices(const spdy::SpdyAltSvcWireFormat::AlternativeServiceVector & alternative_service_vector,bool is_http2_enabled,bool is_quic_enabled,const quic::ParsedQuicVersionVector & supported_quic_versions)135*6777b538SAndroid Build Coastguard Worker AlternativeServiceInfoVector ProcessAlternativeServices(
136*6777b538SAndroid Build Coastguard Worker     const spdy::SpdyAltSvcWireFormat::AlternativeServiceVector&
137*6777b538SAndroid Build Coastguard Worker         alternative_service_vector,
138*6777b538SAndroid Build Coastguard Worker     bool is_http2_enabled,
139*6777b538SAndroid Build Coastguard Worker     bool is_quic_enabled,
140*6777b538SAndroid Build Coastguard Worker     const quic::ParsedQuicVersionVector& supported_quic_versions) {
141*6777b538SAndroid Build Coastguard Worker   // Convert spdy::SpdyAltSvcWireFormat::AlternativeService entries
142*6777b538SAndroid Build Coastguard Worker   // to net::AlternativeServiceInfo.
143*6777b538SAndroid Build Coastguard Worker   AlternativeServiceInfoVector alternative_service_info_vector;
144*6777b538SAndroid Build Coastguard Worker   for (const spdy::SpdyAltSvcWireFormat::AlternativeService&
145*6777b538SAndroid Build Coastguard Worker            alternative_service_entry : alternative_service_vector) {
146*6777b538SAndroid Build Coastguard Worker     if (!IsPortValid(alternative_service_entry.port))
147*6777b538SAndroid Build Coastguard Worker       continue;
148*6777b538SAndroid Build Coastguard Worker 
149*6777b538SAndroid Build Coastguard Worker     NextProto protocol =
150*6777b538SAndroid Build Coastguard Worker         NextProtoFromString(alternative_service_entry.protocol_id);
151*6777b538SAndroid Build Coastguard Worker     quic::ParsedQuicVersionVector advertised_versions;
152*6777b538SAndroid Build Coastguard Worker     if (protocol == kProtoQUIC) {
153*6777b538SAndroid Build Coastguard Worker       continue;  // Ignore legacy QUIC alt-svc advertisements.
154*6777b538SAndroid Build Coastguard Worker     } else if (!IsAlternateProtocolValid(protocol)) {
155*6777b538SAndroid Build Coastguard Worker       quic::ParsedQuicVersion version =
156*6777b538SAndroid Build Coastguard Worker           quic::SpdyUtils::ExtractQuicVersionFromAltSvcEntry(
157*6777b538SAndroid Build Coastguard Worker               alternative_service_entry, supported_quic_versions);
158*6777b538SAndroid Build Coastguard Worker       if (version == quic::ParsedQuicVersion::Unsupported()) {
159*6777b538SAndroid Build Coastguard Worker         continue;
160*6777b538SAndroid Build Coastguard Worker       }
161*6777b538SAndroid Build Coastguard Worker       protocol = kProtoQUIC;
162*6777b538SAndroid Build Coastguard Worker       advertised_versions = {version};
163*6777b538SAndroid Build Coastguard Worker     }
164*6777b538SAndroid Build Coastguard Worker     if (!IsAlternateProtocolValid(protocol) ||
165*6777b538SAndroid Build Coastguard Worker         !IsProtocolEnabled(protocol, is_http2_enabled, is_quic_enabled)) {
166*6777b538SAndroid Build Coastguard Worker       continue;
167*6777b538SAndroid Build Coastguard Worker     }
168*6777b538SAndroid Build Coastguard Worker 
169*6777b538SAndroid Build Coastguard Worker     AlternativeService alternative_service(protocol,
170*6777b538SAndroid Build Coastguard Worker                                            alternative_service_entry.host,
171*6777b538SAndroid Build Coastguard Worker                                            alternative_service_entry.port);
172*6777b538SAndroid Build Coastguard Worker     base::Time expiration =
173*6777b538SAndroid Build Coastguard Worker         base::Time::Now() +
174*6777b538SAndroid Build Coastguard Worker         base::Seconds(alternative_service_entry.max_age_seconds);
175*6777b538SAndroid Build Coastguard Worker     AlternativeServiceInfo alternative_service_info;
176*6777b538SAndroid Build Coastguard Worker     if (protocol == kProtoQUIC) {
177*6777b538SAndroid Build Coastguard Worker       alternative_service_info =
178*6777b538SAndroid Build Coastguard Worker           AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
179*6777b538SAndroid Build Coastguard Worker               alternative_service, expiration, advertised_versions);
180*6777b538SAndroid Build Coastguard Worker     } else {
181*6777b538SAndroid Build Coastguard Worker       alternative_service_info =
182*6777b538SAndroid Build Coastguard Worker           AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
183*6777b538SAndroid Build Coastguard Worker               alternative_service, expiration);
184*6777b538SAndroid Build Coastguard Worker     }
185*6777b538SAndroid Build Coastguard Worker     alternative_service_info_vector.push_back(alternative_service_info);
186*6777b538SAndroid Build Coastguard Worker   }
187*6777b538SAndroid Build Coastguard Worker   return alternative_service_info_vector;
188*6777b538SAndroid Build Coastguard Worker }
189*6777b538SAndroid Build Coastguard Worker 
190*6777b538SAndroid Build Coastguard Worker }  // namespace net
191