Chromium Code Reviews| Index: net/socket/tcp_socket_libevent.cc |
| diff --git a/net/socket/tcp_socket_libevent.cc b/net/socket/tcp_socket_libevent.cc |
| index 426c8b0dd3505e99acc51920ae40b4511c87bc03..dd643159149ab32ae0247aeaba1052c1c06f7615 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" |
| @@ -28,6 +30,12 @@ |
| #define TCPI_OPT_SYN_DATA 32 |
| #endif |
| +// 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; |
| + |
| namespace net { |
| namespace { |
| @@ -69,13 +77,55 @@ 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() { |
| + static const base::FilePath::CharType kTCPFastOpenProcFilePath[] = |
|
mmenke
2014/09/05 19:36:42
I seem to recall reading on Chromium dev that stat
Jana
2014/09/05 20:38:57
Hmm. I don't know why this is static in the first
|
| + "/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 CallbackForTCPFastOpenCheck(bool user_enabled, |
|
mmenke
2014/09/05 19:36:42
Functions should generally be named after what the
Jana
2014/09/05 20:38:57
Good suggestion -- done. (RegisterTCPFastOpenInten
|
| + bool system_supported) { |
| + g_tcp_fastopen_supported = system_supported; |
| + g_tcp_fastopen_user_enabled = user_enabled; |
| +} |
| +#endif |
| + |
| +// Check if TCP FastOpen option is supported by the OS. |
| +bool IsTCPFastOpenSupported() { |
| + return g_tcp_fastopen_supported; |
| +} |
| + |
| } // namespace |
| //----------------------------------------------------------------------------- |
| +// 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), |
|
mmenke
2014/09/05 19:36:42
File IO isn't considered slow?
Jana
2014/09/05 20:38:57
(This was the code prior to me touching it... don'
|
| + FROM_HERE, |
| + base::Bind(SystemSupportsTCPFastOpen), |
| + base::Bind(CallbackForTCPFastOpenCheck, user_enabled)); |
| +#endif |
| +} |
| + |
| TCPSocketLibevent::TCPSocketLibevent(NetLog* net_log, |
| const NetLog::Source& source) |
| - : use_tcp_fastopen_(IsTCPFastOpenEnabled()), |
| + : use_tcp_fastopen_if_supported_(false), |
| tcp_fastopen_connected_(false), |
| fast_open_status_(FAST_OPEN_STATUS_UNKNOWN), |
| logging_multiple_connect_attempts_(false), |
| @@ -167,7 +217,7 @@ int TCPSocketLibevent::Connect(const IPEndPoint& address, |
| if (!address.ToSockAddr(storage.addr, &storage.addr_len)) |
| return ERR_ADDRESS_INVALID; |
| - if (use_tcp_fastopen_) { |
| + if (use_tcp_fastopen_if_supported_) { |
| // With TCP FastOpen, we pretend that the socket is connected. |
| DCHECK(!tcp_fastopen_connected_); |
| socket_->SetPeerAddress(storage); |
| @@ -186,7 +236,7 @@ bool TCPSocketLibevent::IsConnected() const { |
| if (!socket_) |
| return false; |
| - if (use_tcp_fastopen_ && !tcp_fastopen_connected_ && |
| + if (use_tcp_fastopen_if_supported_ && !tcp_fastopen_connected_ && |
| socket_->HasPeerAddress()) { |
| // With TCP FastOpen, we pretend that the socket is connected. |
| // This allows GetPeerAddress() to return peer_address_. |
| @@ -235,7 +285,7 @@ int TCPSocketLibevent::Write(IOBuffer* buf, |
| // ownership of buf to socket. |
| base::Unretained(this), make_scoped_refptr(buf), callback); |
| int rv; |
| - if (use_tcp_fastopen_ && !tcp_fastopen_connected_) { |
| + if (use_tcp_fastopen_if_supported_ && !tcp_fastopen_connected_) { |
| rv = TcpFastOpenWrite(buf, buf_len, write_callback); |
| } else { |
| rv = socket_->Write(buf, buf_len, write_callback); |
| @@ -366,7 +416,12 @@ void TCPSocketLibevent::Close() { |
| } |
| bool TCPSocketLibevent::UsingTCPFastOpen() const { |
| - return use_tcp_fastopen_; |
| + return use_tcp_fastopen_if_supported_; |
| +} |
| + |
| +void TCPSocketLibevent::EnableTCPFastOpen() { |
| + if (!use_tcp_fastopen_if_supported_ && IsTCPFastOpenSupported()) |
|
mmenke
2014/09/05 19:36:42
The "use_tcp_fastopen_if_supported_" check isn't n
Jana
2014/09/05 20:38:57
Good catch -- Done.
|
| + use_tcp_fastopen_if_supported_ = true; |
|
mmenke
2014/09/05 19:36:42
This variable should be renamed to use_tcp_fastope
Jana
2014/09/05 20:38:56
Good suggestion -- done.
|
| } |
| bool TCPSocketLibevent::IsValid() const { |
| @@ -495,7 +550,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(); |
| @@ -590,14 +645,14 @@ int TCPSocketLibevent::TcpFastOpenWrite( |
| } |
| void TCPSocketLibevent::RecordFastOpenStatus() { |
| - if (use_tcp_fastopen_ && |
| + if (use_tcp_fastopen_if_supported_ && |
| (fast_open_status_ == FAST_OPEN_FAST_CONNECT_RETURN || |
| fast_open_status_ == FAST_OPEN_SLOW_CONNECT_RETURN)) { |
| DCHECK_NE(FAST_OPEN_STATUS_UNKNOWN, fast_open_status_); |
| 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 = |