158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "net/socket/tcp_socket.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h> 8d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include <netinet/tcp.h> 9d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include <sys/socket.h> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/bind.h" 1258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/logging.h" 13d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/metrics/histogram.h" 14d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/metrics/stats_counters.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/posix/eintr_wrapper.h" 161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/task_runner_util.h" 171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/threading/worker_pool.h" 18d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "net/base/address_list.h" 19d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "net/base/connection_type_histograms.h" 20d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "net/base/io_buffer.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/ip_endpoint.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h" 24d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "net/base/network_change_notifier.h" 25116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "net/socket/socket_libevent.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/socket_net_log_params.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// If we don't have a definition for TCPI_OPT_SYN_DATA, create one. 29d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#ifndef TCPI_OPT_SYN_DATA 30d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#define TCPI_OPT_SYN_DATA 32 31d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#endif 32d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 35d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)namespace { 36d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// True if OS supports TCP FastOpen. 381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool g_tcp_fastopen_supported = false; 391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// True if TCP FastOpen is user-enabled for all connections. 401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// TODO(jri): Change global variable to param in HttpNetworkSession::Params. 411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool g_tcp_fastopen_user_enabled = false; 421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 43d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// SetTCPNoDelay turns on/off buffering in the kernel. By default, TCP sockets 44d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// will wait up to 200ms for more data to complete a packet before transmitting. 45d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// After calling this function, the kernel will not wait. See TCP_NODELAY in 46d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// `man 7 tcp`. 47d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool SetTCPNoDelay(int fd, bool no_delay) { 48d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int on = no_delay ? 1 : 0; 49d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int error = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)); 50d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return error == 0; 51d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 52d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 53d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// SetTCPKeepAlive sets SO_KEEPALIVE. 54d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool SetTCPKeepAlive(int fd, bool enable, int delay) { 55d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int on = enable ? 1 : 0; 56d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on))) { 57d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) PLOG(ERROR) << "Failed to set SO_KEEPALIVE on fd: " << fd; 58d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return false; 59d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // If we disabled TCP keep alive, our work is done here. 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!enable) 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 65d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#if defined(OS_LINUX) || defined(OS_ANDROID) 66d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Set seconds until first TCP keep alive. 67d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &delay, sizeof(delay))) { 68d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) PLOG(ERROR) << "Failed to set TCP_KEEPIDLE on fd: " << fd; 69d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return false; 70d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 71d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Set seconds between TCP keep alives. 72d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &delay, sizeof(delay))) { 73d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) PLOG(ERROR) << "Failed to set TCP_KEEPINTVL on fd: " << fd; 74d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return false; 75d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 76d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#endif 77d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return true; 78d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 79d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(OS_LINUX) || defined(OS_ANDROID) 811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Checks if the kernel supports TCP FastOpen. 821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool SystemSupportsTCPFastOpen() { 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const base::FilePath::CharType kTCPFastOpenProcFilePath[] = 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "/proc/sys/net/ipv4/tcp_fastopen"; 851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::string system_supports_tcp_fastopen; 861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!base::ReadFileToString(base::FilePath(kTCPFastOpenProcFilePath), 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci &system_supports_tcp_fastopen)) { 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return false; 891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // The read from /proc should return '1' if TCP FastOpen is enabled in the OS. 911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (system_supports_tcp_fastopen.empty() || 921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci (system_supports_tcp_fastopen[0] != '1')) { 931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return false; 941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return true; 961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid RegisterTCPFastOpenIntentAndSupport(bool user_enabled, 991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bool system_supported) { 1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci g_tcp_fastopen_supported = system_supported; 1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci g_tcp_fastopen_user_enabled = user_enabled; 1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif 1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 105d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} // namespace 106d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 107d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)//----------------------------------------------------------------------------- 108d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool IsTCPFastOpenSupported() { 1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return g_tcp_fastopen_supported; 1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool IsTCPFastOpenUserEnabled() { 1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return g_tcp_fastopen_user_enabled; 1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// This is asynchronous because it needs to do file IO, and it isn't allowed to 1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// do that on the IO thread. 1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid CheckSupportAndMaybeEnableTCPFastOpen(bool user_enabled) { 1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(OS_LINUX) || defined(OS_ANDROID) 1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::PostTaskAndReplyWithResult( 1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::WorkerPool::GetTaskRunner(/*task_is_slow=*/false).get(), 1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci FROM_HERE, 1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(SystemSupportsTCPFastOpen), 1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(RegisterTCPFastOpenIntentAndSupport, user_enabled)); 1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif 1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 12958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)TCPSocketLibevent::TCPSocketLibevent(NetLog* net_log, 13058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const NetLog::Source& source) 1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : use_tcp_fastopen_(false), 132d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) tcp_fastopen_connected_(false), 133d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) fast_open_status_(FAST_OPEN_STATUS_UNKNOWN), 134d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) logging_multiple_connect_attempts_(false), 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) { 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source.ToEventParametersCallback()); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)TCPSocketLibevent::~TCPSocketLibevent() { 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE); 142d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (tcp_fastopen_connected_) { 143d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("Net.TcpFastOpenSocketConnection", 144d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) fast_open_status_, FAST_OPEN_MAX_VALUE); 145d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 148d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)int TCPSocketLibevent::Open(AddressFamily family) { 149116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(!socket_); 150116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch socket_.reset(new SocketLibevent); 151116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int rv = socket_->Open(ConvertAddressFamily(family)); 152116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (rv != OK) 153116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch socket_.reset(); 154116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return rv; 15558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 15658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 157116680a4aac90f2aa7413d9095a592090648e557Ben Murdochint TCPSocketLibevent::AdoptConnectedSocket(int socket_fd, 158d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const IPEndPoint& peer_address) { 159116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(!socket_); 16058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 161116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SockaddrStorage storage; 162116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!peer_address.ToSockAddr(storage.addr, &storage.addr_len) && 163116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // For backward compatibility, allows the empty address. 164116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch !(peer_address == IPEndPoint())) { 165116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return ERR_ADDRESS_INVALID; 1667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 168116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch socket_.reset(new SocketLibevent); 169116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int rv = socket_->AdoptConnectedSocket(socket_fd, storage); 170116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (rv != OK) 171116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch socket_.reset(); 172116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return rv; 17358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 17458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 17558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)int TCPSocketLibevent::Bind(const IPEndPoint& address) { 176116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(socket_); 17758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SockaddrStorage storage; 17958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!address.ToSockAddr(storage.addr, &storage.addr_len)) 1807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return ERR_ADDRESS_INVALID; 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 182116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return socket_->Bind(storage); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)int TCPSocketLibevent::Listen(int backlog) { 186116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(socket_); 187116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return socket_->Listen(backlog); 18858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 18958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 190116680a4aac90f2aa7413d9095a592090648e557Ben Murdochint TCPSocketLibevent::Accept(scoped_ptr<TCPSocketLibevent>* tcp_socket, 19158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) IPEndPoint* address, 19258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const CompletionCallback& callback) { 193116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(tcp_socket); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!callback.is_null()); 195116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(socket_); 196116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(!accept_socket_); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.BeginEvent(NetLog::TYPE_TCP_ACCEPT); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 200116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int rv = socket_->Accept( 201116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &accept_socket_, 202116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Bind(&TCPSocketLibevent::AcceptCompleted, 203116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Unretained(this), tcp_socket, address, callback)); 204116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (rv != ERR_IO_PENDING) 205116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch rv = HandleAcceptCompleted(tcp_socket, address, rv); 206116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return rv; 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 209d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)int TCPSocketLibevent::Connect(const IPEndPoint& address, 210d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const CompletionCallback& callback) { 211116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(socket_); 212d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 213d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!logging_multiple_connect_attempts_) 214d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) LogConnectBegin(AddressList(address)); 215d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 216116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT, 217116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CreateNetLogIPEndPointCallback(&address)); 218d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 219116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SockaddrStorage storage; 220116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!address.ToSockAddr(storage.addr, &storage.addr_len)) 221116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return ERR_ADDRESS_INVALID; 222116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 223116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (use_tcp_fastopen_) { 224116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // With TCP FastOpen, we pretend that the socket is connected. 225116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(!tcp_fastopen_connected_); 226116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch socket_->SetPeerAddress(storage); 227116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return OK; 228d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 229d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 230116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int rv = socket_->Connect(storage, 231116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Bind(&TCPSocketLibevent::ConnectCompleted, 232116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Unretained(this), callback)); 233116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (rv != ERR_IO_PENDING) 234116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch rv = HandleConnectCompleted(rv); 235d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return rv; 236d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 237d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 238d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool TCPSocketLibevent::IsConnected() const { 239116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!socket_) 240d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return false; 241d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 242116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (use_tcp_fastopen_ && !tcp_fastopen_connected_ && 243116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch socket_->HasPeerAddress()) { 244d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // With TCP FastOpen, we pretend that the socket is connected. 245d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // This allows GetPeerAddress() to return peer_address_. 246d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return true; 247d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 248d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 249116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return socket_->IsConnected(); 250d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 251d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 252d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool TCPSocketLibevent::IsConnectedAndIdle() const { 253d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // TODO(wtc): should we also handle the TCP FastOpen case here, 254d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // as we do in IsConnected()? 255116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return socket_ && socket_->IsConnectedAndIdle(); 256d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 257d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 258d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)int TCPSocketLibevent::Read(IOBuffer* buf, 259d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int buf_len, 260d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const CompletionCallback& callback) { 261116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(socket_); 262d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(!callback.is_null()); 263d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 264116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int rv = socket_->Read( 265116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch buf, buf_len, 266116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Bind(&TCPSocketLibevent::ReadCompleted, 267116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Grab a reference to |buf| so that ReadCompleted() can still 268116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // use it when Read() completes, as otherwise, this transfers 269116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // ownership of buf to socket. 270116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Unretained(this), make_scoped_refptr(buf), callback)); 271116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (rv >= 0) 272116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch RecordFastOpenStatus(); 273116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (rv != ERR_IO_PENDING) 274116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch rv = HandleReadCompleted(buf, rv); 275116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return rv; 276d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 277d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 278d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)int TCPSocketLibevent::Write(IOBuffer* buf, 279d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int buf_len, 280d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const CompletionCallback& callback) { 281116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(socket_); 282d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(!callback.is_null()); 283d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 284116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CompletionCallback write_callback = 285116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Bind(&TCPSocketLibevent::WriteCompleted, 286116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Grab a reference to |buf| so that WriteCompleted() can still 287116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // use it when Write() completes, as otherwise, this transfers 288116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // ownership of buf to socket. 289116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Unretained(this), make_scoped_refptr(buf), callback); 290116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int rv; 291116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (use_tcp_fastopen_ && !tcp_fastopen_connected_) { 292116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch rv = TcpFastOpenWrite(buf, buf_len, write_callback); 293116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else { 294116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch rv = socket_->Write(buf, buf_len, write_callback); 295d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 296d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 297116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (rv != ERR_IO_PENDING) 298116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch rv = HandleWriteCompleted(buf, rv); 299116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return rv; 300d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 301d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 302d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)int TCPSocketLibevent::GetLocalAddress(IPEndPoint* address) const { 303d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(address); 304d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 305116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!socket_) 306116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return ERR_SOCKET_NOT_CONNECTED; 307116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 308d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SockaddrStorage storage; 309116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int rv = socket_->GetLocalAddress(&storage); 310116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (rv != OK) 311116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return rv; 312116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 313d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!address->FromSockAddr(storage.addr, storage.addr_len)) 314d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return ERR_ADDRESS_INVALID; 315d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 316d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return OK; 317d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 318d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 319d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)int TCPSocketLibevent::GetPeerAddress(IPEndPoint* address) const { 320d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(address); 321116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 322d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!IsConnected()) 323d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return ERR_SOCKET_NOT_CONNECTED; 324116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 325116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SockaddrStorage storage; 326116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int rv = socket_->GetPeerAddress(&storage); 327116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (rv != OK) 328116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return rv; 329116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 330116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!address->FromSockAddr(storage.addr, storage.addr_len)) 331116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return ERR_ADDRESS_INVALID; 332116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 333d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return OK; 334d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 335d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 33658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)int TCPSocketLibevent::SetDefaultOptionsForServer() { 337116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(socket_); 33858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return SetAddressReuse(true); 33958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 34058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 341d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void TCPSocketLibevent::SetDefaultOptionsForClient() { 342116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(socket_); 343d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 344d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // This mirrors the behaviour on Windows. See the comment in 345d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // tcp_socket_win.cc after searching for "NODELAY". 346116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // If SetTCPNoDelay fails, we don't care. 347116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SetTCPNoDelay(socket_->socket_fd(), true); 3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // TCP keep alive wakes up the radio, which is expensive on mobile. Do not 3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // enable it there. It's useful to prevent TCP middleboxes from timing out 3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // connection mappings. Packets for timed out connection mappings at 3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // middleboxes will either lead to: 3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // a) Middleboxes sending TCP RSTs. It's up to higher layers to check for this 3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // and retry. The HTTP network transaction code does this. 3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // b) Middleboxes just drop the unrecognized TCP packet. This leads to the TCP 3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // stack retransmitting packets per TCP stack retransmission timeouts, which 3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // are very high (on the order of seconds). Given the number of 3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // retransmissions required before killing the connection, this can lead to 3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // tens of seconds or even minutes of delay, depending on OS. 3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if !defined(OS_ANDROID) && !defined(OS_IOS) 3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const int kTCPKeepAliveSeconds = 45; 3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 363116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SetTCPKeepAlive(socket_->socket_fd(), true, kTCPKeepAliveSeconds); 3645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif 365d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 366d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 36758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)int TCPSocketLibevent::SetAddressReuse(bool allow) { 368116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(socket_); 369d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 3707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // SO_REUSEADDR is useful for server sockets to bind to a recently unbound 3717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // port. When a socket is closed, the end point changes its state to TIME_WAIT 3727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // and wait for 2 MSL (maximum segment lifetime) to ensure the remote peer 3737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // acknowledges its closure. For server sockets, it is usually safe to 3747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // bind to a TIME_WAIT end point immediately, which is a widely adopted 3757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // behavior. 3767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // 3777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Note that on *nix, SO_REUSEADDR does not enable the TCP socket to bind to 3787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // an end point that is already bound by another socket. To do that one must 3797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // set SO_REUSEPORT instead. This option is not provided on Linux prior 3807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // to 3.9. 3817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // 3827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // SO_REUSEPORT is provided in MacOS X and iOS. 38358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) int boolean_value = allow ? 1 : 0; 384116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int rv = setsockopt(socket_->socket_fd(), SOL_SOCKET, SO_REUSEADDR, 385116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &boolean_value, sizeof(boolean_value)); 3867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (rv < 0) 3877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return MapSystemError(errno); 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 391c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochint TCPSocketLibevent::SetReceiveBufferSize(int32 size) { 392116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(socket_); 393116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int rv = setsockopt(socket_->socket_fd(), SOL_SOCKET, SO_RCVBUF, 394c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch reinterpret_cast<const char*>(&size), sizeof(size)); 395a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return (rv == 0) ? OK : MapSystemError(errno); 396d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 397d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 398c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochint TCPSocketLibevent::SetSendBufferSize(int32 size) { 399116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(socket_); 400116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int rv = setsockopt(socket_->socket_fd(), SOL_SOCKET, SO_SNDBUF, 401c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch reinterpret_cast<const char*>(&size), sizeof(size)); 402a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return (rv == 0) ? OK : MapSystemError(errno); 403d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 404d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 405d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool TCPSocketLibevent::SetKeepAlive(bool enable, int delay) { 406116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(socket_); 407116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return SetTCPKeepAlive(socket_->socket_fd(), enable, delay); 408d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 409d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 410d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool TCPSocketLibevent::SetNoDelay(bool no_delay) { 411116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(socket_); 412116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return SetTCPNoDelay(socket_->socket_fd(), no_delay); 413d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 414d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 41558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void TCPSocketLibevent::Close() { 416116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch socket_.reset(); 417d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) tcp_fastopen_connected_ = false; 418d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) fast_open_status_ = FAST_OPEN_STATUS_UNKNOWN; 419d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 420d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 421d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool TCPSocketLibevent::UsingTCPFastOpen() const { 422d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return use_tcp_fastopen_; 423d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 424d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 4251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid TCPSocketLibevent::EnableTCPFastOpenIfSupported() { 4261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (IsTCPFastOpenSupported()) 4271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci use_tcp_fastopen_ = true; 4281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 4291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 430116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool TCPSocketLibevent::IsValid() const { 431116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return socket_ != NULL && socket_->socket_fd() != kInvalidSocket; 432116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 433116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 434d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void TCPSocketLibevent::StartLoggingMultipleConnectAttempts( 435d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const AddressList& addresses) { 436d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!logging_multiple_connect_attempts_) { 437d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) logging_multiple_connect_attempts_ = true; 438d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) LogConnectBegin(addresses); 439d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } else { 440d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) NOTREACHED(); 441d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 442d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 443d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 444d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void TCPSocketLibevent::EndLoggingMultipleConnectAttempts(int net_error) { 445d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (logging_multiple_connect_attempts_) { 446d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) LogConnectEnd(net_error); 447d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) logging_multiple_connect_attempts_ = false; 448d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } else { 449d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) NOTREACHED(); 450d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 45158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 45258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 453116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid TCPSocketLibevent::AcceptCompleted( 454116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<TCPSocketLibevent>* tcp_socket, 455116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch IPEndPoint* address, 456116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const CompletionCallback& callback, 457116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int rv) { 458116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK_NE(ERR_IO_PENDING, rv); 459116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch callback.Run(HandleAcceptCompleted(tcp_socket, address, rv)); 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 462116680a4aac90f2aa7413d9095a592090648e557Ben Murdochint TCPSocketLibevent::HandleAcceptCompleted( 463116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<TCPSocketLibevent>* tcp_socket, 464116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch IPEndPoint* address, 465116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int rv) { 466116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (rv == OK) 467116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch rv = BuildTcpSocketLibevent(tcp_socket, address); 468d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 469116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (rv == OK) { 470116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch net_log_.EndEvent(NetLog::TYPE_TCP_ACCEPT, 471116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CreateNetLogIPEndPointCallback(address)); 472d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } else { 473116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, rv); 474d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 475d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 476116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return rv; 477116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 478116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 479116680a4aac90f2aa7413d9095a592090648e557Ben Murdochint TCPSocketLibevent::BuildTcpSocketLibevent( 480116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<TCPSocketLibevent>* tcp_socket, 481116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch IPEndPoint* address) { 482116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(accept_socket_); 483116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 484116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SockaddrStorage storage; 485116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (accept_socket_->GetPeerAddress(&storage) != OK || 486116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch !address->FromSockAddr(storage.addr, storage.addr_len)) { 487116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch accept_socket_.reset(); 488116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return ERR_ADDRESS_INVALID; 489d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 490d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 491116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch tcp_socket->reset(new TCPSocketLibevent(net_log_.net_log(), 492116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch net_log_.source())); 493116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch (*tcp_socket)->socket_.reset(accept_socket_.release()); 494116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return OK; 495116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 496116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 497116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid TCPSocketLibevent::ConnectCompleted(const CompletionCallback& callback, 498116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int rv) const { 499116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK_NE(ERR_IO_PENDING, rv); 500116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch callback.Run(HandleConnectCompleted(rv)); 501d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 502d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 503116680a4aac90f2aa7413d9095a592090648e557Ben Murdochint TCPSocketLibevent::HandleConnectCompleted(int rv) const { 504d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Log the end of this attempt (and any OS error it threw). 505116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (rv != OK) { 506d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT, 507116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch NetLog::IntegerCallback("os_error", errno)); 508d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } else { 509d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT); 510d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 511d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 512116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Give a more specific error when the user is offline. 513116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (rv == ERR_ADDRESS_UNREACHABLE && NetworkChangeNotifier::IsOffline()) 514116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch rv = ERR_INTERNET_DISCONNECTED; 515116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 516d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!logging_multiple_connect_attempts_) 517116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LogConnectEnd(rv); 518116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 519116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return rv; 520d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 521d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 522116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid TCPSocketLibevent::LogConnectBegin(const AddressList& addresses) const { 523d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::StatsCounter connects("tcp.connect"); 524d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) connects.Increment(); 525d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 526d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT, 527d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) addresses.CreateNetLogCallback()); 528d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 529d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 530116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid TCPSocketLibevent::LogConnectEnd(int net_error) const { 531d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (net_error != OK) { 532d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, net_error); 533d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return; 534d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 535d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 536116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch UpdateConnectionTypeHistograms(CONNECTION_ANY); 537116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 538d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SockaddrStorage storage; 539116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int rv = socket_->GetLocalAddress(&storage); 540116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (rv != OK) { 541116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch PLOG(ERROR) << "GetLocalAddress() [rv: " << rv << "] error: "; 542d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) NOTREACHED(); 543d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, rv); 544d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return; 545d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 546d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 547d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT, 548d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) CreateNetLogSourceAddressCallback(storage.addr, 549d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) storage.addr_len)); 550d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 551d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 552116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid TCPSocketLibevent::ReadCompleted(const scoped_refptr<IOBuffer>& buf, 553116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const CompletionCallback& callback, 554116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int rv) { 555116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK_NE(ERR_IO_PENDING, rv); 5561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Records TCP FastOpen status regardless of error in asynchronous case. 557116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // TODO(rdsmith,jri): Change histogram name to indicate it could be called on 558116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // error. 559d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) RecordFastOpenStatus(); 5601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callback.Run(HandleReadCompleted(buf.get(), rv)); 561d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 562d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 563116680a4aac90f2aa7413d9095a592090648e557Ben Murdochint TCPSocketLibevent::HandleReadCompleted(IOBuffer* buf, int rv) { 564116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (rv < 0) { 565116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch net_log_.AddEvent(NetLog::TYPE_SOCKET_READ_ERROR, 566116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CreateNetLogSocketErrorCallback(rv, errno)); 567116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return rv; 568d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 569d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 570116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::StatsCounter read_bytes("tcp.read_bytes"); 571116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch read_bytes.Add(rv); 572116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, rv, 573116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch buf->data()); 574116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return rv; 575d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 576d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 577116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid TCPSocketLibevent::WriteCompleted(const scoped_refptr<IOBuffer>& buf, 578116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const CompletionCallback& callback, 579116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int rv) const { 580116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK_NE(ERR_IO_PENDING, rv); 5811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callback.Run(HandleWriteCompleted(buf.get(), rv)); 582d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 583d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 584116680a4aac90f2aa7413d9095a592090648e557Ben Murdochint TCPSocketLibevent::HandleWriteCompleted(IOBuffer* buf, int rv) const { 585116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (rv < 0) { 586116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch net_log_.AddEvent(NetLog::TYPE_SOCKET_WRITE_ERROR, 587116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CreateNetLogSocketErrorCallback(rv, errno)); 588116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return rv; 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 590116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 591116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::StatsCounter write_bytes("tcp.write_bytes"); 592116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch write_bytes.Add(rv); 593116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_SENT, rv, 594116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch buf->data()); 595116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return rv; 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 598116680a4aac90f2aa7413d9095a592090648e557Ben Murdochint TCPSocketLibevent::TcpFastOpenWrite( 599116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch IOBuffer* buf, 600116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int buf_len, 601116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const CompletionCallback& callback) { 602116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SockaddrStorage storage; 603116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int rv = socket_->GetPeerAddress(&storage); 604116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (rv != OK) 605116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return rv; 606d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 607116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int flags = 0x20000000; // Magic flag to enable TCP_FASTOPEN. 6081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(OS_LINUX) || defined(OS_ANDROID) 609116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // sendto() will fail with EPIPE when the system doesn't support TCP Fast 610116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Open. Theoretically that shouldn't happen since the caller should check 611116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // for system support on startup, but users may dynamically disable TCP Fast 612116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Open via sysctl. 613116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch flags |= MSG_NOSIGNAL; 6141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif // defined(OS_LINUX) || defined(OS_ANDROID) 615116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch rv = HANDLE_EINTR(sendto(socket_->socket_fd(), 616116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch buf->data(), 617116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch buf_len, 618116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch flags, 619116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch storage.addr, 620116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch storage.addr_len)); 621116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch tcp_fastopen_connected_ = true; 622116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 623116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (rv >= 0) { 624116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch fast_open_status_ = FAST_OPEN_FAST_CONNECT_RETURN; 625116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return rv; 626116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 627116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 628116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK_NE(EPIPE, errno); 629116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 630116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // If errno == EINPROGRESS, that means the kernel didn't have a cookie 631116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // and would block. The kernel is internally doing a connect() though. 632116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Remap EINPROGRESS to EAGAIN so we treat this the same as our other 633116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // asynchronous cases. Note that the user buffer has not been copied to 634116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // kernel space. 635116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (errno == EINPROGRESS) { 636116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch rv = ERR_IO_PENDING; 637d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } else { 638116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch rv = MapSystemError(errno); 639d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 640116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 641116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (rv != ERR_IO_PENDING) { 642116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch fast_open_status_ = FAST_OPEN_ERROR; 643116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return rv; 644116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 645116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 646116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch fast_open_status_ = FAST_OPEN_SLOW_CONNECT_RETURN; 647116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return socket_->WaitForWrite(buf, buf_len, callback); 648d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 649d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 650d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void TCPSocketLibevent::RecordFastOpenStatus() { 651d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (use_tcp_fastopen_ && 652d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) (fast_open_status_ == FAST_OPEN_FAST_CONNECT_RETURN || 653d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) fast_open_status_ == FAST_OPEN_SLOW_CONNECT_RETURN)) { 654d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK_NE(FAST_OPEN_STATUS_UNKNOWN, fast_open_status_); 655d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) bool getsockopt_success(false); 656d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) bool server_acked_data(false); 657d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#if defined(TCP_INFO) 6581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Probe to see the if the socket used TCP FastOpen. 659d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) tcp_info info; 660d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) socklen_t info_len = sizeof(tcp_info); 661d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) getsockopt_success = 662116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch getsockopt(socket_->socket_fd(), IPPROTO_TCP, TCP_INFO, 663116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &info, &info_len) == 0 && 664d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) info_len == sizeof(tcp_info); 665d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) server_acked_data = getsockopt_success && 666d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) (info.tcpi_options & TCPI_OPT_SYN_DATA); 667d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#endif 668d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (getsockopt_success) { 669d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (fast_open_status_ == FAST_OPEN_FAST_CONNECT_RETURN) { 670d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) fast_open_status_ = (server_acked_data ? FAST_OPEN_SYN_DATA_ACK : 671d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) FAST_OPEN_SYN_DATA_NACK); 672d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } else { 673d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) fast_open_status_ = (server_acked_data ? FAST_OPEN_NO_SYN_DATA_ACK : 674d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) FAST_OPEN_NO_SYN_DATA_NACK); 675d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 676d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } else { 677d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) fast_open_status_ = (fast_open_status_ == FAST_OPEN_FAST_CONNECT_RETURN ? 678d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) FAST_OPEN_SYN_DATA_FAILED : 679d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) FAST_OPEN_NO_SYN_DATA_FAILED); 680d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 681d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 685