Home | History | Annotate | Download | only in socket
      1 // Copyright (c) 2010 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/eintr_wrapper.h"
     17 #include "base/logging.h"
     18 #include "base/message_loop.h"
     19 #include "base/metrics/stats_counters.h"
     20 #include "base/string_util.h"
     21 #include "net/base/address_list_net_log_param.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 #if defined(USE_SYSTEM_LIBEVENT)
     30 #include <event.h>
     31 #else
     32 #include "third_party/libevent/event.h"
     33 #endif
     34 #ifdef ANDROID
     35 #include <cutils/qtaguid.h>
     36 #endif
     37 
     38 namespace net {
     39 
     40 namespace {
     41 
     42 const int kInvalidSocket = -1;
     43 
     44 // DisableNagle turns off buffering in the kernel. By default, TCP sockets will
     45 // wait up to 200ms for more data to complete a packet before transmitting.
     46 // After calling this function, the kernel will not wait. See TCP_NODELAY in
     47 // `man 7 tcp`.
     48 int DisableNagle(int fd) {
     49   int on = 1;
     50   return setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
     51 }
     52 
     53 // SetTCPKeepAlive sets SO_KEEPALIVE.
     54 void SetTCPKeepAlive(int fd) {
     55   int optval = 1;
     56   socklen_t optlen = sizeof(optval);
     57   if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen)) {
     58     PLOG(ERROR) << "Failed to set SO_KEEPALIVE on fd: " << fd;
     59     return;
     60   }
     61 #if defined(OS_LINUX)
     62   // Set seconds until first TCP keep alive.
     63 #ifdef ANDROID
     64   optval = 25;
     65 #else
     66   optval = 45;
     67 #endif
     68   if (setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &optval, optlen)) {
     69     PLOG(ERROR) << "Failed to set TCP_KEEPIDLE on fd: " << fd;
     70     return;
     71   }
     72   // Set seconds between TCP keep alives.
     73   if (setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &optval, optlen)) {
     74     PLOG(ERROR) << "Failed to set TCP_KEEPINTVL on fd: " << fd;
     75     return;
     76   }
     77 #endif
     78 }
     79 
     80 int MapConnectError(int os_error) {
     81   switch (os_error) {
     82     case EACCES:
     83       return ERR_NETWORK_ACCESS_DENIED;
     84     case ETIMEDOUT:
     85       return ERR_CONNECTION_TIMED_OUT;
     86     default: {
     87       int net_error = MapSystemError(os_error);
     88       if (net_error == ERR_FAILED)
     89         return ERR_CONNECTION_FAILED;  // More specific than ERR_FAILED.
     90 
     91       // Give a more specific error when the user is offline.
     92       if (net_error == ERR_ADDRESS_UNREACHABLE &&
     93           NetworkChangeNotifier::IsOffline()) {
     94         return ERR_INTERNET_DISCONNECTED;
     95       }
     96       return net_error;
     97     }
     98   }
     99 }
    100 
    101 }  // namespace
    102 
    103 //-----------------------------------------------------------------------------
    104 
    105 TCPClientSocketLibevent::TCPClientSocketLibevent(
    106     const AddressList& addresses,
    107     net::NetLog* net_log,
    108     const net::NetLog::Source& source)
    109     : socket_(kInvalidSocket),
    110       addresses_(addresses),
    111       current_ai_(NULL),
    112       read_watcher_(this),
    113       write_watcher_(this),
    114       read_callback_(NULL),
    115       write_callback_(NULL),
    116       next_connect_state_(CONNECT_STATE_NONE),
    117       connect_os_error_(0),
    118       net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)),
    119       previously_disconnected_(false),
    120       use_tcp_fastopen_(false),
    121       tcp_fastopen_connected_(false)
    122 #ifdef ANDROID
    123       , wait_for_connect_(false)
    124       , valid_uid_(false)
    125       , calling_uid_(0)
    126 #endif
    127 {
    128   scoped_refptr<NetLog::EventParameters> params;
    129   if (source.is_valid())
    130     params = new NetLogSourceParameter("source_dependency", source);
    131   net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, params);
    132 
    133   if (is_tcp_fastopen_enabled())
    134     use_tcp_fastopen_ = true;
    135 }
    136 
    137 TCPClientSocketLibevent::~TCPClientSocketLibevent() {
    138   Disconnect();
    139   net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE, NULL);
    140 }
    141 
    142 void TCPClientSocketLibevent::AdoptSocket(int socket) {
    143   DCHECK_EQ(socket_, kInvalidSocket);
    144   socket_ = socket;
    145   int error = SetupSocket();
    146   DCHECK_EQ(0, error);
    147   // This is to make GetPeerAddress work. It's up to the test that is calling
    148   // this function to ensure that address_ contains a reasonable address for
    149   // this socket. (i.e. at least match IPv4 vs IPv6!).
    150   current_ai_ = addresses_.head();
    151   use_history_.set_was_ever_connected();
    152 }
    153 
    154 int TCPClientSocketLibevent::Connect(CompletionCallback* callback
    155 #ifdef ANDROID
    156                                      , bool wait_for_connect
    157                                      , bool valid_uid
    158                                      , uid_t calling_uid
    159 #endif
    160                                     ) {
    161 #ifdef ANDROID
    162   wait_for_connect_ = wait_for_connect;
    163   valid_uid_ = valid_uid;
    164   calling_uid_ = calling_uid;
    165 #endif
    166   DCHECK(CalledOnValidThread());
    167 
    168   // If already connected, then just return OK.
    169   if (socket_ != kInvalidSocket)
    170     return OK;
    171 
    172   base::StatsCounter connects("tcp.connect");
    173   connects.Increment();
    174 
    175   DCHECK(!waiting_connect());
    176 
    177   net_log_.BeginEvent(
    178       NetLog::TYPE_TCP_CONNECT,
    179       make_scoped_refptr(new AddressListNetLogParam(addresses_)));
    180 
    181   // We will try to connect to each address in addresses_. Start with the
    182   // first one in the list.
    183   next_connect_state_ = CONNECT_STATE_CONNECT;
    184   current_ai_ = addresses_.head();
    185 
    186   int rv = DoConnectLoop(OK);
    187   if (rv == ERR_IO_PENDING) {
    188     // Synchronous operation not supported.
    189     DCHECK(callback);
    190     write_callback_ = callback;
    191   } else {
    192     LogConnectCompletion(rv);
    193   }
    194 
    195   return rv;
    196 }
    197 
    198 int TCPClientSocketLibevent::DoConnectLoop(int result) {
    199   DCHECK_NE(next_connect_state_, CONNECT_STATE_NONE);
    200 
    201   int rv = result;
    202   do {
    203     ConnectState state = next_connect_state_;
    204     next_connect_state_ = CONNECT_STATE_NONE;
    205     switch (state) {
    206       case CONNECT_STATE_CONNECT:
    207         DCHECK_EQ(OK, rv);
    208         rv = DoConnect();
    209         break;
    210       case CONNECT_STATE_CONNECT_COMPLETE:
    211         rv = DoConnectComplete(rv);
    212         break;
    213       default:
    214         LOG(DFATAL) << "bad state";
    215         rv = ERR_UNEXPECTED;
    216         break;
    217     }
    218   } while (rv != ERR_IO_PENDING && next_connect_state_ != CONNECT_STATE_NONE);
    219 
    220   return rv;
    221 }
    222 
    223 int TCPClientSocketLibevent::DoConnect() {
    224   DCHECK(current_ai_);
    225 
    226   DCHECK_EQ(0, connect_os_error_);
    227 
    228   if (previously_disconnected_) {
    229     use_history_.Reset();
    230     previously_disconnected_ = false;
    231   }
    232 
    233   net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT,
    234                       make_scoped_refptr(new NetLogStringParameter(
    235                           "address", NetAddressToStringWithPort(current_ai_))));
    236 
    237   next_connect_state_ = CONNECT_STATE_CONNECT_COMPLETE;
    238 
    239   // Create a non-blocking socket.
    240   connect_os_error_ = CreateSocket(current_ai_);
    241   if (connect_os_error_)
    242     return MapSystemError(connect_os_error_);
    243 
    244   // Connect the socket.
    245   if (!use_tcp_fastopen_) {
    246     if (!HANDLE_EINTR(connect(socket_, current_ai_->ai_addr,
    247                               static_cast<int>(current_ai_->ai_addrlen)))) {
    248       // Connected without waiting!
    249       return OK;
    250 #ifdef ANDROID
    251     } else if (errno == EINPROGRESS && wait_for_connect_) {
    252       fd_set writeset;
    253       FD_ZERO(&writeset);
    254       FD_SET(socket_, &writeset);
    255       timeval tv;
    256       tv.tv_sec = 20;
    257       tv.tv_usec = 0;
    258       int res = HANDLE_EINTR(select(socket_ + 1, 0, &writeset, 0, &tv));
    259       if (res > 0)
    260         return OK;
    261       return MapConnectError(ETIMEDOUT);
    262 #endif
    263     }
    264   } else {
    265     // With TCP FastOpen, we pretend that the socket is connected.
    266     DCHECK(!tcp_fastopen_connected_);
    267     return OK;
    268   }
    269 
    270   // Check if the connect() failed synchronously.
    271   connect_os_error_ = errno;
    272   if (connect_os_error_ != EINPROGRESS)
    273     return MapConnectError(connect_os_error_);
    274 
    275   // Otherwise the connect() is going to complete asynchronously, so watch
    276   // for its completion.
    277   if (!MessageLoopForIO::current()->WatchFileDescriptor(
    278           socket_, true, MessageLoopForIO::WATCH_WRITE, &write_socket_watcher_,
    279           &write_watcher_)) {
    280     connect_os_error_ = errno;
    281     DVLOG(1) << "WatchFileDescriptor failed: " << connect_os_error_;
    282     return MapSystemError(connect_os_error_);
    283   }
    284 
    285   return ERR_IO_PENDING;
    286 }
    287 
    288 int TCPClientSocketLibevent::DoConnectComplete(int result) {
    289   // Log the end of this attempt (and any OS error it threw).
    290   int os_error = connect_os_error_;
    291   connect_os_error_ = 0;
    292   scoped_refptr<NetLog::EventParameters> params;
    293   if (result != OK)
    294     params = new NetLogIntegerParameter("os_error", os_error);
    295   net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT, params);
    296 
    297   write_socket_watcher_.StopWatchingFileDescriptor();
    298 
    299   if (result == OK) {
    300     use_history_.set_was_ever_connected();
    301     return OK;  // Done!
    302   }
    303 
    304   // Close whatever partially connected socket we currently have.
    305   DoDisconnect();
    306 
    307   // Try to fall back to the next address in the list.
    308   if (current_ai_->ai_next) {
    309     next_connect_state_ = CONNECT_STATE_CONNECT;
    310     current_ai_ = current_ai_->ai_next;
    311     return OK;
    312   }
    313 
    314   // Otherwise there is nothing to fall back to, so give up.
    315   return result;
    316 }
    317 
    318 void TCPClientSocketLibevent::Disconnect() {
    319   DCHECK(CalledOnValidThread());
    320 
    321   DoDisconnect();
    322   current_ai_ = NULL;
    323 }
    324 
    325 void TCPClientSocketLibevent::DoDisconnect() {
    326   if (socket_ == kInvalidSocket)
    327     return;
    328 
    329   bool ok = read_socket_watcher_.StopWatchingFileDescriptor();
    330   DCHECK(ok);
    331   ok = write_socket_watcher_.StopWatchingFileDescriptor();
    332   DCHECK(ok);
    333 
    334 #ifdef ANDROID
    335   if (valid_uid_)
    336     qtaguid_untagSocket(socket_);
    337 #endif
    338 
    339   if (HANDLE_EINTR(close(socket_)) < 0)
    340     PLOG(ERROR) << "close";
    341   socket_ = kInvalidSocket;
    342   previously_disconnected_ = true;
    343 }
    344 
    345 bool TCPClientSocketLibevent::IsConnected() const {
    346   DCHECK(CalledOnValidThread());
    347 
    348   if (socket_ == kInvalidSocket || waiting_connect())
    349     return false;
    350 
    351   // Check if connection is alive.
    352   char c;
    353   int rv = HANDLE_EINTR(recv(socket_, &c, 1, MSG_PEEK));
    354   if (rv == 0)
    355     return false;
    356   if (rv == -1 && errno != EAGAIN && errno != EWOULDBLOCK)
    357     return false;
    358 
    359   return true;
    360 }
    361 
    362 bool TCPClientSocketLibevent::IsConnectedAndIdle() const {
    363   DCHECK(CalledOnValidThread());
    364 
    365   if (socket_ == kInvalidSocket || waiting_connect())
    366     return false;
    367 
    368   // Check if connection is alive and we haven't received any data
    369   // unexpectedly.
    370   char c;
    371   int rv = HANDLE_EINTR(recv(socket_, &c, 1, MSG_PEEK));
    372   if (rv >= 0)
    373     return false;
    374   if (errno != EAGAIN && errno != EWOULDBLOCK)
    375     return false;
    376 
    377   return true;
    378 }
    379 
    380 int TCPClientSocketLibevent::Read(IOBuffer* buf,
    381                                   int buf_len,
    382                                   CompletionCallback* callback) {
    383   DCHECK(CalledOnValidThread());
    384   DCHECK_NE(kInvalidSocket, socket_);
    385   DCHECK(!waiting_connect());
    386   DCHECK(!read_callback_);
    387   // Synchronous operation not supported
    388   DCHECK(callback);
    389   DCHECK_GT(buf_len, 0);
    390 
    391   int nread = HANDLE_EINTR(read(socket_, buf->data(), buf_len));
    392   if (nread >= 0) {
    393     base::StatsCounter read_bytes("tcp.read_bytes");
    394     read_bytes.Add(nread);
    395     if (nread > 0)
    396       use_history_.set_was_used_to_convey_data();
    397     LogByteTransfer(
    398         net_log_, NetLog::TYPE_SOCKET_BYTES_RECEIVED, nread, buf->data());
    399     return nread;
    400   }
    401   if (errno != EAGAIN && errno != EWOULDBLOCK) {
    402     DVLOG(1) << "read failed, errno " << errno;
    403     return MapSystemError(errno);
    404   }
    405 
    406   if (!MessageLoopForIO::current()->WatchFileDescriptor(
    407           socket_, true, MessageLoopForIO::WATCH_READ,
    408           &read_socket_watcher_, &read_watcher_)) {
    409     DVLOG(1) << "WatchFileDescriptor failed on read, errno " << errno;
    410     return MapSystemError(errno);
    411   }
    412 
    413   read_buf_ = buf;
    414   read_buf_len_ = buf_len;
    415   read_callback_ = callback;
    416   return ERR_IO_PENDING;
    417 }
    418 
    419 int TCPClientSocketLibevent::Write(IOBuffer* buf,
    420                                    int buf_len,
    421                                    CompletionCallback* callback) {
    422   DCHECK(CalledOnValidThread());
    423   DCHECK_NE(kInvalidSocket, socket_);
    424   DCHECK(!waiting_connect());
    425   DCHECK(!write_callback_);
    426   // Synchronous operation not supported
    427   DCHECK(callback);
    428   DCHECK_GT(buf_len, 0);
    429 
    430   int nwrite = InternalWrite(buf, buf_len);
    431   if (nwrite >= 0) {
    432     base::StatsCounter write_bytes("tcp.write_bytes");
    433     write_bytes.Add(nwrite);
    434     if (nwrite > 0)
    435       use_history_.set_was_used_to_convey_data();
    436     LogByteTransfer(
    437         net_log_, NetLog::TYPE_SOCKET_BYTES_SENT, nwrite, buf->data());
    438     return nwrite;
    439   }
    440   if (errno != EAGAIN && errno != EWOULDBLOCK)
    441     return MapSystemError(errno);
    442 
    443   if (!MessageLoopForIO::current()->WatchFileDescriptor(
    444           socket_, true, MessageLoopForIO::WATCH_WRITE,
    445           &write_socket_watcher_, &write_watcher_)) {
    446     DVLOG(1) << "WatchFileDescriptor failed on write, errno " << errno;
    447     return MapSystemError(errno);
    448   }
    449 
    450   write_buf_ = buf;
    451   write_buf_len_ = buf_len;
    452   write_callback_ = callback;
    453   return ERR_IO_PENDING;
    454 }
    455 
    456 int TCPClientSocketLibevent::InternalWrite(IOBuffer* buf, int buf_len) {
    457   int nwrite;
    458   if (use_tcp_fastopen_ && !tcp_fastopen_connected_) {
    459     // We have a limited amount of data to send in the SYN packet.
    460     int kMaxFastOpenSendLength = 1420;
    461 
    462     buf_len = std::min(kMaxFastOpenSendLength, buf_len);
    463 
    464     int flags = 0x20000000;  // Magic flag to enable TCP_FASTOPEN
    465     nwrite = HANDLE_EINTR(sendto(socket_,
    466                                  buf->data(),
    467                                  buf_len,
    468                                  flags,
    469                                  current_ai_->ai_addr,
    470                                  static_cast<int>(current_ai_->ai_addrlen)));
    471     tcp_fastopen_connected_ = true;
    472 
    473     if (nwrite < 0) {
    474       // Non-blocking mode is returning EINPROGRESS rather than EAGAIN.
    475       if (errno == EINPROGRESS)
    476          errno = EAGAIN;
    477 
    478       // Unlike "normal" nonblocking sockets, the data is already queued,
    479       // so tell the app that we've consumed it.
    480       return buf_len;
    481     }
    482   } else {
    483     nwrite = HANDLE_EINTR(write(socket_, buf->data(), buf_len));
    484   }
    485   return nwrite;
    486 }
    487 
    488 bool TCPClientSocketLibevent::SetReceiveBufferSize(int32 size) {
    489   DCHECK(CalledOnValidThread());
    490   int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF,
    491       reinterpret_cast<const char*>(&size),
    492       sizeof(size));
    493   DCHECK(!rv) << "Could not set socket receive buffer size: " << errno;
    494   return rv == 0;
    495 }
    496 
    497 bool TCPClientSocketLibevent::SetSendBufferSize(int32 size) {
    498   DCHECK(CalledOnValidThread());
    499   int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF,
    500       reinterpret_cast<const char*>(&size),
    501       sizeof(size));
    502   DCHECK(!rv) << "Could not set socket send buffer size: " << errno;
    503   return rv == 0;
    504 }
    505 
    506 
    507 int TCPClientSocketLibevent::CreateSocket(const addrinfo* ai) {
    508   socket_ = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
    509   if (socket_ == kInvalidSocket)
    510     return errno;
    511   return SetupSocket();
    512 }
    513 
    514 int TCPClientSocketLibevent::SetupSocket() {
    515   if (SetNonBlocking(socket_)) {
    516     const int err = errno;
    517 
    518 #ifdef ANDROID
    519     if (valid_uid_)
    520       qtaguid_untagSocket(socket_);
    521 #endif
    522 
    523     close(socket_);
    524     socket_ = kInvalidSocket;
    525     return err;
    526   }
    527 
    528   // This mirrors the behaviour on Windows. See the comment in
    529   // tcp_client_socket_win.cc after searching for "NODELAY".
    530   DisableNagle(socket_);  // If DisableNagle fails, we don't care.
    531 
    532   // ANDROID: Disable TCP keep-alive for bug 5226268
    533   // [Browser] http keep-alive packets are sent too frequently to network
    534 #ifndef ANDROID
    535   SetTCPKeepAlive(socket_);
    536 #endif
    537 
    538 #ifdef ANDROID
    539   if (valid_uid_)
    540     qtaguid_tagSocket(socket_, geteuid(), calling_uid_);
    541 #endif
    542 
    543   return 0;
    544 }
    545 
    546 void TCPClientSocketLibevent::LogConnectCompletion(int net_error) {
    547   if (net_error == OK)
    548     UpdateConnectionTypeHistograms(CONNECTION_ANY);
    549 
    550   if (net_error != OK) {
    551     net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, net_error);
    552     return;
    553   }
    554 
    555   struct sockaddr_storage source_address;
    556   socklen_t addrlen = sizeof(source_address);
    557   int rv = getsockname(
    558       socket_, reinterpret_cast<struct sockaddr*>(&source_address), &addrlen);
    559   if (rv != 0) {
    560     PLOG(ERROR) << "getsockname() [rv: " << rv << "] error: ";
    561     NOTREACHED();
    562     net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, rv);
    563     return;
    564   }
    565 
    566   const std::string source_address_str =
    567       NetAddressToStringWithPort(
    568           reinterpret_cast<const struct sockaddr*>(&source_address),
    569           sizeof(source_address));
    570   net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT,
    571                     make_scoped_refptr(new NetLogStringParameter(
    572                         "source address",
    573                         source_address_str)));
    574 }
    575 
    576 void TCPClientSocketLibevent::DoReadCallback(int rv) {
    577   DCHECK_NE(rv, ERR_IO_PENDING);
    578   DCHECK(read_callback_);
    579 
    580   // since Run may result in Read being called, clear read_callback_ up front.
    581   CompletionCallback* c = read_callback_;
    582   read_callback_ = NULL;
    583   c->Run(rv);
    584 }
    585 
    586 void TCPClientSocketLibevent::DoWriteCallback(int rv) {
    587   DCHECK_NE(rv, ERR_IO_PENDING);
    588   DCHECK(write_callback_);
    589 
    590   // since Run may result in Write being called, clear write_callback_ up front.
    591   CompletionCallback* c = write_callback_;
    592   write_callback_ = NULL;
    593   c->Run(rv);
    594 }
    595 
    596 void TCPClientSocketLibevent::DidCompleteConnect() {
    597   DCHECK_EQ(next_connect_state_, CONNECT_STATE_CONNECT_COMPLETE);
    598 
    599   // Get the error that connect() completed with.
    600   int os_error = 0;
    601   socklen_t len = sizeof(os_error);
    602   if (getsockopt(socket_, SOL_SOCKET, SO_ERROR, &os_error, &len) < 0)
    603     os_error = errno;
    604 
    605   // TODO(eroman): Is this check really necessary?
    606   if (os_error == EINPROGRESS || os_error == EALREADY) {
    607     NOTREACHED();  // This indicates a bug in libevent or our code.
    608     return;
    609   }
    610 
    611   connect_os_error_ = os_error;
    612   int rv = DoConnectLoop(MapConnectError(os_error));
    613   if (rv != ERR_IO_PENDING) {
    614     LogConnectCompletion(rv);
    615     DoWriteCallback(rv);
    616   }
    617 }
    618 
    619 void TCPClientSocketLibevent::DidCompleteRead() {
    620   int bytes_transferred;
    621   bytes_transferred = HANDLE_EINTR(read(socket_, read_buf_->data(),
    622                                         read_buf_len_));
    623 
    624   int result;
    625   if (bytes_transferred >= 0) {
    626     result = bytes_transferred;
    627     base::StatsCounter read_bytes("tcp.read_bytes");
    628     read_bytes.Add(bytes_transferred);
    629     if (bytes_transferred > 0)
    630       use_history_.set_was_used_to_convey_data();
    631     LogByteTransfer(net_log_, NetLog::TYPE_SOCKET_BYTES_RECEIVED, result,
    632                     read_buf_->data());
    633   } else {
    634     result = MapSystemError(errno);
    635   }
    636 
    637   if (result != ERR_IO_PENDING) {
    638     read_buf_ = NULL;
    639     read_buf_len_ = 0;
    640     bool ok = read_socket_watcher_.StopWatchingFileDescriptor();
    641     DCHECK(ok);
    642     DoReadCallback(result);
    643   }
    644 }
    645 
    646 void TCPClientSocketLibevent::DidCompleteWrite() {
    647   int bytes_transferred;
    648   bytes_transferred = HANDLE_EINTR(write(socket_, write_buf_->data(),
    649                                          write_buf_len_));
    650 
    651   int result;
    652   if (bytes_transferred >= 0) {
    653     result = bytes_transferred;
    654     base::StatsCounter write_bytes("tcp.write_bytes");
    655     write_bytes.Add(bytes_transferred);
    656     if (bytes_transferred > 0)
    657       use_history_.set_was_used_to_convey_data();
    658     LogByteTransfer(net_log_, NetLog::TYPE_SOCKET_BYTES_SENT, result,
    659                     write_buf_->data());
    660   } else {
    661     result = MapSystemError(errno);
    662   }
    663 
    664   if (result != ERR_IO_PENDING) {
    665     write_buf_ = NULL;
    666     write_buf_len_ = 0;
    667     write_socket_watcher_.StopWatchingFileDescriptor();
    668     DoWriteCallback(result);
    669   }
    670 }
    671 
    672 int TCPClientSocketLibevent::GetPeerAddress(AddressList* address) const {
    673   DCHECK(CalledOnValidThread());
    674   DCHECK(address);
    675   if (!IsConnected())
    676     return ERR_SOCKET_NOT_CONNECTED;
    677   address->Copy(current_ai_, false);
    678   return OK;
    679 }
    680 
    681 int TCPClientSocketLibevent::GetLocalAddress(IPEndPoint* address) const {
    682   DCHECK(CalledOnValidThread());
    683   DCHECK(address);
    684   if (!IsConnected())
    685     return ERR_SOCKET_NOT_CONNECTED;
    686 
    687   struct sockaddr_storage addr_storage;
    688   socklen_t addr_len = sizeof(addr_storage);
    689   struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage);
    690   if (getsockname(socket_, addr, &addr_len))
    691     return MapSystemError(errno);
    692   if (!address->FromSockAddr(addr, addr_len))
    693     return ERR_FAILED;
    694 
    695   return OK;
    696 }
    697 
    698 const BoundNetLog& TCPClientSocketLibevent::NetLog() const {
    699   return net_log_;
    700 }
    701 
    702 void TCPClientSocketLibevent::SetSubresourceSpeculation() {
    703   use_history_.set_subresource_speculation();
    704 }
    705 
    706 void TCPClientSocketLibevent::SetOmniboxSpeculation() {
    707   use_history_.set_omnibox_speculation();
    708 }
    709 
    710 bool TCPClientSocketLibevent::WasEverUsed() const {
    711   return use_history_.was_used_to_convey_data();
    712 }
    713 
    714 bool TCPClientSocketLibevent::UsingTCPFastOpen() const {
    715   return use_tcp_fastopen_;
    716 }
    717 
    718 }  // namespace net
    719