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
36namespace net {
37
38namespace {
39
40const int kInvalidSocket = -1;
41const 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`.
47bool 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.
55bool  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).
78int 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).
92int 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
106int 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
131TCPClientSocketLibevent::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
152TCPClientSocketLibevent::~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
161int 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
179int 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
208int 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
240int 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
265int 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
335int 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
366void TCPClientSocketLibevent::Disconnect() {
367  DCHECK(CalledOnValidThread());
368
369  DoDisconnect();
370  current_address_index_ = -1;
371  bind_address_.reset();
372}
373
374void 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
388bool 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
414bool 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
435int 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
477int 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
518int 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
567bool 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
576bool 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
585bool TCPClientSocketLibevent::SetKeepAlive(bool enable, int delay) {
586  int socket = socket_ != kInvalidSocket ? socket_ : bound_socket_;
587  return SetTCPKeepAlive(socket, enable, delay);
588}
589
590bool TCPClientSocketLibevent::SetNoDelay(bool no_delay) {
591  int socket = socket_ != kInvalidSocket ? socket_ : bound_socket_;
592  return SetTCPNoDelay(socket, no_delay);
593}
594
595void TCPClientSocketLibevent::ReadWatcher::OnFileCanReadWithoutBlocking(int) {
596  socket_->RecordFastOpenStatus();
597  if (!socket_->read_callback_.is_null())
598    socket_->DidCompleteRead();
599}
600
601void 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
609void 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
632void 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
642void 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
652void 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
675void 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
706void 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
736int 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
745int 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
765void 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
798const BoundNetLog& TCPClientSocketLibevent::NetLog() const {
799  return net_log_;
800}
801
802void TCPClientSocketLibevent::SetSubresourceSpeculation() {
803  use_history_.set_subresource_speculation();
804}
805
806void TCPClientSocketLibevent::SetOmniboxSpeculation() {
807  use_history_.set_omnibox_speculation();
808}
809
810bool TCPClientSocketLibevent::WasEverUsed() const {
811  return use_history_.was_used_to_convey_data();
812}
813
814bool TCPClientSocketLibevent::UsingTCPFastOpen() const {
815  return use_tcp_fastopen_;
816}
817
818bool TCPClientSocketLibevent::WasNpnNegotiated() const {
819  return false;
820}
821
822NextProto TCPClientSocketLibevent::GetNegotiatedProtocol() const {
823  return kProtoUnknown;
824}
825
826bool TCPClientSocketLibevent::GetSSLInfo(SSLInfo* ssl_info) {
827  return false;
828}
829
830}  // namespace net
831