summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/http/http_network_transaction.cc12
-rw-r--r--net/http/http_network_transaction_unittest.cc4
-rw-r--r--net/spdy/spdy_http_stream_unittest.cc11
-rw-r--r--net/spdy/spdy_network_transaction.cc3
-rw-r--r--net/spdy/spdy_network_transaction_unittest.cc280
-rw-r--r--net/spdy/spdy_session.cc13
-rw-r--r--net/spdy/spdy_session.h15
-rw-r--r--net/spdy/spdy_session_pool.cc52
-rw-r--r--net/spdy/spdy_session_pool.h23
-rw-r--r--net/spdy/spdy_session_unittest.cc21
-rw-r--r--net/spdy/spdy_stream_unittest.cc4
-rw-r--r--net/spdy/spdy_test_util.cc8
-rw-r--r--net/spdy/spdy_test_util.h3
13 files changed, 377 insertions, 72 deletions
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index a3624f3..966eccb 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -744,7 +744,8 @@ int HttpNetworkTransaction::DoInitConnection() {
// Check first if we have a spdy session for this group. If so, then go
// straight to using that.
- if (session_->spdy_session_pool()->HasSession(endpoint_)) {
+ HostPortProxyPair pair(endpoint_, proxy_info_.ToPacString());
+ if (session_->spdy_session_pool()->HasSession(pair)) {
using_spdy_ = true;
reused_socket_ = true;
next_state_ = STATE_SPDY_GET_STREAM;
@@ -1323,8 +1324,9 @@ int HttpNetworkTransaction::DoSpdyGetStream() {
session_->spdy_session_pool();
scoped_refptr<SpdySession> spdy_session;
- if (spdy_pool->HasSession(endpoint_)) {
- spdy_session = spdy_pool->Get(endpoint_, session_, net_log_);
+ HostPortProxyPair pair(endpoint_, proxy_info_.ToPacString());
+ if (spdy_pool->HasSession(pair)) {
+ spdy_session = spdy_pool->Get(pair, session_, net_log_);
} else {
if(using_ssl_) {
// SPDY can be negotiated using the TLS next protocol negotiation (NPN)
@@ -1332,7 +1334,7 @@ int HttpNetworkTransaction::DoSpdyGetStream() {
// contain an SSLClientSocket.
CHECK(connection_->socket());
int error = spdy_pool->GetSpdySessionFromSocket(
- endpoint_, session_, connection_.release(), net_log_,
+ pair, session_, connection_.release(), net_log_,
spdy_certificate_error_, &spdy_session, true);
if (error != OK)
return error;
@@ -1340,7 +1342,7 @@ int HttpNetworkTransaction::DoSpdyGetStream() {
else {
// We may want SPDY without SSL
int error = spdy_pool->GetSpdySessionFromSocket(
- endpoint_, session_, connection_.release(), net_log_,
+ pair, session_, connection_.release(), net_log_,
spdy_certificate_error_, &spdy_session, false);
if (error != OK)
return error;
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc
index ea087d0..ec54865 100644
--- a/net/http/http_network_transaction_unittest.cc
+++ b/net/http/http_network_transaction_unittest.cc
@@ -5606,9 +5606,9 @@ TEST_F(HttpNetworkTransactionTest,
EXPECT_EQ("hello world", response_data);
// Set up an initial SpdySession in the pool to reuse.
+ HostPortProxyPair pair(HostPortPair("www.google.com", 443), "DIRECT");
scoped_refptr<SpdySession> spdy_session =
- session->spdy_session_pool()->Get(HostPortPair("www.google.com", 443),
- session, BoundNetLog());
+ session->spdy_session_pool()->Get(pair, session, BoundNetLog());
scoped_refptr<TCPSocketParams> tcp_params =
new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false);
spdy_session->Connect("www.google.com:443", tcp_params, MEDIUM);
diff --git a/net/spdy/spdy_http_stream_unittest.cc b/net/spdy/spdy_http_stream_unittest.cc
index ee2ef94..7f78142 100644
--- a/net/spdy/spdy_http_stream_unittest.cc
+++ b/net/spdy/spdy_http_stream_unittest.cc
@@ -25,11 +25,12 @@ class SpdyHttpStreamTest : public testing::Test {
int InitSession(MockRead* reads, size_t reads_count,
MockWrite* writes, size_t writes_count,
HostPortPair& host_port_pair) {
+ HostPortProxyPair pair(host_port_pair, "");
data_ = new OrderedSocketData(reads, reads_count, writes, writes_count);
session_deps_.socket_factory.AddSocketDataProvider(data_.get());
http_session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
session_ = http_session_->spdy_session_pool()->
- Get(host_port_pair, http_session_.get(), BoundNetLog());
+ Get(pair, http_session_.get(), BoundNetLog());
tcp_params_ = new TCPSocketParams(host_port_pair.host(),
host_port_pair.port(),
MEDIUM, GURL(), false);
@@ -58,6 +59,7 @@ TEST_F(SpdyHttpStreamTest, SendRequest) {
};
HostPortPair host_port_pair("www.google.com", 80);
+ HostPortProxyPair pair(host_port_pair, "");
EXPECT_EQ(OK, InitSession(reads, arraysize(reads), writes, arraysize(writes),
host_port_pair));
@@ -74,7 +76,7 @@ TEST_F(SpdyHttpStreamTest, SendRequest) {
EXPECT_EQ(ERR_IO_PENDING,
http_stream->SendRequest("", NULL, &response, &callback));
- EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession(host_port_pair));
+ EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession(pair));
// This triggers the MockWrite and read 2
callback.WaitForResult();
@@ -84,7 +86,7 @@ TEST_F(SpdyHttpStreamTest, SendRequest) {
// Because we abandoned the stream, we don't expect to find a session in the
// pool anymore.
- EXPECT_TRUE(!http_session_->spdy_session_pool()->HasSession(host_port_pair));
+ EXPECT_TRUE(!http_session_->spdy_session_pool()->HasSession(pair));
EXPECT_TRUE(data()->at_read_eof());
EXPECT_TRUE(data()->at_write_eof());
}
@@ -105,6 +107,7 @@ TEST_F(SpdyHttpStreamTest, SpdyURLTest) {
};
HostPortPair host_port_pair("www.google.com", 80);
+ HostPortProxyPair pair(host_port_pair, "");
EXPECT_EQ(OK, InitSession(reads, arraysize(reads), writes, arraysize(writes),
host_port_pair));
@@ -131,7 +134,7 @@ TEST_F(SpdyHttpStreamTest, SpdyURLTest) {
FAIL() << "No url is set in spdy_header!";
MessageLoop::current()->RunAllPending();
- EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession(host_port_pair));
+ EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession(pair));
http_session_->spdy_session_pool()->CloseAllSessions();
EXPECT_TRUE(!data()->at_read_eof());
}
diff --git a/net/spdy/spdy_network_transaction.cc b/net/spdy/spdy_network_transaction.cc
index 6b3e26b..cdfd216 100644
--- a/net/spdy/spdy_network_transaction.cc
+++ b/net/spdy/spdy_network_transaction.cc
@@ -230,8 +230,9 @@ int SpdyNetworkTransaction::DoInitConnection() {
new TCPSocketParams(host_port_pair, request_->priority,
request_->referrer, false);
+ HostPortProxyPair pair(host_port_pair, "");
spdy_ = session_->spdy_session_pool()->Get(
- host_port_pair, session_, net_log_);
+ pair, session_, net_log_);
DCHECK(spdy_);
return spdy_->Connect(
diff --git a/net/spdy/spdy_network_transaction_unittest.cc b/net/spdy/spdy_network_transaction_unittest.cc
index 5460aae..ef1f03e 100644
--- a/net/spdy/spdy_network_transaction_unittest.cc
+++ b/net/spdy/spdy_network_transaction_unittest.cc
@@ -59,7 +59,9 @@ class SpdyNetworkTransactionTest
const BoundNetLog& log,
SpdyNetworkTransactionTestTypes test_type)
: request_(request),
- session_(SpdySessionDependencies::SpdyCreateSession(&session_deps_)),
+ session_deps_(new SpdySessionDependencies()),
+ session_(SpdySessionDependencies::SpdyCreateSession(
+ session_deps_.get())),
log_(log),
test_type_(test_type) {
switch (test_type_) {
@@ -76,6 +78,12 @@ class SpdyNetworkTransactionTest
}
void RunPreTestSetup() {
+ if (!session_deps_.get())
+ session_deps_.reset(new SpdySessionDependencies());
+ if (!session_.get())
+ session_ = SpdySessionDependencies::SpdyCreateSession(
+ session_deps_.get());
+
HttpNetworkTransaction::SetUseAlternateProtocols(false);
HttpNetworkTransaction::SetUseSSLOverSpdyWithoutNPN(false);
HttpNetworkTransaction::SetUseSpdyWithoutNPN(false);
@@ -189,15 +197,15 @@ class SpdyNetworkTransactionTest
ssl_->was_npn_negotiated = true;
}
ssl_vector_.push_back(ssl_);
- if (test_type_ == SPDYNPN || test_type_ == SPDYSSL)
- session_deps_.socket_factory.AddSSLSocketDataProvider(ssl_.get());
- session_deps_.socket_factory.AddSocketDataProvider(data);
+ if(test_type_ == SPDYNPN || test_type_ == SPDYSSL)
+ session_deps_->socket_factory.AddSSLSocketDataProvider(ssl_.get());
+ session_deps_->socket_factory.AddSocketDataProvider(data);
}
// This can only be called after RunPreTestSetup. It adds a Data Provider,
// but not a corresponding SSL data provider
void AddDataNoSSL(StaticSocketDataProvider* data) {
- session_deps_.socket_factory.AddSocketDataProvider(data);
+ session_deps_->socket_factory.AddSocketDataProvider(data);
}
void SetSession(const scoped_refptr<HttpNetworkSession>& session) {
@@ -208,13 +216,16 @@ class SpdyNetworkTransactionTest
TransactionHelperResult& output() { return output_; }
HttpRequestInfo& request() { return request_; }
scoped_refptr<HttpNetworkSession>& session() { return session_; }
+ scoped_ptr<SpdySessionDependencies>& session_deps() {
+ return session_deps_;
+ }
int port() { return port_; }
private:
typedef std::vector<StaticSocketDataProvider*> DataVector;
typedef std::vector<linked_ptr<SSLSocketDataProvider> > SSLVector;
HttpRequestInfo request_;
- SpdySessionDependencies session_deps_;
+ scoped_ptr<SpdySessionDependencies> session_deps_;
scoped_refptr<HttpNetworkSession> session_;
TransactionHelperResult output_;
scoped_ptr<StaticSocketDataProvider> first_transaction_;
@@ -2783,6 +2794,262 @@ TEST_P(SpdyNetworkTransactionTest, CloseWithActiveStream) {
helper.VerifyDataConsumed();
}
+// Test to make sure we can correctly connect through a proxy.
+TEST_P(SpdyNetworkTransactionTest, ProxyConnect) {
+ NormalSpdyTransactionHelper helper(CreateGetRequest(),
+ BoundNetLog(), GetParam());
+ helper.session_deps().reset(new SpdySessionDependencies(
+ net::SpdyCreateFixedProxyService("myproxy:70")));
+ helper.session() = SpdySessionDependencies::SpdyCreateSession(
+ helper.session_deps().get());
+ helper.RunPreTestSetup();
+ HttpNetworkTransaction* trans = helper.trans();
+
+ const char kConnect443[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
+ "Host: www.google.com\r\n"
+ "Proxy-Connection: keep-alive\r\n\r\n"};
+ const char kConnect80[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
+ "Host: www.google.com\r\n"
+ "Proxy-Connection: keep-alive\r\n\r\n"};
+ const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
+ scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
+ scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
+
+ MockWrite writes_SPDYNPN[] = {
+ MockWrite(false, kConnect443, arraysize(kConnect443) - 1, 0),
+ CreateMockWrite(*req, 2),
+ };
+ MockRead reads_SPDYNPN[] = {
+ MockRead(false, kHTTP200, arraysize(kHTTP200) - 1, 1),
+ CreateMockRead(*resp, 3),
+ CreateMockRead(*body.get(), 4),
+ MockRead(true, 0, 0, 5),
+ };
+
+ MockWrite writes_SPDYSSL[] = {
+ MockWrite(false, kConnect80, arraysize(kConnect80) - 1, 0),
+ CreateMockWrite(*req, 2),
+ };
+ MockRead reads_SPDYSSL[] = {
+ MockRead(false, kHTTP200, arraysize(kHTTP200) - 1, 1),
+ CreateMockRead(*resp, 3),
+ CreateMockRead(*body.get(), 4),
+ MockRead(true, 0, 0, 5),
+ };
+
+ MockWrite writes_SPDYNOSSL[] = {
+ CreateMockWrite(*req, 0),
+ };
+
+ MockRead reads_SPDYNOSSL[] = {
+ CreateMockRead(*resp, 1),
+ CreateMockRead(*body.get(), 2),
+ MockRead(true, 0, 0, 3),
+ };
+
+ scoped_refptr<OrderedSocketData> data;
+ switch(GetParam()) {
+ case SPDYNOSSL:
+ data = new OrderedSocketData(reads_SPDYNOSSL,
+ arraysize(reads_SPDYNOSSL),
+ writes_SPDYNOSSL,
+ arraysize(writes_SPDYNOSSL));
+ break;
+ case SPDYSSL:
+ data = new OrderedSocketData(reads_SPDYSSL, arraysize(reads_SPDYSSL),
+ writes_SPDYSSL, arraysize(writes_SPDYSSL));
+ break;
+ case SPDYNPN:
+ data = new OrderedSocketData(reads_SPDYNPN, arraysize(reads_SPDYNPN),
+ writes_SPDYNPN, arraysize(writes_SPDYNPN));
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ helper.AddData(data.get());
+ TestCompletionCallback callback;
+
+ int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ rv = callback.WaitForResult();
+ EXPECT_EQ(0, rv);
+
+ // Verify the SYN_REPLY.
+ HttpResponseInfo response = *trans->GetResponseInfo();
+ EXPECT_TRUE(response.headers != NULL);
+ EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
+
+ std::string response_data;
+ ASSERT_EQ(OK, ReadTransaction(trans, &response_data));
+ EXPECT_EQ("hello!", response_data);
+ helper.VerifyDataConsumed();
+}
+
+// Test to make sure we can correctly connect through a proxy to www.google.com,
+// if there already exists a direct spdy connection to www.google.com. See
+// http://crbug.com/49874
+TEST_P(SpdyNetworkTransactionTest, DirectConnectProxyReconnect) {
+ // When setting up the first transaction, we store the SpdySessionPool so that
+ // we can use the same pool in the second transaction.
+ NormalSpdyTransactionHelper helper(CreateGetRequest(),
+ BoundNetLog(), GetParam());
+ scoped_refptr<SpdySessionPool> spdy_session_pool =
+ helper.session_deps()->spdy_session_pool;
+ helper.RunPreTestSetup();
+
+ // Construct and send a simple GET request.
+ scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
+ MockWrite writes[] = {
+ CreateMockWrite(*req, 1),
+ };
+
+ scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
+ MockRead reads[] = {
+ CreateMockRead(*resp, 2),
+ CreateMockRead(*body, 3),
+ MockRead(true, ERR_IO_PENDING, 4), // Force a pause
+ MockRead(true, 0, 5) // EOF
+ };
+ scoped_refptr<OrderedSocketData> data(
+ new OrderedSocketData(reads, arraysize(reads),
+ writes, arraysize(writes)));
+ helper.AddData(data.get());
+ HttpNetworkTransaction* trans = helper.trans();
+
+ TestCompletionCallback callback;
+ TransactionHelperResult out;
+ out.rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
+
+ EXPECT_EQ(out.rv, ERR_IO_PENDING);
+ out.rv = callback.WaitForResult();
+ EXPECT_EQ(out.rv, OK);
+
+ const HttpResponseInfo* response = trans->GetResponseInfo();
+ EXPECT_TRUE(response->headers != NULL);
+ EXPECT_TRUE(response->was_fetched_via_spdy);
+ out.rv = ReadTransaction(trans, &out.response_data);
+ EXPECT_EQ(OK, out.rv);
+ out.status_line = response->headers->GetStatusLine();
+ EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
+ EXPECT_EQ("hello!", out.response_data);
+
+ // Check that the SpdySession is still in the SpdySessionPool.
+ HostPortPair host_port_pair("www.google.com", helper.port());
+ HostPortProxyPair pair(host_port_pair, "DIRECT");
+ EXPECT_TRUE(spdy_session_pool->HasSession(pair));
+ HostPortProxyPair nonexistent_pair(host_port_pair, "PROXY www.foo.com");
+ EXPECT_FALSE(spdy_session_pool->HasSession(nonexistent_pair));
+
+ // Set up data for the proxy connection.
+ const char kConnect443[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
+ "Host: www.google.com\r\n"
+ "Proxy-Connection: keep-alive\r\n\r\n"};
+ const char kConnect80[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
+ "Host: www.google.com\r\n"
+ "Proxy-Connection: keep-alive\r\n\r\n"};
+ const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
+ scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(
+ "http://www.google.com/foo.dat", false, 1, LOWEST));
+ scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 1));
+ scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(1, true));
+
+ MockWrite writes_SPDYNPN[] = {
+ MockWrite(false, kConnect443, arraysize(kConnect443) - 1, 0),
+ CreateMockWrite(*req2, 2),
+ };
+ MockRead reads_SPDYNPN[] = {
+ MockRead(false, kHTTP200, arraysize(kHTTP200) - 1, 1),
+ CreateMockRead(*resp2, 3),
+ CreateMockRead(*body2, 4),
+ MockRead(true, 0, 5) // EOF
+ };
+
+ MockWrite writes_SPDYNOSSL[] = {
+ CreateMockWrite(*req2, 0),
+ };
+ MockRead reads_SPDYNOSSL[] = {
+ CreateMockRead(*resp2, 1),
+ CreateMockRead(*body2, 2),
+ MockRead(true, 0, 3) // EOF
+ };
+
+ MockWrite writes_SPDYSSL[] = {
+ MockWrite(false, kConnect80, arraysize(kConnect80) - 1, 0),
+ CreateMockWrite(*req2, 2),
+ };
+ MockRead reads_SPDYSSL[] = {
+ MockRead(false, kHTTP200, arraysize(kHTTP200) - 1, 1),
+ CreateMockRead(*resp2, 3),
+ CreateMockRead(*body2, 4),
+ MockRead(true, 0, 0, 5),
+ };
+
+ scoped_refptr<OrderedSocketData> data_proxy;
+ switch(GetParam()) {
+ case SPDYNPN:
+ data_proxy = new OrderedSocketData(reads_SPDYNPN,
+ arraysize(reads_SPDYNPN),
+ writes_SPDYNPN,
+ arraysize(writes_SPDYNPN));
+ break;
+ case SPDYNOSSL:
+ data_proxy = new OrderedSocketData(reads_SPDYNOSSL,
+ arraysize(reads_SPDYNOSSL),
+ writes_SPDYNOSSL,
+ arraysize(writes_SPDYNOSSL));
+ break;
+ case SPDYSSL:
+ data_proxy = new OrderedSocketData(reads_SPDYSSL,
+ arraysize(reads_SPDYSSL),
+ writes_SPDYSSL,
+ arraysize(writes_SPDYSSL));
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ // Create another request to www.google.com, but this time through a proxy.
+ HttpRequestInfo request_proxy;
+ request_proxy.method = "GET";
+ request_proxy.url = GURL("http://www.google.com/foo.dat");
+ request_proxy.load_flags = 0;
+ scoped_ptr<SpdySessionDependencies> ssd_proxy(
+ new SpdySessionDependencies(net::SpdyCreateFixedProxyService(
+ "myproxy:70")));
+ // Ensure that this transaction uses the same SpdySessionPool.
+ ssd_proxy->spdy_session_pool = spdy_session_pool;
+ scoped_refptr<HttpNetworkSession> session_proxy =
+ SpdySessionDependencies::SpdyCreateSession(ssd_proxy.get());
+ NormalSpdyTransactionHelper helper_proxy(request_proxy,
+ BoundNetLog(), GetParam());
+ helper_proxy.session_deps().swap(ssd_proxy);
+ helper_proxy.session() = session_proxy;
+ helper_proxy.RunPreTestSetup();
+ helper_proxy.AddData(data_proxy.get());
+
+ HttpNetworkTransaction* trans_proxy = helper_proxy.trans();
+ TestCompletionCallback callback_proxy;
+ int rv = trans_proxy->Start(&request_proxy, &callback_proxy, BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ rv = callback_proxy.WaitForResult();
+ EXPECT_EQ(0, rv);
+
+ HttpResponseInfo response_proxy = *trans_proxy->GetResponseInfo();
+ EXPECT_TRUE(response_proxy.headers != NULL);
+ EXPECT_EQ("HTTP/1.1 200 OK", response_proxy.headers->GetStatusLine());
+
+ std::string response_data;
+ ASSERT_EQ(OK, ReadTransaction(trans_proxy, &response_data));
+ EXPECT_EQ("hello!", response_data);
+
+ data->CompleteRead();
+ helper_proxy.VerifyDataConsumed();
+}
+
// When we get a TCP-level RST, we need to retry a HttpNetworkTransaction
// on a new connection, if the connection was previously known to be good.
// This can happen when a server reboots without saying goodbye, or when
@@ -2865,5 +3132,4 @@ TEST_P(SpdyNetworkTransactionTest, VerifyRetryOnConnectionReset) {
helper.VerifyDataConsumed();
}
}
-
} // namespace net
diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc
index 2aa2289..9776bce 100644
--- a/net/spdy/spdy_session.cc
+++ b/net/spdy/spdy_session.cc
@@ -138,7 +138,7 @@ bool SpdySession::use_ssl_ = true;
// static
bool SpdySession::use_flow_control_ = false;
-SpdySession::SpdySession(const HostPortPair& host_port_pair,
+SpdySession::SpdySession(const HostPortProxyPair& host_port_proxy_pair,
HttpNetworkSession* session,
NetLog* net_log)
: ALLOW_THIS_IN_INITIALIZER_LIST(
@@ -149,7 +149,7 @@ SpdySession::SpdySession(const HostPortPair& host_port_pair,
read_callback_(this, &SpdySession::OnReadComplete)),
ALLOW_THIS_IN_INITIALIZER_LIST(
write_callback_(this, &SpdySession::OnWriteComplete)),
- host_port_pair_(host_port_pair),
+ host_port_proxy_pair_(host_port_proxy_pair),
session_(session),
connection_(new ClientSocketHandle),
read_buffer_(new IOBuffer(kReadBufferSize)),
@@ -174,7 +174,8 @@ SpdySession::SpdySession(const HostPortPair& host_port_pair,
net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SPDY_SESSION)) {
net_log_.BeginEvent(
NetLog::TYPE_SPDY_SESSION,
- new NetLogStringParameter("host_port", host_port_pair_.ToString()));
+ new NetLogStringParameter("host_port",
+ host_port_proxy_pair_.first.ToString()));
// TODO(mbelshe): consider randomization of the stream_hi_water_mark.
@@ -1225,7 +1226,7 @@ void SpdySession::OnSettings(const spdy::SpdySettingsControlFrame& frame) {
if (spdy_framer_.ParseSettings(&frame, &settings)) {
HandleSettings(settings);
SpdySettingsStorage* settings_storage = session_->mutable_spdy_settings();
- settings_storage->Set(host_port_pair_, settings);
+ settings_storage->Set(host_port_pair(), settings);
}
received_settings_ = true;
@@ -1263,7 +1264,7 @@ void SpdySession::OnWindowUpdate(
void SpdySession::SendSettings() {
const SpdySettingsStorage& settings_storage = session_->spdy_settings();
- const spdy::SpdySettings& settings = settings_storage.Get(host_port_pair_);
+ const spdy::SpdySettings& settings = settings_storage.Get(host_port_pair());
if (settings.empty())
return;
HandleSettings(settings);
@@ -1314,7 +1315,7 @@ void SpdySession::RecordHistograms() {
if (received_settings_) {
// Enumerate the saved settings, and set histograms for it.
const SpdySettingsStorage& settings_storage = session_->spdy_settings();
- const spdy::SpdySettings& settings = settings_storage.Get(host_port_pair_);
+ const spdy::SpdySettings& settings = settings_storage.Get(host_port_pair());
spdy::SpdySettings::const_iterator it;
for (it = settings.begin(); it != settings.end(); ++it) {
diff --git a/net/spdy/spdy_session.h b/net/spdy/spdy_session.h
index 22facba..39fe56b 100644
--- a/net/spdy/spdy_session.h
+++ b/net/spdy/spdy_session.h
@@ -48,13 +48,20 @@ class SpdySession : public base::RefCounted<SpdySession>,
public spdy::SpdyFramerVisitorInterface {
public:
// Create a new SpdySession.
- // |host_port_pair| is the host/port that this session connects to.
+ // |host_port_proxy_pair| is the host/port that this session connects to, and
+ // the proxy configuration settings that it's using.
// |session| is the HttpNetworkSession. |net_log| is the NetLog that we log
// network events to.
- SpdySession(const HostPortPair& host_port_pair, HttpNetworkSession* session,
+ SpdySession(const HostPortProxyPair& host_port_proxy_pair,
+ HttpNetworkSession* session,
NetLog* net_log);
- const HostPortPair& host_port_pair() const { return host_port_pair_; }
+ const HostPortPair& host_port_pair() const {
+ return host_port_proxy_pair_.first;
+ }
+ const HostPortProxyPair& host_port_proxy_pair() const {
+ return host_port_proxy_pair_;
+ }
// Connect the Spdy Socket.
// Returns net::Error::OK on success.
@@ -271,7 +278,7 @@ class SpdySession : public base::RefCounted<SpdySession>,
CompletionCallbackImpl<SpdySession> write_callback_;
// The domain this session is connected to.
- const HostPortPair host_port_pair_;
+ const HostPortProxyPair host_port_proxy_pair_;
SSLConfig ssl_config_;
diff --git a/net/spdy/spdy_session_pool.cc b/net/spdy/spdy_session_pool.cc
index da8b358..7bccd5c43 100644
--- a/net/spdy/spdy_session_pool.cc
+++ b/net/spdy/spdy_session_pool.cc
@@ -25,22 +25,24 @@ SpdySessionPool::~SpdySessionPool() {
}
scoped_refptr<SpdySession> SpdySessionPool::Get(
- const HostPortPair& host_port_pair, HttpNetworkSession* session,
+ const HostPortProxyPair& host_port_proxy_pair, HttpNetworkSession* session,
const BoundNetLog& net_log) {
scoped_refptr<SpdySession> spdy_session;
- SpdySessionList* list = GetSessionList(host_port_pair);
+ SpdySessionList* list = GetSessionList(host_port_proxy_pair);
if (list) {
if (list->size() >= static_cast<unsigned int>(g_max_sessions_per_domain)) {
spdy_session = list->front();
list->pop_front();
}
} else {
- list = AddSessionList(host_port_pair);
+ list = AddSessionList(host_port_proxy_pair);
}
DCHECK(list);
if (!spdy_session)
- spdy_session = new SpdySession(host_port_pair, session, net_log.net_log());
+ spdy_session = new SpdySession(host_port_proxy_pair,
+ session,
+ net_log.net_log());
DCHECK(spdy_session);
list->push_back(spdy_session);
@@ -49,7 +51,7 @@ scoped_refptr<SpdySession> SpdySessionPool::Get(
}
net::Error SpdySessionPool::GetSpdySessionFromSocket(
- const HostPortPair& host_port_pair,
+ const HostPortProxyPair& host_port_proxy_pair,
HttpNetworkSession* session,
ClientSocketHandle* connection,
const BoundNetLog& net_log,
@@ -57,10 +59,11 @@ net::Error SpdySessionPool::GetSpdySessionFromSocket(
scoped_refptr<SpdySession>* spdy_session,
bool is_secure) {
// Create the SPDY session and add it to the pool.
- *spdy_session = new SpdySession(host_port_pair, session, net_log.net_log());
- SpdySessionList* list = GetSessionList(host_port_pair);
+ *spdy_session = new SpdySession(host_port_proxy_pair,
+ session, net_log.net_log());
+ SpdySessionList* list = GetSessionList(host_port_proxy_pair);
if (!list)
- list = AddSessionList(host_port_pair);
+ list = AddSessionList(host_port_proxy_pair);
DCHECK(list->empty());
list->push_back(*spdy_session);
@@ -69,20 +72,21 @@ net::Error SpdySessionPool::GetSpdySessionFromSocket(
certificate_error_code);
}
-bool SpdySessionPool::HasSession(const HostPortPair& host_port_pair) const {
- if (GetSessionList(host_port_pair))
+bool SpdySessionPool::HasSession(
+ const HostPortProxyPair& host_port_proxy_pair) const {
+ if (GetSessionList(host_port_proxy_pair))
return true;
return false;
}
void SpdySessionPool::Remove(const scoped_refptr<SpdySession>& session) {
- SpdySessionList* list = GetSessionList(session->host_port_pair());
+ SpdySessionList* list = GetSessionList(session->host_port_proxy_pair());
DCHECK(list); // We really shouldn't remove if we've already been removed.
if (!list)
return;
list->remove(session);
if (list->empty())
- RemoveSessionList(session->host_port_pair());
+ RemoveSessionList(session->host_port_proxy_pair());
}
void SpdySessionPool::OnIPAddressChanged() {
@@ -90,34 +94,38 @@ void SpdySessionPool::OnIPAddressChanged() {
}
SpdySessionPool::SpdySessionList*
- SpdySessionPool::AddSessionList(const HostPortPair& host_port_pair) {
- DCHECK(sessions_.find(host_port_pair) == sessions_.end());
+ SpdySessionPool::AddSessionList(
+ const HostPortProxyPair& host_port_proxy_pair) {
+ DCHECK(sessions_.find(host_port_proxy_pair) == sessions_.end());
SpdySessionPool::SpdySessionList* list = new SpdySessionList();
- sessions_[host_port_pair] = list;
+ sessions_[host_port_proxy_pair] = list;
return list;
}
SpdySessionPool::SpdySessionList*
- SpdySessionPool::GetSessionList(const HostPortPair& host_port_pair) {
- SpdySessionsMap::iterator it = sessions_.find(host_port_pair);
+ SpdySessionPool::GetSessionList(
+ const HostPortProxyPair& host_port_proxy_pair) {
+ SpdySessionsMap::iterator it = sessions_.find(host_port_proxy_pair);
if (it == sessions_.end())
return NULL;
return it->second;
}
const SpdySessionPool::SpdySessionList*
- SpdySessionPool::GetSessionList(const HostPortPair& host_port_pair) const {
- SpdySessionsMap::const_iterator it = sessions_.find(host_port_pair);
+ SpdySessionPool::GetSessionList(
+ const HostPortProxyPair& host_port_proxy_pair) const {
+ SpdySessionsMap::const_iterator it = sessions_.find(host_port_proxy_pair);
if (it == sessions_.end())
return NULL;
return it->second;
}
-void SpdySessionPool::RemoveSessionList(const HostPortPair& host_port_pair) {
- SpdySessionList* list = GetSessionList(host_port_pair);
+void SpdySessionPool::RemoveSessionList(
+ const HostPortProxyPair& host_port_proxy_pair) {
+ SpdySessionList* list = GetSessionList(host_port_proxy_pair);
if (list) {
delete list;
- sessions_.erase(host_port_pair);
+ sessions_.erase(host_port_proxy_pair);
} else {
DCHECK(false) << "removing orphaned session list";
}
diff --git a/net/spdy/spdy_session_pool.h b/net/spdy/spdy_session_pool.h
index e0320d3..3bdd2b3 100644
--- a/net/spdy/spdy_session_pool.h
+++ b/net/spdy/spdy_session_pool.h
@@ -17,8 +17,12 @@
#include "net/base/host_port_pair.h"
#include "net/base/net_errors.h"
#include "net/base/network_change_notifier.h"
+#include "net/proxy/proxy_config.h"
namespace net {
+// Sessions are uniquely identified by their HostPortPair and the PAC-style list
+// of valid proxy servers.
+typedef std::pair<HostPortPair, std::string> HostPortProxyPair;
class BoundNetLog;
class ClientSocketHandle;
@@ -36,7 +40,8 @@ class SpdySessionPool
// Either returns an existing SpdySession or creates a new SpdySession for
// use.
scoped_refptr<SpdySession> Get(
- const HostPortPair& host_port_pair, HttpNetworkSession* session,
+ const HostPortProxyPair& host_port_proxy_pair,
+ HttpNetworkSession* session,
const BoundNetLog& net_log);
// Set the maximum concurrent sessions per domain.
@@ -56,7 +61,7 @@ class SpdySessionPool
// Returns OK on success, and the |spdy_session| will be provided.
// Returns an error on failure, and |spdy_session| will be NULL.
net::Error GetSpdySessionFromSocket(
- const HostPortPair& host_port_pair,
+ const HostPortProxyPair& host_port_proxy_pair,
HttpNetworkSession* session,
ClientSocketHandle* connection,
const BoundNetLog& net_log,
@@ -66,7 +71,7 @@ class SpdySessionPool
// TODO(willchan): Consider renaming to HasReusableSession, since perhaps we
// should be creating a new session.
- bool HasSession(const HostPortPair& host_port_pair)const;
+ bool HasSession(const HostPortProxyPair& host_port_proxy_pair) const;
// Close all Spdy Sessions; used for debugging.
void CloseAllSessions();
@@ -89,16 +94,18 @@ class SpdySessionPool
FRIEND_TEST_ALL_PREFIXES(SpdyNetworkTransactionTest, WindowUpdateOverflow);
typedef std::list<scoped_refptr<SpdySession> > SpdySessionList;
- typedef std::map<HostPortPair, SpdySessionList*> SpdySessionsMap;
+ typedef std::map<HostPortProxyPair, SpdySessionList*> SpdySessionsMap;
virtual ~SpdySessionPool();
// Helper functions for manipulating the lists.
- SpdySessionList* AddSessionList(const HostPortPair& host_port_pair);
- SpdySessionList* GetSessionList(const HostPortPair& host_port_pair);
+ SpdySessionList* AddSessionList(
+ const HostPortProxyPair& host_port_proxy_pair);
+ SpdySessionList* GetSessionList(
+ const HostPortProxyPair& host_port_proxy_pair);
const SpdySessionList* GetSessionList(
- const HostPortPair& host_port_pair) const;
- void RemoveSessionList(const HostPortPair& host_port_pair);
+ const HostPortProxyPair& host_port_proxy_pair) const;
+ void RemoveSessionList(const HostPortProxyPair& host_port_proxy_pair);
// Releases the SpdySessionPool reference to all sessions. Will result in all
// idle sessions being deleted, and the active sessions from being reused, so
// they will be deleted once all active streams belonging to that session go
diff --git a/net/spdy/spdy_session_unittest.cc b/net/spdy/spdy_session_unittest.cc
index 70c7863..e78f0d9 100644
--- a/net/spdy/spdy_session_unittest.cc
+++ b/net/spdy/spdy_session_unittest.cc
@@ -80,14 +80,14 @@ TEST_F(SpdySessionTest, GoAway) {
const std::string kTestHost("www.foo.com");
const int kTestPort = 80;
HostPortPair test_host_port_pair(kTestHost, kTestPort);
+ HostPortProxyPair pair(test_host_port_pair, "");
scoped_refptr<SpdySessionPool> spdy_session_pool(
http_session->spdy_session_pool());
- EXPECT_FALSE(spdy_session_pool->HasSession(test_host_port_pair));
+ EXPECT_FALSE(spdy_session_pool->HasSession(pair));
scoped_refptr<SpdySession> session =
- spdy_session_pool->Get(
- test_host_port_pair, http_session.get(), BoundNetLog());
- EXPECT_TRUE(spdy_session_pool->HasSession(test_host_port_pair));
+ spdy_session_pool->Get(pair, http_session.get(), BoundNetLog());
+ EXPECT_TRUE(spdy_session_pool->HasSession(pair));
scoped_refptr<TCPSocketParams> tcp_params =
new TCPSocketParams(kTestHost, kTestPort, MEDIUM, GURL(), false);
@@ -97,11 +97,10 @@ TEST_F(SpdySessionTest, GoAway) {
// Flush the SpdySession::OnReadComplete() task.
MessageLoop::current()->RunAllPending();
- EXPECT_FALSE(spdy_session_pool->HasSession(test_host_port_pair));
+ EXPECT_FALSE(spdy_session_pool->HasSession(pair));
scoped_refptr<SpdySession> session2 =
- spdy_session_pool->Get(
- test_host_port_pair, http_session.get(), BoundNetLog());
+ spdy_session_pool->Get(pair, http_session.get(), BoundNetLog());
// Delete the first session.
session = NULL;
@@ -144,14 +143,14 @@ TEST_F(SpdySessionTest, GetActivePushStream) {
const std::string kTestHost("www.foo.com");
const int kTestPort = 80;
HostPortPair test_host_port_pair(kTestHost, kTestPort);
+ HostPortProxyPair pair(test_host_port_pair, "");
scoped_refptr<SpdySessionPool> spdy_session_pool(
http_session->spdy_session_pool());
- EXPECT_FALSE(spdy_session_pool->HasSession(test_host_port_pair));
+ EXPECT_FALSE(spdy_session_pool->HasSession(pair));
scoped_refptr<SpdySession> session =
- spdy_session_pool->Get(
- test_host_port_pair, http_session.get(), BoundNetLog());
- EXPECT_TRUE(spdy_session_pool->HasSession(test_host_port_pair));
+ spdy_session_pool->Get(pair, http_session.get(), BoundNetLog());
+ EXPECT_TRUE(spdy_session_pool->HasSession(pair));
// No push streams should exist in the beginning.
std::string test_push_path = "/foo.js";
diff --git a/net/spdy/spdy_stream_unittest.cc b/net/spdy/spdy_stream_unittest.cc
index 471a1786..94b08ec 100644
--- a/net/spdy/spdy_stream_unittest.cc
+++ b/net/spdy/spdy_stream_unittest.cc
@@ -118,9 +118,9 @@ class SpdyStreamTest : public testing::Test {
scoped_refptr<SpdySession> CreateSpdySession() {
spdy::SpdyFramer::set_enable_compression_default(false);
HostPortPair host_port_pair("www.google.com", 80);
+ HostPortProxyPair pair(host_port_pair, "");
scoped_refptr<SpdySession> session(
- session_->spdy_session_pool()->Get(
- host_port_pair, session_, BoundNetLog()));
+ session_->spdy_session_pool()->Get(pair, session_, BoundNetLog()));
return session;
}
diff --git a/net/spdy/spdy_test_util.cc b/net/spdy/spdy_test_util.cc
index 94b9889..aa566d1 100644
--- a/net/spdy/spdy_test_util.cc
+++ b/net/spdy/spdy_test_util.cc
@@ -599,4 +599,12 @@ int CombineFrames(const spdy::SpdyFrame** frames, int num_frames,
return total_len;
}
+// This creates a proxy for testing purposes.
+// |proxy| should be in the form "myproxy:70".
+ProxyService* SpdyCreateFixedProxyService(const std::string& proxy) {
+ net::ProxyConfig proxy_config;
+ proxy_config.proxy_rules().ParseFromString(proxy);
+ return ProxyService::CreateFixed(proxy_config);
+}
+
} // namespace net
diff --git a/net/spdy/spdy_test_util.h b/net/spdy/spdy_test_util.h
index 0282763..26b9a87 100644
--- a/net/spdy/spdy_test_util.h
+++ b/net/spdy/spdy_test_util.h
@@ -261,6 +261,9 @@ class SpdySessionDependencies {
}
};
+// This creates a proxy for testing purposes.
+// |proxy| should be in the form "myproxy:70".
+ProxyService* SpdyCreateFixedProxyService(const std::string& proxy);
} // namespace net