// 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. #ifndef NET_HTTP_ALTERNATIVE_SERVICE_H_ #define NET_HTTP_ALTERNATIVE_SERVICE_H_ #include #include #include #include #include "base/time/time.h" #include "net/base/host_port_pair.h" #include "net/base/net_export.h" #include "net/http/alternate_protocol_usage.h" #include "net/quic/quic_http_utils.h" #include "net/socket/next_proto.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_versions.h" #include "net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.h" namespace net { // Log a histogram to reflect |usage|. NET_EXPORT void HistogramAlternateProtocolUsage(AlternateProtocolUsage usage, bool is_google_host); enum BrokenAlternateProtocolLocation { BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_JOB = 0, BROKEN_ALTERNATE_PROTOCOL_LOCATION_QUIC_STREAM_FACTORY = 1, BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_JOB_ALT = 2, BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_JOB_MAIN = 3, BROKEN_ALTERNATE_PROTOCOL_LOCATION_QUIC_HTTP_STREAM = 4, BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_NETWORK_TRANSACTION = 5, BROKEN_ALTERNATE_PROTOCOL_LOCATION_MAX, }; // Log a histogram to reflect |location|. NET_EXPORT void HistogramBrokenAlternateProtocolLocation( BrokenAlternateProtocolLocation location); // Returns true if |protocol| is a valid protocol. NET_EXPORT bool IsAlternateProtocolValid(NextProto protocol); // Returns true if |protocol| is enabled, based on |is_http2_enabled| // and |is_quic_enabled|.. NET_EXPORT bool IsProtocolEnabled(NextProto protocol, bool is_http2_enabled, bool is_quic_enabled); // (protocol, host, port) triple as defined in // https://tools.ietf.org/id/draft-ietf-httpbis-alt-svc-06.html // // TODO(mmenke): Seems like most of this stuff should be de-inlined. struct NET_EXPORT AlternativeService { AlternativeService() : protocol(kProtoUnknown), host(), port(0) {} AlternativeService(NextProto protocol, const std::string& host, uint16_t port) : protocol(protocol), host(host), port(port) {} AlternativeService(NextProto protocol, const HostPortPair& host_port_pair) : protocol(protocol), host(host_port_pair.host()), port(host_port_pair.port()) {} AlternativeService(const AlternativeService& alternative_service) = default; AlternativeService& operator=(const AlternativeService& alternative_service) = default; HostPortPair host_port_pair() const { return HostPortPair(host, port); } bool operator==(const AlternativeService& other) const { return protocol == other.protocol && host == other.host && port == other.port; } bool operator!=(const AlternativeService& other) const { return !this->operator==(other); } bool operator<(const AlternativeService& other) const { return std::tie(protocol, host, port) < std::tie(other.protocol, other.host, other.port); } // Output format: "protocol host:port", e.g. "h2 www.google.com:1234". std::string ToString() const; NextProto protocol; std::string host; uint16_t port; }; NET_EXPORT_PRIVATE std::ostream& operator<<( std::ostream& os, const AlternativeService& alternative_service); class NET_EXPORT_PRIVATE AlternativeServiceInfo { public: static AlternativeServiceInfo CreateHttp2AlternativeServiceInfo( const AlternativeService& alternative_service, base::Time expiration); static AlternativeServiceInfo CreateQuicAlternativeServiceInfo( const AlternativeService& alternative_service, base::Time expiration, const quic::ParsedQuicVersionVector& advertised_versions); AlternativeServiceInfo(); ~AlternativeServiceInfo(); AlternativeServiceInfo( const AlternativeServiceInfo& alternative_service_info); AlternativeServiceInfo& operator=( const AlternativeServiceInfo& alternative_service_info); bool operator==(const AlternativeServiceInfo& other) const { return alternative_service_ == other.alternative_service() && expiration_ == other.expiration() && advertised_versions_ == other.advertised_versions(); } bool operator!=(const AlternativeServiceInfo& other) const { return !this->operator==(other); } std::string ToString() const; void set_alternative_service(const AlternativeService& alternative_service) { alternative_service_ = alternative_service; } void set_protocol(const NextProto& protocol) { alternative_service_.protocol = protocol; } void set_host(const std::string& host) { alternative_service_.host = host; } void set_port(uint16_t port) { alternative_service_.port = port; } void set_expiration(const base::Time& expiration) { expiration_ = expiration; } void set_advertised_versions( const quic::ParsedQuicVersionVector& advertised_versions) { if (alternative_service_.protocol != kProtoQUIC) return; advertised_versions_ = advertised_versions; std::sort(advertised_versions_.begin(), advertised_versions_.end(), TransportVersionLessThan); } const AlternativeService& alternative_service() const { return alternative_service_; } NextProto protocol() const { return alternative_service_.protocol; } HostPortPair host_port_pair() const { return alternative_service_.host_port_pair(); } base::Time expiration() const { return expiration_; } const quic::ParsedQuicVersionVector& advertised_versions() const { return advertised_versions_; } private: AlternativeServiceInfo( const AlternativeService& alternative_service, base::Time expiration, const quic::ParsedQuicVersionVector& advertised_versions); static bool TransportVersionLessThan(const quic::ParsedQuicVersion& lhs, const quic::ParsedQuicVersion& rhs); AlternativeService alternative_service_; base::Time expiration_; // Lists all the QUIC versions that are advertised by the server and supported // by Chrome. If empty, defaults to versions used by the current instance of // the netstack. This list is sorted according to the server's preference. quic::ParsedQuicVersionVector advertised_versions_; }; using AlternativeServiceInfoVector = std::vector; NET_EXPORT_PRIVATE AlternativeServiceInfoVector ProcessAlternativeServices( const spdy::SpdyAltSvcWireFormat::AlternativeServiceVector& alternative_service_vector, bool is_http2_enabled, bool is_quic_enabled, const quic::ParsedQuicVersionVector& supported_quic_versions); } // namespace net #endif // NET_HTTP_ALTERNATIVE_SERVICE_H_