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