15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 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) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/tcp_client_socket.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <fcntl.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <netdb.h> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/socket.h> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <netinet/tcp.h> 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <netinet/in.h> 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 17ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h" 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/metrics/histogram.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/stats_counters.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/posix/eintr_wrapper.h" 215e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/connection_type_histograms.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/io_buffer.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/ip_endpoint.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_log.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/network_change_notifier.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/socket_net_log_params.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// If we don't have a definition for TCPI_OPT_SYN_DATA, create one. 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#ifndef TCPI_OPT_SYN_DATA 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#define TCPI_OPT_SYN_DATA 32 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kInvalidSocket = -1; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kTCPKeepAliveSeconds = 45; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SetTCPNoDelay turns on/off buffering in the kernel. By default, TCP sockets 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// will wait up to 200ms for more data to complete a packet before transmitting. 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// After calling this function, the kernel will not wait. See TCP_NODELAY in 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// `man 7 tcp`. 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SetTCPNoDelay(int fd, bool no_delay) { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int on = no_delay ? 1 : 0; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int error = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizeof(on)); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return error == 0; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SetTCPKeepAlive sets SO_KEEPALIVE. 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SetTCPKeepAlive(int fd, bool enable, int delay) { 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int on = enable ? 1 : 0; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on))) { 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLOG(ERROR) << "Failed to set SO_KEEPALIVE on fd: " << fd; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_LINUX) || defined(OS_ANDROID) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set seconds until first TCP keep alive. 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &delay, sizeof(delay))) { 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLOG(ERROR) << "Failed to set TCP_KEEPIDLE on fd: " << fd; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set seconds between TCP keep alives. 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &delay, sizeof(delay))) { 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLOG(ERROR) << "Failed to set TCP_KEEPINTVL on fd: " << fd; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Sets socket parameters. Returns the OS error code (or 0 on 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// success). 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SetupSocket(int socket) { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (SetNonBlocking(socket)) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return errno; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This mirrors the behaviour on Windows. See the comment in 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // tcp_client_socket_win.cc after searching for "NODELAY". 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetTCPNoDelay(socket, true); // If SetTCPNoDelay fails, we don't care. 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetTCPKeepAlive(socket, true, kTCPKeepAliveSeconds); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Creates a new socket and sets default parameters for it. Returns 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the OS error code (or 0 on success). 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CreateSocket(int family, int* socket) { 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *socket = ::socket(family, SOCK_STREAM, IPPROTO_TCP); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*socket == kInvalidSocket) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return errno; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int error = SetupSocket(*socket); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error) { 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (HANDLE_EINTR(close(*socket)) < 0) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLOG(ERROR) << "close"; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *socket = kInvalidSocket; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return error; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int MapConnectError(int os_error) { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (os_error) { 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case EACCES: 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_NETWORK_ACCESS_DENIED; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ETIMEDOUT: 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_CONNECTION_TIMED_OUT; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int net_error = MapSystemError(os_error); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (net_error == ERR_FAILED) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_CONNECTION_FAILED; // More specific than ERR_FAILED. 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Give a more specific error when the user is offline. 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (net_error == ERR_ADDRESS_UNREACHABLE && 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetworkChangeNotifier::IsOffline()) { 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_INTERNET_DISCONNECTED; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return net_error; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//----------------------------------------------------------------------------- 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TCPClientSocketLibevent::TCPClientSocketLibevent( 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const AddressList& addresses, 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::NetLog* net_log, 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::NetLog::Source& source) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : socket_(kInvalidSocket), 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bound_socket_(kInvalidSocket), 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addresses_(addresses), 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_address_index_(-1), 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_watcher_(this), 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_watcher_(this), 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_connect_state_(CONNECT_STATE_NONE), 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connect_os_error_(0), 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)), 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) previously_disconnected_(false), 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) use_tcp_fastopen_(IsTCPFastOpenEnabled()), 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tcp_fastopen_connected_(false), 147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) fast_open_status_(FAST_OPEN_STATUS_UNKNOWN) { 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source.ToEventParametersCallback()); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TCPClientSocketLibevent::~TCPClientSocketLibevent() { 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Disconnect(); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE); 155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (tcp_fastopen_connected_) { 156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("Net.TcpFastOpenSocketConnection", 157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) fast_open_status_, FAST_OPEN_MAX_VALUE); 158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TCPClientSocketLibevent::AdoptSocket(int socket) { 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(socket_, kInvalidSocket); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int error = SetupSocket(socket); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MapSystemError(error); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socket_ = socket; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is to make GetPeerAddress() work. It's up to the caller ensure 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that |address_| contains a reasonable address for this 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // socket. (i.e. at least match IPv4 vs IPv6!). 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_address_index_ = 0; 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) use_history_.set_was_ever_connected(); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TCPClientSocketLibevent::Bind(const IPEndPoint& address) { 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (current_address_index_ >= 0 || bind_address_.get()) { 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cannot bind the socket if we are already bound connected or 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // connecting. 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_UNEXPECTED; 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SockaddrStorage storage; 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!address.ToSockAddr(storage.addr, &storage.addr_len)) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_INVALID_ARGUMENT; 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create |bound_socket_| and try to bind it to |address|. 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int error = CreateSocket(address.GetSockAddrFamily(), &bound_socket_); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MapSystemError(error); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (HANDLE_EINTR(bind(bound_socket_, storage.addr, storage.addr_len))) { 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error = errno; 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (HANDLE_EINTR(close(bound_socket_)) < 0) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLOG(ERROR) << "close"; 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bound_socket_ = kInvalidSocket; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MapSystemError(error); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bind_address_.reset(new IPEndPoint(address)); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TCPClientSocketLibevent::Connect(const CompletionCallback& callback) { 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If already connected, then just return OK. 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (socket_ != kInvalidSocket) 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StatsCounter connects("tcp.connect"); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connects.Increment(); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!waiting_connect()); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT, 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addresses_.CreateNetLogCallback()); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We will try to connect to each address in addresses_. Start with the 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // first one in the list. 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_connect_state_ = CONNECT_STATE_CONNECT; 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_address_index_ = 0; 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = DoConnectLoop(OK); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv == ERR_IO_PENDING) { 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Synchronous operation not supported. 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!callback.is_null()); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_callback_ = callback; 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogConnectCompletion(rv); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TCPClientSocketLibevent::DoConnectLoop(int result) { 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(next_connect_state_, CONNECT_STATE_NONE); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = result; 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ConnectState state = next_connect_state_; 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_connect_state_ = CONNECT_STATE_NONE; 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (state) { 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CONNECT_STATE_CONNECT: 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(OK, rv); 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = DoConnect(); 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CONNECT_STATE_CONNECT_COMPLETE: 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = DoConnectComplete(rv); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "bad state"; 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = ERR_UNEXPECTED; 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (rv != ERR_IO_PENDING && next_connect_state_ != CONNECT_STATE_NONE); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TCPClientSocketLibevent::DoConnect() { 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GE(current_address_index_, 0); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LT(current_address_index_, static_cast<int>(addresses_.size())); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(0, connect_os_error_); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const IPEndPoint& endpoint = addresses_[current_address_index_]; 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (previously_disconnected_) { 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) use_history_.Reset(); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) previously_disconnected_ = false; 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT, 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateNetLogIPEndPointCallback(&endpoint)); 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_connect_state_ = CONNECT_STATE_CONNECT_COMPLETE; 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bound_socket_ != kInvalidSocket) { 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(bind_address_.get()); 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socket_ = bound_socket_; 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bound_socket_ = kInvalidSocket; 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create a non-blocking socket. 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) connect_os_error_ = CreateSocket(endpoint.GetSockAddrFamily(), &socket_); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (connect_os_error_) 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MapSystemError(connect_os_error_); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bind_address_.get()) { 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SockaddrStorage storage; 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!bind_address_->ToSockAddr(storage.addr, &storage.addr_len)) 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_INVALID_ARGUMENT; 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (HANDLE_EINTR(bind(socket_, storage.addr, storage.addr_len))) 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MapSystemError(errno); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Connect the socket. 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!use_tcp_fastopen_) { 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SockaddrStorage storage; 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!endpoint.ToSockAddr(storage.addr, &storage.addr_len)) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_INVALID_ARGUMENT; 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!HANDLE_EINTR(connect(socket_, storage.addr, storage.addr_len))) { 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Connected without waiting! 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // With TCP FastOpen, we pretend that the socket is connected. 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!tcp_fastopen_connected_); 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check if the connect() failed synchronously. 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connect_os_error_ = errno; 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (connect_os_error_ != EINPROGRESS) 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MapConnectError(connect_os_error_); 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Otherwise the connect() is going to complete asynchronously, so watch 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for its completion. 32490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!base::MessageLoopForIO::current()->WatchFileDescriptor( 32590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) socket_, true, base::MessageLoopForIO::WATCH_WRITE, 32690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) &write_socket_watcher_, &write_watcher_)) { 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connect_os_error_ = errno; 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "WatchFileDescriptor failed: " << connect_os_error_; 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MapSystemError(connect_os_error_); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_IO_PENDING; 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TCPClientSocketLibevent::DoConnectComplete(int result) { 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Log the end of this attempt (and any OS error it threw). 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int os_error = connect_os_error_; 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connect_os_error_ = 0; 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result != OK) { 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT, 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetLog::IntegerCallback("os_error", os_error)); 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result == OK) { 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_socket_watcher_.StopWatchingFileDescriptor(); 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) use_history_.set_was_ever_connected(); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; // Done! 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Close whatever partially connected socket we currently have. 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DoDisconnect(); 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Try to fall back to the next address in the list. 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (current_address_index_ + 1 < static_cast<int>(addresses_.size())) { 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_connect_state_ = CONNECT_STATE_CONNECT; 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++current_address_index_; 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Otherwise there is nothing to fall back to, so give up. 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPClientSocketLibevent::Disconnect() { 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DoDisconnect(); 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_address_index_ = -1; 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bind_address_.reset(); 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPClientSocketLibevent::DoDisconnect() { 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (socket_ == kInvalidSocket) 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool ok = read_socket_watcher_.StopWatchingFileDescriptor(); 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ok); 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ok = write_socket_watcher_.StopWatchingFileDescriptor(); 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ok); 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (HANDLE_EINTR(close(socket_)) < 0) 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLOG(ERROR) << "close"; 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socket_ = kInvalidSocket; 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) previously_disconnected_ = true; 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TCPClientSocketLibevent::IsConnected() const { 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (socket_ == kInvalidSocket || waiting_connect()) 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (use_tcp_fastopen_ && !tcp_fastopen_connected_) { 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // With TCP FastOpen, we pretend that the socket is connected. 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This allows GetPeerAddress() to return current_ai_ as the peer 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // address. Since we don't fail over to the next address if 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // sendto() fails, current_ai_ is the only possible peer address. 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_LT(current_address_index_, static_cast<int>(addresses_.size())); 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check if connection is alive. 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char c; 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = HANDLE_EINTR(recv(socket_, &c, 1, MSG_PEEK)); 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv == 0) 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv == -1 && errno != EAGAIN && errno != EWOULDBLOCK) 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TCPClientSocketLibevent::IsConnectedAndIdle() const { 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (socket_ == kInvalidSocket || waiting_connect()) 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(wtc): should we also handle the TCP FastOpen case here, 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // as we do in IsConnected()? 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check if connection is alive and we haven't received any data 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // unexpectedly. 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char c; 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = HANDLE_EINTR(recv(socket_, &c, 1, MSG_PEEK)); 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv >= 0) 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (errno != EAGAIN && errno != EWOULDBLOCK) 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TCPClientSocketLibevent::Read(IOBuffer* buf, 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int buf_len, 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CompletionCallback& callback) { 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(kInvalidSocket, socket_); 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!waiting_connect()); 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(read_callback_.is_null()); 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Synchronous operation not supported 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!callback.is_null()); 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GT(buf_len, 0); 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int nread = HANDLE_EINTR(read(socket_, buf->data(), buf_len)); 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (nread >= 0) { 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StatsCounter read_bytes("tcp.read_bytes"); 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_bytes.Add(nread); 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (nread > 0) 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) use_history_.set_was_used_to_convey_data(); 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, nread, 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf->data()); 454c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) RecordFastOpenStatus(); 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return nread; 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (errno != EAGAIN && errno != EWOULDBLOCK) { 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int net_error = MapSystemError(errno); 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.AddEvent(NetLog::TYPE_SOCKET_READ_ERROR, 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateNetLogSocketErrorCallback(net_error, errno)); 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return net_error; 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 46490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!base::MessageLoopForIO::current()->WatchFileDescriptor( 46590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) socket_, true, base::MessageLoopForIO::WATCH_READ, 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &read_socket_watcher_, &read_watcher_)) { 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "WatchFileDescriptor failed on read, errno " << errno; 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MapSystemError(errno); 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buf_ = buf; 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buf_len_ = buf_len; 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_callback_ = callback; 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_IO_PENDING; 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TCPClientSocketLibevent::Write(IOBuffer* buf, 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int buf_len, 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CompletionCallback& callback) { 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(kInvalidSocket, socket_); 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!waiting_connect()); 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(write_callback_.is_null()); 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Synchronous operation not supported 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!callback.is_null()); 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GT(buf_len, 0); 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int nwrite = InternalWrite(buf, buf_len); 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (nwrite >= 0) { 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StatsCounter write_bytes("tcp.write_bytes"); 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_bytes.Add(nwrite); 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (nwrite > 0) 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) use_history_.set_was_used_to_convey_data(); 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_SENT, nwrite, 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf->data()); 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return nwrite; 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (errno != EAGAIN && errno != EWOULDBLOCK) { 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int net_error = MapSystemError(errno); 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.AddEvent(NetLog::TYPE_SOCKET_WRITE_ERROR, 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateNetLogSocketErrorCallback(net_error, errno)); 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return net_error; 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 50590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!base::MessageLoopForIO::current()->WatchFileDescriptor( 50690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) socket_, true, base::MessageLoopForIO::WATCH_WRITE, 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &write_socket_watcher_, &write_watcher_)) { 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "WatchFileDescriptor failed on write, errno " << errno; 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MapSystemError(errno); 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_buf_ = buf; 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_buf_len_ = buf_len; 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_callback_ = callback; 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_IO_PENDING; 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TCPClientSocketLibevent::InternalWrite(IOBuffer* buf, int buf_len) { 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int nwrite; 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (use_tcp_fastopen_ && !tcp_fastopen_connected_) { 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SockaddrStorage storage; 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!addresses_[current_address_index_].ToSockAddr(storage.addr, 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &storage.addr_len)) { 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errno = EINVAL; 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int flags = 0x20000000; // Magic flag to enable TCP_FASTOPEN. 5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_LINUX) 5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // sendto() will fail with EPIPE when the system doesn't support TCP Fast 5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Open. Theoretically that shouldn't happen since the caller should check 5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // for system support on startup, but users may dynamically disable TCP Fast 5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Open via sysctl. 5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) flags |= MSG_NOSIGNAL; 5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif // defined(OS_LINUX) 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nwrite = HANDLE_EINTR(sendto(socket_, 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf->data(), 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf_len, 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) flags, 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) storage.addr, 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) storage.addr_len)); 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tcp_fastopen_connected_ = true; 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (nwrite < 0) { 5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_NE(EPIPE, errno); 5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If errno == EINPROGRESS, that means the kernel didn't have a cookie 5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // and would block. The kernel is internally doing a connect() though. 5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Remap EINPROGRESS to EAGAIN so we treat this the same as our other 5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // asynchronous cases. Note that the user buffer has not been copied to 5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // kernel space. 552c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (errno == EINPROGRESS) { 553c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) errno = EAGAIN; 554c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) fast_open_status_ = FAST_OPEN_SLOW_CONNECT_RETURN; 555c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else { 556c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) fast_open_status_ = FAST_OPEN_ERROR; 557c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 558c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else { 559c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) fast_open_status_ = FAST_OPEN_FAST_CONNECT_RETURN; 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nwrite = HANDLE_EINTR(write(socket_, buf->data(), buf_len)); 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return nwrite; 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TCPClientSocketLibevent::SetReceiveBufferSize(int32 size) { 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF, 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const char*>(&size), 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizeof(size)); 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!rv) << "Could not set socket receive buffer size: " << errno; 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv == 0; 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TCPClientSocketLibevent::SetSendBufferSize(int32 size) { 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const char*>(&size), 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizeof(size)); 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!rv) << "Could not set socket send buffer size: " << errno; 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv == 0; 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TCPClientSocketLibevent::SetKeepAlive(bool enable, int delay) { 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int socket = socket_ != kInvalidSocket ? socket_ : bound_socket_; 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SetTCPKeepAlive(socket, enable, delay); 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TCPClientSocketLibevent::SetNoDelay(bool no_delay) { 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int socket = socket_ != kInvalidSocket ? socket_ : bound_socket_; 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SetTCPNoDelay(socket, no_delay); 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPClientSocketLibevent::ReadWatcher::OnFileCanReadWithoutBlocking(int) { 596c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) socket_->RecordFastOpenStatus(); 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!socket_->read_callback_.is_null()) 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socket_->DidCompleteRead(); 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPClientSocketLibevent::WriteWatcher::OnFileCanWriteWithoutBlocking(int) { 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (socket_->waiting_connect()) { 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socket_->DidCompleteConnect(); 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (!socket_->write_callback_.is_null()) { 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socket_->DidCompleteWrite(); 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPClientSocketLibevent::LogConnectCompletion(int net_error) { 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (net_error == OK) 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateConnectionTypeHistograms(CONNECTION_ANY); 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (net_error != OK) { 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, net_error); 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SockaddrStorage storage; 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = getsockname(socket_, storage.addr, &storage.addr_len); 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv != 0) { 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLOG(ERROR) << "getsockname() [rv: " << rv << "] error: "; 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, rv); 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT, 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateNetLogSourceAddressCallback(storage.addr, 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) storage.addr_len)); 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPClientSocketLibevent::DoReadCallback(int rv) { 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(rv, ERR_IO_PENDING); 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!read_callback_.is_null()); 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // since Run may result in Read being called, clear read_callback_ up front. 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CompletionCallback c = read_callback_; 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_callback_.Reset(); 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) c.Run(rv); 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPClientSocketLibevent::DoWriteCallback(int rv) { 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(rv, ERR_IO_PENDING); 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!write_callback_.is_null()); 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // since Run may result in Write being called, clear write_callback_ up front. 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CompletionCallback c = write_callback_; 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_callback_.Reset(); 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) c.Run(rv); 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPClientSocketLibevent::DidCompleteConnect() { 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(next_connect_state_, CONNECT_STATE_CONNECT_COMPLETE); 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the error that connect() completed with. 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int os_error = 0; 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socklen_t len = sizeof(os_error); 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (getsockopt(socket_, SOL_SOCKET, SO_ERROR, &os_error, &len) < 0) 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os_error = errno; 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(eroman): Is this check really necessary? 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (os_error == EINPROGRESS || os_error == EALREADY) { 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); // This indicates a bug in libevent or our code. 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connect_os_error_ = os_error; 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = DoConnectLoop(MapConnectError(os_error)); 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv != ERR_IO_PENDING) { 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogConnectCompletion(rv); 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DoWriteCallback(rv); 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPClientSocketLibevent::DidCompleteRead() { 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int bytes_transferred; 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytes_transferred = HANDLE_EINTR(read(socket_, read_buf_->data(), 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buf_len_)); 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result; 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bytes_transferred >= 0) { 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = bytes_transferred; 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StatsCounter read_bytes("tcp.read_bytes"); 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_bytes.Add(bytes_transferred); 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bytes_transferred > 0) 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) use_history_.set_was_used_to_convey_data(); 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, result, 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buf_->data()); 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = MapSystemError(errno); 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result != ERR_IO_PENDING) { 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.AddEvent(NetLog::TYPE_SOCKET_READ_ERROR, 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateNetLogSocketErrorCallback(result, errno)); 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result != ERR_IO_PENDING) { 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buf_ = NULL; 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buf_len_ = 0; 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool ok = read_socket_watcher_.StopWatchingFileDescriptor(); 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ok); 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DoReadCallback(result); 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPClientSocketLibevent::DidCompleteWrite() { 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int bytes_transferred; 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytes_transferred = HANDLE_EINTR(write(socket_, write_buf_->data(), 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_buf_len_)); 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result; 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bytes_transferred >= 0) { 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = bytes_transferred; 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StatsCounter write_bytes("tcp.write_bytes"); 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_bytes.Add(bytes_transferred); 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bytes_transferred > 0) 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) use_history_.set_was_used_to_convey_data(); 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_SENT, result, 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_buf_->data()); 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = MapSystemError(errno); 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result != ERR_IO_PENDING) { 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.AddEvent(NetLog::TYPE_SOCKET_WRITE_ERROR, 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateNetLogSocketErrorCallback(result, errno)); 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result != ERR_IO_PENDING) { 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_buf_ = NULL; 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_buf_len_ = 0; 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_socket_watcher_.StopWatchingFileDescriptor(); 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DoWriteCallback(result); 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TCPClientSocketLibevent::GetPeerAddress(IPEndPoint* address) const { 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(address); 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsConnected()) 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_SOCKET_NOT_CONNECTED; 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *address = addresses_[current_address_index_]; 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TCPClientSocketLibevent::GetLocalAddress(IPEndPoint* address) const { 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(address); 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (socket_ == kInvalidSocket) { 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bind_address_.get()) { 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *address = *bind_address_; 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_SOCKET_NOT_CONNECTED; 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SockaddrStorage storage; 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (getsockname(socket_, storage.addr, &storage.addr_len)) 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MapSystemError(errno); 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!address->FromSockAddr(storage.addr, storage.addr_len)) 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_FAILED; 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void TCPClientSocketLibevent::RecordFastOpenStatus() { 766c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (use_tcp_fastopen_ && 767c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) (fast_open_status_ == FAST_OPEN_FAST_CONNECT_RETURN || 768c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) fast_open_status_ == FAST_OPEN_SLOW_CONNECT_RETURN)) { 769c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_NE(FAST_OPEN_STATUS_UNKNOWN, fast_open_status_); 770c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool getsockopt_success(false); 771c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool server_acked_data(false); 772c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(TCP_INFO) 773c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Probe to see the if the socket used TCP Fast Open. 774c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) tcp_info info; 775c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) socklen_t info_len = sizeof(tcp_info); 776c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) getsockopt_success = 777c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) getsockopt(socket_, IPPROTO_TCP, TCP_INFO, &info, &info_len) == 0 && 778c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) info_len == sizeof(tcp_info); 779c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) server_acked_data = getsockopt_success && 780c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) (info.tcpi_options & TCPI_OPT_SYN_DATA); 781c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif 782c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (getsockopt_success) { 783c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (fast_open_status_ == FAST_OPEN_FAST_CONNECT_RETURN) { 784c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) fast_open_status_ = (server_acked_data ? FAST_OPEN_SYN_DATA_ACK : 785c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FAST_OPEN_SYN_DATA_NACK); 786c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else { 787c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) fast_open_status_ = (server_acked_data ? FAST_OPEN_NO_SYN_DATA_ACK : 788c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FAST_OPEN_NO_SYN_DATA_NACK); 789c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 790c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else { 791c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) fast_open_status_ = (fast_open_status_ == FAST_OPEN_FAST_CONNECT_RETURN ? 792c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FAST_OPEN_SYN_DATA_FAILED : 793c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FAST_OPEN_NO_SYN_DATA_FAILED); 794c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 795c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 796c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 797c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const BoundNetLog& TCPClientSocketLibevent::NetLog() const { 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return net_log_; 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPClientSocketLibevent::SetSubresourceSpeculation() { 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) use_history_.set_subresource_speculation(); 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCPClientSocketLibevent::SetOmniboxSpeculation() { 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) use_history_.set_omnibox_speculation(); 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TCPClientSocketLibevent::WasEverUsed() const { 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return use_history_.was_used_to_convey_data(); 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TCPClientSocketLibevent::UsingTCPFastOpen() const { 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return use_tcp_fastopen_; 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TCPClientSocketLibevent::WasNpnNegotiated() const { 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NextProto TCPClientSocketLibevent::GetNegotiatedProtocol() const { 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kProtoUnknown; 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TCPClientSocketLibevent::GetSSLInfo(SSLInfo* ssl_info) { 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 831