• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef NET_HTTP_ALTERNATIVE_SERVICE_H_
6 #define NET_HTTP_ALTERNATIVE_SERVICE_H_
7 
8 #include <stdint.h>
9 
10 #include <algorithm>
11 #include <ostream>
12 #include <string>
13 
14 #include "base/time/time.h"
15 #include "net/base/host_port_pair.h"
16 #include "net/base/net_export.h"
17 #include "net/http/alternate_protocol_usage.h"
18 #include "net/quic/quic_http_utils.h"
19 #include "net/socket/next_proto.h"
20 #include "net/third_party/quiche/src/quiche/quic/core/quic_versions.h"
21 #include "net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.h"
22 
23 namespace net {
24 
25 // Log a histogram to reflect |usage|.
26 NET_EXPORT void HistogramAlternateProtocolUsage(AlternateProtocolUsage usage,
27                                                 bool is_google_host);
28 
29 enum BrokenAlternateProtocolLocation {
30   BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_JOB = 0,
31   BROKEN_ALTERNATE_PROTOCOL_LOCATION_QUIC_STREAM_FACTORY = 1,
32   BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_JOB_ALT = 2,
33   BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_JOB_MAIN = 3,
34   BROKEN_ALTERNATE_PROTOCOL_LOCATION_QUIC_HTTP_STREAM = 4,
35   BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_NETWORK_TRANSACTION = 5,
36   BROKEN_ALTERNATE_PROTOCOL_LOCATION_MAX,
37 };
38 
39 // Log a histogram to reflect |location|.
40 NET_EXPORT void HistogramBrokenAlternateProtocolLocation(
41     BrokenAlternateProtocolLocation location);
42 
43 // Returns true if |protocol| is a valid protocol.
44 NET_EXPORT bool IsAlternateProtocolValid(NextProto protocol);
45 
46 // Returns true if |protocol| is enabled, based on |is_http2_enabled|
47 // and |is_quic_enabled|..
48 NET_EXPORT bool IsProtocolEnabled(NextProto protocol,
49                                   bool is_http2_enabled,
50                                   bool is_quic_enabled);
51 
52 // (protocol, host, port) triple as defined in
53 // https://tools.ietf.org/id/draft-ietf-httpbis-alt-svc-06.html
54 //
55 // TODO(mmenke):  Seems like most of this stuff should be de-inlined.
56 struct NET_EXPORT AlternativeService {
AlternativeServiceAlternativeService57   AlternativeService() : protocol(kProtoUnknown), host(), port(0) {}
58 
AlternativeServiceAlternativeService59   AlternativeService(NextProto protocol, const std::string& host, uint16_t port)
60       : protocol(protocol), host(host), port(port) {}
61 
AlternativeServiceAlternativeService62   AlternativeService(NextProto protocol, const HostPortPair& host_port_pair)
63       : protocol(protocol),
64         host(host_port_pair.host()),
65         port(host_port_pair.port()) {}
66 
67   AlternativeService(const AlternativeService& alternative_service) = default;
68   AlternativeService& operator=(const AlternativeService& alternative_service) =
69       default;
70 
host_port_pairAlternativeService71   HostPortPair host_port_pair() const { return HostPortPair(host, port); }
72 
73   bool operator==(const AlternativeService& other) const {
74     return protocol == other.protocol && host == other.host &&
75            port == other.port;
76   }
77 
78   bool operator!=(const AlternativeService& other) const {
79     return !this->operator==(other);
80   }
81 
82   bool operator<(const AlternativeService& other) const {
83     return std::tie(protocol, host, port) <
84            std::tie(other.protocol, other.host, other.port);
85   }
86 
87   // Output format: "protocol host:port", e.g. "h2 www.google.com:1234".
88   std::string ToString() const;
89 
90   NextProto protocol;
91   std::string host;
92   uint16_t port;
93 };
94 
95 NET_EXPORT_PRIVATE std::ostream& operator<<(
96     std::ostream& os,
97     const AlternativeService& alternative_service);
98 
99 class NET_EXPORT_PRIVATE AlternativeServiceInfo {
100  public:
101   static AlternativeServiceInfo CreateHttp2AlternativeServiceInfo(
102       const AlternativeService& alternative_service,
103       base::Time expiration);
104 
105   static AlternativeServiceInfo CreateQuicAlternativeServiceInfo(
106       const AlternativeService& alternative_service,
107       base::Time expiration,
108       const quic::ParsedQuicVersionVector& advertised_versions);
109 
110   AlternativeServiceInfo();
111   ~AlternativeServiceInfo();
112 
113   AlternativeServiceInfo(
114       const AlternativeServiceInfo& alternative_service_info);
115 
116   AlternativeServiceInfo& operator=(
117       const AlternativeServiceInfo& alternative_service_info);
118 
119   bool operator==(const AlternativeServiceInfo& other) const {
120     return alternative_service_ == other.alternative_service() &&
121            expiration_ == other.expiration() &&
122            advertised_versions_ == other.advertised_versions();
123   }
124 
125   bool operator!=(const AlternativeServiceInfo& other) const {
126     return !this->operator==(other);
127   }
128 
129   std::string ToString() const;
130 
set_alternative_service(const AlternativeService & alternative_service)131   void set_alternative_service(const AlternativeService& alternative_service) {
132     alternative_service_ = alternative_service;
133   }
134 
set_protocol(const NextProto & protocol)135   void set_protocol(const NextProto& protocol) {
136     alternative_service_.protocol = protocol;
137   }
138 
set_host(const std::string & host)139   void set_host(const std::string& host) { alternative_service_.host = host; }
140 
set_port(uint16_t port)141   void set_port(uint16_t port) { alternative_service_.port = port; }
142 
set_expiration(const base::Time & expiration)143   void set_expiration(const base::Time& expiration) {
144     expiration_ = expiration;
145   }
146 
set_advertised_versions(const quic::ParsedQuicVersionVector & advertised_versions)147   void set_advertised_versions(
148       const quic::ParsedQuicVersionVector& advertised_versions) {
149     if (alternative_service_.protocol != kProtoQUIC)
150       return;
151 
152     advertised_versions_ = advertised_versions;
153     std::sort(advertised_versions_.begin(), advertised_versions_.end(),
154               TransportVersionLessThan);
155   }
156 
alternative_service()157   const AlternativeService& alternative_service() const {
158     return alternative_service_;
159   }
160 
protocol()161   NextProto protocol() const { return alternative_service_.protocol; }
162 
host_port_pair()163   HostPortPair host_port_pair() const {
164     return alternative_service_.host_port_pair();
165   }
166 
expiration()167   base::Time expiration() const { return expiration_; }
168 
advertised_versions()169   const quic::ParsedQuicVersionVector& advertised_versions() const {
170     return advertised_versions_;
171   }
172 
173  private:
174   AlternativeServiceInfo(
175       const AlternativeService& alternative_service,
176       base::Time expiration,
177       const quic::ParsedQuicVersionVector& advertised_versions);
178 
179   static bool TransportVersionLessThan(const quic::ParsedQuicVersion& lhs,
180                                        const quic::ParsedQuicVersion& rhs);
181 
182   AlternativeService alternative_service_;
183   base::Time expiration_;
184 
185   // Lists all the QUIC versions that are advertised by the server and supported
186   // by Chrome. If empty, defaults to versions used by the current instance of
187   // the netstack. This list is sorted according to the server's preference.
188   quic::ParsedQuicVersionVector advertised_versions_;
189 };
190 
191 using AlternativeServiceInfoVector = std::vector<AlternativeServiceInfo>;
192 
193 NET_EXPORT_PRIVATE AlternativeServiceInfoVector ProcessAlternativeServices(
194     const spdy::SpdyAltSvcWireFormat::AlternativeServiceVector&
195         alternative_service_vector,
196     bool is_http2_enabled,
197     bool is_quic_enabled,
198     const quic::ParsedQuicVersionVector& supported_quic_versions);
199 
200 }  // namespace net
201 
202 #endif  // NET_HTTP_ALTERNATIVE_SERVICE_H_
203