blob: 6a8cfa6ffe9ead5d9f286eed4ff328498720191e [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/http/http_stream_factory.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/time/time.h"
#include "net/base/host_mapping_rules.h"
#include "net/base/host_port_pair.h"
#include "net/base/parse_number.h"
#include "net/base/port_util.h"
#include "net/http/http_network_session.h"
#include "net/http/http_response_headers.h"
#include "net/quic/chromium/quic_http_utils.h"
#include "net/quic/core/quic_packets.h"
#include "net/spdy/core/spdy_alt_svc_wire_format.h"
#include "url/gurl.h"
namespace net {
HttpStreamFactory::~HttpStreamFactory() {}
void HttpStreamFactory::ProcessAlternativeServices(
HttpNetworkSession* session,
const HttpResponseHeaders* headers,
const url::SchemeHostPort& http_server) {
if (!headers->HasHeader(kAlternativeServiceHeader))
return;
std::string alternative_service_str;
headers->GetNormalizedHeader(kAlternativeServiceHeader,
&alternative_service_str);
SpdyAltSvcWireFormat::AlternativeServiceVector alternative_service_vector;
if (!SpdyAltSvcWireFormat::ParseHeaderFieldValue(
alternative_service_str, &alternative_service_vector)) {
return;
}
// Convert SpdyAltSvcWireFormat::AlternativeService entries
// to net::AlternativeServiceInfo.
AlternativeServiceInfoVector alternative_service_info_vector;
for (const SpdyAltSvcWireFormat::AlternativeService&
alternative_service_entry : alternative_service_vector) {
NextProto protocol =
NextProtoFromString(alternative_service_entry.protocol_id);
if (!IsAlternateProtocolValid(protocol) ||
!session->IsProtocolEnabled(protocol) ||
!IsPortValid(alternative_service_entry.port)) {
continue;
}
// Check if QUIC version is supported. Filter supported QUIC versions.
QuicTransportVersionVector advertised_versions;
if (protocol == kProtoQUIC && !alternative_service_entry.version.empty()) {
advertised_versions = FilterSupportedAltSvcVersions(
alternative_service_entry, session->params().quic_supported_versions,
session->params().support_ietf_format_quic_altsvc);
if (advertised_versions.empty())
continue;
}
AlternativeService alternative_service(protocol,
alternative_service_entry.host,
alternative_service_entry.port);
base::Time expiration =
base::Time::Now() +
base::TimeDelta::FromSeconds(alternative_service_entry.max_age);
AlternativeServiceInfo alternative_service_info;
if (protocol == kProtoQUIC) {
alternative_service_info =
AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
alternative_service, expiration, advertised_versions);
} else {
alternative_service_info =
AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
alternative_service, expiration);
}
alternative_service_info_vector.push_back(alternative_service_info);
}
session->http_server_properties()->SetAlternativeServices(
RewriteHost(http_server), alternative_service_info_vector);
}
HttpStreamFactory::HttpStreamFactory() {}
url::SchemeHostPort HttpStreamFactory::RewriteHost(
const url::SchemeHostPort& server) {
HostPortPair host_port_pair(server.host(), server.port());
const HostMappingRules* mapping_rules = GetHostMappingRules();
if (mapping_rules)
mapping_rules->RewriteHost(&host_port_pair);
return url::SchemeHostPort(server.scheme(), host_port_pair.host(),
host_port_pair.port());
}
} // namespace net