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