| // 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_proxy_client_socket_pool.h" | |
| #include "base/callback.h" | |
| #include "base/compiler_specific.h" | |
| #include "base/string_util.h" | |
| #include "base/time.h" | |
| #include "base/utf_string_conversions.h" | |
| #include "net/base/auth.h" | |
| #include "net/base/cert_verifier.h" | |
| #include "net/base/mock_host_resolver.h" | |
| #include "net/base/net_errors.h" | |
| #include "net/base/ssl_config_service_defaults.h" | |
| #include "net/base/test_certificate_data.h" | |
| #include "net/base/test_completion_callback.h" | |
| #include "net/http/http_auth_handler_factory.h" | |
| #include "net/http/http_network_session.h" | |
| #include "net/http/http_request_headers.h" | |
| #include "net/http/http_response_headers.h" | |
| #include "net/http/http_server_properties_impl.h" | |
| #include "net/proxy/proxy_service.h" | |
| #include "net/socket/client_socket_handle.h" | |
| #include "net/socket/client_socket_pool_histograms.h" | |
| #include "net/socket/socket_test_util.h" | |
| #include "net/spdy/spdy_session.h" | |
| #include "net/spdy/spdy_session_pool.h" | |
| #include "net/spdy/spdy_test_util_spdy2.h" | |
| #include "testing/gtest/include/gtest/gtest.h" | |
| using namespace net::test_spdy2; | |
| namespace net { | |
| namespace { | |
| const int kMaxSockets = 32; | |
| const int kMaxSocketsPerGroup = 6; | |
| class SSLClientSocketPoolTest : public testing::Test { | |
| protected: | |
| SSLClientSocketPoolTest() | |
| : proxy_service_(ProxyService::CreateDirect()), | |
| ssl_config_service_(new SSLConfigServiceDefaults), | |
| http_auth_handler_factory_(HttpAuthHandlerFactory::CreateDefault( | |
| &host_resolver_)), | |
| session_(CreateNetworkSession()), | |
| direct_transport_socket_params_(new TransportSocketParams( | |
| HostPortPair("host", 443), MEDIUM, false, false, | |
| OnHostResolutionCallback())), | |
| transport_histograms_("MockTCP"), | |
| transport_socket_pool_( | |
| kMaxSockets, | |
| kMaxSocketsPerGroup, | |
| &transport_histograms_, | |
| &socket_factory_), | |
| proxy_transport_socket_params_(new TransportSocketParams( | |
| HostPortPair("proxy", 443), MEDIUM, false, false, | |
| OnHostResolutionCallback())), | |
| socks_socket_params_(new SOCKSSocketParams( | |
| proxy_transport_socket_params_, true, | |
| HostPortPair("sockshost", 443), MEDIUM)), | |
| socks_histograms_("MockSOCKS"), | |
| socks_socket_pool_( | |
| kMaxSockets, | |
| kMaxSocketsPerGroup, | |
| &socks_histograms_, | |
| &transport_socket_pool_), | |
| http_proxy_socket_params_(new HttpProxySocketParams( | |
| proxy_transport_socket_params_, NULL, GURL("http://host"), "", | |
| HostPortPair("host", 80), | |
| session_->http_auth_cache(), | |
| session_->http_auth_handler_factory(), | |
| session_->spdy_session_pool(), | |
| true)), | |
| http_proxy_histograms_("MockHttpProxy"), | |
| http_proxy_socket_pool_( | |
| kMaxSockets, | |
| kMaxSocketsPerGroup, | |
| &http_proxy_histograms_, | |
| &host_resolver_, | |
| &transport_socket_pool_, | |
| NULL, | |
| NULL) { | |
| scoped_refptr<SSLConfigService> ssl_config_service( | |
| new SSLConfigServiceDefaults); | |
| ssl_config_service->GetSSLConfig(&ssl_config_); | |
| } | |
| void CreatePool(bool transport_pool, bool http_proxy_pool, bool socks_pool) { | |
| ssl_histograms_.reset(new ClientSocketPoolHistograms("SSLUnitTest")); | |
| pool_.reset(new SSLClientSocketPool( | |
| kMaxSockets, | |
| kMaxSocketsPerGroup, | |
| ssl_histograms_.get(), | |
| NULL /* host_resolver */, | |
| NULL /* cert_verifier */, | |
| NULL /* server_bound_cert_service */, | |
| NULL /* transport_security_state */, | |
| "" /* ssl_session_cache_shard */, | |
| &socket_factory_, | |
| transport_pool ? &transport_socket_pool_ : NULL, | |
| socks_pool ? &socks_socket_pool_ : NULL, | |
| http_proxy_pool ? &http_proxy_socket_pool_ : NULL, | |
| NULL, | |
| NULL)); | |
| } | |
| scoped_refptr<SSLSocketParams> SSLParams(ProxyServer::Scheme proxy, | |
| bool want_spdy_over_npn) { | |
| return make_scoped_refptr(new SSLSocketParams( | |
| proxy == ProxyServer::SCHEME_DIRECT ? | |
| direct_transport_socket_params_ : NULL, | |
| proxy == ProxyServer::SCHEME_SOCKS5 ? socks_socket_params_ : NULL, | |
| proxy == ProxyServer::SCHEME_HTTP ? http_proxy_socket_params_ : NULL, | |
| proxy, | |
| HostPortPair("host", 443), | |
| ssl_config_, | |
| 0, | |
| false, | |
| want_spdy_over_npn)); | |
| } | |
| void AddAuthToCache() { | |
| const string16 kFoo(ASCIIToUTF16("foo")); | |
| const string16 kBar(ASCIIToUTF16("bar")); | |
| session_->http_auth_cache()->Add(GURL("http://proxy:443/"), | |
| "MyRealm1", | |
| HttpAuth::AUTH_SCHEME_BASIC, | |
| "Basic realm=MyRealm1", | |
| AuthCredentials(kFoo, kBar), | |
| "/"); | |
| } | |
| HttpNetworkSession* CreateNetworkSession() { | |
| HttpNetworkSession::Params params; | |
| params.host_resolver = &host_resolver_; | |
| params.cert_verifier = cert_verifier_.get(); | |
| params.proxy_service = proxy_service_.get(); | |
| params.client_socket_factory = &socket_factory_; | |
| params.ssl_config_service = ssl_config_service_; | |
| params.http_auth_handler_factory = http_auth_handler_factory_.get(); | |
| params.http_server_properties = &http_server_properties_; | |
| params.enable_spdy_compression = false; | |
| return new HttpNetworkSession(params); | |
| } | |
| void TestIPPoolingDisabled(SSLSocketDataProvider* ssl); | |
| MockClientSocketFactory socket_factory_; | |
| MockCachingHostResolver host_resolver_; | |
| scoped_ptr<CertVerifier> cert_verifier_; | |
| const scoped_ptr<ProxyService> proxy_service_; | |
| const scoped_refptr<SSLConfigService> ssl_config_service_; | |
| const scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory_; | |
| HttpServerPropertiesImpl http_server_properties_; | |
| const scoped_refptr<HttpNetworkSession> session_; | |
| scoped_refptr<TransportSocketParams> direct_transport_socket_params_; | |
| ClientSocketPoolHistograms transport_histograms_; | |
| MockTransportClientSocketPool transport_socket_pool_; | |
| scoped_refptr<TransportSocketParams> proxy_transport_socket_params_; | |
| scoped_refptr<SOCKSSocketParams> socks_socket_params_; | |
| ClientSocketPoolHistograms socks_histograms_; | |
| MockSOCKSClientSocketPool socks_socket_pool_; | |
| scoped_refptr<HttpProxySocketParams> http_proxy_socket_params_; | |
| ClientSocketPoolHistograms http_proxy_histograms_; | |
| HttpProxyClientSocketPool http_proxy_socket_pool_; | |
| SSLConfig ssl_config_; | |
| scoped_ptr<ClientSocketPoolHistograms> ssl_histograms_; | |
| scoped_ptr<SSLClientSocketPool> pool_; | |
| }; | |
| TEST_F(SSLClientSocketPoolTest, TCPFail) { | |
| StaticSocketDataProvider data; | |
| data.set_connect_data(MockConnect(SYNCHRONOUS, ERR_CONNECTION_FAILED)); | |
| socket_factory_.AddSocketDataProvider(&data); | |
| CreatePool(true /* tcp pool */, false, false); | |
| scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT, | |
| false); | |
| ClientSocketHandle handle; | |
| int rv = handle.Init("a", params, MEDIUM, CompletionCallback(), pool_.get(), | |
| BoundNetLog()); | |
| EXPECT_EQ(ERR_CONNECTION_FAILED, rv); | |
| EXPECT_FALSE(handle.is_initialized()); | |
| EXPECT_FALSE(handle.socket()); | |
| EXPECT_FALSE(handle.is_ssl_error()); | |
| } | |
| TEST_F(SSLClientSocketPoolTest, TCPFailAsync) { | |
| StaticSocketDataProvider data; | |
| data.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_FAILED)); | |
| socket_factory_.AddSocketDataProvider(&data); | |
| CreatePool(true /* tcp pool */, false, false); | |
| scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT, | |
| false); | |
| ClientSocketHandle handle; | |
| TestCompletionCallback callback; | |
| int rv = handle.Init( | |
| "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog()); | |
| EXPECT_EQ(ERR_IO_PENDING, rv); | |
| EXPECT_FALSE(handle.is_initialized()); | |
| EXPECT_FALSE(handle.socket()); | |
| EXPECT_EQ(ERR_CONNECTION_FAILED, callback.WaitForResult()); | |
| EXPECT_FALSE(handle.is_initialized()); | |
| EXPECT_FALSE(handle.socket()); | |
| EXPECT_FALSE(handle.is_ssl_error()); | |
| } | |
| TEST_F(SSLClientSocketPoolTest, BasicDirect) { | |
| StaticSocketDataProvider data; | |
| data.set_connect_data(MockConnect(SYNCHRONOUS, OK)); | |
| socket_factory_.AddSocketDataProvider(&data); | |
| SSLSocketDataProvider ssl(SYNCHRONOUS, OK); | |
| socket_factory_.AddSSLSocketDataProvider(&ssl); | |
| CreatePool(true /* tcp pool */, false, false); | |
| scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT, | |
| false); | |
| ClientSocketHandle handle; | |
| TestCompletionCallback callback; | |
| int rv = handle.Init( | |
| "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog()); | |
| EXPECT_EQ(OK, rv); | |
| EXPECT_TRUE(handle.is_initialized()); | |
| EXPECT_TRUE(handle.socket()); | |
| } | |
| TEST_F(SSLClientSocketPoolTest, BasicDirectAsync) { | |
| StaticSocketDataProvider data; | |
| socket_factory_.AddSocketDataProvider(&data); | |
| SSLSocketDataProvider ssl(ASYNC, OK); | |
| socket_factory_.AddSSLSocketDataProvider(&ssl); | |
| CreatePool(true /* tcp pool */, false, false); | |
| scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT, | |
| false); | |
| ClientSocketHandle handle; | |
| TestCompletionCallback callback; | |
| int rv = handle.Init( | |
| "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog()); | |
| EXPECT_EQ(ERR_IO_PENDING, rv); | |
| EXPECT_FALSE(handle.is_initialized()); | |
| EXPECT_FALSE(handle.socket()); | |
| EXPECT_EQ(OK, callback.WaitForResult()); | |
| EXPECT_TRUE(handle.is_initialized()); | |
| EXPECT_TRUE(handle.socket()); | |
| } | |
| TEST_F(SSLClientSocketPoolTest, DirectCertError) { | |
| StaticSocketDataProvider data; | |
| socket_factory_.AddSocketDataProvider(&data); | |
| SSLSocketDataProvider ssl(ASYNC, ERR_CERT_COMMON_NAME_INVALID); | |
| socket_factory_.AddSSLSocketDataProvider(&ssl); | |
| CreatePool(true /* tcp pool */, false, false); | |
| scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT, | |
| false); | |
| ClientSocketHandle handle; | |
| TestCompletionCallback callback; | |
| int rv = handle.Init( | |
| "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog()); | |
| EXPECT_EQ(ERR_IO_PENDING, rv); | |
| EXPECT_FALSE(handle.is_initialized()); | |
| EXPECT_FALSE(handle.socket()); | |
| EXPECT_EQ(ERR_CERT_COMMON_NAME_INVALID, callback.WaitForResult()); | |
| EXPECT_TRUE(handle.is_initialized()); | |
| EXPECT_TRUE(handle.socket()); | |
| } | |
| TEST_F(SSLClientSocketPoolTest, DirectSSLError) { | |
| StaticSocketDataProvider data; | |
| socket_factory_.AddSocketDataProvider(&data); | |
| SSLSocketDataProvider ssl(ASYNC, ERR_SSL_PROTOCOL_ERROR); | |
| socket_factory_.AddSSLSocketDataProvider(&ssl); | |
| CreatePool(true /* tcp pool */, false, false); | |
| scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT, | |
| false); | |
| ClientSocketHandle handle; | |
| TestCompletionCallback callback; | |
| int rv = handle.Init( | |
| "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog()); | |
| EXPECT_EQ(ERR_IO_PENDING, rv); | |
| EXPECT_FALSE(handle.is_initialized()); | |
| EXPECT_FALSE(handle.socket()); | |
| EXPECT_EQ(ERR_SSL_PROTOCOL_ERROR, callback.WaitForResult()); | |
| EXPECT_FALSE(handle.is_initialized()); | |
| EXPECT_FALSE(handle.socket()); | |
| EXPECT_TRUE(handle.is_ssl_error()); | |
| } | |
| TEST_F(SSLClientSocketPoolTest, DirectWithNPN) { | |
| StaticSocketDataProvider data; | |
| socket_factory_.AddSocketDataProvider(&data); | |
| SSLSocketDataProvider ssl(ASYNC, OK); | |
| ssl.SetNextProto(kProtoHTTP11); | |
| socket_factory_.AddSSLSocketDataProvider(&ssl); | |
| CreatePool(true /* tcp pool */, false, false); | |
| scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT, | |
| false); | |
| ClientSocketHandle handle; | |
| TestCompletionCallback callback; | |
| int rv = handle.Init( | |
| "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog()); | |
| EXPECT_EQ(ERR_IO_PENDING, rv); | |
| EXPECT_FALSE(handle.is_initialized()); | |
| EXPECT_FALSE(handle.socket()); | |
| EXPECT_EQ(OK, callback.WaitForResult()); | |
| EXPECT_TRUE(handle.is_initialized()); | |
| EXPECT_TRUE(handle.socket()); | |
| SSLClientSocket* ssl_socket = static_cast<SSLClientSocket*>(handle.socket()); | |
| EXPECT_TRUE(ssl_socket->WasNpnNegotiated()); | |
| } | |
| TEST_F(SSLClientSocketPoolTest, DirectNoSPDY) { | |
| StaticSocketDataProvider data; | |
| socket_factory_.AddSocketDataProvider(&data); | |
| SSLSocketDataProvider ssl(ASYNC, OK); | |
| ssl.SetNextProto(kProtoHTTP11); | |
| socket_factory_.AddSSLSocketDataProvider(&ssl); | |
| CreatePool(true /* tcp pool */, false, false); | |
| scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT, | |
| true); | |
| ClientSocketHandle handle; | |
| TestCompletionCallback callback; | |
| int rv = handle.Init( | |
| "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog()); | |
| EXPECT_EQ(ERR_IO_PENDING, rv); | |
| EXPECT_FALSE(handle.is_initialized()); | |
| EXPECT_FALSE(handle.socket()); | |
| EXPECT_EQ(ERR_NPN_NEGOTIATION_FAILED, callback.WaitForResult()); | |
| EXPECT_FALSE(handle.is_initialized()); | |
| EXPECT_FALSE(handle.socket()); | |
| EXPECT_TRUE(handle.is_ssl_error()); | |
| } | |
| TEST_F(SSLClientSocketPoolTest, DirectGotSPDY) { | |
| StaticSocketDataProvider data; | |
| socket_factory_.AddSocketDataProvider(&data); | |
| SSLSocketDataProvider ssl(ASYNC, OK); | |
| ssl.SetNextProto(kProtoSPDY2); | |
| socket_factory_.AddSSLSocketDataProvider(&ssl); | |
| CreatePool(true /* tcp pool */, false, false); | |
| scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT, | |
| true); | |
| ClientSocketHandle handle; | |
| TestCompletionCallback callback; | |
| int rv = handle.Init( | |
| "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog()); | |
| EXPECT_EQ(ERR_IO_PENDING, rv); | |
| EXPECT_FALSE(handle.is_initialized()); | |
| EXPECT_FALSE(handle.socket()); | |
| EXPECT_EQ(OK, callback.WaitForResult()); | |
| EXPECT_TRUE(handle.is_initialized()); | |
| EXPECT_TRUE(handle.socket()); | |
| SSLClientSocket* ssl_socket = static_cast<SSLClientSocket*>(handle.socket()); | |
| EXPECT_TRUE(ssl_socket->WasNpnNegotiated()); | |
| std::string proto; | |
| std::string server_protos; | |
| ssl_socket->GetNextProto(&proto, &server_protos); | |
| EXPECT_EQ(SSLClientSocket::NextProtoFromString(proto), | |
| kProtoSPDY2); | |
| } | |
| TEST_F(SSLClientSocketPoolTest, DirectGotBonusSPDY) { | |
| StaticSocketDataProvider data; | |
| socket_factory_.AddSocketDataProvider(&data); | |
| SSLSocketDataProvider ssl(ASYNC, OK); | |
| ssl.SetNextProto(kProtoSPDY2); | |
| socket_factory_.AddSSLSocketDataProvider(&ssl); | |
| CreatePool(true /* tcp pool */, false, false); | |
| scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT, | |
| true); | |
| ClientSocketHandle handle; | |
| TestCompletionCallback callback; | |
| int rv = handle.Init( | |
| "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog()); | |
| EXPECT_EQ(ERR_IO_PENDING, rv); | |
| EXPECT_FALSE(handle.is_initialized()); | |
| EXPECT_FALSE(handle.socket()); | |
| EXPECT_EQ(OK, callback.WaitForResult()); | |
| EXPECT_TRUE(handle.is_initialized()); | |
| EXPECT_TRUE(handle.socket()); | |
| SSLClientSocket* ssl_socket = static_cast<SSLClientSocket*>(handle.socket()); | |
| EXPECT_TRUE(ssl_socket->WasNpnNegotiated()); | |
| std::string proto; | |
| std::string server_protos; | |
| ssl_socket->GetNextProto(&proto, &server_protos); | |
| EXPECT_EQ(SSLClientSocket::NextProtoFromString(proto), | |
| kProtoSPDY2); | |
| } | |
| TEST_F(SSLClientSocketPoolTest, SOCKSFail) { | |
| StaticSocketDataProvider data; | |
| data.set_connect_data(MockConnect(SYNCHRONOUS, ERR_CONNECTION_FAILED)); | |
| socket_factory_.AddSocketDataProvider(&data); | |
| CreatePool(false, true /* http proxy pool */, true /* socks pool */); | |
| scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_SOCKS5, | |
| false); | |
| ClientSocketHandle handle; | |
| TestCompletionCallback callback; | |
| int rv = handle.Init( | |
| "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog()); | |
| EXPECT_EQ(ERR_CONNECTION_FAILED, rv); | |
| EXPECT_FALSE(handle.is_initialized()); | |
| EXPECT_FALSE(handle.socket()); | |
| EXPECT_FALSE(handle.is_ssl_error()); | |
| } | |
| TEST_F(SSLClientSocketPoolTest, SOCKSFailAsync) { | |
| StaticSocketDataProvider data; | |
| data.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_FAILED)); | |
| socket_factory_.AddSocketDataProvider(&data); | |
| CreatePool(false, true /* http proxy pool */, true /* socks pool */); | |
| scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_SOCKS5, | |
| false); | |
| ClientSocketHandle handle; | |
| TestCompletionCallback callback; | |
| int rv = handle.Init( | |
| "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog()); | |
| EXPECT_EQ(ERR_IO_PENDING, rv); | |
| EXPECT_FALSE(handle.is_initialized()); | |
| EXPECT_FALSE(handle.socket()); | |
| EXPECT_EQ(ERR_CONNECTION_FAILED, callback.WaitForResult()); | |
| EXPECT_FALSE(handle.is_initialized()); | |
| EXPECT_FALSE(handle.socket()); | |
| EXPECT_FALSE(handle.is_ssl_error()); | |
| } | |
| TEST_F(SSLClientSocketPoolTest, SOCKSBasic) { | |
| StaticSocketDataProvider data; | |
| data.set_connect_data(MockConnect(SYNCHRONOUS, OK)); | |
| socket_factory_.AddSocketDataProvider(&data); | |
| SSLSocketDataProvider ssl(SYNCHRONOUS, OK); | |
| socket_factory_.AddSSLSocketDataProvider(&ssl); | |
| CreatePool(false, true /* http proxy pool */, true /* socks pool */); | |
| scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_SOCKS5, | |
| false); | |
| ClientSocketHandle handle; | |
| TestCompletionCallback callback; | |
| int rv = handle.Init( | |
| "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog()); | |
| EXPECT_EQ(OK, rv); | |
| EXPECT_TRUE(handle.is_initialized()); | |
| EXPECT_TRUE(handle.socket()); | |
| } | |
| TEST_F(SSLClientSocketPoolTest, SOCKSBasicAsync) { | |
| StaticSocketDataProvider data; | |
| socket_factory_.AddSocketDataProvider(&data); | |
| SSLSocketDataProvider ssl(ASYNC, OK); | |
| socket_factory_.AddSSLSocketDataProvider(&ssl); | |
| CreatePool(false, true /* http proxy pool */, true /* socks pool */); | |
| scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_SOCKS5, | |
| false); | |
| ClientSocketHandle handle; | |
| TestCompletionCallback callback; | |
| int rv = handle.Init( | |
| "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog()); | |
| EXPECT_EQ(ERR_IO_PENDING, rv); | |
| EXPECT_FALSE(handle.is_initialized()); | |
| EXPECT_FALSE(handle.socket()); | |
| EXPECT_EQ(OK, callback.WaitForResult()); | |
| EXPECT_TRUE(handle.is_initialized()); | |
| EXPECT_TRUE(handle.socket()); | |
| } | |
| TEST_F(SSLClientSocketPoolTest, HttpProxyFail) { | |
| StaticSocketDataProvider data; | |
| data.set_connect_data(MockConnect(SYNCHRONOUS, ERR_CONNECTION_FAILED)); | |
| socket_factory_.AddSocketDataProvider(&data); | |
| CreatePool(false, true /* http proxy pool */, true /* socks pool */); | |
| scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_HTTP, | |
| false); | |
| ClientSocketHandle handle; | |
| TestCompletionCallback callback; | |
| int rv = handle.Init( | |
| "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog()); | |
| EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv); | |
| EXPECT_FALSE(handle.is_initialized()); | |
| EXPECT_FALSE(handle.socket()); | |
| EXPECT_FALSE(handle.is_ssl_error()); | |
| } | |
| TEST_F(SSLClientSocketPoolTest, HttpProxyFailAsync) { | |
| StaticSocketDataProvider data; | |
| data.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_FAILED)); | |
| socket_factory_.AddSocketDataProvider(&data); | |
| CreatePool(false, true /* http proxy pool */, true /* socks pool */); | |
| scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_HTTP, | |
| false); | |
| ClientSocketHandle handle; | |
| TestCompletionCallback callback; | |
| int rv = handle.Init( | |
| "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog()); | |
| EXPECT_EQ(ERR_IO_PENDING, rv); | |
| EXPECT_FALSE(handle.is_initialized()); | |
| EXPECT_FALSE(handle.socket()); | |
| EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, callback.WaitForResult()); | |
| EXPECT_FALSE(handle.is_initialized()); | |
| EXPECT_FALSE(handle.socket()); | |
| EXPECT_FALSE(handle.is_ssl_error()); | |
| } | |
| TEST_F(SSLClientSocketPoolTest, HttpProxyBasic) { | |
| MockWrite writes[] = { | |
| MockWrite(SYNCHRONOUS, | |
| "CONNECT host:80 HTTP/1.1\r\n" | |
| "Host: host\r\n" | |
| "Proxy-Connection: keep-alive\r\n" | |
| "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), | |
| }; | |
| MockRead reads[] = { | |
| MockRead(SYNCHRONOUS, "HTTP/1.1 200 Connection Established\r\n\r\n"), | |
| }; | |
| StaticSocketDataProvider data(reads, arraysize(reads), writes, | |
| arraysize(writes)); | |
| data.set_connect_data(MockConnect(SYNCHRONOUS, OK)); | |
| socket_factory_.AddSocketDataProvider(&data); | |
| AddAuthToCache(); | |
| SSLSocketDataProvider ssl(SYNCHRONOUS, OK); | |
| socket_factory_.AddSSLSocketDataProvider(&ssl); | |
| CreatePool(false, true /* http proxy pool */, true /* socks pool */); | |
| scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_HTTP, | |
| false); | |
| ClientSocketHandle handle; | |
| TestCompletionCallback callback; | |
| int rv = handle.Init( | |
| "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog()); | |
| EXPECT_EQ(OK, rv); | |
| EXPECT_TRUE(handle.is_initialized()); | |
| EXPECT_TRUE(handle.socket()); | |
| } | |
| TEST_F(SSLClientSocketPoolTest, HttpProxyBasicAsync) { | |
| MockWrite writes[] = { | |
| MockWrite("CONNECT host:80 HTTP/1.1\r\n" | |
| "Host: host\r\n" | |
| "Proxy-Connection: keep-alive\r\n" | |
| "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), | |
| }; | |
| MockRead reads[] = { | |
| MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"), | |
| }; | |
| StaticSocketDataProvider data(reads, arraysize(reads), writes, | |
| arraysize(writes)); | |
| socket_factory_.AddSocketDataProvider(&data); | |
| AddAuthToCache(); | |
| SSLSocketDataProvider ssl(ASYNC, OK); | |
| socket_factory_.AddSSLSocketDataProvider(&ssl); | |
| CreatePool(false, true /* http proxy pool */, true /* socks pool */); | |
| scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_HTTP, | |
| false); | |
| ClientSocketHandle handle; | |
| TestCompletionCallback callback; | |
| int rv = handle.Init( | |
| "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog()); | |
| EXPECT_EQ(ERR_IO_PENDING, rv); | |
| EXPECT_FALSE(handle.is_initialized()); | |
| EXPECT_FALSE(handle.socket()); | |
| EXPECT_EQ(OK, callback.WaitForResult()); | |
| EXPECT_TRUE(handle.is_initialized()); | |
| EXPECT_TRUE(handle.socket()); | |
| } | |
| TEST_F(SSLClientSocketPoolTest, NeedProxyAuth) { | |
| MockWrite writes[] = { | |
| MockWrite("CONNECT host:80 HTTP/1.1\r\n" | |
| "Host: host\r\n" | |
| "Proxy-Connection: keep-alive\r\n\r\n"), | |
| }; | |
| MockRead reads[] = { | |
| MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"), | |
| MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), | |
| MockRead("Content-Length: 10\r\n\r\n"), | |
| MockRead("0123456789"), | |
| }; | |
| StaticSocketDataProvider data(reads, arraysize(reads), writes, | |
| arraysize(writes)); | |
| socket_factory_.AddSocketDataProvider(&data); | |
| SSLSocketDataProvider ssl(ASYNC, OK); | |
| socket_factory_.AddSSLSocketDataProvider(&ssl); | |
| CreatePool(false, true /* http proxy pool */, true /* socks pool */); | |
| scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_HTTP, | |
| false); | |
| ClientSocketHandle handle; | |
| TestCompletionCallback callback; | |
| int rv = handle.Init( | |
| "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog()); | |
| EXPECT_EQ(ERR_IO_PENDING, rv); | |
| EXPECT_FALSE(handle.is_initialized()); | |
| EXPECT_FALSE(handle.socket()); | |
| EXPECT_EQ(ERR_PROXY_AUTH_REQUESTED, callback.WaitForResult()); | |
| EXPECT_FALSE(handle.is_initialized()); | |
| EXPECT_FALSE(handle.socket()); | |
| EXPECT_FALSE(handle.is_ssl_error()); | |
| const HttpResponseInfo& tunnel_info = handle.ssl_error_response_info(); | |
| EXPECT_EQ(tunnel_info.headers->response_code(), 407); | |
| scoped_ptr<ClientSocketHandle> tunnel_handle( | |
| handle.release_pending_http_proxy_connection()); | |
| EXPECT_TRUE(tunnel_handle->socket()); | |
| EXPECT_FALSE(tunnel_handle->socket()->IsConnected()); | |
| } | |
| TEST_F(SSLClientSocketPoolTest, IPPooling) { | |
| const int kTestPort = 80; | |
| struct TestHosts { | |
| std::string name; | |
| std::string iplist; | |
| HostPortProxyPair pair; | |
| AddressList addresses; | |
| } test_hosts[] = { | |
| { "www.webkit.org", "192.0.2.33,192.168.0.1,192.168.0.5" }, | |
| { "code.google.com", "192.168.0.2,192.168.0.3,192.168.0.5" }, | |
| { "js.webkit.org", "192.168.0.4,192.168.0.1,192.0.2.33" }, | |
| }; | |
| host_resolver_.set_synchronous_mode(true); | |
| for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_hosts); i++) { | |
| host_resolver_.rules()->AddIPLiteralRule(test_hosts[i].name, | |
| test_hosts[i].iplist, ""); | |
| // This test requires that the HostResolver cache be populated. Normal | |
| // code would have done this already, but we do it manually. | |
| HostResolver::RequestInfo info(HostPortPair(test_hosts[i].name, kTestPort)); | |
| host_resolver_.Resolve(info, &test_hosts[i].addresses, CompletionCallback(), | |
| NULL, BoundNetLog()); | |
| // Setup a HostPortProxyPair | |
| test_hosts[i].pair = HostPortProxyPair( | |
| HostPortPair(test_hosts[i].name, kTestPort), ProxyServer::Direct()); | |
| } | |
| MockRead reads[] = { | |
| MockRead(ASYNC, ERR_IO_PENDING), | |
| }; | |
| StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); | |
| socket_factory_.AddSocketDataProvider(&data); | |
| SSLSocketDataProvider ssl(ASYNC, OK); | |
| ssl.cert = X509Certificate::CreateFromBytes( | |
| reinterpret_cast<const char*>(webkit_der), sizeof(webkit_der)); | |
| ssl.SetNextProto(kProtoSPDY2); | |
| socket_factory_.AddSSLSocketDataProvider(&ssl); | |
| CreatePool(true /* tcp pool */, false, false); | |
| scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT, | |
| true); | |
| scoped_ptr<ClientSocketHandle> handle(new ClientSocketHandle()); | |
| TestCompletionCallback callback; | |
| int rv = handle->Init( | |
| "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog()); | |
| EXPECT_EQ(ERR_IO_PENDING, rv); | |
| EXPECT_FALSE(handle->is_initialized()); | |
| EXPECT_FALSE(handle->socket()); | |
| EXPECT_EQ(OK, callback.WaitForResult()); | |
| EXPECT_TRUE(handle->is_initialized()); | |
| EXPECT_TRUE(handle->socket()); | |
| SSLClientSocket* ssl_socket = static_cast<SSLClientSocket*>(handle->socket()); | |
| EXPECT_TRUE(ssl_socket->WasNpnNegotiated()); | |
| std::string proto; | |
| std::string server_protos; | |
| ssl_socket->GetNextProto(&proto, &server_protos); | |
| EXPECT_EQ(SSLClientSocket::NextProtoFromString(proto), | |
| kProtoSPDY2); | |
| #if !defined(COBALT_DISABLE_SPDY) | |
| // TODO(rtenneti): MockClientSocket::GetPeerAddress returns 0 as the port | |
| // number. Fix it to return port 80 and then use GetPeerAddress to AddAlias. | |
| SpdySessionPoolPeer pool_peer(session_->spdy_session_pool()); | |
| pool_peer.AddAlias(test_hosts[0].addresses.front(), test_hosts[0].pair); | |
| scoped_refptr<SpdySession> spdy_session; | |
| rv = session_->spdy_session_pool()->GetSpdySessionFromSocket( | |
| test_hosts[0].pair, handle.release(), BoundNetLog(), 0, | |
| &spdy_session, true); | |
| EXPECT_EQ(0, rv); | |
| EXPECT_TRUE(session_->spdy_session_pool()->HasSession(test_hosts[0].pair)); | |
| EXPECT_FALSE(session_->spdy_session_pool()->HasSession(test_hosts[1].pair)); | |
| EXPECT_TRUE(session_->spdy_session_pool()->HasSession(test_hosts[2].pair)); | |
| session_->spdy_session_pool()->CloseAllSessions(); | |
| #endif // !defined(COBALT_DISABLE_SPDY) | |
| } | |
| void SSLClientSocketPoolTest::TestIPPoolingDisabled( | |
| SSLSocketDataProvider* ssl) { | |
| const int kTestPort = 80; | |
| struct TestHosts { | |
| std::string name; | |
| std::string iplist; | |
| HostPortProxyPair pair; | |
| AddressList addresses; | |
| } test_hosts[] = { | |
| { "www.webkit.org", "192.0.2.33,192.168.0.1,192.168.0.5" }, | |
| { "js.webkit.com", "192.168.0.4,192.168.0.1,192.0.2.33" }, | |
| }; | |
| TestCompletionCallback callback; | |
| int rv; | |
| for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_hosts); i++) { | |
| host_resolver_.rules()->AddIPLiteralRule(test_hosts[i].name, | |
| test_hosts[i].iplist, ""); | |
| // This test requires that the HostResolver cache be populated. Normal | |
| // code would have done this already, but we do it manually. | |
| HostResolver::RequestInfo info(HostPortPair(test_hosts[i].name, kTestPort)); | |
| rv = host_resolver_.Resolve(info, &test_hosts[i].addresses, | |
| callback.callback(), NULL, BoundNetLog()); | |
| EXPECT_EQ(OK, callback.GetResult(rv)); | |
| // Setup a HostPortProxyPair | |
| test_hosts[i].pair = HostPortProxyPair( | |
| HostPortPair(test_hosts[i].name, kTestPort), ProxyServer::Direct()); | |
| } | |
| MockRead reads[] = { | |
| MockRead(ASYNC, ERR_IO_PENDING), | |
| }; | |
| StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); | |
| socket_factory_.AddSocketDataProvider(&data); | |
| socket_factory_.AddSSLSocketDataProvider(ssl); | |
| CreatePool(true /* tcp pool */, false, false); | |
| scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT, | |
| true); | |
| scoped_ptr<ClientSocketHandle> handle(new ClientSocketHandle()); | |
| rv = handle->Init( | |
| "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog()); | |
| EXPECT_EQ(ERR_IO_PENDING, rv); | |
| EXPECT_FALSE(handle->is_initialized()); | |
| EXPECT_FALSE(handle->socket()); | |
| EXPECT_EQ(OK, callback.WaitForResult()); | |
| EXPECT_TRUE(handle->is_initialized()); | |
| EXPECT_TRUE(handle->socket()); | |
| SSLClientSocket* ssl_socket = static_cast<SSLClientSocket*>(handle->socket()); | |
| EXPECT_TRUE(ssl_socket->WasNpnNegotiated()); | |
| std::string proto; | |
| std::string server_protos; | |
| ssl_socket->GetNextProto(&proto, &server_protos); | |
| EXPECT_EQ(SSLClientSocket::NextProtoFromString(proto), | |
| kProtoSPDY2); | |
| #if !defined(COBALT_DISABLE_SPDY) | |
| // TODO(rtenneti): MockClientSocket::GetPeerAddress returns 0 as the port | |
| // number. Fix it to return port 80 and then use GetPeerAddress to AddAlias. | |
| SpdySessionPoolPeer pool_peer(session_->spdy_session_pool()); | |
| pool_peer.AddAlias(test_hosts[0].addresses.front(), test_hosts[0].pair); | |
| scoped_refptr<SpdySession> spdy_session; | |
| rv = session_->spdy_session_pool()->GetSpdySessionFromSocket( | |
| test_hosts[0].pair, handle.release(), BoundNetLog(), 0, | |
| &spdy_session, true); | |
| EXPECT_EQ(0, rv); | |
| EXPECT_TRUE(session_->spdy_session_pool()->HasSession(test_hosts[0].pair)); | |
| EXPECT_FALSE(session_->spdy_session_pool()->HasSession(test_hosts[1].pair)); | |
| session_->spdy_session_pool()->CloseAllSessions(); | |
| #endif // !defined(COBALT_DISABLE_SPDY) | |
| } | |
| // Verifies that an SSL connection with client authentication disables SPDY IP | |
| // pooling. | |
| TEST_F(SSLClientSocketPoolTest, IPPoolingClientCert) { | |
| SSLSocketDataProvider ssl(ASYNC, OK); | |
| ssl.cert = X509Certificate::CreateFromBytes( | |
| reinterpret_cast<const char*>(webkit_der), sizeof(webkit_der)); | |
| ssl.client_cert_sent = true; | |
| ssl.SetNextProto(kProtoSPDY2); | |
| TestIPPoolingDisabled(&ssl); | |
| } | |
| // Verifies that an SSL connection with channel ID disables SPDY IP pooling. | |
| TEST_F(SSLClientSocketPoolTest, IPPoolingChannelID) { | |
| SSLSocketDataProvider ssl(ASYNC, OK); | |
| ssl.channel_id_sent = true; | |
| ssl.SetNextProto(kProtoSPDY2); | |
| TestIPPoolingDisabled(&ssl); | |
| } | |
| // It would be nice to also test the timeouts in SSLClientSocketPool. | |
| } // namespace | |
| } // namespace net |