diff options
author | jri <jri@chromium.org> | 2014-09-12 16:52:39 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-09-12 23:56:43 +0000 |
commit | dcb4ae922b46a90ef6ec199b772f399e4610f514 (patch) | |
tree | 52018c194a806003b471fdba0f928ff9d44512a3 /net | |
parent | ca2e1496db635fb826949d54c72798fd56f7fcfd (diff) | |
download | chromium_src-dcb4ae922b46a90ef6ec199b772f399e4610f514.zip chromium_src-dcb4ae922b46a90ef6ec199b772f399e4610f514.tar.gz chromium_src-dcb4ae922b46a90ef6ec199b772f399e4610f514.tar.bz2 |
Plumbing for TCP FastOpen for SSL sockets.
TCP FastOpen is currently turned on for all TCP connections when explicitly enabled from flags. This CL implements the plumbing required to turn it on for SSL connections by default. A subsequent CL will do the Finch plumbing.
BUG=402005
Review URL: https://codereview.chromium.org/451383002
Cr-Commit-Position: refs/heads/master@{#294697}
Diffstat (limited to 'net')
22 files changed, 424 insertions, 181 deletions
diff --git a/net/http/http_proxy_client_socket_pool_unittest.cc b/net/http/http_proxy_client_socket_pool_unittest.cc index 9590877..c6433af 100644 --- a/net/http/http_proxy_client_socket_pool_unittest.cc +++ b/net/http/http_proxy_client_socket_pool_unittest.cc @@ -192,10 +192,12 @@ class HttpProxyClientSocketPoolTest scoped_refptr<TransportSocketParams> CreateHttpProxyParams() const { if (GetParam().proxy_type != HTTP) return NULL; - return new TransportSocketParams(HostPortPair(kHttpProxyHost, 80), - false, - false, - OnHostResolutionCallback()); + return new TransportSocketParams( + HostPortPair(kHttpProxyHost, 80), + false, + false, + OnHostResolutionCallback(), + TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT); } scoped_refptr<SSLSocketParams> CreateHttpsProxyParams() const { @@ -206,7 +208,8 @@ class HttpProxyClientSocketPoolTest HostPortPair(kHttpsProxyHost, 443), false, false, - OnHostResolutionCallback()), + OnHostResolutionCallback(), + TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT), NULL, NULL, HostPortPair(kHttpsProxyHost, 443), diff --git a/net/net.gypi b/net/net.gypi index f309dd8..1f60118 100644 --- a/net/net.gypi +++ b/net/net.gypi @@ -980,7 +980,6 @@ 'socket/tcp_listen_socket.h', 'socket/tcp_server_socket.cc', 'socket/tcp_server_socket.h', - 'socket/tcp_socket.cc', 'socket/tcp_socket.h', 'socket/tcp_socket_libevent.cc', 'socket/tcp_socket_libevent.h', diff --git a/net/socket/client_socket_pool_manager.cc b/net/socket/client_socket_pool_manager.cc index 08fc487..a11965c 100644 --- a/net/socket/client_socket_pool_manager.cc +++ b/net/socket/client_socket_pool_manager.cc @@ -84,7 +84,6 @@ int InitSocketPoolHelper(const GURL& request_url, HttpNetworkSession::SocketPoolType socket_pool_type, const OnHostResolutionCallback& resolution_callback, const CompletionCallback& callback) { - scoped_refptr<TransportSocketParams> tcp_params; scoped_refptr<HttpProxySocketParams> http_proxy_params; scoped_refptr<SOCKSSocketParams> socks_params; scoped_ptr<HostPortPair> proxy_host_port; @@ -155,19 +154,16 @@ int InitSocketPoolHelper(const GURL& request_url, } bool ignore_limits = (request_load_flags & LOAD_IGNORE_LIMITS) != 0; - if (proxy_info.is_direct()) { - tcp_params = new TransportSocketParams(origin_host_port, - disable_resolver_cache, - ignore_limits, - resolution_callback); - } else { + if (!proxy_info.is_direct()) { ProxyServer proxy_server = proxy_info.proxy_server(); proxy_host_port.reset(new HostPortPair(proxy_server.host_port_pair())); scoped_refptr<TransportSocketParams> proxy_tcp_params( - new TransportSocketParams(*proxy_host_port, - disable_resolver_cache, - ignore_limits, - resolution_callback)); + new TransportSocketParams( + *proxy_host_port, + disable_resolver_cache, + ignore_limits, + resolution_callback, + TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT)); if (proxy_info.is_http() || proxy_info.is_https()) { std::string user_agent; @@ -175,6 +171,15 @@ int InitSocketPoolHelper(const GURL& request_url, &user_agent); scoped_refptr<SSLSocketParams> ssl_params; if (proxy_info.is_https()) { + // TODO (jri): Enable a finch trial to use + // COMBINE_CONNECT_AND_WRITE_DESIRED for SSL sockets. + proxy_tcp_params = + new TransportSocketParams( + *proxy_host_port, + disable_resolver_cache, + ignore_limits, + resolution_callback, + TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT); // Set ssl_params, and unset proxy_tcp_params ssl_params = new SSLSocketParams(proxy_tcp_params, NULL, @@ -221,8 +226,21 @@ int InitSocketPoolHelper(const GURL& request_url, // Deal with SSL - which layers on top of any given proxy. if (using_ssl) { + scoped_refptr<TransportSocketParams> ssl_tcp_params; + if (proxy_info.is_direct()) { + // Setup TCP params if non-proxied SSL connection. + // TODO (jri): Enable a finch trial to use + // COMBINE_CONNECT_AND_WRITE_DESIRED for SSL sockets. + ssl_tcp_params = + new TransportSocketParams( + origin_host_port, + disable_resolver_cache, + ignore_limits, + resolution_callback, + TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT); + } scoped_refptr<SSLSocketParams> ssl_params = - new SSLSocketParams(tcp_params, + new SSLSocketParams(ssl_tcp_params, socks_params, http_proxy_params, origin_host_port, @@ -281,7 +299,13 @@ int InitSocketPoolHelper(const GURL& request_url, } DCHECK(proxy_info.is_direct()); - + scoped_refptr<TransportSocketParams> tcp_params = + new TransportSocketParams( + origin_host_port, + disable_resolver_cache, + ignore_limits, + resolution_callback, + TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT); TransportClientSocketPool* pool = session->GetTransportSocketPool(socket_pool_type); if (num_preconnect_streams) { diff --git a/net/socket/deterministic_socket_data_unittest.cc b/net/socket/deterministic_socket_data_unittest.cc index dc1c42c..9a2d833 100644 --- a/net/socket/deterministic_socket_data_unittest.cc +++ b/net/socket/deterministic_socket_data_unittest.cc @@ -71,10 +71,12 @@ DeterministicSocketDataTest::DeterministicSocketDataTest() read_buf_(NULL), connect_data_(SYNCHRONOUS, OK), endpoint_("www.google.com", 443), - tcp_params_(new TransportSocketParams(endpoint_, - false, - false, - OnHostResolutionCallback())), + tcp_params_(new TransportSocketParams( + endpoint_, + false, + false, + OnHostResolutionCallback(), + TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT)), histograms_(std::string()), socket_pool_(10, 10, &histograms_, &socket_factory_) {} diff --git a/net/socket/socks_client_socket_pool_unittest.cc b/net/socket/socks_client_socket_pool_unittest.cc index b2b8655..ec2230c 100644 --- a/net/socket/socks_client_socket_pool_unittest.cc +++ b/net/socket/socks_client_socket_pool_unittest.cc @@ -44,8 +44,8 @@ void TestLoadTimingInfo(const ClientSocketHandle& handle) { scoped_refptr<TransportSocketParams> CreateProxyHostParams() { return new TransportSocketParams( - HostPortPair("proxy", 80), false, false, - OnHostResolutionCallback()); + HostPortPair("proxy", 80), false, false, OnHostResolutionCallback(), + TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT); } scoped_refptr<SOCKSSocketParams> CreateSOCKSv4Params() { diff --git a/net/socket/ssl_client_socket_pool_unittest.cc b/net/socket/ssl_client_socket_pool_unittest.cc index c05ac6c..54b4ee1 100644 --- a/net/socket/ssl_client_socket_pool_unittest.cc +++ b/net/socket/ssl_client_socket_pool_unittest.cc @@ -87,20 +87,24 @@ class SSLClientSocketPoolTest HttpAuthHandlerFactory::CreateDefault(&host_resolver_)), session_(CreateNetworkSession()), direct_transport_socket_params_( - new TransportSocketParams(HostPortPair("host", 443), - false, - false, - OnHostResolutionCallback())), + new TransportSocketParams( + HostPortPair("host", 443), + false, + false, + OnHostResolutionCallback(), + TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT)), transport_histograms_("MockTCP"), transport_socket_pool_(kMaxSockets, kMaxSocketsPerGroup, &transport_histograms_, &socket_factory_), proxy_transport_socket_params_( - new TransportSocketParams(HostPortPair("proxy", 443), - false, - false, - OnHostResolutionCallback())), + new TransportSocketParams( + HostPortPair("proxy", 443), + false, + false, + OnHostResolutionCallback(), + TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT)), socks_socket_params_( new SOCKSSocketParams(proxy_transport_socket_params_, true, diff --git a/net/socket/stream_socket.h b/net/socket/stream_socket.h index 7208810..7631e12 100644 --- a/net/socket/stream_socket.h +++ b/net/socket/stream_socket.h @@ -75,10 +75,15 @@ class NET_EXPORT_PRIVATE StreamSocket : public Socket { // Write() methods had been called, not the underlying transport's. virtual bool WasEverUsed() const = 0; + // TODO(jri): Clean up -- remove this method. // Returns true if the underlying transport socket is using TCP FastOpen. // TCP FastOpen is an experiment with sending data in the TCP SYN packet. virtual bool UsingTCPFastOpen() const = 0; + // TODO(jri): Clean up -- rename to a more general EnableAutoConnectOnWrite. + // Enables use of TCP FastOpen for the underlying transport socket. + virtual void EnableTCPFastOpenIfSupported() {} + // Returns true if NPN was negotiated during the connection of this socket. virtual bool WasNpnNegotiated() const = 0; diff --git a/net/socket/tcp_client_socket.cc b/net/socket/tcp_client_socket.cc index 53d8d1f..a16e11e 100644 --- a/net/socket/tcp_client_socket.cc +++ b/net/socket/tcp_client_socket.cc @@ -225,6 +225,10 @@ bool TCPClientSocket::UsingTCPFastOpen() const { return socket_->UsingTCPFastOpen(); } +void TCPClientSocket::EnableTCPFastOpenIfSupported() { + socket_->EnableTCPFastOpenIfSupported(); +} + bool TCPClientSocket::WasNpnNegotiated() const { return false; } diff --git a/net/socket/tcp_client_socket.h b/net/socket/tcp_client_socket.h index 970da2a..9322624 100644 --- a/net/socket/tcp_client_socket.h +++ b/net/socket/tcp_client_socket.h @@ -49,6 +49,7 @@ class NET_EXPORT TCPClientSocket : public StreamSocket { virtual void SetOmniboxSpeculation() OVERRIDE; virtual bool WasEverUsed() const OVERRIDE; virtual bool UsingTCPFastOpen() const OVERRIDE; + virtual void EnableTCPFastOpenIfSupported() OVERRIDE; virtual bool WasNpnNegotiated() const OVERRIDE; virtual NextProto GetNegotiatedProtocol() const OVERRIDE; virtual bool GetSSLInfo(SSLInfo* ssl_info) OVERRIDE; diff --git a/net/socket/tcp_socket.cc b/net/socket/tcp_socket.cc deleted file mode 100644 index 842cc06..0000000 --- a/net/socket/tcp_socket.cc +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2013 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/socket/tcp_socket.h" - -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/location.h" -#include "base/memory/ref_counted.h" -#include "base/threading/worker_pool.h" - -namespace net { - -namespace { - -bool g_tcp_fastopen_enabled = false; - -#if defined(OS_LINUX) || defined(OS_ANDROID) - -typedef base::RefCountedData<bool> SharedBoolean; - -// Checks to see if the system supports TCP FastOpen. Notably, it requires -// kernel support. Additionally, this checks system configuration to ensure that -// it's enabled. -void SystemSupportsTCPFastOpen(scoped_refptr<SharedBoolean> supported) { - supported->data = false; - static const base::FilePath::CharType kTCPFastOpenProcFilePath[] = - "/proc/sys/net/ipv4/tcp_fastopen"; - std::string system_enabled_tcp_fastopen; - if (!base::ReadFileToString(base::FilePath(kTCPFastOpenProcFilePath), - &system_enabled_tcp_fastopen)) { - return; - } - - // As per http://lxr.linux.no/linux+v3.7.7/include/net/tcp.h#L225 - // TFO_CLIENT_ENABLE is the LSB - if (system_enabled_tcp_fastopen.empty() || - (system_enabled_tcp_fastopen[0] & 0x1) == 0) { - return; - } - - supported->data = true; -} - -void EnableCallback(scoped_refptr<SharedBoolean> supported) { - g_tcp_fastopen_enabled = supported->data; -} - -// This is asynchronous because it needs to do file IO, and it isn't allowed to -// do that on the IO thread. -void EnableFastOpenIfSupported() { - scoped_refptr<SharedBoolean> supported = new SharedBoolean; - base::WorkerPool::PostTaskAndReply( - FROM_HERE, - base::Bind(SystemSupportsTCPFastOpen, supported), - base::Bind(EnableCallback, supported), - false); -} - -#else - -void EnableFastOpenIfSupported() { - g_tcp_fastopen_enabled = false; -} - -#endif - -} // namespace - -void SetTCPFastOpenEnabled(bool value) { - if (value) { - EnableFastOpenIfSupported(); - } else { - g_tcp_fastopen_enabled = false; - } -} - -bool IsTCPFastOpenEnabled() { - return g_tcp_fastopen_enabled; -} - -} // namespace net diff --git a/net/socket/tcp_socket.h b/net/socket/tcp_socket.h index 8b36fad..04fd7d2 100644 --- a/net/socket/tcp_socket.h +++ b/net/socket/tcp_socket.h @@ -16,13 +16,6 @@ namespace net { -// Enable/disable experimental TCP FastOpen option. -// Not thread safe. Must be called during initialization/startup only. -NET_EXPORT void SetTCPFastOpenEnabled(bool value); - -// Check if the TCP FastOpen option is enabled. -bool IsTCPFastOpenEnabled(); - // TCPSocket provides a platform-independent interface for TCP sockets. // // It is recommended to use TCPClientSocket/TCPServerSocket instead of this @@ -35,6 +28,17 @@ typedef TCPSocketWin TCPSocket; typedef TCPSocketLibevent TCPSocket; #endif +// Check if TCP FastOpen is supported by the OS. +bool IsTCPFastOpenSupported(); + +// Check if TCP FastOpen is enabled by the user. +bool IsTCPFastOpenUserEnabled(); + +// Checks if TCP FastOpen is supported by the kernel. Also enables TFO for all +// connections if indicated by user. +// Not thread safe. Must be called during initialization/startup only. +NET_EXPORT void CheckSupportAndMaybeEnableTCPFastOpen(bool user_enabled); + } // namespace net #endif // NET_SOCKET_TCP_SOCKET_H_ diff --git a/net/socket/tcp_socket_libevent.cc b/net/socket/tcp_socket_libevent.cc index 426c8b0..f39611b 100644 --- a/net/socket/tcp_socket_libevent.cc +++ b/net/socket/tcp_socket_libevent.cc @@ -13,6 +13,8 @@ #include "base/metrics/histogram.h" #include "base/metrics/stats_counters.h" #include "base/posix/eintr_wrapper.h" +#include "base/task_runner_util.h" +#include "base/threading/worker_pool.h" #include "net/base/address_list.h" #include "net/base/connection_type_histograms.h" #include "net/base/io_buffer.h" @@ -32,6 +34,12 @@ namespace net { namespace { +// True if OS supports TCP FastOpen. +bool g_tcp_fastopen_supported = false; +// True if TCP FastOpen is user-enabled for all connections. +// TODO(jri): Change global variable to param in HttpNetworkSession::Params. +bool g_tcp_fastopen_user_enabled = false; + // SetTCPNoDelay turns on/off buffering in the kernel. By default, TCP sockets // will wait up to 200ms for more data to complete a packet before transmitting. // After calling this function, the kernel will not wait. See TCP_NODELAY in @@ -69,13 +77,58 @@ bool SetTCPKeepAlive(int fd, bool enable, int delay) { return true; } +#if defined(OS_LINUX) || defined(OS_ANDROID) +// Checks if the kernel supports TCP FastOpen. +bool SystemSupportsTCPFastOpen() { + const base::FilePath::CharType kTCPFastOpenProcFilePath[] = + "/proc/sys/net/ipv4/tcp_fastopen"; + std::string system_supports_tcp_fastopen; + if (!base::ReadFileToString(base::FilePath(kTCPFastOpenProcFilePath), + &system_supports_tcp_fastopen)) { + return false; + } + // The read from /proc should return '1' if TCP FastOpen is enabled in the OS. + if (system_supports_tcp_fastopen.empty() || + (system_supports_tcp_fastopen[0] != '1')) { + return false; + } + return true; +} + +void RegisterTCPFastOpenIntentAndSupport(bool user_enabled, + bool system_supported) { + g_tcp_fastopen_supported = system_supported; + g_tcp_fastopen_user_enabled = user_enabled; +} +#endif + } // namespace //----------------------------------------------------------------------------- +bool IsTCPFastOpenSupported() { + return g_tcp_fastopen_supported; +} + +bool IsTCPFastOpenUserEnabled() { + return g_tcp_fastopen_user_enabled; +} + +// This is asynchronous because it needs to do file IO, and it isn't allowed to +// do that on the IO thread. +void CheckSupportAndMaybeEnableTCPFastOpen(bool user_enabled) { +#if defined(OS_LINUX) || defined(OS_ANDROID) + base::PostTaskAndReplyWithResult( + base::WorkerPool::GetTaskRunner(/*task_is_slow=*/false).get(), + FROM_HERE, + base::Bind(SystemSupportsTCPFastOpen), + base::Bind(RegisterTCPFastOpenIntentAndSupport, user_enabled)); +#endif +} + TCPSocketLibevent::TCPSocketLibevent(NetLog* net_log, const NetLog::Source& source) - : use_tcp_fastopen_(IsTCPFastOpenEnabled()), + : use_tcp_fastopen_(false), tcp_fastopen_connected_(false), fast_open_status_(FAST_OPEN_STATUS_UNKNOWN), logging_multiple_connect_attempts_(false), @@ -369,6 +422,11 @@ bool TCPSocketLibevent::UsingTCPFastOpen() const { return use_tcp_fastopen_; } +void TCPSocketLibevent::EnableTCPFastOpenIfSupported() { + if (IsTCPFastOpenSupported()) + use_tcp_fastopen_ = true; +} + bool TCPSocketLibevent::IsValid() const { return socket_ != NULL && socket_->socket_fd() != kInvalidSocket; } @@ -495,7 +553,7 @@ void TCPSocketLibevent::ReadCompleted(const scoped_refptr<IOBuffer>& buf, const CompletionCallback& callback, int rv) { DCHECK_NE(ERR_IO_PENDING, rv); - // Records fast open status regardless of error in asynchronous case. + // Records TCP FastOpen status regardless of error in asynchronous case. // TODO(rdsmith,jri): Change histogram name to indicate it could be called on // error. RecordFastOpenStatus(); @@ -597,7 +655,7 @@ void TCPSocketLibevent::RecordFastOpenStatus() { bool getsockopt_success(false); bool server_acked_data(false); #if defined(TCP_INFO) - // Probe to see the if the socket used TCP Fast Open. + // Probe to see the if the socket used TCP FastOpen. tcp_info info; socklen_t info_len = sizeof(tcp_info); getsockopt_success = diff --git a/net/socket/tcp_socket_libevent.h b/net/socket/tcp_socket_libevent.h index 0335c9e..89b6a22 100644 --- a/net/socket/tcp_socket_libevent.h +++ b/net/socket/tcp_socket_libevent.h @@ -65,7 +65,10 @@ class NET_EXPORT TCPSocketLibevent { void Close(); + // Setter/Getter methods for TCP FastOpen socket option. bool UsingTCPFastOpen() const; + void EnableTCPFastOpenIfSupported(); + bool IsValid() const; // Marks the start/end of a series of connect attempts for logging purpose. @@ -168,11 +171,10 @@ class NET_EXPORT TCPSocketLibevent { scoped_ptr<SocketLibevent> accept_socket_; // Enables experimental TCP FastOpen option. - const bool use_tcp_fastopen_; + bool use_tcp_fastopen_; // True when TCP FastOpen is in use and we have done the connect. bool tcp_fastopen_connected_; - FastOpenStatus fast_open_status_; bool logging_multiple_connect_attempts_; diff --git a/net/socket/tcp_socket_win.cc b/net/socket/tcp_socket_win.cc index 88db36f..35bfb9b 100644 --- a/net/socket/tcp_socket_win.cc +++ b/net/socket/tcp_socket_win.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "net/socket/tcp_socket.h" #include "net/socket/tcp_socket_win.h" #include <mstcpip.h> @@ -123,6 +124,12 @@ int MapConnectError(int os_error) { //----------------------------------------------------------------------------- +// Nothing to do for Windows since it doesn't support TCP FastOpen. +// TODO(jri): Remove these along with the corresponding global variables. +bool IsTCPFastOpenSupported() { return false; } +bool IsTCPFastOpenUserEnabled() { return false; } +void CheckSupportAndMaybeEnableTCPFastOpen(bool user_enabled) {} + // This class encapsulates all the state that has to be preserved as long as // there is a network IO operation in progress. If the owner TCPSocketWin is // destroyed while an operation is in progress, the Core is detached and it @@ -694,11 +701,6 @@ void TCPSocketWin::Close() { connect_os_error_ = 0; } -bool TCPSocketWin::UsingTCPFastOpen() const { - // Not supported on windows. - return false; -} - void TCPSocketWin::StartLoggingMultipleConnectAttempts( const AddressList& addresses) { if (!logging_multiple_connect_attempts_) { @@ -1021,4 +1023,3 @@ void TCPSocketWin::DidSignalRead() { } } // namespace net - diff --git a/net/socket/tcp_socket_win.h b/net/socket/tcp_socket_win.h index 2ddd538..a5eed419 100644 --- a/net/socket/tcp_socket_win.h +++ b/net/socket/tcp_socket_win.h @@ -75,7 +75,11 @@ class NET_EXPORT TCPSocketWin : NON_EXPORTED_BASE(public base::NonThreadSafe), void Close(); - bool UsingTCPFastOpen() const; + // Setter/Getter methods for TCP FastOpen socket option. + // NOOPs since TCP FastOpen is not implemented in Windows. + bool UsingTCPFastOpen() const { return false; } + void EnableTCPFastOpenIfSupported() {} + bool IsValid() const { return socket_ != INVALID_SOCKET; } // Marks the start/end of a series of connect attempts for logging purpose. @@ -152,4 +156,3 @@ class NET_EXPORT TCPSocketWin : NON_EXPORTED_BASE(public base::NonThreadSafe), } // namespace net #endif // NET_SOCKET_TCP_SOCKET_WIN_H_ - diff --git a/net/socket/transport_client_socket_pool.cc b/net/socket/transport_client_socket_pool.cc index 7527eca..06202f1 100644 --- a/net/socket/transport_client_socket_pool.cc +++ b/net/socket/transport_client_socket_pool.cc @@ -60,12 +60,21 @@ TransportSocketParams::TransportSocketParams( const HostPortPair& host_port_pair, bool disable_resolver_cache, bool ignore_limits, - const OnHostResolutionCallback& host_resolution_callback) + const OnHostResolutionCallback& host_resolution_callback, + CombineConnectAndWritePolicy combine_connect_and_write_if_supported) : destination_(host_port_pair), ignore_limits_(ignore_limits), - host_resolution_callback_(host_resolution_callback) { + host_resolution_callback_(host_resolution_callback), + combine_connect_and_write_(combine_connect_and_write_if_supported) { if (disable_resolver_cache) destination_.set_allow_cached_response(false); + // combine_connect_and_write currently translates to TCP FastOpen. + // Enable TCP FastOpen if user wants it. + if (combine_connect_and_write_ == COMBINE_CONNECT_AND_WRITE_DEFAULT) { + IsTCPFastOpenUserEnabled() ? combine_connect_and_write_ = + COMBINE_CONNECT_AND_WRITE_DESIRED : + COMBINE_CONNECT_AND_WRITE_PROHIBITED; + } } TransportSocketParams::~TransportSocketParams() {} @@ -261,10 +270,25 @@ int TransportConnectJob::DoTransportConnect() { transport_socket_ = helper_.client_socket_factory()->CreateTransportClientSocket( helper_.addresses(), net_log().net_log(), net_log().source()); - int rv = transport_socket_->Connect(helper_.on_io_complete()); - if (rv == ERR_IO_PENDING && + + // If the list contains IPv6 and IPv4 addresses, the first address will + // be IPv6, and the IPv4 addresses will be tried as fallback addresses, + // per "Happy Eyeballs" (RFC 6555). + bool try_ipv6_connect_with_ipv4_fallback = helper_.addresses().front().GetFamily() == ADDRESS_FAMILY_IPV6 && - !AddressListOnlyContainsIPv6(helper_.addresses())) { + !AddressListOnlyContainsIPv6(helper_.addresses()); + + // Enable TCP FastOpen if indicated by transport socket params. + // Note: We currently do not turn on TCP FastOpen for destinations where + // we try a TCP connect over IPv6 with fallback to IPv4. + if (!try_ipv6_connect_with_ipv4_fallback && + helper_.params()->combine_connect_and_write() == + TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DESIRED) { + transport_socket_->EnableTCPFastOpenIfSupported(); + } + + int rv = transport_socket_->Connect(helper_.on_io_complete()); + if (rv == ERR_IO_PENDING && try_ipv6_connect_with_ipv4_fallback) { fallback_timer_.Start( FROM_HERE, base::TimeDelta::FromMilliseconds( diff --git a/net/socket/transport_client_socket_pool.h b/net/socket/transport_client_socket_pool.h index 003008a..fce5432 100644 --- a/net/socket/transport_client_socket_pool.h +++ b/net/socket/transport_client_socket_pool.h @@ -29,14 +29,30 @@ OnHostResolutionCallback; class NET_EXPORT_PRIVATE TransportSocketParams : public base::RefCounted<TransportSocketParams> { public: + // CombineConnectAndWrite currently translates to using TCP FastOpen. + // TCP FastOpen should not be used if the first write to the socket may + // be non-idempotent, as the underlying socket could retransmit the data + // on failure of the first transmission. + // NOTE: Currently, COMBINE_CONNECT_AND_WRITE_DESIRED is used if the data in + // the write is known to be idempotent, and COMBINE_CONNECT_AND_WRITE_DEFAULT + // is used as a default for other cases (including non-idempotent writes). + enum CombineConnectAndWritePolicy { + COMBINE_CONNECT_AND_WRITE_DEFAULT, // Default policy, implemented in + // TransportSocketParams constructor. + COMBINE_CONNECT_AND_WRITE_DESIRED, // Combine if supported by socket. + COMBINE_CONNECT_AND_WRITE_PROHIBITED // Do not combine. + }; + // |host_resolution_callback| will be invoked after the the hostname is // resolved. If |host_resolution_callback| does not return OK, then the - // connection will be aborted with that value. + // connection will be aborted with that value. |combine_connect_and_write| + // defines the policy for use of TCP FastOpen on this socket. TransportSocketParams( const HostPortPair& host_port_pair, bool disable_resolver_cache, bool ignore_limits, - const OnHostResolutionCallback& host_resolution_callback); + const OnHostResolutionCallback& host_resolution_callback, + CombineConnectAndWritePolicy combine_connect_and_write); const HostResolver::RequestInfo& destination() const { return destination_; } bool ignore_limits() const { return ignore_limits_; } @@ -44,6 +60,10 @@ class NET_EXPORT_PRIVATE TransportSocketParams return host_resolution_callback_; } + CombineConnectAndWritePolicy combine_connect_and_write() const { + return combine_connect_and_write_; + } + private: friend class base::RefCounted<TransportSocketParams>; ~TransportSocketParams(); @@ -51,6 +71,7 @@ class NET_EXPORT_PRIVATE TransportSocketParams HostResolver::RequestInfo destination_; bool ignore_limits_; const OnHostResolutionCallback host_resolution_callback_; + CombineConnectAndWritePolicy combine_connect_and_write_; DISALLOW_COPY_AND_ASSIGN(TransportSocketParams); }; @@ -90,6 +111,7 @@ class NET_EXPORT_PRIVATE TransportConnectJobHelper { State next_state() const { return next_state_; } void set_next_state(State next_state) { next_state_ = next_state; } CompletionCallback on_io_complete() const { return on_io_complete_; } + const TransportSocketParams* params() { return params_.get(); } int DoResolveHost(RequestPriority priority, const BoundNetLog& net_log); int DoResolveHostComplete(int result, const BoundNetLog& net_log); diff --git a/net/socket/transport_client_socket_pool_test_util.cc b/net/socket/transport_client_socket_pool_test_util.cc index a94167c..98a615d 100644 --- a/net/socket/transport_client_socket_pool_test_util.cc +++ b/net/socket/transport_client_socket_pool_test_util.cc @@ -34,7 +34,8 @@ class MockConnectClientSocket : public StreamSocket { MockConnectClientSocket(const AddressList& addrlist, net::NetLog* net_log) : connected_(false), addrlist_(addrlist), - net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) {} + net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)), + use_tcp_fastopen_(false) {} // StreamSocket implementation. virtual int Connect(const CompletionCallback& callback) OVERRIDE { @@ -63,7 +64,10 @@ class MockConnectClientSocket : public StreamSocket { virtual void SetSubresourceSpeculation() OVERRIDE {} virtual void SetOmniboxSpeculation() OVERRIDE {} virtual bool WasEverUsed() const OVERRIDE { return false; } - virtual bool UsingTCPFastOpen() const OVERRIDE { return false; } + virtual void EnableTCPFastOpenIfSupported() OVERRIDE { + use_tcp_fastopen_ = true; + } + virtual bool UsingTCPFastOpen() const OVERRIDE { return use_tcp_fastopen_; } virtual bool WasNpnNegotiated() const OVERRIDE { return false; } virtual NextProto GetNegotiatedProtocol() const OVERRIDE { return kProtoUnknown; @@ -88,6 +92,7 @@ class MockConnectClientSocket : public StreamSocket { bool connected_; const AddressList addrlist_; BoundNetLog net_log_; + bool use_tcp_fastopen_; DISALLOW_COPY_AND_ASSIGN(MockConnectClientSocket); }; @@ -96,7 +101,8 @@ class MockFailingClientSocket : public StreamSocket { public: MockFailingClientSocket(const AddressList& addrlist, net::NetLog* net_log) : addrlist_(addrlist), - net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) {} + net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)), + use_tcp_fastopen_(false) {} // StreamSocket implementation. virtual int Connect(const CompletionCallback& callback) OVERRIDE { @@ -118,7 +124,10 @@ class MockFailingClientSocket : public StreamSocket { virtual void SetSubresourceSpeculation() OVERRIDE {} virtual void SetOmniboxSpeculation() OVERRIDE {} virtual bool WasEverUsed() const OVERRIDE { return false; } - virtual bool UsingTCPFastOpen() const OVERRIDE { return false; } + virtual void EnableTCPFastOpenIfSupported() OVERRIDE { + use_tcp_fastopen_ = true; + } + virtual bool UsingTCPFastOpen() const OVERRIDE { return use_tcp_fastopen_; } virtual bool WasNpnNegotiated() const OVERRIDE { return false; } virtual NextProto GetNegotiatedProtocol() const OVERRIDE { return kProtoUnknown; @@ -143,6 +152,7 @@ class MockFailingClientSocket : public StreamSocket { private: const AddressList addrlist_; BoundNetLog net_log_; + bool use_tcp_fastopen_; DISALLOW_COPY_AND_ASSIGN(MockFailingClientSocket); }; @@ -158,6 +168,7 @@ class MockTriggerableClientSocket : public StreamSocket { is_connected_(false), addrlist_(addrlist), net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)), + use_tcp_fastopen_(false), weak_factory_(this) {} // Call this method to get a closure which will trigger the connect callback @@ -228,7 +239,10 @@ class MockTriggerableClientSocket : public StreamSocket { virtual void SetSubresourceSpeculation() OVERRIDE {} virtual void SetOmniboxSpeculation() OVERRIDE {} virtual bool WasEverUsed() const OVERRIDE { return false; } - virtual bool UsingTCPFastOpen() const OVERRIDE { return false; } + virtual void EnableTCPFastOpenIfSupported() OVERRIDE { + use_tcp_fastopen_ = true; + } + virtual bool UsingTCPFastOpen() const OVERRIDE { return use_tcp_fastopen_; } virtual bool WasNpnNegotiated() const OVERRIDE { return false; } virtual NextProto GetNegotiatedProtocol() const OVERRIDE { return kProtoUnknown; @@ -261,6 +275,7 @@ class MockTriggerableClientSocket : public StreamSocket { const AddressList addrlist_; BoundNetLog net_log_; CompletionCallback callback_; + bool use_tcp_fastopen_; base::WeakPtrFactory<MockTriggerableClientSocket> weak_factory_; diff --git a/net/socket/transport_client_socket_pool_unittest.cc b/net/socket/transport_client_socket_pool_unittest.cc index 1cc015a..2a05b44 100644 --- a/net/socket/transport_client_socket_pool_unittest.cc +++ b/net/socket/transport_client_socket_pool_unittest.cc @@ -40,9 +40,12 @@ class TransportClientSocketPoolTest : public testing::Test { : connect_backup_jobs_enabled_( ClientSocketPoolBaseHelper::set_connect_backup_jobs_enabled(true)), params_( - new TransportSocketParams(HostPortPair("www.google.com", 80), - false, false, - OnHostResolutionCallback())), + new TransportSocketParams( + HostPortPair("www.google.com", 80), + false, + false, + OnHostResolutionCallback(), + TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT)), histograms_(new ClientSocketPoolHistograms("TCPUnitTest")), host_resolver_(new MockHostResolver), client_socket_factory_(&net_log_), @@ -59,10 +62,17 @@ class TransportClientSocketPoolTest : public testing::Test { connect_backup_jobs_enabled_); } + scoped_refptr<TransportSocketParams> CreateParamsForTCPFastOpen() { + return new TransportSocketParams(HostPortPair("www.google.com", 80), + false, false, OnHostResolutionCallback(), + TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DESIRED); + } + int StartRequest(const std::string& group_name, RequestPriority priority) { scoped_refptr<TransportSocketParams> params(new TransportSocketParams( HostPortPair("www.google.com", 80), false, false, - OnHostResolutionCallback())); + OnHostResolutionCallback(), + TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT)); return test_base_.StartRequestUsingPool( &pool_, group_name, priority, params); } @@ -201,8 +211,8 @@ TEST_F(TransportClientSocketPoolTest, InitHostResolutionFailure) { ClientSocketHandle handle; HostPortPair host_port_pair("unresolvable.host.name", 80); scoped_refptr<TransportSocketParams> dest(new TransportSocketParams( - host_port_pair, false, false, - OnHostResolutionCallback())); + host_port_pair, false, false, OnHostResolutionCallback(), + TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT)); EXPECT_EQ(ERR_IO_PENDING, handle.Init("a", dest, kDefaultPriority, callback.callback(), &pool_, BoundNetLog())); @@ -477,7 +487,8 @@ class RequestSocketCallback : public TestCompletionCallbackBase { within_callback_ = true; scoped_refptr<TransportSocketParams> dest(new TransportSocketParams( HostPortPair("www.google.com", 80), false, false, - OnHostResolutionCallback())); + OnHostResolutionCallback(), + TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT)); int rv = handle_->Init("a", dest, LOWEST, callback(), pool_, BoundNetLog()); EXPECT_EQ(OK, rv); @@ -497,7 +508,8 @@ TEST_F(TransportClientSocketPoolTest, RequestTwice) { RequestSocketCallback callback(&handle, &pool_); scoped_refptr<TransportSocketParams> dest(new TransportSocketParams( HostPortPair("www.google.com", 80), false, false, - OnHostResolutionCallback())); + OnHostResolutionCallback(), + TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT)); int rv = handle.Init("a", dest, LOWEST, callback.callback(), &pool_, BoundNetLog()); ASSERT_EQ(ERR_IO_PENDING, rv); @@ -964,6 +976,137 @@ TEST_F(TransportClientSocketPoolTest, IPv4HasNoFallback) { EXPECT_EQ(1, client_socket_factory_.allocation_count()); } +// Test that if TCP FastOpen is enabled, it is set on the socket +// when we have only an IPv4 address. +TEST_F(TransportClientSocketPoolTest, TCPFastOpenOnIPv4WithNoFallback) { + // Create a pool without backup jobs. + ClientSocketPoolBaseHelper::set_connect_backup_jobs_enabled(false); + TransportClientSocketPool pool(kMaxSockets, + kMaxSocketsPerGroup, + histograms_.get(), + host_resolver_.get(), + &client_socket_factory_, + NULL); + client_socket_factory_.set_default_client_socket_type( + MockTransportClientSocketFactory::MOCK_DELAYED_CLIENT_SOCKET); + // Resolve an AddressList with only IPv4 addresses. + host_resolver_->rules()->AddIPLiteralRule("*", "1.1.1.1", std::string()); + + TestCompletionCallback callback; + ClientSocketHandle handle; + // Enable TCP FastOpen in TransportSocketParams. + scoped_refptr<TransportSocketParams> params = CreateParamsForTCPFastOpen(); + handle.Init("a", params, LOW, callback.callback(), &pool, BoundNetLog()); + EXPECT_EQ(OK, callback.WaitForResult()); + EXPECT_TRUE(handle.socket()->UsingTCPFastOpen()); +} + +// Test that if TCP FastOpen is enabled, it is set on the socket +// when we have only IPv6 addresses. +TEST_F(TransportClientSocketPoolTest, TCPFastOpenOnIPv6WithNoFallback) { + // Create a pool without backup jobs. + ClientSocketPoolBaseHelper::set_connect_backup_jobs_enabled(false); + TransportClientSocketPool pool(kMaxSockets, + kMaxSocketsPerGroup, + histograms_.get(), + host_resolver_.get(), + &client_socket_factory_, + NULL); + client_socket_factory_.set_default_client_socket_type( + MockTransportClientSocketFactory::MOCK_DELAYED_CLIENT_SOCKET); + // Resolve an AddressList with only IPv6 addresses. + host_resolver_->rules() + ->AddIPLiteralRule("*", "2:abcd::3:4:ff,3:abcd::3:4:ff", std::string()); + + TestCompletionCallback callback; + ClientSocketHandle handle; + // Enable TCP FastOpen in TransportSocketParams. + scoped_refptr<TransportSocketParams> params = CreateParamsForTCPFastOpen(); + handle.Init("a", params, LOW, callback.callback(), &pool, BoundNetLog()); + EXPECT_EQ(OK, callback.WaitForResult()); + EXPECT_TRUE(handle.socket()->UsingTCPFastOpen()); +} + +// Test that if TCP FastOpen is enabled, it does not do anything when there +// is a IPv6 address with fallback to an IPv4 address. This test tests the case +// when the IPv6 connect fails and the IPv4 one succeeds. +TEST_F(TransportClientSocketPoolTest, + NoTCPFastOpenOnIPv6FailureWithIPv4Fallback) { + // Create a pool without backup jobs. + ClientSocketPoolBaseHelper::set_connect_backup_jobs_enabled(false); + TransportClientSocketPool pool(kMaxSockets, + kMaxSocketsPerGroup, + histograms_.get(), + host_resolver_.get(), + &client_socket_factory_, + NULL); + + MockTransportClientSocketFactory::ClientSocketType case_types[] = { + // This is the IPv6 socket. + MockTransportClientSocketFactory::MOCK_STALLED_CLIENT_SOCKET, + // This is the IPv4 socket. + MockTransportClientSocketFactory::MOCK_PENDING_CLIENT_SOCKET + }; + client_socket_factory_.set_client_socket_types(case_types, 2); + // Resolve an AddressList with a IPv6 address first and then a IPv4 address. + host_resolver_->rules() + ->AddIPLiteralRule("*", "2:abcd::3:4:ff,2.2.2.2", std::string()); + + TestCompletionCallback callback; + ClientSocketHandle handle; + // Enable TCP FastOpen in TransportSocketParams. + scoped_refptr<TransportSocketParams> params = CreateParamsForTCPFastOpen(); + handle.Init("a", params, LOW, callback.callback(), &pool, BoundNetLog()); + EXPECT_EQ(OK, callback.WaitForResult()); + // Verify that the socket used is connected to the fallback IPv4 address. + IPEndPoint endpoint; + handle.socket()->GetLocalAddress(&endpoint); + EXPECT_EQ(kIPv4AddressSize, endpoint.address().size()); + EXPECT_EQ(2, client_socket_factory_.allocation_count()); + // Verify that TCP FastOpen was not turned on for the socket. + EXPECT_FALSE(handle.socket()->UsingTCPFastOpen()); +} + +// Test that if TCP FastOpen is enabled, it does not do anything when there +// is a IPv6 address with fallback to an IPv4 address. This test tests the case +// when the IPv6 connect succeeds. +TEST_F(TransportClientSocketPoolTest, + NoTCPFastOpenOnIPv6SuccessWithIPv4Fallback) { + // Create a pool without backup jobs. + ClientSocketPoolBaseHelper::set_connect_backup_jobs_enabled(false); + TransportClientSocketPool pool(kMaxSockets, + kMaxSocketsPerGroup, + histograms_.get(), + host_resolver_.get(), + &client_socket_factory_, + NULL); + + MockTransportClientSocketFactory::ClientSocketType case_types[] = { + // This is the IPv6 socket. + MockTransportClientSocketFactory::MOCK_PENDING_CLIENT_SOCKET, + // This is the IPv4 socket. + MockTransportClientSocketFactory::MOCK_PENDING_CLIENT_SOCKET + }; + client_socket_factory_.set_client_socket_types(case_types, 2); + // Resolve an AddressList with a IPv6 address first and then a IPv4 address. + host_resolver_->rules() + ->AddIPLiteralRule("*", "2:abcd::3:4:ff,2.2.2.2", std::string()); + + TestCompletionCallback callback; + ClientSocketHandle handle; + // Enable TCP FastOpen in TransportSocketParams. + scoped_refptr<TransportSocketParams> params = CreateParamsForTCPFastOpen(); + handle.Init("a", params, LOW, callback.callback(), &pool, BoundNetLog()); + EXPECT_EQ(OK, callback.WaitForResult()); + // Verify that the socket used is connected to the IPv6 address. + IPEndPoint endpoint; + handle.socket()->GetLocalAddress(&endpoint); + EXPECT_EQ(kIPv6AddressSize, endpoint.address().size()); + EXPECT_EQ(1, client_socket_factory_.allocation_count()); + // Verify that TCP FastOpen was not turned on for the socket. + EXPECT_FALSE(handle.socket()->UsingTCPFastOpen()); +} + } // namespace } // namespace net diff --git a/net/socket/websocket_transport_client_socket_pool_unittest.cc b/net/socket/websocket_transport_client_socket_pool_unittest.cc index 38ad6f0..bfb2090 100644 --- a/net/socket/websocket_transport_client_socket_pool_unittest.cc +++ b/net/socket/websocket_transport_client_socket_pool_unittest.cc @@ -51,10 +51,12 @@ void RunLoopForTimePeriod(base::TimeDelta period) { class WebSocketTransportClientSocketPoolTest : public testing::Test { protected: WebSocketTransportClientSocketPoolTest() - : params_(new TransportSocketParams(HostPortPair("www.google.com", 80), - false, - false, - OnHostResolutionCallback())), + : params_(new TransportSocketParams( + HostPortPair("www.google.com", 80), + false, + false, + OnHostResolutionCallback(), + TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT)), histograms_(new ClientSocketPoolHistograms("TCPUnitTest")), host_resolver_(new MockHostResolver), client_socket_factory_(&net_log_), @@ -72,10 +74,12 @@ class WebSocketTransportClientSocketPoolTest : public testing::Test { int StartRequest(const std::string& group_name, RequestPriority priority) { scoped_refptr<TransportSocketParams> params( - new TransportSocketParams(HostPortPair("www.google.com", 80), - false, - false, - OnHostResolutionCallback())); + new TransportSocketParams( + HostPortPair("www.google.com", 80), + false, + false, + OnHostResolutionCallback(), + TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT)); return test_base_.StartRequestUsingPool( &pool_, group_name, priority, params); } @@ -148,7 +152,8 @@ TEST_F(WebSocketTransportClientSocketPoolTest, InitHostResolutionFailure) { ClientSocketHandle handle; HostPortPair host_port_pair("unresolvable.host.name", 80); scoped_refptr<TransportSocketParams> dest(new TransportSocketParams( - host_port_pair, false, false, OnHostResolutionCallback())); + host_port_pair, false, false, OnHostResolutionCallback(), + TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT)); EXPECT_EQ(ERR_IO_PENDING, handle.Init("a", dest, @@ -398,10 +403,12 @@ class RequestSocketCallback : public TestCompletionCallbackBase { } within_callback_ = true; scoped_refptr<TransportSocketParams> dest( - new TransportSocketParams(HostPortPair("www.google.com", 80), - false, - false, - OnHostResolutionCallback())); + new TransportSocketParams( + HostPortPair("www.google.com", 80), + false, + false, + OnHostResolutionCallback(), + TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT)); int rv = handle_->Init("a", dest, LOWEST, callback(), pool_, BoundNetLog()); EXPECT_EQ(OK, rv); @@ -420,10 +427,12 @@ TEST_F(WebSocketTransportClientSocketPoolTest, RequestTwice) { ClientSocketHandle handle; RequestSocketCallback callback(&handle, &pool_); scoped_refptr<TransportSocketParams> dest( - new TransportSocketParams(HostPortPair("www.google.com", 80), - false, - false, - OnHostResolutionCallback())); + new TransportSocketParams( + HostPortPair("www.google.com", 80), + false, + false, + OnHostResolutionCallback(), + TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT)); int rv = handle.Init( "a", dest, LOWEST, callback.callback(), &pool_, BoundNetLog()); ASSERT_EQ(ERR_IO_PENDING, rv); diff --git a/net/spdy/spdy_session_unittest.cc b/net/spdy/spdy_session_unittest.cc index ac52ccc..938f6e5 100644 --- a/net/spdy/spdy_session_unittest.cc +++ b/net/spdy/spdy_session_unittest.cc @@ -3139,8 +3139,9 @@ TEST_P(SpdySessionTest, CloseOneIdleConnection) { TestCompletionCallback callback2; HostPortPair host_port2("2.com", 80); scoped_refptr<TransportSocketParams> params2( - new TransportSocketParams(host_port2, false, false, - OnHostResolutionCallback())); + new TransportSocketParams( + host_port2, false, false, OnHostResolutionCallback(), + TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT)); scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle); EXPECT_EQ(ERR_IO_PENDING, connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY, @@ -3218,8 +3219,9 @@ TEST_P(SpdySessionTest, CloseOneIdleConnectionWithAlias) { TestCompletionCallback callback3; HostPortPair host_port3("3.com", 80); scoped_refptr<TransportSocketParams> params3( - new TransportSocketParams(host_port3, false, false, - OnHostResolutionCallback())); + new TransportSocketParams( + host_port3, false, false, OnHostResolutionCallback(), + TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT)); scoped_ptr<ClientSocketHandle> connection3(new ClientSocketHandle); EXPECT_EQ(ERR_IO_PENDING, connection3->Init(host_port3.ToString(), params3, DEFAULT_PRIORITY, @@ -3307,8 +3309,9 @@ TEST_P(SpdySessionTest, CloseSessionOnIdleWhenPoolStalled) { TestCompletionCallback callback2; HostPortPair host_port2("2.com", 80); scoped_refptr<TransportSocketParams> params2( - new TransportSocketParams(host_port2, false, false, - OnHostResolutionCallback())); + new TransportSocketParams( + host_port2, false, false, OnHostResolutionCallback(), + TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT)); scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle); EXPECT_EQ(ERR_IO_PENDING, connection2->Init(host_port2.ToString(), params2, DEFAULT_PRIORITY, diff --git a/net/spdy/spdy_test_util_common.cc b/net/spdy/spdy_test_util_common.cc index 73d0afc..99c0747 100644 --- a/net/spdy/spdy_test_util_common.cc +++ b/net/spdy/spdy_test_util_common.cc @@ -523,8 +523,8 @@ base::WeakPtr<SpdySession> CreateSpdySessionHelper( scoped_refptr<TransportSocketParams> transport_params( new TransportSocketParams( - key.host_port_pair(), false, false, - OnHostResolutionCallback())); + key.host_port_pair(), false, false, OnHostResolutionCallback(), + TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT)); scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); TestCompletionCallback callback; |