blob: 4028bbcb6c4a5852d520581e1e5dcb4cfc17158a [file] [log] [blame]
// 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 <stdint.h>
#include <algorithm>
#include <ostream>
#include <string>
#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_SESSION_POOL = 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<AlternativeServiceInfo>;
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_