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