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"
2272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "net/base/connection_type_histograms.h"
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/io_buffer.h"
24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "net/base/ip_endpoint.h"
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/net_errors.h"
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_log.h"
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_util.h"
28731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "net/base/network_change_notifier.h"
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(USE_SYSTEM_LIBEVENT)
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <event.h>
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#else
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "third_party/libevent/event.h"
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
34e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma#ifdef ANDROID
35e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma#include <cutils/qtaguid.h>
36e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma#endif
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace net {
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace {
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst int kInvalidSocket = -1;
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// DisableNagle turns off buffering in the kernel. By default, TCP sockets will
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// wait up to 200ms for more data to complete a packet before transmitting.
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// After calling this function, the kernel will not wait. See TCP_NODELAY in
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// `man 7 tcp`.
48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint DisableNagle(int fd) {
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int on = 1;
50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
533d6f5e4a9a66d7ad3fb2cb548adc5da3f82b31b5Ben Murdoch// SetTCPKeepAlive sets SO_KEEPALIVE.
543d6f5e4a9a66d7ad3fb2cb548adc5da3f82b31b5Ben Murdochvoid SetTCPKeepAlive(int fd) {
553d6f5e4a9a66d7ad3fb2cb548adc5da3f82b31b5Ben Murdoch  int optval = 1;
563d6f5e4a9a66d7ad3fb2cb548adc5da3f82b31b5Ben Murdoch  socklen_t optlen = sizeof(optval);
573d6f5e4a9a66d7ad3fb2cb548adc5da3f82b31b5Ben Murdoch  if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen)) {
583d6f5e4a9a66d7ad3fb2cb548adc5da3f82b31b5Ben Murdoch    PLOG(ERROR) << "Failed to set SO_KEEPALIVE on fd: " << fd;
593d6f5e4a9a66d7ad3fb2cb548adc5da3f82b31b5Ben Murdoch    return;
603d6f5e4a9a66d7ad3fb2cb548adc5da3f82b31b5Ben Murdoch  }
613d6f5e4a9a66d7ad3fb2cb548adc5da3f82b31b5Ben Murdoch#if defined(OS_LINUX)
623d6f5e4a9a66d7ad3fb2cb548adc5da3f82b31b5Ben Murdoch  // Set seconds until first TCP keep alive.
6314b5a7d81bfff56b54d90e469ecfc3622bd37f30Kristian Monsen#ifdef ANDROID
64df5fef6c965bc95a2b6c3827a6a90c51667ffb9eBen Murdoch  optval = 25;
6514b5a7d81bfff56b54d90e469ecfc3622bd37f30Kristian Monsen#else
6672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  optval = 45;
6714b5a7d81bfff56b54d90e469ecfc3622bd37f30Kristian Monsen#endif
683d6f5e4a9a66d7ad3fb2cb548adc5da3f82b31b5Ben Murdoch  if (setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &optval, optlen)) {
693d6f5e4a9a66d7ad3fb2cb548adc5da3f82b31b5Ben Murdoch    PLOG(ERROR) << "Failed to set TCP_KEEPIDLE on fd: " << fd;
703d6f5e4a9a66d7ad3fb2cb548adc5da3f82b31b5Ben Murdoch    return;
713d6f5e4a9a66d7ad3fb2cb548adc5da3f82b31b5Ben Murdoch  }
723d6f5e4a9a66d7ad3fb2cb548adc5da3f82b31b5Ben Murdoch  // Set seconds between TCP keep alives.
733d6f5e4a9a66d7ad3fb2cb548adc5da3f82b31b5Ben Murdoch  if (setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &optval, optlen)) {
743d6f5e4a9a66d7ad3fb2cb548adc5da3f82b31b5Ben Murdoch    PLOG(ERROR) << "Failed to set TCP_KEEPINTVL on fd: " << fd;
753d6f5e4a9a66d7ad3fb2cb548adc5da3f82b31b5Ben Murdoch    return;
763d6f5e4a9a66d7ad3fb2cb548adc5da3f82b31b5Ben Murdoch  }
773d6f5e4a9a66d7ad3fb2cb548adc5da3f82b31b5Ben Murdoch#endif
783d6f5e4a9a66d7ad3fb2cb548adc5da3f82b31b5Ben Murdoch}
793d6f5e4a9a66d7ad3fb2cb548adc5da3f82b31b5Ben Murdoch
80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint MapConnectError(int os_error) {
81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  switch (os_error) {
82513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    case EACCES:
83513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      return ERR_NETWORK_ACCESS_DENIED;
84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case ETIMEDOUT:
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return ERR_CONNECTION_TIMED_OUT;
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    default: {
87ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      int net_error = MapSystemError(os_error);
88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (net_error == ERR_FAILED)
89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return ERR_CONNECTION_FAILED;  // More specific than ERR_FAILED.
90731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
91731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      // Give a more specific error when the user is offline.
92731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      if (net_error == ERR_ADDRESS_UNREACHABLE &&
93731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          NetworkChangeNotifier::IsOffline()) {
94731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        return ERR_INTERNET_DISCONNECTED;
95731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      }
96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return net_error;
97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace
102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//-----------------------------------------------------------------------------
104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1053345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTCPClientSocketLibevent::TCPClientSocketLibevent(
1063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const AddressList& addresses,
1073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    net::NetLog* net_log,
1083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const net::NetLog::Source& source)
109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    : socket_(kInvalidSocket),
110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      addresses_(addresses),
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      current_ai_(NULL),
112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      read_watcher_(this),
113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      write_watcher_(this),
114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      read_callback_(NULL),
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      write_callback_(NULL),
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      next_connect_state_(CONNECT_STATE_NONE),
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      connect_os_error_(0),
118513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)),
119513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      previously_disconnected_(false),
120513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      use_tcp_fastopen_(false),
1217b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen      tcp_fastopen_connected_(false)
1227b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#ifdef ANDROID
1237b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen      , wait_for_connect_(false)
124e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma      , valid_uid_(false)
125e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma      , calling_uid_(0)
1267b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#endif
1277b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen{
1283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<NetLog::EventParameters> params;
1293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (source.is_valid())
1303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    params = new NetLogSourceParameter("source_dependency", source);
1313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, params);
132513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
133513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (is_tcp_fastopen_enabled())
134513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    use_tcp_fastopen_ = true;
135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTCPClientSocketLibevent::~TCPClientSocketLibevent() {
138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Disconnect();
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE, NULL);
140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1424a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochvoid TCPClientSocketLibevent::AdoptSocket(int socket) {
1434a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  DCHECK_EQ(socket_, kInvalidSocket);
1444a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  socket_ = socket;
1454a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  int error = SetupSocket();
1464a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  DCHECK_EQ(0, error);
1474a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // This is to make GetPeerAddress work. It's up to the test that is calling
1484a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // this function to ensure that address_ contains a reasonable address for
1494a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // this socket. (i.e. at least match IPv4 vs IPv6!).
1504a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  current_ai_ = addresses_.head();
1514a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  use_history_.set_was_ever_connected();
1524a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch}
1534a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1547b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsenint TCPClientSocketLibevent::Connect(CompletionCallback* callback
1557b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#ifdef ANDROID
1567b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen                                     , bool wait_for_connect
157e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma                                     , bool valid_uid
158e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma                                     , uid_t calling_uid
1597b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#endif
1607b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen                                    ) {
1617b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#ifdef ANDROID
1627b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen  wait_for_connect_ = wait_for_connect;
163e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma  valid_uid_ = valid_uid;
164e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma  calling_uid_ = calling_uid;
1657b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#endif
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(CalledOnValidThread());
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // If already connected, then just return OK.
169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (socket_ != kInvalidSocket)
170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return OK;
171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
172ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  base::StatsCounter connects("tcp.connect");
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  connects.Increment();
174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(!waiting_connect());
176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
177513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  net_log_.BeginEvent(
178513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      NetLog::TYPE_TCP_CONNECT,
179513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      make_scoped_refptr(new AddressListNetLogParam(addresses_)));
180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We will try to connect to each address in addresses_. Start with the
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // first one in the list.
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  next_connect_state_ = CONNECT_STATE_CONNECT;
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  current_ai_ = addresses_.head();
185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int rv = DoConnectLoop(OK);
187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (rv == ERR_IO_PENDING) {
188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Synchronous operation not supported.
189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DCHECK(callback);
190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    write_callback_ = callback;
191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    LogConnectCompletion(rv);
193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return rv;
196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint TCPClientSocketLibevent::DoConnectLoop(int result) {
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_NE(next_connect_state_, CONNECT_STATE_NONE);
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int rv = result;
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  do {
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ConnectState state = next_connect_state_;
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    next_connect_state_ = CONNECT_STATE_NONE;
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    switch (state) {
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case CONNECT_STATE_CONNECT:
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        DCHECK_EQ(OK, rv);
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        rv = DoConnect();
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case CONNECT_STATE_CONNECT_COMPLETE:
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        rv = DoConnectComplete(rv);
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      default:
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        LOG(DFATAL) << "bad state";
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        rv = ERR_UNEXPECTED;
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } while (rv != ERR_IO_PENDING && next_connect_state_ != CONNECT_STATE_NONE);
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return rv;
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint TCPClientSocketLibevent::DoConnect() {
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(current_ai_);
225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_EQ(0, connect_os_error_);
227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
228513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (previously_disconnected_) {
229513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    use_history_.Reset();
230513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    previously_disconnected_ = false;
231513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
232513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT,
234513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                      make_scoped_refptr(new NetLogStringParameter(
235513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                          "address", NetAddressToStringWithPort(current_ai_))));
236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  next_connect_state_ = CONNECT_STATE_CONNECT_COMPLETE;
238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Create a non-blocking socket.
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  connect_os_error_ = CreateSocket(current_ai_);
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (connect_os_error_)
242ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return MapSystemError(connect_os_error_);
243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Connect the socket.
245513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (!use_tcp_fastopen_) {
246513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (!HANDLE_EINTR(connect(socket_, current_ai_->ai_addr,
247513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                              static_cast<int>(current_ai_->ai_addrlen)))) {
248513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      // Connected without waiting!
249513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      return OK;
2507b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#ifdef ANDROID
2517b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen    } else if (errno == EINPROGRESS && wait_for_connect_) {
2527b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen      fd_set writeset;
2537b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen      FD_ZERO(&writeset);
2547b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen      FD_SET(socket_, &writeset);
2557b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen      timeval tv;
2567b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen      tv.tv_sec = 20;
2577b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen      tv.tv_usec = 0;
2587b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen      int res = HANDLE_EINTR(select(socket_ + 1, 0, &writeset, 0, &tv));
2597b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen      if (res > 0)
2607b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen        return OK;
2617b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen      return MapConnectError(ETIMEDOUT);
2627b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#endif
263513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    }
264513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  } else {
265513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    // With TCP FastOpen, we pretend that the socket is connected.
266513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    DCHECK(!tcp_fastopen_connected_);
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return OK;
268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Check if the connect() failed synchronously.
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  connect_os_error_ = errno;
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (connect_os_error_ != EINPROGRESS)
2733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return MapConnectError(connect_os_error_);
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Otherwise the connect() is going to complete asynchronously, so watch
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // for its completion.
277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!MessageLoopForIO::current()->WatchFileDescriptor(
278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          socket_, true, MessageLoopForIO::WATCH_WRITE, &write_socket_watcher_,
279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          &write_watcher_)) {
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    connect_os_error_ = errno;
281731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    DVLOG(1) << "WatchFileDescriptor failed: " << connect_os_error_;
282ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return MapSystemError(connect_os_error_);
283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return ERR_IO_PENDING;
286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint TCPClientSocketLibevent::DoConnectComplete(int result) {
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Log the end of this attempt (and any OS error it threw).
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int os_error = connect_os_error_;
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  connect_os_error_ = 0;
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<NetLog::EventParameters> params;
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (result != OK)
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    params = new NetLogIntegerParameter("os_error", os_error);
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT, params);
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  write_socket_watcher_.StopWatchingFileDescriptor();
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (result == OK) {
3003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    use_history_.set_was_ever_connected();
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return OK;  // Done!
3023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Close whatever partially connected socket we currently have.
305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DoDisconnect();
306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Try to fall back to the next address in the list.
308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (current_ai_->ai_next) {
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    next_connect_state_ = CONNECT_STATE_CONNECT;
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    current_ai_ = current_ai_->ai_next;
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return OK;
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Otherwise there is nothing to fall back to, so give up.
315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return result;
316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid TCPClientSocketLibevent::Disconnect() {
319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(CalledOnValidThread());
320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DoDisconnect();
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  current_ai_ = NULL;
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TCPClientSocketLibevent::DoDisconnect() {
326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (socket_ == kInvalidSocket)
327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool ok = read_socket_watcher_.StopWatchingFileDescriptor();
330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(ok);
331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ok = write_socket_watcher_.StopWatchingFileDescriptor();
332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(ok);
333e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma
334e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma#ifdef ANDROID
335e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma  if (valid_uid_)
336e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma    qtaguid_untagSocket(socket_);
337e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma#endif
338e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (HANDLE_EINTR(close(socket_)) < 0)
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    PLOG(ERROR) << "close";
341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  socket_ = kInvalidSocket;
342513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  previously_disconnected_ = true;
343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool TCPClientSocketLibevent::IsConnected() const {
346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(CalledOnValidThread());
347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (socket_ == kInvalidSocket || waiting_connect())
349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Check if connection is alive.
352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  char c;
353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int rv = HANDLE_EINTR(recv(socket_, &c, 1, MSG_PEEK));
354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (rv == 0)
355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (rv == -1 && errno != EAGAIN && errno != EWOULDBLOCK)
357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool TCPClientSocketLibevent::IsConnectedAndIdle() const {
363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(CalledOnValidThread());
364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (socket_ == kInvalidSocket || waiting_connect())
366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Check if connection is alive and we haven't received any data
369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // unexpectedly.
370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  char c;
371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int rv = HANDLE_EINTR(recv(socket_, &c, 1, MSG_PEEK));
372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (rv >= 0)
373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (errno != EAGAIN && errno != EWOULDBLOCK)
375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint TCPClientSocketLibevent::Read(IOBuffer* buf,
381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                  int buf_len,
382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                  CompletionCallback* callback) {
383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(CalledOnValidThread());
384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_NE(kInvalidSocket, socket_);
385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(!waiting_connect());
386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(!read_callback_);
387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Synchronous operation not supported
388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(callback);
389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_GT(buf_len, 0);
390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int nread = HANDLE_EINTR(read(socket_, buf->data(), buf_len));
392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (nread >= 0) {
393ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    base::StatsCounter read_bytes("tcp.read_bytes");
394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    read_bytes.Add(nread);
3953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (nread > 0)
3963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      use_history_.set_was_used_to_convey_data();
397731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    LogByteTransfer(
398731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        net_log_, NetLog::TYPE_SOCKET_BYTES_RECEIVED, nread, buf->data());
399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return nread;
400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
401c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (errno != EAGAIN && errno != EWOULDBLOCK) {
402731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    DVLOG(1) << "read failed, errno " << errno;
403ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return MapSystemError(errno);
404c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
405c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
406c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!MessageLoopForIO::current()->WatchFileDescriptor(
407c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          socket_, true, MessageLoopForIO::WATCH_READ,
408c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          &read_socket_watcher_, &read_watcher_)) {
409731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    DVLOG(1) << "WatchFileDescriptor failed on read, errno " << errno;
410ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return MapSystemError(errno);
411c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
412c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
413c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  read_buf_ = buf;
414c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  read_buf_len_ = buf_len;
415c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  read_callback_ = callback;
416c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return ERR_IO_PENDING;
417c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
418c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
419c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint TCPClientSocketLibevent::Write(IOBuffer* buf,
420c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   int buf_len,
421c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   CompletionCallback* callback) {
422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(CalledOnValidThread());
423c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_NE(kInvalidSocket, socket_);
424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(!waiting_connect());
425c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(!write_callback_);
426c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Synchronous operation not supported
427c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(callback);
428c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_GT(buf_len, 0);
429c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
430513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  int nwrite = InternalWrite(buf, buf_len);
431c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (nwrite >= 0) {
432ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    base::StatsCounter write_bytes("tcp.write_bytes");
433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    write_bytes.Add(nwrite);
4343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (nwrite > 0)
4353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      use_history_.set_was_used_to_convey_data();
436731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    LogByteTransfer(
437731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        net_log_, NetLog::TYPE_SOCKET_BYTES_SENT, nwrite, buf->data());
438c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return nwrite;
439c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
440c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (errno != EAGAIN && errno != EWOULDBLOCK)
441ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return MapSystemError(errno);
442c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
443c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!MessageLoopForIO::current()->WatchFileDescriptor(
444c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          socket_, true, MessageLoopForIO::WATCH_WRITE,
445c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          &write_socket_watcher_, &write_watcher_)) {
446731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    DVLOG(1) << "WatchFileDescriptor failed on write, errno " << errno;
447ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return MapSystemError(errno);
448c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
449c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
450c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  write_buf_ = buf;
451c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  write_buf_len_ = buf_len;
452c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  write_callback_ = callback;
453c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return ERR_IO_PENDING;
454c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
455c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
456513209b27ff55e2841eac0e4120199c23acce758Ben Murdochint TCPClientSocketLibevent::InternalWrite(IOBuffer* buf, int buf_len) {
457513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  int nwrite;
458513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (use_tcp_fastopen_ && !tcp_fastopen_connected_) {
459513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    // We have a limited amount of data to send in the SYN packet.
460513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    int kMaxFastOpenSendLength = 1420;
461513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
462513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    buf_len = std::min(kMaxFastOpenSendLength, buf_len);
463513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
464513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    int flags = 0x20000000;  // Magic flag to enable TCP_FASTOPEN
465513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    nwrite = HANDLE_EINTR(sendto(socket_,
466513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                 buf->data(),
467513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                 buf_len,
468513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                 flags,
469513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                 current_ai_->ai_addr,
470513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                 static_cast<int>(current_ai_->ai_addrlen)));
471513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    tcp_fastopen_connected_ = true;
472513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
473513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (nwrite < 0) {
474513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      // Non-blocking mode is returning EINPROGRESS rather than EAGAIN.
475513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      if (errno == EINPROGRESS)
476513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch         errno = EAGAIN;
477513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
478513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      // Unlike "normal" nonblocking sockets, the data is already queued,
479513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      // so tell the app that we've consumed it.
480513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      return buf_len;
481513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    }
482513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  } else {
483513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    nwrite = HANDLE_EINTR(write(socket_, buf->data(), buf_len));
484513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
485513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return nwrite;
486513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
487513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
488c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool TCPClientSocketLibevent::SetReceiveBufferSize(int32 size) {
489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(CalledOnValidThread());
490c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF,
491c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      reinterpret_cast<const char*>(&size),
492c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      sizeof(size));
493c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(!rv) << "Could not set socket receive buffer size: " << errno;
494c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return rv == 0;
495c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
496c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
497c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool TCPClientSocketLibevent::SetSendBufferSize(int32 size) {
498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(CalledOnValidThread());
499c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF,
500c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      reinterpret_cast<const char*>(&size),
501c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      sizeof(size));
502c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(!rv) << "Could not set socket send buffer size: " << errno;
503c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return rv == 0;
504c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
505c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
506c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
507c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint TCPClientSocketLibevent::CreateSocket(const addrinfo* ai) {
508c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  socket_ = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
509c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (socket_ == kInvalidSocket)
510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return errno;
5114a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  return SetupSocket();
5124a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch}
513c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5144a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochint TCPClientSocketLibevent::SetupSocket() {
515c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (SetNonBlocking(socket_)) {
516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const int err = errno;
517e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma
518e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma#ifdef ANDROID
519e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma    if (valid_uid_)
520e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma      qtaguid_untagSocket(socket_);
521e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma#endif
522e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma
523c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    close(socket_);
524c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    socket_ = kInvalidSocket;
525c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return err;
526c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
527c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
528c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // This mirrors the behaviour on Windows. See the comment in
529c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // tcp_client_socket_win.cc after searching for "NODELAY".
530c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DisableNagle(socket_);  // If DisableNagle fails, we don't care.
531e4aeb840e5cd2acd20cf6b18af808af55a92e745Kristian Monsen
532e4aeb840e5cd2acd20cf6b18af808af55a92e745Kristian Monsen  // ANDROID: Disable TCP keep-alive for bug 5226268
533e4aeb840e5cd2acd20cf6b18af808af55a92e745Kristian Monsen  // [Browser] http keep-alive packets are sent too frequently to network
534e4aeb840e5cd2acd20cf6b18af808af55a92e745Kristian Monsen#ifndef ANDROID
5353d6f5e4a9a66d7ad3fb2cb548adc5da3f82b31b5Ben Murdoch  SetTCPKeepAlive(socket_);
536e4aeb840e5cd2acd20cf6b18af808af55a92e745Kristian Monsen#endif
537c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
538e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma#ifdef ANDROID
539e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma  if (valid_uid_)
540e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma    qtaguid_tagSocket(socket_, geteuid(), calling_uid_);
541e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma#endif
542e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma
543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return 0;
544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TCPClientSocketLibevent::LogConnectCompletion(int net_error) {
54772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (net_error == OK)
54872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    UpdateConnectionTypeHistograms(CONNECTION_ANY);
54972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
55072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (net_error != OK) {
55172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, net_error);
55272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return;
55372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
55472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
55572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  struct sockaddr_storage source_address;
55672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  socklen_t addrlen = sizeof(source_address);
55772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  int rv = getsockname(
55872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      socket_, reinterpret_cast<struct sockaddr*>(&source_address), &addrlen);
55972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (rv != 0) {
56072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    PLOG(ERROR) << "getsockname() [rv: " << rv << "] error: ";
56172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    NOTREACHED();
56272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, rv);
56372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return;
56472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
56572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
56672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  const std::string source_address_str =
56772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      NetAddressToStringWithPort(
56872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          reinterpret_cast<const struct sockaddr*>(&source_address),
56972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          sizeof(source_address));
57072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT,
57172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                    make_scoped_refptr(new NetLogStringParameter(
57272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                        "source address",
57372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                        source_address_str)));
574c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
575c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
576c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid TCPClientSocketLibevent::DoReadCallback(int rv) {
577c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_NE(rv, ERR_IO_PENDING);
578c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(read_callback_);
579c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
580c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // since Run may result in Read being called, clear read_callback_ up front.
581c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CompletionCallback* c = read_callback_;
582c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  read_callback_ = NULL;
583c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  c->Run(rv);
584c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
585c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
586c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid TCPClientSocketLibevent::DoWriteCallback(int rv) {
587c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_NE(rv, ERR_IO_PENDING);
588c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(write_callback_);
589c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
590c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // since Run may result in Write being called, clear write_callback_ up front.
591c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CompletionCallback* c = write_callback_;
592c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  write_callback_ = NULL;
593c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  c->Run(rv);
594c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
595c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
596c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid TCPClientSocketLibevent::DidCompleteConnect() {
597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_EQ(next_connect_state_, CONNECT_STATE_CONNECT_COMPLETE);
598c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Get the error that connect() completed with.
600c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int os_error = 0;
601c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  socklen_t len = sizeof(os_error);
602c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (getsockopt(socket_, SOL_SOCKET, SO_ERROR, &os_error, &len) < 0)
603c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    os_error = errno;
604c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(eroman): Is this check really necessary?
606c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (os_error == EINPROGRESS || os_error == EALREADY) {
607c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    NOTREACHED();  // This indicates a bug in libevent or our code.
608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
609c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
610c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  connect_os_error_ = os_error;
612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int rv = DoConnectLoop(MapConnectError(os_error));
613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (rv != ERR_IO_PENDING) {
614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    LogConnectCompletion(rv);
615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DoWriteCallback(rv);
616c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
617c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
618c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
619c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid TCPClientSocketLibevent::DidCompleteRead() {
620c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int bytes_transferred;
621c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bytes_transferred = HANDLE_EINTR(read(socket_, read_buf_->data(),
622c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                        read_buf_len_));
623c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
624c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int result;
625c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (bytes_transferred >= 0) {
626c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    result = bytes_transferred;
627ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    base::StatsCounter read_bytes("tcp.read_bytes");
6283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    read_bytes.Add(bytes_transferred);
6293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (bytes_transferred > 0)
6303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      use_history_.set_was_used_to_convey_data();
631731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    LogByteTransfer(net_log_, NetLog::TYPE_SOCKET_BYTES_RECEIVED, result,
632731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                    read_buf_->data());
633c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
634ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    result = MapSystemError(errno);
635c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
636c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
637c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (result != ERR_IO_PENDING) {
638c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    read_buf_ = NULL;
639c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    read_buf_len_ = 0;
640c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    bool ok = read_socket_watcher_.StopWatchingFileDescriptor();
641c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DCHECK(ok);
642c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DoReadCallback(result);
643c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
644c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
645c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
646c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid TCPClientSocketLibevent::DidCompleteWrite() {
647c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int bytes_transferred;
648c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bytes_transferred = HANDLE_EINTR(write(socket_, write_buf_->data(),
649c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                         write_buf_len_));
650c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
651c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int result;
652c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (bytes_transferred >= 0) {
653c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    result = bytes_transferred;
654ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    base::StatsCounter write_bytes("tcp.write_bytes");
6553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    write_bytes.Add(bytes_transferred);
6563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (bytes_transferred > 0)
6573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      use_history_.set_was_used_to_convey_data();
658731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    LogByteTransfer(net_log_, NetLog::TYPE_SOCKET_BYTES_SENT, result,
659731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                    write_buf_->data());
660c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
661ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    result = MapSystemError(errno);
662c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
663c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
664c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (result != ERR_IO_PENDING) {
665c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    write_buf_ = NULL;
666c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    write_buf_len_ = 0;
667c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    write_socket_watcher_.StopWatchingFileDescriptor();
668c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DoWriteCallback(result);
669c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
670c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
671c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
672c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint TCPClientSocketLibevent::GetPeerAddress(AddressList* address) const {
673c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(CalledOnValidThread());
674c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(address);
6753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!IsConnected())
676731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return ERR_SOCKET_NOT_CONNECTED;
677c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  address->Copy(current_ai_, false);
678c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return OK;
679c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
680c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
681ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint TCPClientSocketLibevent::GetLocalAddress(IPEndPoint* address) const {
682ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(CalledOnValidThread());
683ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(address);
684ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!IsConnected())
685ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return ERR_SOCKET_NOT_CONNECTED;
686ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
687ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  struct sockaddr_storage addr_storage;
688ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  socklen_t addr_len = sizeof(addr_storage);
689ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage);
690ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (getsockname(socket_, addr, &addr_len))
691ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return MapSystemError(errno);
692ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!address->FromSockAddr(addr, addr_len))
693ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return ERR_FAILED;
694ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
695ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return OK;
696ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
697ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
69821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenconst BoundNetLog& TCPClientSocketLibevent::NetLog() const {
69921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return net_log_;
70021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
70121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
7023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid TCPClientSocketLibevent::SetSubresourceSpeculation() {
7033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  use_history_.set_subresource_speculation();
7043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
7053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
7063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid TCPClientSocketLibevent::SetOmniboxSpeculation() {
7073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  use_history_.set_omnibox_speculation();
7083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
7093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
7103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool TCPClientSocketLibevent::WasEverUsed() const {
7113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return use_history_.was_used_to_convey_data();
7123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
7133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
714513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool TCPClientSocketLibevent::UsingTCPFastOpen() const {
715513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return use_tcp_fastopen_;
716513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
717513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
718c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace net
719