Home | History | Annotate | Download | only in socket
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "net/socket/tcp_client_socket.h"
      6 
      7 #include <errno.h>
      8 #include <fcntl.h>
      9 #include <netdb.h>
     10 #include <sys/socket.h>
     11 #include <netinet/tcp.h>
     12 #if defined(OS_POSIX)
     13 #include <netinet/in.h>
     14 #endif
     15 
     16 #include "base/logging.h"
     17 #include "base/message_loop/message_loop.h"
     18 #include "base/metrics/histogram.h"
     19 #include "base/metrics/stats_counters.h"
     20 #include "base/posix/eintr_wrapper.h"
     21 #include "base/strings/string_util.h"
     22 #include "net/base/connection_type_histograms.h"
     23 #include "net/base/io_buffer.h"
     24 #include "net/base/ip_endpoint.h"
     25 #include "net/base/net_errors.h"
     26 #include "net/base/net_log.h"
     27 #include "net/base/net_util.h"
     28 #include "net/base/network_change_notifier.h"
     29 #include "net/socket/socket_net_log_params.h"
     30 
     31 // If we don't have a definition for TCPI_OPT_SYN_DATA, create one.
     32 #ifndef TCPI_OPT_SYN_DATA
     33 #define TCPI_OPT_SYN_DATA 32
     34 #endif
     35 
     36 namespace net {
     37 
     38 namespace {
     39 
     40 const int kInvalidSocket = -1;
     41 const int kTCPKeepAliveSeconds = 45;
     42 
     43 // SetTCPNoDelay turns on/off buffering in the kernel. By default, TCP sockets
     44 // will wait up to 200ms for more data to complete a packet before transmitting.
     45 // After calling this function, the kernel will not wait. See TCP_NODELAY in
     46 // `man 7 tcp`.
     47 bool SetTCPNoDelay(int fd, bool no_delay) {
     48   int on = no_delay ? 1 : 0;
     49   int error = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on,
     50       sizeof(on));
     51   return error == 0;
     52 }
     53 
     54 // SetTCPKeepAlive sets SO_KEEPALIVE.
     55 bool  SetTCPKeepAlive(int fd, bool enable, int delay) {
     56   int on = enable ? 1 : 0;
     57   if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on))) {
     58     PLOG(ERROR) << "Failed to set SO_KEEPALIVE on fd: " << fd;
     59     return false;
     60   }
     61 #if defined(OS_LINUX) || defined(OS_ANDROID)
     62   // Set seconds until first TCP keep alive.
     63   if (setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &delay, sizeof(delay))) {
     64     PLOG(ERROR) << "Failed to set TCP_KEEPIDLE on fd: " << fd;
     65     return false;
     66   }
     67   // Set seconds between TCP keep alives.
     68   if (setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &delay, sizeof(delay))) {
     69     PLOG(ERROR) << "Failed to set TCP_KEEPINTVL on fd: " << fd;
     70     return false;
     71   }
     72 #endif
     73   return true;
     74 }
     75 
     76 // Sets socket parameters. Returns the OS error code (or 0 on
     77 // success).
     78 int SetupSocket(int socket) {
     79   if (SetNonBlocking(socket))
     80     return errno;
     81 
     82   // This mirrors the behaviour on Windows. See the comment in
     83   // tcp_client_socket_win.cc after searching for "NODELAY".
     84   SetTCPNoDelay(socket, true);  // If SetTCPNoDelay fails, we don't care.
     85   SetTCPKeepAlive(socket, true, kTCPKeepAliveSeconds);
     86 
     87   return 0;
     88 }
     89 
     90 // Creates a new socket and sets default parameters for it. Returns
     91 // the OS error code (or 0 on success).
     92 int CreateSocket(int family, int* socket) {
     93   *socket = ::socket(family, SOCK_STREAM, IPPROTO_TCP);
     94   if (*socket == kInvalidSocket)
     95     return errno;
     96   int error = SetupSocket(*socket);
     97   if (error) {
     98     if (HANDLE_EINTR(close(*socket)) < 0)
     99       PLOG(ERROR) << "close";
    100     *socket = kInvalidSocket;
    101     return error;
    102   }
    103   return 0;
    104 }
    105 
    106 int MapConnectError(int os_error) {
    107   switch (os_error) {
    108     case EACCES:
    109       return ERR_NETWORK_ACCESS_DENIED;
    110     case ETIMEDOUT:
    111       return ERR_CONNECTION_TIMED_OUT;
    112     default: {
    113       int net_error = MapSystemError(os_error);
    114       if (net_error == ERR_FAILED)
    115         return ERR_CONNECTION_FAILED;  // More specific than ERR_FAILED.
    116 
    117       // Give a more specific error when the user is offline.
    118       if (net_error == ERR_ADDRESS_UNREACHABLE &&
    119           NetworkChangeNotifier::IsOffline()) {
    120         return ERR_INTERNET_DISCONNECTED;
    121       }
    122       return net_error;
    123     }
    124   }
    125 }
    126 
    127 }  // namespace
    128 
    129 //-----------------------------------------------------------------------------
    130 
    131 TCPClientSocketLibevent::TCPClientSocketLibevent(
    132     const AddressList& addresses,
    133     net::NetLog* net_log,
    134     const net::NetLog::Source& source)
    135     : socket_(kInvalidSocket),
    136       bound_socket_(kInvalidSocket),
    137       addresses_(addresses),
    138       current_address_index_(-1),
    139       read_watcher_(this),
    140       write_watcher_(this),
    141       next_connect_state_(CONNECT_STATE_NONE),
    142       connect_os_error_(0),
    143       net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)),
    144       previously_disconnected_(false),
    145       use_tcp_fastopen_(IsTCPFastOpenEnabled()),
    146       tcp_fastopen_connected_(false),
    147       fast_open_status_(FAST_OPEN_STATUS_UNKNOWN) {
    148   net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE,
    149                       source.ToEventParametersCallback());
    150 }
    151 
    152 TCPClientSocketLibevent::~TCPClientSocketLibevent() {
    153   Disconnect();
    154   net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE);
    155   if (tcp_fastopen_connected_) {
    156     UMA_HISTOGRAM_ENUMERATION("Net.TcpFastOpenSocketConnection",
    157                               fast_open_status_, FAST_OPEN_MAX_VALUE);
    158   }
    159 }
    160 
    161 int TCPClientSocketLibevent::AdoptSocket(int socket) {
    162   DCHECK_EQ(socket_, kInvalidSocket);
    163 
    164   int error = SetupSocket(socket);
    165   if (error)
    166     return MapSystemError(error);
    167 
    168   socket_ = socket;
    169 
    170   // This is to make GetPeerAddress() work. It's up to the caller ensure
    171   // that |address_| contains a reasonable address for this
    172   // socket. (i.e. at least match IPv4 vs IPv6!).
    173   current_address_index_ = 0;
    174   use_history_.set_was_ever_connected();
    175 
    176   return OK;
    177 }
    178 
    179 int TCPClientSocketLibevent::Bind(const IPEndPoint& address) {
    180   if (current_address_index_ >= 0 || bind_address_.get()) {
    181     // Cannot bind the socket if we are already bound connected or
    182     // connecting.
    183     return ERR_UNEXPECTED;
    184   }
    185 
    186   SockaddrStorage storage;
    187   if (!address.ToSockAddr(storage.addr, &storage.addr_len))
    188     return ERR_INVALID_ARGUMENT;
    189 
    190   // Create |bound_socket_| and try to bind it to |address|.
    191   int error = CreateSocket(address.GetSockAddrFamily(), &bound_socket_);
    192   if (error)
    193     return MapSystemError(error);
    194 
    195   if (HANDLE_EINTR(bind(bound_socket_, storage.addr, storage.addr_len))) {
    196     error = errno;
    197     if (HANDLE_EINTR(close(bound_socket_)) < 0)
    198       PLOG(ERROR) << "close";
    199     bound_socket_ = kInvalidSocket;
    200     return MapSystemError(error);
    201   }
    202 
    203   bind_address_.reset(new IPEndPoint(address));
    204 
    205   return 0;
    206 }
    207 
    208 int TCPClientSocketLibevent::Connect(const CompletionCallback& callback) {
    209   DCHECK(CalledOnValidThread());
    210 
    211   // If already connected, then just return OK.
    212   if (socket_ != kInvalidSocket)
    213     return OK;
    214 
    215   base::StatsCounter connects("tcp.connect");
    216   connects.Increment();
    217 
    218   DCHECK(!waiting_connect());
    219 
    220   net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT,
    221                       addresses_.CreateNetLogCallback());
    222 
    223   // We will try to connect to each address in addresses_. Start with the
    224   // first one in the list.
    225   next_connect_state_ = CONNECT_STATE_CONNECT;
    226   current_address_index_ = 0;
    227 
    228   int rv = DoConnectLoop(OK);
    229   if (rv == ERR_IO_PENDING) {
    230     // Synchronous operation not supported.
    231     DCHECK(!callback.is_null());
    232     write_callback_ = callback;
    233   } else {
    234     LogConnectCompletion(rv);
    235   }
    236 
    237   return rv;
    238 }
    239 
    240 int TCPClientSocketLibevent::DoConnectLoop(int result) {
    241   DCHECK_NE(next_connect_state_, CONNECT_STATE_NONE);
    242 
    243   int rv = result;
    244   do {
    245     ConnectState state = next_connect_state_;
    246     next_connect_state_ = CONNECT_STATE_NONE;
    247     switch (state) {
    248       case CONNECT_STATE_CONNECT:
    249         DCHECK_EQ(OK, rv);
    250         rv = DoConnect();
    251         break;
    252       case CONNECT_STATE_CONNECT_COMPLETE:
    253         rv = DoConnectComplete(rv);
    254         break;
    255       default:
    256         LOG(DFATAL) << "bad state";
    257         rv = ERR_UNEXPECTED;
    258         break;
    259     }
    260   } while (rv != ERR_IO_PENDING && next_connect_state_ != CONNECT_STATE_NONE);
    261 
    262   return rv;
    263 }
    264 
    265 int TCPClientSocketLibevent::DoConnect() {
    266   DCHECK_GE(current_address_index_, 0);
    267   DCHECK_LT(current_address_index_, static_cast<int>(addresses_.size()));
    268   DCHECK_EQ(0, connect_os_error_);
    269 
    270   const IPEndPoint& endpoint = addresses_[current_address_index_];
    271 
    272   if (previously_disconnected_) {
    273     use_history_.Reset();
    274     previously_disconnected_ = false;
    275   }
    276 
    277   net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT,
    278                       CreateNetLogIPEndPointCallback(&endpoint));
    279 
    280   next_connect_state_ = CONNECT_STATE_CONNECT_COMPLETE;
    281 
    282   if (bound_socket_ != kInvalidSocket) {
    283     DCHECK(bind_address_.get());
    284     socket_ = bound_socket_;
    285     bound_socket_ = kInvalidSocket;
    286   } else {
    287     // Create a non-blocking socket.
    288     connect_os_error_ = CreateSocket(endpoint.GetSockAddrFamily(), &socket_);
    289     if (connect_os_error_)
    290       return MapSystemError(connect_os_error_);
    291 
    292     if (bind_address_.get()) {
    293       SockaddrStorage storage;
    294       if (!bind_address_->ToSockAddr(storage.addr, &storage.addr_len))
    295         return ERR_INVALID_ARGUMENT;
    296       if (HANDLE_EINTR(bind(socket_, storage.addr, storage.addr_len)))
    297         return MapSystemError(errno);
    298     }
    299   }
    300 
    301   // Connect the socket.
    302   if (!use_tcp_fastopen_) {
    303     SockaddrStorage storage;
    304     if (!endpoint.ToSockAddr(storage.addr, &storage.addr_len))
    305       return ERR_INVALID_ARGUMENT;
    306 
    307     if (!HANDLE_EINTR(connect(socket_, storage.addr, storage.addr_len))) {
    308       // Connected without waiting!
    309       return OK;
    310     }
    311   } else {
    312     // With TCP FastOpen, we pretend that the socket is connected.
    313     DCHECK(!tcp_fastopen_connected_);
    314     return OK;
    315   }
    316 
    317   // Check if the connect() failed synchronously.
    318   connect_os_error_ = errno;
    319   if (connect_os_error_ != EINPROGRESS)
    320     return MapConnectError(connect_os_error_);
    321 
    322   // Otherwise the connect() is going to complete asynchronously, so watch
    323   // for its completion.
    324   if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
    325           socket_, true, base::MessageLoopForIO::WATCH_WRITE,
    326           &write_socket_watcher_, &write_watcher_)) {
    327     connect_os_error_ = errno;
    328     DVLOG(1) << "WatchFileDescriptor failed: " << connect_os_error_;
    329     return MapSystemError(connect_os_error_);
    330   }
    331 
    332   return ERR_IO_PENDING;
    333 }
    334 
    335 int TCPClientSocketLibevent::DoConnectComplete(int result) {
    336   // Log the end of this attempt (and any OS error it threw).
    337   int os_error = connect_os_error_;
    338   connect_os_error_ = 0;
    339   if (result != OK) {
    340     net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT,
    341                       NetLog::IntegerCallback("os_error", os_error));
    342   } else {
    343     net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT);
    344   }
    345 
    346   if (result == OK) {
    347     write_socket_watcher_.StopWatchingFileDescriptor();
    348     use_history_.set_was_ever_connected();
    349     return OK;  // Done!
    350   }
    351 
    352   // Close whatever partially connected socket we currently have.
    353   DoDisconnect();
    354 
    355   // Try to fall back to the next address in the list.
    356   if (current_address_index_ + 1 < static_cast<int>(addresses_.size())) {
    357     next_connect_state_ = CONNECT_STATE_CONNECT;
    358     ++current_address_index_;
    359     return OK;
    360   }
    361 
    362   // Otherwise there is nothing to fall back to, so give up.
    363   return result;
    364 }
    365 
    366 void TCPClientSocketLibevent::Disconnect() {
    367   DCHECK(CalledOnValidThread());
    368 
    369   DoDisconnect();
    370   current_address_index_ = -1;
    371   bind_address_.reset();
    372 }
    373 
    374 void TCPClientSocketLibevent::DoDisconnect() {
    375   if (socket_ == kInvalidSocket)
    376     return;
    377 
    378   bool ok = read_socket_watcher_.StopWatchingFileDescriptor();
    379   DCHECK(ok);
    380   ok = write_socket_watcher_.StopWatchingFileDescriptor();
    381   DCHECK(ok);
    382   if (HANDLE_EINTR(close(socket_)) < 0)
    383     PLOG(ERROR) << "close";
    384   socket_ = kInvalidSocket;
    385   previously_disconnected_ = true;
    386 }
    387 
    388 bool TCPClientSocketLibevent::IsConnected() const {
    389   DCHECK(CalledOnValidThread());
    390 
    391   if (socket_ == kInvalidSocket || waiting_connect())
    392     return false;
    393 
    394   if (use_tcp_fastopen_ && !tcp_fastopen_connected_) {
    395     // With TCP FastOpen, we pretend that the socket is connected.
    396     // This allows GetPeerAddress() to return current_ai_ as the peer
    397     // address.  Since we don't fail over to the next address if
    398     // sendto() fails, current_ai_ is the only possible peer address.
    399     CHECK_LT(current_address_index_, static_cast<int>(addresses_.size()));
    400     return true;
    401   }
    402 
    403   // Check if connection is alive.
    404   char c;
    405   int rv = HANDLE_EINTR(recv(socket_, &c, 1, MSG_PEEK));
    406   if (rv == 0)
    407     return false;
    408   if (rv == -1 && errno != EAGAIN && errno != EWOULDBLOCK)
    409     return false;
    410 
    411   return true;
    412 }
    413 
    414 bool TCPClientSocketLibevent::IsConnectedAndIdle() const {
    415   DCHECK(CalledOnValidThread());
    416 
    417   if (socket_ == kInvalidSocket || waiting_connect())
    418     return false;
    419 
    420   // TODO(wtc): should we also handle the TCP FastOpen case here,
    421   // as we do in IsConnected()?
    422 
    423   // Check if connection is alive and we haven't received any data
    424   // unexpectedly.
    425   char c;
    426   int rv = HANDLE_EINTR(recv(socket_, &c, 1, MSG_PEEK));
    427   if (rv >= 0)
    428     return false;
    429   if (errno != EAGAIN && errno != EWOULDBLOCK)
    430     return false;
    431 
    432   return true;
    433 }
    434 
    435 int TCPClientSocketLibevent::Read(IOBuffer* buf,
    436                                   int buf_len,
    437                                   const CompletionCallback& callback) {
    438   DCHECK(CalledOnValidThread());
    439   DCHECK_NE(kInvalidSocket, socket_);
    440   DCHECK(!waiting_connect());
    441   DCHECK(read_callback_.is_null());
    442   // Synchronous operation not supported
    443   DCHECK(!callback.is_null());
    444   DCHECK_GT(buf_len, 0);
    445 
    446   int nread = HANDLE_EINTR(read(socket_, buf->data(), buf_len));
    447   if (nread >= 0) {
    448     base::StatsCounter read_bytes("tcp.read_bytes");
    449     read_bytes.Add(nread);
    450     if (nread > 0)
    451       use_history_.set_was_used_to_convey_data();
    452     net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, nread,
    453                                   buf->data());
    454     RecordFastOpenStatus();
    455     return nread;
    456   }
    457   if (errno != EAGAIN && errno != EWOULDBLOCK) {
    458     int net_error = MapSystemError(errno);
    459     net_log_.AddEvent(NetLog::TYPE_SOCKET_READ_ERROR,
    460                       CreateNetLogSocketErrorCallback(net_error, errno));
    461     return net_error;
    462   }
    463 
    464   if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
    465           socket_, true, base::MessageLoopForIO::WATCH_READ,
    466           &read_socket_watcher_, &read_watcher_)) {
    467     DVLOG(1) << "WatchFileDescriptor failed on read, errno " << errno;
    468     return MapSystemError(errno);
    469   }
    470 
    471   read_buf_ = buf;
    472   read_buf_len_ = buf_len;
    473   read_callback_ = callback;
    474   return ERR_IO_PENDING;
    475 }
    476 
    477 int TCPClientSocketLibevent::Write(IOBuffer* buf,
    478                                    int buf_len,
    479                                    const CompletionCallback& callback) {
    480   DCHECK(CalledOnValidThread());
    481   DCHECK_NE(kInvalidSocket, socket_);
    482   DCHECK(!waiting_connect());
    483   DCHECK(write_callback_.is_null());
    484   // Synchronous operation not supported
    485   DCHECK(!callback.is_null());
    486   DCHECK_GT(buf_len, 0);
    487 
    488   int nwrite = InternalWrite(buf, buf_len);
    489   if (nwrite >= 0) {
    490     base::StatsCounter write_bytes("tcp.write_bytes");
    491     write_bytes.Add(nwrite);
    492     if (nwrite > 0)
    493       use_history_.set_was_used_to_convey_data();
    494     net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_SENT, nwrite,
    495                                   buf->data());
    496     return nwrite;
    497   }
    498   if (errno != EAGAIN && errno != EWOULDBLOCK) {
    499     int net_error = MapSystemError(errno);
    500     net_log_.AddEvent(NetLog::TYPE_SOCKET_WRITE_ERROR,
    501                       CreateNetLogSocketErrorCallback(net_error, errno));
    502     return net_error;
    503   }
    504 
    505   if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
    506           socket_, true, base::MessageLoopForIO::WATCH_WRITE,
    507           &write_socket_watcher_, &write_watcher_)) {
    508     DVLOG(1) << "WatchFileDescriptor failed on write, errno " << errno;
    509     return MapSystemError(errno);
    510   }
    511 
    512   write_buf_ = buf;
    513   write_buf_len_ = buf_len;
    514   write_callback_ = callback;
    515   return ERR_IO_PENDING;
    516 }
    517 
    518 int TCPClientSocketLibevent::InternalWrite(IOBuffer* buf, int buf_len) {
    519   int nwrite;
    520   if (use_tcp_fastopen_ && !tcp_fastopen_connected_) {
    521     SockaddrStorage storage;
    522     if (!addresses_[current_address_index_].ToSockAddr(storage.addr,
    523                                                        &storage.addr_len)) {
    524       errno = EINVAL;
    525       return -1;
    526     }
    527 
    528     int flags = 0x20000000; // Magic flag to enable TCP_FASTOPEN.
    529 #if defined(OS_LINUX)
    530     // sendto() will fail with EPIPE when the system doesn't support TCP Fast
    531     // Open. Theoretically that shouldn't happen since the caller should check
    532     // for system support on startup, but users may dynamically disable TCP Fast
    533     // Open via sysctl.
    534     flags |= MSG_NOSIGNAL;
    535 #endif // defined(OS_LINUX)
    536     nwrite = HANDLE_EINTR(sendto(socket_,
    537                                  buf->data(),
    538                                  buf_len,
    539                                  flags,
    540                                  storage.addr,
    541                                  storage.addr_len));
    542     tcp_fastopen_connected_ = true;
    543 
    544     if (nwrite < 0) {
    545       DCHECK_NE(EPIPE, errno);
    546 
    547       // If errno == EINPROGRESS, that means the kernel didn't have a cookie
    548       // and would block. The kernel is internally doing a connect() though.
    549       // Remap EINPROGRESS to EAGAIN so we treat this the same as our other
    550       // asynchronous cases. Note that the user buffer has not been copied to
    551       // kernel space.
    552       if (errno == EINPROGRESS) {
    553         errno = EAGAIN;
    554         fast_open_status_ = FAST_OPEN_SLOW_CONNECT_RETURN;
    555       } else {
    556         fast_open_status_ = FAST_OPEN_ERROR;
    557       }
    558     } else {
    559       fast_open_status_ = FAST_OPEN_FAST_CONNECT_RETURN;
    560     }
    561   } else {
    562     nwrite = HANDLE_EINTR(write(socket_, buf->data(), buf_len));
    563   }
    564   return nwrite;
    565 }
    566 
    567 bool TCPClientSocketLibevent::SetReceiveBufferSize(int32 size) {
    568   DCHECK(CalledOnValidThread());
    569   int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF,
    570       reinterpret_cast<const char*>(&size),
    571       sizeof(size));
    572   DCHECK(!rv) << "Could not set socket receive buffer size: " << errno;
    573   return rv == 0;
    574 }
    575 
    576 bool TCPClientSocketLibevent::SetSendBufferSize(int32 size) {
    577   DCHECK(CalledOnValidThread());
    578   int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF,
    579       reinterpret_cast<const char*>(&size),
    580       sizeof(size));
    581   DCHECK(!rv) << "Could not set socket send buffer size: " << errno;
    582   return rv == 0;
    583 }
    584 
    585 bool TCPClientSocketLibevent::SetKeepAlive(bool enable, int delay) {
    586   int socket = socket_ != kInvalidSocket ? socket_ : bound_socket_;
    587   return SetTCPKeepAlive(socket, enable, delay);
    588 }
    589 
    590 bool TCPClientSocketLibevent::SetNoDelay(bool no_delay) {
    591   int socket = socket_ != kInvalidSocket ? socket_ : bound_socket_;
    592   return SetTCPNoDelay(socket, no_delay);
    593 }
    594 
    595 void TCPClientSocketLibevent::ReadWatcher::OnFileCanReadWithoutBlocking(int) {
    596   socket_->RecordFastOpenStatus();
    597   if (!socket_->read_callback_.is_null())
    598     socket_->DidCompleteRead();
    599 }
    600 
    601 void TCPClientSocketLibevent::WriteWatcher::OnFileCanWriteWithoutBlocking(int) {
    602   if (socket_->waiting_connect()) {
    603     socket_->DidCompleteConnect();
    604   } else if (!socket_->write_callback_.is_null()) {
    605     socket_->DidCompleteWrite();
    606   }
    607 }
    608 
    609 void TCPClientSocketLibevent::LogConnectCompletion(int net_error) {
    610   if (net_error == OK)
    611     UpdateConnectionTypeHistograms(CONNECTION_ANY);
    612 
    613   if (net_error != OK) {
    614     net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, net_error);
    615     return;
    616   }
    617 
    618   SockaddrStorage storage;
    619   int rv = getsockname(socket_, storage.addr, &storage.addr_len);
    620   if (rv != 0) {
    621     PLOG(ERROR) << "getsockname() [rv: " << rv << "] error: ";
    622     NOTREACHED();
    623     net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, rv);
    624     return;
    625   }
    626 
    627   net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT,
    628                     CreateNetLogSourceAddressCallback(storage.addr,
    629                                                       storage.addr_len));
    630 }
    631 
    632 void TCPClientSocketLibevent::DoReadCallback(int rv) {
    633   DCHECK_NE(rv, ERR_IO_PENDING);
    634   DCHECK(!read_callback_.is_null());
    635 
    636   // since Run may result in Read being called, clear read_callback_ up front.
    637   CompletionCallback c = read_callback_;
    638   read_callback_.Reset();
    639   c.Run(rv);
    640 }
    641 
    642 void TCPClientSocketLibevent::DoWriteCallback(int rv) {
    643   DCHECK_NE(rv, ERR_IO_PENDING);
    644   DCHECK(!write_callback_.is_null());
    645 
    646   // since Run may result in Write being called, clear write_callback_ up front.
    647   CompletionCallback c = write_callback_;
    648   write_callback_.Reset();
    649   c.Run(rv);
    650 }
    651 
    652 void TCPClientSocketLibevent::DidCompleteConnect() {
    653   DCHECK_EQ(next_connect_state_, CONNECT_STATE_CONNECT_COMPLETE);
    654 
    655   // Get the error that connect() completed with.
    656   int os_error = 0;
    657   socklen_t len = sizeof(os_error);
    658   if (getsockopt(socket_, SOL_SOCKET, SO_ERROR, &os_error, &len) < 0)
    659     os_error = errno;
    660 
    661   // TODO(eroman): Is this check really necessary?
    662   if (os_error == EINPROGRESS || os_error == EALREADY) {
    663     NOTREACHED();  // This indicates a bug in libevent or our code.
    664     return;
    665   }
    666 
    667   connect_os_error_ = os_error;
    668   int rv = DoConnectLoop(MapConnectError(os_error));
    669   if (rv != ERR_IO_PENDING) {
    670     LogConnectCompletion(rv);
    671     DoWriteCallback(rv);
    672   }
    673 }
    674 
    675 void TCPClientSocketLibevent::DidCompleteRead() {
    676   int bytes_transferred;
    677   bytes_transferred = HANDLE_EINTR(read(socket_, read_buf_->data(),
    678                                         read_buf_len_));
    679 
    680   int result;
    681   if (bytes_transferred >= 0) {
    682     result = bytes_transferred;
    683     base::StatsCounter read_bytes("tcp.read_bytes");
    684     read_bytes.Add(bytes_transferred);
    685     if (bytes_transferred > 0)
    686       use_history_.set_was_used_to_convey_data();
    687     net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, result,
    688                                   read_buf_->data());
    689   } else {
    690     result = MapSystemError(errno);
    691     if (result != ERR_IO_PENDING) {
    692       net_log_.AddEvent(NetLog::TYPE_SOCKET_READ_ERROR,
    693                         CreateNetLogSocketErrorCallback(result, errno));
    694     }
    695   }
    696 
    697   if (result != ERR_IO_PENDING) {
    698     read_buf_ = NULL;
    699     read_buf_len_ = 0;
    700     bool ok = read_socket_watcher_.StopWatchingFileDescriptor();
    701     DCHECK(ok);
    702     DoReadCallback(result);
    703   }
    704 }
    705 
    706 void TCPClientSocketLibevent::DidCompleteWrite() {
    707   int bytes_transferred;
    708   bytes_transferred = HANDLE_EINTR(write(socket_, write_buf_->data(),
    709                                          write_buf_len_));
    710 
    711   int result;
    712   if (bytes_transferred >= 0) {
    713     result = bytes_transferred;
    714     base::StatsCounter write_bytes("tcp.write_bytes");
    715     write_bytes.Add(bytes_transferred);
    716     if (bytes_transferred > 0)
    717       use_history_.set_was_used_to_convey_data();
    718     net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_SENT, result,
    719                                   write_buf_->data());
    720   } else {
    721     result = MapSystemError(errno);
    722     if (result != ERR_IO_PENDING) {
    723       net_log_.AddEvent(NetLog::TYPE_SOCKET_WRITE_ERROR,
    724                         CreateNetLogSocketErrorCallback(result, errno));
    725     }
    726   }
    727 
    728   if (result != ERR_IO_PENDING) {
    729     write_buf_ = NULL;
    730     write_buf_len_ = 0;
    731     write_socket_watcher_.StopWatchingFileDescriptor();
    732     DoWriteCallback(result);
    733   }
    734 }
    735 
    736 int TCPClientSocketLibevent::GetPeerAddress(IPEndPoint* address) const {
    737   DCHECK(CalledOnValidThread());
    738   DCHECK(address);
    739   if (!IsConnected())
    740     return ERR_SOCKET_NOT_CONNECTED;
    741   *address = addresses_[current_address_index_];
    742   return OK;
    743 }
    744 
    745 int TCPClientSocketLibevent::GetLocalAddress(IPEndPoint* address) const {
    746   DCHECK(CalledOnValidThread());
    747   DCHECK(address);
    748   if (socket_ == kInvalidSocket) {
    749     if (bind_address_.get()) {
    750       *address = *bind_address_;
    751       return OK;
    752     }
    753     return ERR_SOCKET_NOT_CONNECTED;
    754   }
    755 
    756   SockaddrStorage storage;
    757   if (getsockname(socket_, storage.addr, &storage.addr_len))
    758     return MapSystemError(errno);
    759   if (!address->FromSockAddr(storage.addr, storage.addr_len))
    760     return ERR_FAILED;
    761 
    762   return OK;
    763 }
    764 
    765 void TCPClientSocketLibevent::RecordFastOpenStatus() {
    766   if (use_tcp_fastopen_ &&
    767       (fast_open_status_ == FAST_OPEN_FAST_CONNECT_RETURN ||
    768        fast_open_status_ == FAST_OPEN_SLOW_CONNECT_RETURN)) {
    769     DCHECK_NE(FAST_OPEN_STATUS_UNKNOWN, fast_open_status_);
    770     bool getsockopt_success(false);
    771     bool server_acked_data(false);
    772 #if defined(TCP_INFO)
    773     // Probe to see the if the socket used TCP Fast Open.
    774     tcp_info info;
    775     socklen_t info_len = sizeof(tcp_info);
    776     getsockopt_success =
    777         getsockopt(socket_, IPPROTO_TCP, TCP_INFO, &info, &info_len) == 0 &&
    778         info_len == sizeof(tcp_info);
    779     server_acked_data = getsockopt_success &&
    780         (info.tcpi_options & TCPI_OPT_SYN_DATA);
    781 #endif
    782     if (getsockopt_success) {
    783       if (fast_open_status_ == FAST_OPEN_FAST_CONNECT_RETURN) {
    784         fast_open_status_ = (server_acked_data ? FAST_OPEN_SYN_DATA_ACK :
    785                              FAST_OPEN_SYN_DATA_NACK);
    786       } else {
    787         fast_open_status_ = (server_acked_data ? FAST_OPEN_NO_SYN_DATA_ACK :
    788                              FAST_OPEN_NO_SYN_DATA_NACK);
    789       }
    790     } else {
    791       fast_open_status_ = (fast_open_status_ == FAST_OPEN_FAST_CONNECT_RETURN ?
    792                            FAST_OPEN_SYN_DATA_FAILED :
    793                            FAST_OPEN_NO_SYN_DATA_FAILED);
    794     }
    795   }
    796 }
    797 
    798 const BoundNetLog& TCPClientSocketLibevent::NetLog() const {
    799   return net_log_;
    800 }
    801 
    802 void TCPClientSocketLibevent::SetSubresourceSpeculation() {
    803   use_history_.set_subresource_speculation();
    804 }
    805 
    806 void TCPClientSocketLibevent::SetOmniboxSpeculation() {
    807   use_history_.set_omnibox_speculation();
    808 }
    809 
    810 bool TCPClientSocketLibevent::WasEverUsed() const {
    811   return use_history_.was_used_to_convey_data();
    812 }
    813 
    814 bool TCPClientSocketLibevent::UsingTCPFastOpen() const {
    815   return use_tcp_fastopen_;
    816 }
    817 
    818 bool TCPClientSocketLibevent::WasNpnNegotiated() const {
    819   return false;
    820 }
    821 
    822 NextProto TCPClientSocketLibevent::GetNegotiatedProtocol() const {
    823   return kProtoUnknown;
    824 }
    825 
    826 bool TCPClientSocketLibevent::GetSSLInfo(SSLInfo* ssl_info) {
    827   return false;
    828 }
    829 
    830 }  // namespace net
    831