summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwillchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-10 17:22:42 +0000
committerwillchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-10 17:22:42 +0000
commita2cb812a4d1fa85fc864b96e70213b72a16cdd1b (patch)
tree7eb2f244e6b0f470a4a0eb0773c3e3bff3d87d78
parent79ed860501b01bcc06297aaa1483b0feee72132e (diff)
downloadchromium_src-a2cb812a4d1fa85fc864b96e70213b72a16cdd1b.zip
chromium_src-a2cb812a4d1fa85fc864b96e70213b72a16cdd1b.tar.gz
chromium_src-a2cb812a4d1fa85fc864b96e70213b72a16cdd1b.tar.bz2
SPDY: Alternate-Protocol changes.
Add npn-spdy fallback support. Update protocol from spdy=>npn-spdy. Don't process Alternate-Protocol unless it we enabled NPN. Review URL: http://codereview.chromium.org/763001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@41169 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--net/http/http_alternate_protocols.cc4
-rw-r--r--net/http/http_alternate_protocols.h6
-rw-r--r--net/http/http_alternate_protocols_unittest.cc6
-rw-r--r--net/http/http_network_transaction.cc62
-rw-r--r--net/http/http_network_transaction.h9
-rw-r--r--net/http/http_network_transaction_unittest.cc76
6 files changed, 122 insertions, 41 deletions
diff --git a/net/http/http_alternate_protocols.cc b/net/http/http_alternate_protocols.cc
index 7f8bdfa..a945917 100644
--- a/net/http/http_alternate_protocols.cc
+++ b/net/http/http_alternate_protocols.cc
@@ -10,7 +10,9 @@
namespace net {
const char HttpAlternateProtocols::kHeader[] = "Alternate-Protocol";
-const char HttpAlternateProtocols::kSpdyProtocol[] = "SPDY";
+const char* const HttpAlternateProtocols::kProtocolStrings[] = {
+ "npn-spdy",
+};
HttpAlternateProtocols::HttpAlternateProtocols() {}
HttpAlternateProtocols::~HttpAlternateProtocols() {}
diff --git a/net/http/http_alternate_protocols.h b/net/http/http_alternate_protocols.h
index 9ce5157..a6ccab33 100644
--- a/net/http/http_alternate_protocols.h
+++ b/net/http/http_alternate_protocols.h
@@ -19,9 +19,9 @@ namespace net {
class HttpAlternateProtocols {
public:
enum Protocol {
- BROKEN, // The alternate protocol is known to be broken.
- SPDY,
+ NPN_SPDY,
NUM_ALTERNATE_PROTOCOLS,
+ BROKEN, // The alternate protocol is known to be broken.
};
struct PortProtocolPair {
@@ -34,7 +34,7 @@ class HttpAlternateProtocols {
};
static const char kHeader[];
- static const char kSpdyProtocol[];
+ static const char* const kProtocolStrings[NUM_ALTERNATE_PROTOCOLS];
HttpAlternateProtocols();
~HttpAlternateProtocols();
diff --git a/net/http/http_alternate_protocols_unittest.cc b/net/http/http_alternate_protocols_unittest.cc
index df1a832..7f94534 100644
--- a/net/http/http_alternate_protocols_unittest.cc
+++ b/net/http/http_alternate_protocols_unittest.cc
@@ -21,12 +21,12 @@ TEST(HttpAlternateProtocols, Basic) {
alternate_protocols.HasAlternateProtocolFor(test_host_port_pair));
alternate_protocols.SetAlternateProtocolFor(test_host_port_pair,
443,
- HttpAlternateProtocols::SPDY);
+ HttpAlternateProtocols::NPN_SPDY);
ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(test_host_port_pair));
const HttpAlternateProtocols::PortProtocolPair alternate =
alternate_protocols.GetAlternateProtocolFor(test_host_port_pair);
EXPECT_EQ(443, alternate.port);
- EXPECT_EQ(HttpAlternateProtocols::SPDY, alternate.protocol);
+ EXPECT_EQ(HttpAlternateProtocols::NPN_SPDY, alternate.protocol);
}
TEST(HttpAlternateProtocols, SetBroken) {
@@ -43,7 +43,7 @@ TEST(HttpAlternateProtocols, SetBroken) {
alternate_protocols.SetAlternateProtocolFor(
test_host_port_pair,
1234,
- HttpAlternateProtocols::SPDY),
+ HttpAlternateProtocols::NPN_SPDY),
alternate = alternate_protocols.GetAlternateProtocolFor(test_host_port_pair);
EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol)
<< "Second attempt should be ignored.";
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index fd26195..10f32431 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -44,6 +44,8 @@ namespace net {
namespace {
+const std::string* g_next_protos = NULL;
+
void BuildRequestHeaders(const HttpRequestInfo* request_info,
const std::string& authorization_headers,
const UploadDataStream* upload_data_stream,
@@ -141,6 +143,12 @@ void BuildTunnelRequest(const HttpRequestInfo* request_info,
void ProcessAlternateProtocol(const HttpResponseHeaders& headers,
const HostPortPair& http_host_port_pair,
HttpAlternateProtocols* alternate_protocols) {
+ if (!g_next_protos || g_next_protos->empty()) {
+ // This implies that NPN is not suppoted. We don't currently support any
+ // alternate protocols that don't use NPN.
+ return;
+ }
+
std::string alternate_protocol_str;
if (!headers.EnumerateHeader(NULL, HttpAlternateProtocols::kHeader,
&alternate_protocol_str)) {
@@ -166,8 +174,10 @@ void ProcessAlternateProtocol(const HttpResponseHeaders& headers,
return;
}
- if (port_protocol_vector[1] != HttpAlternateProtocols::kSpdyProtocol) {
- // Currently, we only recognize the Spdy protocol.
+ if (port_protocol_vector[1] !=
+ HttpAlternateProtocols::kProtocolStrings[
+ HttpAlternateProtocols::NPN_SPDY]) {
+ // Currently, we only recognize the npn-spdy protocol.
DLOG(WARNING) << HttpAlternateProtocols::kHeader
<< " header has unrecognized protocol: "
<< port_protocol_vector[1];
@@ -182,16 +192,14 @@ void ProcessAlternateProtocol(const HttpResponseHeaders& headers,
return;
}
- alternate_protocols->SetAlternateProtocolFor(http_host_port_pair,
- port,
- HttpAlternateProtocols::SPDY);
+ alternate_protocols->SetAlternateProtocolFor(
+ http_host_port_pair, port, HttpAlternateProtocols::NPN_SPDY);
}
} // namespace
//-----------------------------------------------------------------------------
-std::string* HttpNetworkTransaction::g_next_protos = NULL;
bool HttpNetworkTransaction::g_ignore_certificate_errors = false;
HttpNetworkTransaction::HttpNetworkTransaction(HttpNetworkSession* session)
@@ -709,9 +717,10 @@ int HttpNetworkTransaction::DoInitConnection() {
HttpAlternateProtocols::PortProtocolPair alternate =
alternate_protocols.GetAlternateProtocolFor(host, port);
if (alternate.protocol != HttpAlternateProtocols::BROKEN) {
- DCHECK_EQ(HttpAlternateProtocols::SPDY, alternate.protocol);
+ DCHECK_EQ(HttpAlternateProtocols::NPN_SPDY, alternate.protocol);
port = alternate.port;
using_ssl_ = true;
+ alternate_protocol_ = HttpAlternateProtocols::NPN_SPDY;
alternate_protocol_mode_ = kUsingAlternateProtocol;
}
}
@@ -760,20 +769,7 @@ int HttpNetworkTransaction::DoInitConnectionComplete(int result) {
if (result < 0) {
if (alternate_protocol_mode_ == kUsingAlternateProtocol) {
// Mark the alternate protocol as broken and fallback.
-
- HostPortPair http_host_port_pair;
- http_host_port_pair.host = request_->url.host();
- http_host_port_pair.port = request_->url.EffectiveIntPort();
-
- session_->mutable_alternate_protocols()->MarkBrokenAlternateProtocolFor(
- http_host_port_pair);
-
- alternate_protocol_mode_ = kDoNotUseAlternateProtocol;
-
- if (connection_->socket())
- connection_->socket()->Disconnect();
- connection_->Reset();
- next_state_ = STATE_INIT_CONNECTION;
+ MarkBrokenAlternateProtocolAndFallback();
return OK;
}
@@ -881,6 +877,15 @@ int HttpNetworkTransaction::DoSSLConnectComplete(int result) {
using_spdy_ = (status == SSLClientSocket::kNextProtoNegotiated &&
proto == kSpdyProto);
+ if (alternate_protocol_mode_ == kUsingAlternateProtocol &&
+ alternate_protocol_ == HttpAlternateProtocols::NPN_SPDY &&
+ !using_spdy_) {
+ // We tried using the NPN_SPDY alternate protocol, but failed, so we
+ // fallback.
+ MarkBrokenAlternateProtocolAndFallback();
+ return OK;
+ }
+
if (IsCertificateError(result)) {
result = HandleCertificateError(result);
if (result == OK && !connection_->socket()->IsConnectedAndIdle()) {
@@ -1913,4 +1918,19 @@ void HttpNetworkTransaction::PopulateAuthChallenge(HttpAuth::Target target,
response_.auth_challenge = auth_info;
}
+void HttpNetworkTransaction::MarkBrokenAlternateProtocolAndFallback() {
+ HostPortPair http_host_port_pair;
+ http_host_port_pair.host = request_->url.host();
+ http_host_port_pair.port = request_->url.EffectiveIntPort();
+
+ session_->mutable_alternate_protocols()->MarkBrokenAlternateProtocolFor(
+ http_host_port_pair);
+
+ alternate_protocol_mode_ = kDoNotUseAlternateProtocol;
+ if (connection_->socket())
+ connection_->socket()->Disconnect();
+ connection_->Reset();
+ next_state_ = STATE_INIT_CONNECTION;
+}
+
} // namespace net
diff --git a/net/http/http_network_transaction.h b/net/http/http_network_transaction.h
index 80957bf..bf5327a 100644
--- a/net/http/http_network_transaction.h
+++ b/net/http/http_network_transaction.h
@@ -17,6 +17,7 @@
#include "net/base/load_flags.h"
#include "net/base/load_states.h"
#include "net/base/ssl_config_service.h"
+#include "net/http/http_alternate_protocols.h"
#include "net/http/http_auth.h"
#include "net/http/http_auth_handler.h"
#include "net/http/http_response_info.h"
@@ -262,12 +263,12 @@ class HttpNetworkTransaction : public HttpTransaction {
// For proxy authentication the path is always empty string.
std::string AuthPath(HttpAuth::Target target) const;
+ void MarkBrokenAlternateProtocolAndFallback();
+
// Returns a string representation of a HttpAuth::Target value that can be
// used in log messages.
static std::string AuthTargetString(HttpAuth::Target target);
- static std::string* g_next_protos;
-
static bool g_ignore_certificate_errors;
// The following three auth members are arrays of size two -- index 0 is
@@ -327,8 +328,10 @@ class HttpNetworkTransaction : public HttpTransaction {
// True if this network transaction is using SPDY instead of HTTP.
bool using_spdy_;
- // True if this network transaction is using an alternate protocol to connect.
AlternateProtocolMode alternate_protocol_mode_;
+
+ // Only valid if |alternate_protocol_mode_| == kUsingAlternateProtocol.
+ HttpAlternateProtocols::Protocol alternate_protocol_;
// True if we've used the username/password embedded in the URL. This
// makes sure we use the embedded identity only once for the transaction,
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc
index 1cdc818..aa0bca8 100644
--- a/net/http/http_network_transaction_unittest.cc
+++ b/net/http/http_network_transaction_unittest.cc
@@ -4253,11 +4253,13 @@ TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
}
TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
+ HttpNetworkTransaction::SetNextProtos("needs_to_be_set_for_this_test");
+
SessionDependencies session_deps;
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"),
- MockRead("Alternate-Protocol: 443:SPDY\r\n\r\n"),
+ MockRead("Alternate-Protocol: 443:npn-spdy\r\n\r\n"),
MockRead("hello world"),
MockRead(false, OK),
};
@@ -4303,8 +4305,10 @@ TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
alternate_protocols.GetAlternateProtocolFor(http_host_port_pair);
HttpAlternateProtocols::PortProtocolPair expected_alternate;
expected_alternate.port = 443;
- expected_alternate.protocol = HttpAlternateProtocols::SPDY;
+ expected_alternate.protocol = HttpAlternateProtocols::NPN_SPDY;
EXPECT_TRUE(expected_alternate.Equals(alternate));
+
+ HttpNetworkTransaction::SetNextProtos("");
}
TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocol) {
@@ -4345,7 +4349,7 @@ TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocol) {
session->mutable_alternate_protocols();
alternate_protocols->SetAlternateProtocolFor(
http_host_port_pair, 1234 /* port is ignored by MockConnect anyway */,
- HttpAlternateProtocols::SPDY);
+ HttpAlternateProtocols::NPN_SPDY);
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
@@ -4374,7 +4378,55 @@ TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocol) {
// response does not indicate SPDY, so we just do standard HTTPS over the port.
// We should add code such that we don't fallback to HTTPS, but fallback to HTTP
// on the original port.
-TEST_F(HttpNetworkTransactionTest, UseAlternateProtocol) {
+// TEST_F(HttpNetworkTransactionTest, UseAlternateProtocol) {
+// SessionDependencies session_deps;
+//
+// HttpRequestInfo request;
+// request.method = "GET";
+// request.url = GURL("http://www.google.com/");
+// request.load_flags = 0;
+//
+// MockRead data_reads[] = {
+// MockRead("HTTP/1.1 200 OK\r\n\r\n"),
+// MockRead("hello world"),
+// MockRead(true, OK),
+// };
+// StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
+// session_deps.socket_factory.AddSocketDataProvider(&data);
+//
+// SSLSocketDataProvider ssl(true, OK);
+// session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
+//
+// TestCompletionCallback callback;
+//
+// scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
+//
+// HostPortPair http_host_port_pair;
+// http_host_port_pair.host = "www.google.com";
+// http_host_port_pair.port = 80;
+// HttpAlternateProtocols* alternate_protocols =
+// session->mutable_alternate_protocols();
+// alternate_protocols->SetAlternateProtocolFor(
+// http_host_port_pair, 1234 /* port is ignored */,
+// HttpAlternateProtocols::NPN_SPDY);
+//
+// scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
+//
+// int rv = trans->Start(&request, &callback, NULL);
+// EXPECT_EQ(ERR_IO_PENDING, rv);
+// EXPECT_EQ(OK, callback.WaitForResult());
+//
+// const HttpResponseInfo* response = trans->GetResponseInfo();
+// ASSERT_TRUE(response != NULL);
+// ASSERT_TRUE(response->headers != NULL);
+// EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
+//
+// std::string response_data;
+// ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
+// EXPECT_EQ("hello world", response_data);
+// }
+
+TEST_F(HttpNetworkTransactionTest, FailNpnSpdyAndFallback) {
SessionDependencies session_deps;
HttpRequestInfo request;
@@ -4382,16 +4434,20 @@ TEST_F(HttpNetworkTransactionTest, UseAlternateProtocol) {
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
+ StaticSocketDataProvider first_tcp_connect;
+ session_deps.socket_factory.AddSocketDataProvider(&first_tcp_connect);
+
+ SSLSocketDataProvider ssl(true, OK);
+ session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
+
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n\r\n"),
MockRead("hello world"),
MockRead(true, OK),
};
- StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
- session_deps.socket_factory.AddSocketDataProvider(&data);
-
- SSLSocketDataProvider ssl(true, OK);
- session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
+ StaticSocketDataProvider fallback_data(
+ data_reads, arraysize(data_reads), NULL, 0);
+ session_deps.socket_factory.AddSocketDataProvider(&fallback_data);
TestCompletionCallback callback;
@@ -4404,7 +4460,7 @@ TEST_F(HttpNetworkTransactionTest, UseAlternateProtocol) {
session->mutable_alternate_protocols();
alternate_protocols->SetAlternateProtocolFor(
http_host_port_pair, 1234 /* port is ignored */,
- HttpAlternateProtocols::SPDY);
+ HttpAlternateProtocols::NPN_SPDY);
scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));