summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorxunjieli <xunjieli@chromium.org>2016-03-21 20:39:51 -0700
committerCommit bot <commit-bot@chromium.org>2016-03-22 03:42:17 +0000
commitb3a648e3abbf08d0b08ba9cf1b273ef0e960b748 (patch)
tree1a886f5642fd0cd3d2846eb2d30d4730f7755f62 /net
parented6ca6fe46c2f728192b5492ce67362181a47280 (diff)
downloadchromium_src-b3a648e3abbf08d0b08ba9cf1b273ef0e960b748.zip
chromium_src-b3a648e3abbf08d0b08ba9cf1b273ef0e960b748.tar.gz
chromium_src-b3a648e3abbf08d0b08ba9cf1b273ef0e960b748.tar.bz2
Process Alternative Service headers in net::BidirectionalStream
This CL adds processing of alternative service headers to net::BidirectionalStream, so that protocols advertised in alternative service headers can be discovered. BUG=584338 Review URL: https://codereview.chromium.org/1817583002 Cr-Commit-Position: refs/heads/master@{#382501}
Diffstat (limited to 'net')
-rw-r--r--net/http/bidirectional_stream.cc13
-rw-r--r--net/http/bidirectional_stream.h2
-rw-r--r--net/http/bidirectional_stream_unittest.cc68
-rw-r--r--net/http/http_network_transaction.cc42
-rw-r--r--net/http/http_stream_factory.cc70
-rw-r--r--net/http/http_stream_factory.h27
-rw-r--r--net/spdy/spdy_test_util_common.cc3
-rw-r--r--net/spdy/spdy_test_util_common.h1
8 files changed, 159 insertions, 67 deletions
diff --git a/net/http/bidirectional_stream.cc b/net/http/bidirectional_stream.cc
index cacb084..d9b04e0 100644
--- a/net/http/bidirectional_stream.cc
+++ b/net/http/bidirectional_stream.cc
@@ -15,7 +15,9 @@
#include "net/base/net_errors.h"
#include "net/http/bidirectional_stream_request_info.h"
#include "net/http/http_network_session.h"
+#include "net/http/http_response_headers.h"
#include "net/http/http_stream.h"
+#include "net/spdy/spdy_http_utils.h"
#include "net/ssl/ssl_cert_request_info.h"
#include "net/ssl/ssl_config.h"
#include "url/gurl.h"
@@ -43,6 +45,7 @@ BidirectionalStream::BidirectionalStream(
: request_info_(std::move(request_info)),
net_log_(BoundNetLog::Make(session->net_log(),
NetLog::SOURCE_BIDIRECTIONAL_STREAM)),
+ session_(session),
delegate_(delegate),
timer_(std::move(timer)) {
DCHECK(delegate_);
@@ -129,6 +132,16 @@ void BidirectionalStream::OnHeadersSent() {
void BidirectionalStream::OnHeadersReceived(
const SpdyHeaderBlock& response_headers) {
+ HttpResponseInfo response_info;
+ if (!SpdyHeadersToHttpResponse(response_headers, HTTP2, &response_info)) {
+ DLOG(WARNING) << "Invalid headers";
+ delegate_->OnFailed(ERR_FAILED);
+ return;
+ }
+
+ session_->http_stream_factory()->ProcessAlternativeServices(
+ session_, response_info.headers.get(),
+ HostPortPair::FromURL(request_info_->url));
delegate_->OnHeadersReceived(response_headers);
}
diff --git a/net/http/bidirectional_stream.h b/net/http/bidirectional_stream.h
index 0cb3a15..78aeeaf 100644
--- a/net/http/bidirectional_stream.h
+++ b/net/http/bidirectional_stream.h
@@ -187,6 +187,8 @@ class NET_EXPORT BidirectionalStream
scoped_ptr<BidirectionalStreamRequestInfo> request_info_;
const BoundNetLog net_log_;
+ HttpNetworkSession* session_;
+
Delegate* const delegate_;
// Timer used to buffer data received in short time-spans and send a single
diff --git a/net/http/bidirectional_stream_unittest.cc b/net/http/bidirectional_stream_unittest.cc
index a3bc810..6d4cb81 100644
--- a/net/http/bidirectional_stream_unittest.cc
+++ b/net/http/bidirectional_stream_unittest.cc
@@ -16,6 +16,7 @@
#include "net/http/bidirectional_stream_request_info.h"
#include "net/http/http_network_session.h"
#include "net/http/http_response_headers.h"
+#include "net/http/http_server_properties.h"
#include "net/log/net_log.h"
#include "net/socket/socket_test_util.h"
#include "net/spdy/spdy_session.h"
@@ -1195,4 +1196,71 @@ TEST_P(BidirectionalStreamTest, CancelOrDeleteStreamDuringOnFailed) {
EXPECT_EQ(kProtoUnknown, delegate->GetProtocol());
}
+TEST_F(BidirectionalStreamTest, TestHonorAlternativeServiceHeader) {
+ scoped_ptr<SpdyFrame> req(
+ spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
+ // Empty DATA frame with an END_STREAM flag.
+ scoped_ptr<SpdyFrame> end_stream(
+ spdy_util_.ConstructSpdyBodyFrame(1, nullptr, 0, true));
+
+ MockWrite writes[] = {CreateMockWrite(*req.get(), 0)};
+
+ std::string alt_svc_header_value = AlternateProtocolToString(QUIC);
+ alt_svc_header_value.append("=\"www.example.org:443\"");
+ const char* const kExtraResponseHeaders[] = {"alt-svc",
+ alt_svc_header_value.c_str()};
+
+ scoped_ptr<SpdyFrame> resp(
+ spdy_util_.ConstructSpdyGetSynReply(kExtraResponseHeaders, 1, 1));
+ scoped_ptr<SpdyFrame> body_frame(spdy_util_.ConstructSpdyBodyFrame(1, true));
+
+ MockRead reads[] = {
+ CreateMockRead(*resp, 1), CreateMockRead(*body_frame, 2),
+ MockRead(SYNCHRONOUS, 0, 3),
+ };
+
+ HostPortPair host_port_pair("www.example.org", 443);
+ SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
+ PRIVACY_MODE_DISABLED);
+ session_deps_.parse_alternative_services = true;
+ // Enable QUIC so that the alternative service header can be added to
+ // HttpServerProperties.
+ session_deps_.enable_quic = true;
+ InitSession(reads, arraysize(reads), writes, arraysize(writes), key);
+
+ scoped_ptr<BidirectionalStreamRequestInfo> request_info(
+ new BidirectionalStreamRequestInfo);
+ request_info->method = "GET";
+ request_info->url = GURL("https://www.example.org/");
+ request_info->priority = LOWEST;
+ request_info->end_stream_on_headers = true;
+
+ scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
+ MockTimer* timer = new MockTimer();
+ scoped_ptr<TestDelegateBase> delegate(new TestDelegateBase(
+ read_buffer.get(), kReadBufferSize, make_scoped_ptr(timer)));
+ delegate->SetRunUntilCompletion(true);
+ delegate->Start(std::move(request_info), http_session_.get());
+
+ const SpdyHeaderBlock response_headers = delegate->response_headers();
+ EXPECT_EQ("200", response_headers.find(":status")->second);
+ EXPECT_EQ(alt_svc_header_value, response_headers.find("alt-svc")->second);
+ EXPECT_EQ(0, delegate->on_data_sent_count());
+ EXPECT_EQ(kProtoHTTP2, delegate->GetProtocol());
+ EXPECT_EQ(kUploadData, delegate->data_received());
+ EXPECT_EQ(CountWriteBytes(writes, arraysize(writes)),
+ delegate->GetTotalSentBytes());
+ EXPECT_EQ(CountReadBytes(reads, arraysize(reads)),
+ delegate->GetTotalReceivedBytes());
+
+ AlternativeServiceVector alternative_service_vector =
+ http_session_->http_server_properties()->GetAlternativeServices(
+ host_port_pair);
+ ASSERT_EQ(1u, alternative_service_vector.size());
+ EXPECT_EQ(AlternateProtocolFromNextProto(kProtoQUIC1SPDY3),
+ alternative_service_vector[0].protocol);
+ EXPECT_EQ("www.example.org", alternative_service_vector[0].host);
+ EXPECT_EQ(443, alternative_service_vector[0].port);
+}
+
} // namespace net
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index 14da6c7..41c1acf 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -71,44 +71,6 @@ namespace net {
namespace {
-void ProcessAlternativeServices(HttpNetworkSession* session,
- const HttpResponseHeaders& headers,
- const HostPortPair& http_host_port_pair) {
- if (session->params().parse_alternative_services) {
- if (headers.HasHeader(kAlternativeServiceHeader)) {
- std::string alternative_service_str;
- headers.GetNormalizedHeader(kAlternativeServiceHeader,
- &alternative_service_str);
- session->http_stream_factory()->ProcessAlternativeService(
- session->http_server_properties(), alternative_service_str,
- http_host_port_pair, *session);
- }
- // If "Alt-Svc" is enabled, then ignore "Alternate-Protocol".
- return;
- }
-
- if (!headers.HasHeader(kAlternateProtocolHeader))
- return;
-
- std::vector<std::string> alternate_protocol_values;
- size_t iter = 0;
- std::string alternate_protocol_str;
- while (headers.EnumerateHeader(&iter, kAlternateProtocolHeader,
- &alternate_protocol_str)) {
- base::TrimWhitespaceASCII(alternate_protocol_str, base::TRIM_ALL,
- &alternate_protocol_str);
- if (!alternate_protocol_str.empty()) {
- alternate_protocol_values.push_back(alternate_protocol_str);
- }
- }
-
- session->http_stream_factory()->ProcessAlternateProtocol(
- session->http_server_properties(),
- alternate_protocol_values,
- http_host_port_pair,
- *session);
-}
-
scoped_ptr<base::Value> NetLogSSLVersionFallbackCallback(
const GURL* url,
int net_error,
@@ -1238,8 +1200,8 @@ int HttpNetworkTransaction::DoReadHeadersComplete(int result) {
return OK;
}
- ProcessAlternativeServices(session_, *response_.headers.get(),
- HostPortPair::FromURL(request_->url));
+ session_->http_stream_factory()->ProcessAlternativeServices(
+ session_, response_.headers.get(), HostPortPair::FromURL(request_->url));
int rv = HandleAuthChallenge();
if (rv != OK)
diff --git a/net/http/http_stream_factory.cc b/net/http/http_stream_factory.cc
index f61a317..6ea3224 100644
--- a/net/http/http_stream_factory.cc
+++ b/net/http/http_stream_factory.cc
@@ -13,6 +13,7 @@
#include "net/base/host_port_pair.h"
#include "net/base/port_util.h"
#include "net/http/http_network_session.h"
+#include "net/http/http_response_headers.h"
#include "net/quic/quic_protocol.h"
#include "net/spdy/spdy_alt_svc_wire_format.h"
#include "url/gurl.h"
@@ -32,6 +33,59 @@ void HttpStreamFactory::ResetStaticSettingsToInit() {
spdy_enabled_ = true;
}
+void HttpStreamFactory::ProcessAlternativeServices(
+ HttpNetworkSession* session,
+ const HttpResponseHeaders* headers,
+ const HostPortPair& http_host_port_pair) {
+ if (session->params().parse_alternative_services) {
+ if (headers->HasHeader(kAlternativeServiceHeader)) {
+ std::string alternative_service_str;
+ headers->GetNormalizedHeader(kAlternativeServiceHeader,
+ &alternative_service_str);
+ ProcessAlternativeService(session->http_server_properties(),
+ alternative_service_str, http_host_port_pair,
+ *session);
+ }
+ // If "Alt-Svc" is enabled, then ignore "Alternate-Protocol".
+ return;
+ }
+
+ if (!headers->HasHeader(kAlternateProtocolHeader))
+ return;
+
+ std::vector<std::string> alternate_protocol_values;
+ size_t iter = 0;
+ std::string alternate_protocol_str;
+ while (headers->EnumerateHeader(&iter, kAlternateProtocolHeader,
+ &alternate_protocol_str)) {
+ base::TrimWhitespaceASCII(alternate_protocol_str, base::TRIM_ALL,
+ &alternate_protocol_str);
+ if (!alternate_protocol_str.empty()) {
+ alternate_protocol_values.push_back(alternate_protocol_str);
+ }
+ }
+
+ ProcessAlternateProtocol(session->http_server_properties(),
+ alternate_protocol_values, http_host_port_pair,
+ *session);
+}
+
+GURL HttpStreamFactory::ApplyHostMappingRules(const GURL& url,
+ HostPortPair* endpoint) {
+ const HostMappingRules* mapping_rules = GetHostMappingRules();
+ if (mapping_rules && mapping_rules->RewriteHost(endpoint)) {
+ url::Replacements<char> replacements;
+ const std::string port_str = base::UintToString(endpoint->port());
+ replacements.SetPort(port_str.c_str(), url::Component(0, port_str.size()));
+ replacements.SetHost(endpoint->host().c_str(),
+ url::Component(0, endpoint->host().size()));
+ return url.ReplaceComponents(replacements);
+ }
+ return url;
+}
+
+HttpStreamFactory::HttpStreamFactory() {}
+
void HttpStreamFactory::ProcessAlternativeService(
const base::WeakPtr<HttpServerProperties>& http_server_properties,
base::StringPiece alternative_service_str,
@@ -146,22 +200,6 @@ void HttpStreamFactory::ProcessAlternateProtocol(
base::Time::Now() + base::TimeDelta::FromDays(30));
}
-GURL HttpStreamFactory::ApplyHostMappingRules(const GURL& url,
- HostPortPair* endpoint) {
- const HostMappingRules* mapping_rules = GetHostMappingRules();
- if (mapping_rules && mapping_rules->RewriteHost(endpoint)) {
- url::Replacements<char> replacements;
- const std::string port_str = base::UintToString(endpoint->port());
- replacements.SetPort(port_str.c_str(), url::Component(0, port_str.size()));
- replacements.SetHost(endpoint->host().c_str(),
- url::Component(0, endpoint->host().size()));
- return url.ReplaceComponents(replacements);
- }
- return url;
-}
-
-HttpStreamFactory::HttpStreamFactory() {}
-
HostPortPair HttpStreamFactory::RewriteHost(HostPortPair host_port_pair) {
const HostMappingRules* mapping_rules = GetHostMappingRules();
if (mapping_rules)
diff --git a/net/http/http_stream_factory.h b/net/http/http_stream_factory.h
index f47ada1..e207a86 100644
--- a/net/http/http_stream_factory.h
+++ b/net/http/http_stream_factory.h
@@ -38,6 +38,7 @@ class HostMappingRules;
class HostPortPair;
class HttpAuthController;
class HttpNetworkSession;
+class HttpResponseHeaders;
class HttpResponseInfo;
class HttpServerProperties;
class HttpStream;
@@ -200,17 +201,9 @@ class NET_EXPORT HttpStreamFactory {
public:
virtual ~HttpStreamFactory();
- void ProcessAlternativeService(
- const base::WeakPtr<HttpServerProperties>& http_server_properties,
- base::StringPiece alternative_service_str,
- const HostPortPair& http_host_port_pair,
- const HttpNetworkSession& session);
-
- void ProcessAlternateProtocol(
- const base::WeakPtr<HttpServerProperties>& http_server_properties,
- const std::vector<std::string>& alternate_protocol_values,
- const HostPortPair& http_host_port_pair,
- const HttpNetworkSession& session);
+ void ProcessAlternativeServices(HttpNetworkSession* session,
+ const HttpResponseHeaders* headers,
+ const HostPortPair& http_host_port_pair);
GURL ApplyHostMappingRules(const GURL& url, HostPortPair* endpoint);
@@ -274,6 +267,18 @@ class NET_EXPORT HttpStreamFactory {
HttpStreamFactory();
private:
+ void ProcessAlternativeService(
+ const base::WeakPtr<HttpServerProperties>& http_server_properties,
+ base::StringPiece alternative_service_str,
+ const HostPortPair& http_host_port_pair,
+ const HttpNetworkSession& session);
+
+ void ProcessAlternateProtocol(
+ const base::WeakPtr<HttpServerProperties>& http_server_properties,
+ const std::vector<std::string>& alternate_protocol_values,
+ const HostPortPair& http_host_port_pair,
+ const HttpNetworkSession& session);
+
static bool spdy_enabled_;
HostPortPair RewriteHost(HostPortPair host_port_pair);
diff --git a/net/spdy/spdy_test_util_common.cc b/net/spdy/spdy_test_util_common.cc
index 2a37dab..250819e 100644
--- a/net/spdy/spdy_test_util_common.cc
+++ b/net/spdy/spdy_test_util_common.cc
@@ -342,6 +342,7 @@ SpdySessionDependencies::SpdySessionDependencies(NextProto protocol)
enable_user_alternate_protocol_ports(false),
enable_npn(true),
enable_priority_dependencies(true),
+ enable_quic(false),
protocol(protocol),
session_max_recv_window_size(
SpdySession::GetDefaultInitialWindowSize(protocol)),
@@ -379,6 +380,7 @@ SpdySessionDependencies::SpdySessionDependencies(
enable_user_alternate_protocol_ports(false),
enable_npn(true),
enable_priority_dependencies(true),
+ enable_quic(false),
protocol(protocol),
session_max_recv_window_size(
SpdySession::GetDefaultInitialWindowSize(protocol)),
@@ -428,6 +430,7 @@ HttpNetworkSession::Params SpdySessionDependencies::CreateSessionParams(
params.enable_npn = session_deps->enable_npn;
params.enable_priority_dependencies =
session_deps->enable_priority_dependencies;
+ params.enable_quic = session_deps->enable_quic;
params.spdy_default_protocol = session_deps->protocol;
params.spdy_session_max_recv_window_size =
session_deps->session_max_recv_window_size;
diff --git a/net/spdy/spdy_test_util_common.h b/net/spdy/spdy_test_util_common.h
index 64992a6..f7b4800 100644
--- a/net/spdy/spdy_test_util_common.h
+++ b/net/spdy/spdy_test_util_common.h
@@ -198,6 +198,7 @@ struct SpdySessionDependencies {
bool enable_user_alternate_protocol_ports;
bool enable_npn;
bool enable_priority_dependencies;
+ bool enable_quic;
NextProto protocol;
size_t session_max_recv_window_size;
size_t stream_max_recv_window_size;