tcp_client_socket_libevent.cc revision 4a5e2dc747d50c653511c68ccb2cfbfb740bd5a7
1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "net/socket/tcp_client_socket.h"
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <errno.h>
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <fcntl.h>
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <netdb.h>
10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <sys/socket.h>
11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <netinet/tcp.h>
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_POSIX)
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <netinet/in.h>
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/eintr_wrapper.h"
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/logging.h"
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/message_loop.h"
19731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/metrics/stats_counters.h"
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/string_util.h"
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/address_list_net_log_param.h"
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/io_buffer.h"
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/net_errors.h"
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_log.h"
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_util.h"
26731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "net/base/network_change_notifier.h"
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(USE_SYSTEM_LIBEVENT)
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <event.h>
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#else
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "third_party/libevent/event.h"
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace net {
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace {
36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst int kInvalidSocket = -1;
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// DisableNagle turns off buffering in the kernel. By default, TCP sockets will
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// wait up to 200ms for more data to complete a packet before transmitting.
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// After calling this function, the kernel will not wait. See TCP_NODELAY in
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// `man 7 tcp`.
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint DisableNagle(int fd) {
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int on = 1;
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Convert values from <errno.h> to values from "net/base/net_errors.h"
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint MapPosixError(int os_error) {
50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // There are numerous posix error codes, but these are the ones we thus far
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // find interesting.
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  switch (os_error) {
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case EAGAIN:
54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if EWOULDBLOCK != EAGAIN
55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case EWOULDBLOCK:
56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return ERR_IO_PENDING;
58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case EACCES:
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return ERR_ACCESS_DENIED;
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case ENETDOWN:
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return ERR_INTERNET_DISCONNECTED;
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case ETIMEDOUT:
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return ERR_TIMED_OUT;
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case ECONNRESET:
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case ENETRESET:  // Related to keep-alive
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case EPIPE:
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return ERR_CONNECTION_RESET;
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case ECONNABORTED:
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return ERR_CONNECTION_ABORTED;
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case ECONNREFUSED:
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return ERR_CONNECTION_REFUSED;
72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case EHOSTUNREACH:
733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case EHOSTDOWN:
74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case ENETUNREACH:
75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return ERR_ADDRESS_UNREACHABLE;
76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case EADDRNOTAVAIL:
77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return ERR_ADDRESS_INVALID;
78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case 0:
79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return OK;
80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    default:
81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      LOG(WARNING) << "Unknown error " << os_error
82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                   << " mapped to net::ERR_FAILED";
83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return ERR_FAILED;
84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint MapConnectError(int os_error) {
88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  switch (os_error) {
89513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    case EACCES:
90513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      return ERR_NETWORK_ACCESS_DENIED;
91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case ETIMEDOUT:
92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return ERR_CONNECTION_TIMED_OUT;
93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    default: {
94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      int net_error = MapPosixError(os_error);
95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (net_error == ERR_FAILED)
96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return ERR_CONNECTION_FAILED;  // More specific than ERR_FAILED.
97731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
98731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      // Give a more specific error when the user is offline.
99731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      if (net_error == ERR_ADDRESS_UNREACHABLE &&
100731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          NetworkChangeNotifier::IsOffline()) {
101731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        return ERR_INTERNET_DISCONNECTED;
102731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      }
103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return net_error;
104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace
109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//-----------------------------------------------------------------------------
111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1123345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTCPClientSocketLibevent::TCPClientSocketLibevent(
1133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const AddressList& addresses,
1143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    net::NetLog* net_log,
1153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const net::NetLog::Source& source)
116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    : socket_(kInvalidSocket),
117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      addresses_(addresses),
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      current_ai_(NULL),
119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      read_watcher_(this),
120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      write_watcher_(this),
121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      read_callback_(NULL),
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      write_callback_(NULL),
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      next_connect_state_(CONNECT_STATE_NONE),
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      connect_os_error_(0),
125513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)),
126513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      previously_disconnected_(false),
127513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      use_tcp_fastopen_(false),
128513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      tcp_fastopen_connected_(false) {
1293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<NetLog::EventParameters> params;
1303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (source.is_valid())
1313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    params = new NetLogSourceParameter("source_dependency", source);
1323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, params);
133513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
134513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (is_tcp_fastopen_enabled())
135513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    use_tcp_fastopen_ = true;
136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTCPClientSocketLibevent::~TCPClientSocketLibevent() {
139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Disconnect();
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE, NULL);
141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1434a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochvoid TCPClientSocketLibevent::AdoptSocket(int socket) {
1444a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  DCHECK_EQ(socket_, kInvalidSocket);
1454a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  socket_ = socket;
1464a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  int error = SetupSocket();
1474a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  DCHECK_EQ(0, error);
1484a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // This is to make GetPeerAddress work. It's up to the test that is calling
1494a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // this function to ensure that address_ contains a reasonable address for
1504a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // this socket. (i.e. at least match IPv4 vs IPv6!).
1514a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  current_ai_ = addresses_.head();
1524a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  use_history_.set_was_ever_connected();
1534a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch}
1544a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint TCPClientSocketLibevent::Connect(CompletionCallback* callback) {
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(CalledOnValidThread());
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // If already connected, then just return OK.
159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (socket_ != kInvalidSocket)
160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return OK;
161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
162731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  static base::StatsCounter connects("tcp.connect");
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  connects.Increment();
164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(!waiting_connect());
166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
167513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  net_log_.BeginEvent(
168513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      NetLog::TYPE_TCP_CONNECT,
169513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      make_scoped_refptr(new AddressListNetLogParam(addresses_)));
170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We will try to connect to each address in addresses_. Start with the
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // first one in the list.
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  next_connect_state_ = CONNECT_STATE_CONNECT;
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  current_ai_ = addresses_.head();
175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int rv = DoConnectLoop(OK);
177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (rv == ERR_IO_PENDING) {
178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Synchronous operation not supported.
179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DCHECK(callback);
180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    write_callback_ = callback;
181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    LogConnectCompletion(rv);
183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return rv;
186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint TCPClientSocketLibevent::DoConnectLoop(int result) {
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_NE(next_connect_state_, CONNECT_STATE_NONE);
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int rv = result;
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  do {
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ConnectState state = next_connect_state_;
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    next_connect_state_ = CONNECT_STATE_NONE;
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    switch (state) {
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case CONNECT_STATE_CONNECT:
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        DCHECK_EQ(OK, rv);
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        rv = DoConnect();
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case CONNECT_STATE_CONNECT_COMPLETE:
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        rv = DoConnectComplete(rv);
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      default:
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        LOG(DFATAL) << "bad state";
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        rv = ERR_UNEXPECTED;
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } while (rv != ERR_IO_PENDING && next_connect_state_ != CONNECT_STATE_NONE);
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return rv;
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint TCPClientSocketLibevent::DoConnect() {
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(current_ai_);
215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_EQ(0, connect_os_error_);
217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
218513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (previously_disconnected_) {
219513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    use_history_.Reset();
220513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    previously_disconnected_ = false;
221513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
222513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT,
224513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                      make_scoped_refptr(new NetLogStringParameter(
225513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                          "address", NetAddressToStringWithPort(current_ai_))));
226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  next_connect_state_ = CONNECT_STATE_CONNECT_COMPLETE;
228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Create a non-blocking socket.
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  connect_os_error_ = CreateSocket(current_ai_);
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (connect_os_error_)
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return MapPosixError(connect_os_error_);
233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Connect the socket.
235513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (!use_tcp_fastopen_) {
236513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (!HANDLE_EINTR(connect(socket_, current_ai_->ai_addr,
237513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                              static_cast<int>(current_ai_->ai_addrlen)))) {
238513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      // Connected without waiting!
239513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      return OK;
240513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    }
241513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  } else {
242513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    // With TCP FastOpen, we pretend that the socket is connected.
243513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    DCHECK(!tcp_fastopen_connected_);
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return OK;
245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Check if the connect() failed synchronously.
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  connect_os_error_ = errno;
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (connect_os_error_ != EINPROGRESS)
2503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return MapConnectError(connect_os_error_);
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Otherwise the connect() is going to complete asynchronously, so watch
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // for its completion.
254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!MessageLoopForIO::current()->WatchFileDescriptor(
255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          socket_, true, MessageLoopForIO::WATCH_WRITE, &write_socket_watcher_,
256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          &write_watcher_)) {
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    connect_os_error_ = errno;
258731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    DVLOG(1) << "WatchFileDescriptor failed: " << connect_os_error_;
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return MapPosixError(connect_os_error_);
260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return ERR_IO_PENDING;
263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint TCPClientSocketLibevent::DoConnectComplete(int result) {
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Log the end of this attempt (and any OS error it threw).
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int os_error = connect_os_error_;
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  connect_os_error_ = 0;
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<NetLog::EventParameters> params;
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (result != OK)
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    params = new NetLogIntegerParameter("os_error", os_error);
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT, params);
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  write_socket_watcher_.StopWatchingFileDescriptor();
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (result == OK) {
2773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    use_history_.set_was_ever_connected();
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return OK;  // Done!
2793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Close whatever partially connected socket we currently have.
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DoDisconnect();
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Try to fall back to the next address in the list.
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (current_ai_->ai_next) {
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    next_connect_state_ = CONNECT_STATE_CONNECT;
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    current_ai_ = current_ai_->ai_next;
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return OK;
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Otherwise there is nothing to fall back to, so give up.
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return result;
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid TCPClientSocketLibevent::Disconnect() {
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(CalledOnValidThread());
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DoDisconnect();
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  current_ai_ = NULL;
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TCPClientSocketLibevent::DoDisconnect() {
303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (socket_ == kInvalidSocket)
304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool ok = read_socket_watcher_.StopWatchingFileDescriptor();
307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(ok);
308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ok = write_socket_watcher_.StopWatchingFileDescriptor();
309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(ok);
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (HANDLE_EINTR(close(socket_)) < 0)
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    PLOG(ERROR) << "close";
312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  socket_ = kInvalidSocket;
313513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  previously_disconnected_ = true;
314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool TCPClientSocketLibevent::IsConnected() const {
317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(CalledOnValidThread());
318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (socket_ == kInvalidSocket || waiting_connect())
320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Check if connection is alive.
323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  char c;
324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int rv = HANDLE_EINTR(recv(socket_, &c, 1, MSG_PEEK));
325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (rv == 0)
326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (rv == -1 && errno != EAGAIN && errno != EWOULDBLOCK)
328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool TCPClientSocketLibevent::IsConnectedAndIdle() const {
334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(CalledOnValidThread());
335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (socket_ == kInvalidSocket || waiting_connect())
337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Check if connection is alive and we haven't received any data
340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // unexpectedly.
341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  char c;
342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int rv = HANDLE_EINTR(recv(socket_, &c, 1, MSG_PEEK));
343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (rv >= 0)
344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (errno != EAGAIN && errno != EWOULDBLOCK)
346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint TCPClientSocketLibevent::Read(IOBuffer* buf,
352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                  int buf_len,
353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                  CompletionCallback* callback) {
354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(CalledOnValidThread());
355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_NE(kInvalidSocket, socket_);
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(!waiting_connect());
357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(!read_callback_);
358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Synchronous operation not supported
359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(callback);
360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_GT(buf_len, 0);
361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int nread = HANDLE_EINTR(read(socket_, buf->data(), buf_len));
363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (nread >= 0) {
364731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    static base::StatsCounter read_bytes("tcp.read_bytes");
365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    read_bytes.Add(nread);
3663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (nread > 0)
3673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      use_history_.set_was_used_to_convey_data();
368731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    LogByteTransfer(
369731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        net_log_, NetLog::TYPE_SOCKET_BYTES_RECEIVED, nread, buf->data());
370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return nread;
371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (errno != EAGAIN && errno != EWOULDBLOCK) {
373731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    DVLOG(1) << "read failed, errno " << errno;
374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return MapPosixError(errno);
375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!MessageLoopForIO::current()->WatchFileDescriptor(
378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          socket_, true, MessageLoopForIO::WATCH_READ,
379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          &read_socket_watcher_, &read_watcher_)) {
380731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    DVLOG(1) << "WatchFileDescriptor failed on read, errno " << errno;
381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return MapPosixError(errno);
382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  read_buf_ = buf;
385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  read_buf_len_ = buf_len;
386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  read_callback_ = callback;
387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return ERR_IO_PENDING;
388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint TCPClientSocketLibevent::Write(IOBuffer* buf,
391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   int buf_len,
392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   CompletionCallback* callback) {
393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(CalledOnValidThread());
394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_NE(kInvalidSocket, socket_);
395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(!waiting_connect());
396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(!write_callback_);
397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Synchronous operation not supported
398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(callback);
399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_GT(buf_len, 0);
400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
401513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  int nwrite = InternalWrite(buf, buf_len);
402c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (nwrite >= 0) {
403731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    static base::StatsCounter write_bytes("tcp.write_bytes");
404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    write_bytes.Add(nwrite);
4053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (nwrite > 0)
4063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      use_history_.set_was_used_to_convey_data();
407731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    LogByteTransfer(
408731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        net_log_, NetLog::TYPE_SOCKET_BYTES_SENT, nwrite, buf->data());
409c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return nwrite;
410c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
411c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (errno != EAGAIN && errno != EWOULDBLOCK)
412c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return MapPosixError(errno);
413c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
414c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!MessageLoopForIO::current()->WatchFileDescriptor(
415c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          socket_, true, MessageLoopForIO::WATCH_WRITE,
416c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          &write_socket_watcher_, &write_watcher_)) {
417731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    DVLOG(1) << "WatchFileDescriptor failed on write, errno " << errno;
418c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return MapPosixError(errno);
419c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
420c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
421c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  write_buf_ = buf;
422c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  write_buf_len_ = buf_len;
423c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  write_callback_ = callback;
424c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return ERR_IO_PENDING;
425c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
426c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
427513209b27ff55e2841eac0e4120199c23acce758Ben Murdochint TCPClientSocketLibevent::InternalWrite(IOBuffer* buf, int buf_len) {
428513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  int nwrite;
429513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (use_tcp_fastopen_ && !tcp_fastopen_connected_) {
430513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    // We have a limited amount of data to send in the SYN packet.
431513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    int kMaxFastOpenSendLength = 1420;
432513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
433513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    buf_len = std::min(kMaxFastOpenSendLength, buf_len);
434513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
435513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    int flags = 0x20000000;  // Magic flag to enable TCP_FASTOPEN
436513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    nwrite = HANDLE_EINTR(sendto(socket_,
437513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                 buf->data(),
438513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                 buf_len,
439513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                 flags,
440513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                 current_ai_->ai_addr,
441513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                 static_cast<int>(current_ai_->ai_addrlen)));
442513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    tcp_fastopen_connected_ = true;
443513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
444513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (nwrite < 0) {
445513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      // Non-blocking mode is returning EINPROGRESS rather than EAGAIN.
446513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      if (errno == EINPROGRESS)
447513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch         errno = EAGAIN;
448513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
449513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      // Unlike "normal" nonblocking sockets, the data is already queued,
450513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      // so tell the app that we've consumed it.
451513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      return buf_len;
452513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    }
453513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  } else {
454513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    nwrite = HANDLE_EINTR(write(socket_, buf->data(), buf_len));
455513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
456513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return nwrite;
457513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
458513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
459c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool TCPClientSocketLibevent::SetReceiveBufferSize(int32 size) {
460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(CalledOnValidThread());
461c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF,
462c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      reinterpret_cast<const char*>(&size),
463c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      sizeof(size));
464c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(!rv) << "Could not set socket receive buffer size: " << errno;
465c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return rv == 0;
466c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
467c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
468c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool TCPClientSocketLibevent::SetSendBufferSize(int32 size) {
469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(CalledOnValidThread());
470c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF,
471c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      reinterpret_cast<const char*>(&size),
472c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      sizeof(size));
473c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(!rv) << "Could not set socket send buffer size: " << errno;
474c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return rv == 0;
475c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
476c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
477c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
478c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint TCPClientSocketLibevent::CreateSocket(const addrinfo* ai) {
479c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  socket_ = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
480c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (socket_ == kInvalidSocket)
481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return errno;
4824a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  return SetupSocket();
4834a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch}
484c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
4854a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochint TCPClientSocketLibevent::SetupSocket() {
486c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (SetNonBlocking(socket_)) {
487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const int err = errno;
488c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    close(socket_);
489c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    socket_ = kInvalidSocket;
490c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return err;
491c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
492c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
493c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // This mirrors the behaviour on Windows. See the comment in
494c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // tcp_client_socket_win.cc after searching for "NODELAY".
495c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DisableNagle(socket_);  // If DisableNagle fails, we don't care.
496c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return 0;
498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TCPClientSocketLibevent::LogConnectCompletion(int net_error) {
501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<NetLog::EventParameters> params;
502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (net_error != OK)
503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    params = new NetLogIntegerParameter("net_error", net_error);
504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT, params);
505c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
506c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
507c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid TCPClientSocketLibevent::DoReadCallback(int rv) {
508c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_NE(rv, ERR_IO_PENDING);
509c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(read_callback_);
510c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
511c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // since Run may result in Read being called, clear read_callback_ up front.
512c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CompletionCallback* c = read_callback_;
513c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  read_callback_ = NULL;
514c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  c->Run(rv);
515c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
516c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
517c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid TCPClientSocketLibevent::DoWriteCallback(int rv) {
518c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_NE(rv, ERR_IO_PENDING);
519c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(write_callback_);
520c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
521c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // since Run may result in Write being called, clear write_callback_ up front.
522c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CompletionCallback* c = write_callback_;
523c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  write_callback_ = NULL;
524c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  c->Run(rv);
525c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
526c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
527c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid TCPClientSocketLibevent::DidCompleteConnect() {
528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_EQ(next_connect_state_, CONNECT_STATE_CONNECT_COMPLETE);
529c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Get the error that connect() completed with.
531c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int os_error = 0;
532c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  socklen_t len = sizeof(os_error);
533c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (getsockopt(socket_, SOL_SOCKET, SO_ERROR, &os_error, &len) < 0)
534c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    os_error = errno;
535c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(eroman): Is this check really necessary?
537c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (os_error == EINPROGRESS || os_error == EALREADY) {
538c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    NOTREACHED();  // This indicates a bug in libevent or our code.
539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
540c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
541c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  connect_os_error_ = os_error;
543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int rv = DoConnectLoop(MapConnectError(os_error));
544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (rv != ERR_IO_PENDING) {
545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    LogConnectCompletion(rv);
546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DoWriteCallback(rv);
547c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
548c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
549c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
550c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid TCPClientSocketLibevent::DidCompleteRead() {
551c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int bytes_transferred;
552c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bytes_transferred = HANDLE_EINTR(read(socket_, read_buf_->data(),
553c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                        read_buf_len_));
554c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
555c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int result;
556c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (bytes_transferred >= 0) {
557c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    result = bytes_transferred;
558731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    static base::StatsCounter read_bytes("tcp.read_bytes");
5593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    read_bytes.Add(bytes_transferred);
5603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (bytes_transferred > 0)
5613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      use_history_.set_was_used_to_convey_data();
562731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    LogByteTransfer(net_log_, NetLog::TYPE_SOCKET_BYTES_RECEIVED, result,
563731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                    read_buf_->data());
564c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
565c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    result = MapPosixError(errno);
566c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
567c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
568c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (result != ERR_IO_PENDING) {
569c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    read_buf_ = NULL;
570c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    read_buf_len_ = 0;
571c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    bool ok = read_socket_watcher_.StopWatchingFileDescriptor();
572c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DCHECK(ok);
573c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DoReadCallback(result);
574c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
575c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
576c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
577c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid TCPClientSocketLibevent::DidCompleteWrite() {
578c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int bytes_transferred;
579c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bytes_transferred = HANDLE_EINTR(write(socket_, write_buf_->data(),
580c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                         write_buf_len_));
581c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
582c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int result;
583c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (bytes_transferred >= 0) {
584c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    result = bytes_transferred;
585731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    static base::StatsCounter write_bytes("tcp.write_bytes");
5863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    write_bytes.Add(bytes_transferred);
5873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (bytes_transferred > 0)
5883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      use_history_.set_was_used_to_convey_data();
589731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    LogByteTransfer(net_log_, NetLog::TYPE_SOCKET_BYTES_SENT, result,
590731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                    write_buf_->data());
591c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
592c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    result = MapPosixError(errno);
593c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
594c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
595c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (result != ERR_IO_PENDING) {
596c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    write_buf_ = NULL;
597c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    write_buf_len_ = 0;
598c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    write_socket_watcher_.StopWatchingFileDescriptor();
599c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DoWriteCallback(result);
600c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
601c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
602c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint TCPClientSocketLibevent::GetPeerAddress(AddressList* address) const {
604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(CalledOnValidThread());
605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(address);
6063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!IsConnected())
607731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return ERR_SOCKET_NOT_CONNECTED;
608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  address->Copy(current_ai_, false);
609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return OK;
610c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
611c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
6123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid TCPClientSocketLibevent::SetSubresourceSpeculation() {
6133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  use_history_.set_subresource_speculation();
6143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
6153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
6163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid TCPClientSocketLibevent::SetOmniboxSpeculation() {
6173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  use_history_.set_omnibox_speculation();
6183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
6193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
6203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool TCPClientSocketLibevent::WasEverUsed() const {
6213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return use_history_.was_used_to_convey_data();
6223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
6233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
624513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool TCPClientSocketLibevent::UsingTCPFastOpen() const {
625513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return use_tcp_fastopen_;
626513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
627513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
628c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace net
629