1*6777b538SAndroid Build Coastguard Worker // Copyright 2013 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "net/socket/tcp_client_socket.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <memory>
8*6777b538SAndroid Build Coastguard Worker #include <utility>
9*6777b538SAndroid Build Coastguard Worker
10*6777b538SAndroid Build Coastguard Worker #include "base/check_op.h"
11*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/functional/callback_helpers.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/memory/ptr_util.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/metrics/histogram_macros.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/notreached.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/time/time.h"
17*6777b538SAndroid Build Coastguard Worker #include "net/base/features.h"
18*6777b538SAndroid Build Coastguard Worker #include "net/base/io_buffer.h"
19*6777b538SAndroid Build Coastguard Worker #include "net/base/ip_endpoint.h"
20*6777b538SAndroid Build Coastguard Worker #include "net/base/net_errors.h"
21*6777b538SAndroid Build Coastguard Worker #include "net/nqe/network_quality_estimator.h"
22*6777b538SAndroid Build Coastguard Worker #include "net/socket/socket_performance_watcher.h"
23*6777b538SAndroid Build Coastguard Worker #include "net/traffic_annotation/network_traffic_annotation.h"
24*6777b538SAndroid Build Coastguard Worker
25*6777b538SAndroid Build Coastguard Worker #if defined(TCP_CLIENT_SOCKET_OBSERVES_SUSPEND)
26*6777b538SAndroid Build Coastguard Worker #include "base/power_monitor/power_monitor.h"
27*6777b538SAndroid Build Coastguard Worker #endif
28*6777b538SAndroid Build Coastguard Worker
29*6777b538SAndroid Build Coastguard Worker namespace net {
30*6777b538SAndroid Build Coastguard Worker
31*6777b538SAndroid Build Coastguard Worker class NetLogWithSource;
32*6777b538SAndroid Build Coastguard Worker
TCPClientSocket(const AddressList & addresses,std::unique_ptr<SocketPerformanceWatcher> socket_performance_watcher,NetworkQualityEstimator * network_quality_estimator,net::NetLog * net_log,const net::NetLogSource & source,handles::NetworkHandle network)33*6777b538SAndroid Build Coastguard Worker TCPClientSocket::TCPClientSocket(
34*6777b538SAndroid Build Coastguard Worker const AddressList& addresses,
35*6777b538SAndroid Build Coastguard Worker std::unique_ptr<SocketPerformanceWatcher> socket_performance_watcher,
36*6777b538SAndroid Build Coastguard Worker NetworkQualityEstimator* network_quality_estimator,
37*6777b538SAndroid Build Coastguard Worker net::NetLog* net_log,
38*6777b538SAndroid Build Coastguard Worker const net::NetLogSource& source,
39*6777b538SAndroid Build Coastguard Worker handles::NetworkHandle network)
40*6777b538SAndroid Build Coastguard Worker : TCPClientSocket(
41*6777b538SAndroid Build Coastguard Worker std::make_unique<TCPSocket>(std::move(socket_performance_watcher),
42*6777b538SAndroid Build Coastguard Worker net_log,
43*6777b538SAndroid Build Coastguard Worker source),
44*6777b538SAndroid Build Coastguard Worker addresses,
45*6777b538SAndroid Build Coastguard Worker -1 /* current_address_index */,
46*6777b538SAndroid Build Coastguard Worker nullptr /* bind_address */,
47*6777b538SAndroid Build Coastguard Worker network_quality_estimator,
48*6777b538SAndroid Build Coastguard Worker network) {}
49*6777b538SAndroid Build Coastguard Worker
TCPClientSocket(std::unique_ptr<TCPSocket> connected_socket,const IPEndPoint & peer_address)50*6777b538SAndroid Build Coastguard Worker TCPClientSocket::TCPClientSocket(std::unique_ptr<TCPSocket> connected_socket,
51*6777b538SAndroid Build Coastguard Worker const IPEndPoint& peer_address)
52*6777b538SAndroid Build Coastguard Worker : TCPClientSocket(std::move(connected_socket),
53*6777b538SAndroid Build Coastguard Worker AddressList(peer_address),
54*6777b538SAndroid Build Coastguard Worker 0 /* current_address_index */,
55*6777b538SAndroid Build Coastguard Worker nullptr /* bind_address */,
56*6777b538SAndroid Build Coastguard Worker // TODO(https://crbug.com/1123197: Pass non-null
57*6777b538SAndroid Build Coastguard Worker // NetworkQualityEstimator
58*6777b538SAndroid Build Coastguard Worker nullptr /* network_quality_estimator */,
59*6777b538SAndroid Build Coastguard Worker handles::kInvalidNetworkHandle) {}
60*6777b538SAndroid Build Coastguard Worker
TCPClientSocket(std::unique_ptr<TCPSocket> unconnected_socket,const AddressList & addresses,std::unique_ptr<IPEndPoint> bound_address,NetworkQualityEstimator * network_quality_estimator)61*6777b538SAndroid Build Coastguard Worker TCPClientSocket::TCPClientSocket(
62*6777b538SAndroid Build Coastguard Worker std::unique_ptr<TCPSocket> unconnected_socket,
63*6777b538SAndroid Build Coastguard Worker const AddressList& addresses,
64*6777b538SAndroid Build Coastguard Worker std::unique_ptr<IPEndPoint> bound_address,
65*6777b538SAndroid Build Coastguard Worker NetworkQualityEstimator* network_quality_estimator)
66*6777b538SAndroid Build Coastguard Worker : TCPClientSocket(std::move(unconnected_socket),
67*6777b538SAndroid Build Coastguard Worker addresses,
68*6777b538SAndroid Build Coastguard Worker -1 /* current_address_index */,
69*6777b538SAndroid Build Coastguard Worker std::move(bound_address),
70*6777b538SAndroid Build Coastguard Worker network_quality_estimator,
71*6777b538SAndroid Build Coastguard Worker handles::kInvalidNetworkHandle) {}
72*6777b538SAndroid Build Coastguard Worker
~TCPClientSocket()73*6777b538SAndroid Build Coastguard Worker TCPClientSocket::~TCPClientSocket() {
74*6777b538SAndroid Build Coastguard Worker Disconnect();
75*6777b538SAndroid Build Coastguard Worker #if defined(TCP_CLIENT_SOCKET_OBSERVES_SUSPEND)
76*6777b538SAndroid Build Coastguard Worker base::PowerMonitor::RemovePowerSuspendObserver(this);
77*6777b538SAndroid Build Coastguard Worker #endif // defined(TCP_CLIENT_SOCKET_OBSERVES_SUSPEND)
78*6777b538SAndroid Build Coastguard Worker }
79*6777b538SAndroid Build Coastguard Worker
CreateFromBoundSocket(std::unique_ptr<TCPSocket> bound_socket,const AddressList & addresses,const IPEndPoint & bound_address,NetworkQualityEstimator * network_quality_estimator)80*6777b538SAndroid Build Coastguard Worker std::unique_ptr<TCPClientSocket> TCPClientSocket::CreateFromBoundSocket(
81*6777b538SAndroid Build Coastguard Worker std::unique_ptr<TCPSocket> bound_socket,
82*6777b538SAndroid Build Coastguard Worker const AddressList& addresses,
83*6777b538SAndroid Build Coastguard Worker const IPEndPoint& bound_address,
84*6777b538SAndroid Build Coastguard Worker NetworkQualityEstimator* network_quality_estimator) {
85*6777b538SAndroid Build Coastguard Worker return base::WrapUnique(new TCPClientSocket(
86*6777b538SAndroid Build Coastguard Worker std::move(bound_socket), addresses, -1 /* current_address_index */,
87*6777b538SAndroid Build Coastguard Worker std::make_unique<IPEndPoint>(bound_address), network_quality_estimator,
88*6777b538SAndroid Build Coastguard Worker handles::kInvalidNetworkHandle));
89*6777b538SAndroid Build Coastguard Worker }
90*6777b538SAndroid Build Coastguard Worker
Bind(const IPEndPoint & address)91*6777b538SAndroid Build Coastguard Worker int TCPClientSocket::Bind(const IPEndPoint& address) {
92*6777b538SAndroid Build Coastguard Worker if (current_address_index_ >= 0 || bind_address_) {
93*6777b538SAndroid Build Coastguard Worker // Cannot bind the socket if we are already connected or connecting.
94*6777b538SAndroid Build Coastguard Worker NOTREACHED();
95*6777b538SAndroid Build Coastguard Worker return ERR_UNEXPECTED;
96*6777b538SAndroid Build Coastguard Worker }
97*6777b538SAndroid Build Coastguard Worker
98*6777b538SAndroid Build Coastguard Worker int result = OK;
99*6777b538SAndroid Build Coastguard Worker if (!socket_->IsValid()) {
100*6777b538SAndroid Build Coastguard Worker result = OpenSocket(address.GetFamily());
101*6777b538SAndroid Build Coastguard Worker if (result != OK)
102*6777b538SAndroid Build Coastguard Worker return result;
103*6777b538SAndroid Build Coastguard Worker }
104*6777b538SAndroid Build Coastguard Worker
105*6777b538SAndroid Build Coastguard Worker result = socket_->Bind(address);
106*6777b538SAndroid Build Coastguard Worker if (result != OK)
107*6777b538SAndroid Build Coastguard Worker return result;
108*6777b538SAndroid Build Coastguard Worker
109*6777b538SAndroid Build Coastguard Worker bind_address_ = std::make_unique<IPEndPoint>(address);
110*6777b538SAndroid Build Coastguard Worker return OK;
111*6777b538SAndroid Build Coastguard Worker }
112*6777b538SAndroid Build Coastguard Worker
SetKeepAlive(bool enable,int delay)113*6777b538SAndroid Build Coastguard Worker bool TCPClientSocket::SetKeepAlive(bool enable, int delay) {
114*6777b538SAndroid Build Coastguard Worker return socket_->SetKeepAlive(enable, delay);
115*6777b538SAndroid Build Coastguard Worker }
116*6777b538SAndroid Build Coastguard Worker
SetNoDelay(bool no_delay)117*6777b538SAndroid Build Coastguard Worker bool TCPClientSocket::SetNoDelay(bool no_delay) {
118*6777b538SAndroid Build Coastguard Worker return socket_->SetNoDelay(no_delay);
119*6777b538SAndroid Build Coastguard Worker }
120*6777b538SAndroid Build Coastguard Worker
SetBeforeConnectCallback(const BeforeConnectCallback & before_connect_callback)121*6777b538SAndroid Build Coastguard Worker void TCPClientSocket::SetBeforeConnectCallback(
122*6777b538SAndroid Build Coastguard Worker const BeforeConnectCallback& before_connect_callback) {
123*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(CONNECT_STATE_NONE, next_connect_state_);
124*6777b538SAndroid Build Coastguard Worker before_connect_callback_ = before_connect_callback;
125*6777b538SAndroid Build Coastguard Worker }
126*6777b538SAndroid Build Coastguard Worker
Connect(CompletionOnceCallback callback)127*6777b538SAndroid Build Coastguard Worker int TCPClientSocket::Connect(CompletionOnceCallback callback) {
128*6777b538SAndroid Build Coastguard Worker DCHECK(!callback.is_null());
129*6777b538SAndroid Build Coastguard Worker
130*6777b538SAndroid Build Coastguard Worker // If connecting or already connected, then just return OK.
131*6777b538SAndroid Build Coastguard Worker if (socket_->IsValid() && current_address_index_ >= 0)
132*6777b538SAndroid Build Coastguard Worker return OK;
133*6777b538SAndroid Build Coastguard Worker
134*6777b538SAndroid Build Coastguard Worker DCHECK(!read_callback_);
135*6777b538SAndroid Build Coastguard Worker DCHECK(!write_callback_);
136*6777b538SAndroid Build Coastguard Worker
137*6777b538SAndroid Build Coastguard Worker if (was_disconnected_on_suspend_) {
138*6777b538SAndroid Build Coastguard Worker Disconnect();
139*6777b538SAndroid Build Coastguard Worker was_disconnected_on_suspend_ = false;
140*6777b538SAndroid Build Coastguard Worker }
141*6777b538SAndroid Build Coastguard Worker
142*6777b538SAndroid Build Coastguard Worker socket_->StartLoggingMultipleConnectAttempts(addresses_);
143*6777b538SAndroid Build Coastguard Worker
144*6777b538SAndroid Build Coastguard Worker // We will try to connect to each address in addresses_. Start with the
145*6777b538SAndroid Build Coastguard Worker // first one in the list.
146*6777b538SAndroid Build Coastguard Worker next_connect_state_ = CONNECT_STATE_CONNECT;
147*6777b538SAndroid Build Coastguard Worker current_address_index_ = 0;
148*6777b538SAndroid Build Coastguard Worker
149*6777b538SAndroid Build Coastguard Worker int rv = DoConnectLoop(OK);
150*6777b538SAndroid Build Coastguard Worker if (rv == ERR_IO_PENDING) {
151*6777b538SAndroid Build Coastguard Worker connect_callback_ = std::move(callback);
152*6777b538SAndroid Build Coastguard Worker } else {
153*6777b538SAndroid Build Coastguard Worker socket_->EndLoggingMultipleConnectAttempts(rv);
154*6777b538SAndroid Build Coastguard Worker }
155*6777b538SAndroid Build Coastguard Worker
156*6777b538SAndroid Build Coastguard Worker return rv;
157*6777b538SAndroid Build Coastguard Worker }
158*6777b538SAndroid Build Coastguard Worker
TCPClientSocket(std::unique_ptr<TCPSocket> socket,const AddressList & addresses,int current_address_index,std::unique_ptr<IPEndPoint> bind_address,NetworkQualityEstimator * network_quality_estimator,handles::NetworkHandle network)159*6777b538SAndroid Build Coastguard Worker TCPClientSocket::TCPClientSocket(
160*6777b538SAndroid Build Coastguard Worker std::unique_ptr<TCPSocket> socket,
161*6777b538SAndroid Build Coastguard Worker const AddressList& addresses,
162*6777b538SAndroid Build Coastguard Worker int current_address_index,
163*6777b538SAndroid Build Coastguard Worker std::unique_ptr<IPEndPoint> bind_address,
164*6777b538SAndroid Build Coastguard Worker NetworkQualityEstimator* network_quality_estimator,
165*6777b538SAndroid Build Coastguard Worker handles::NetworkHandle network)
166*6777b538SAndroid Build Coastguard Worker : socket_(std::move(socket)),
167*6777b538SAndroid Build Coastguard Worker bind_address_(std::move(bind_address)),
168*6777b538SAndroid Build Coastguard Worker addresses_(addresses),
169*6777b538SAndroid Build Coastguard Worker current_address_index_(current_address_index),
170*6777b538SAndroid Build Coastguard Worker network_quality_estimator_(network_quality_estimator),
171*6777b538SAndroid Build Coastguard Worker network_(network) {
172*6777b538SAndroid Build Coastguard Worker DCHECK(socket_);
173*6777b538SAndroid Build Coastguard Worker if (socket_->IsValid())
174*6777b538SAndroid Build Coastguard Worker socket_->SetDefaultOptionsForClient();
175*6777b538SAndroid Build Coastguard Worker #if defined(TCP_CLIENT_SOCKET_OBSERVES_SUSPEND)
176*6777b538SAndroid Build Coastguard Worker base::PowerMonitor::AddPowerSuspendObserver(this);
177*6777b538SAndroid Build Coastguard Worker #endif // defined(TCP_CLIENT_SOCKET_OBSERVES_SUSPEND)
178*6777b538SAndroid Build Coastguard Worker }
179*6777b538SAndroid Build Coastguard Worker
ReadCommon(IOBuffer * buf,int buf_len,CompletionOnceCallback callback,bool read_if_ready)180*6777b538SAndroid Build Coastguard Worker int TCPClientSocket::ReadCommon(IOBuffer* buf,
181*6777b538SAndroid Build Coastguard Worker int buf_len,
182*6777b538SAndroid Build Coastguard Worker CompletionOnceCallback callback,
183*6777b538SAndroid Build Coastguard Worker bool read_if_ready) {
184*6777b538SAndroid Build Coastguard Worker DCHECK(!callback.is_null());
185*6777b538SAndroid Build Coastguard Worker DCHECK(read_callback_.is_null());
186*6777b538SAndroid Build Coastguard Worker
187*6777b538SAndroid Build Coastguard Worker if (was_disconnected_on_suspend_)
188*6777b538SAndroid Build Coastguard Worker return ERR_NETWORK_IO_SUSPENDED;
189*6777b538SAndroid Build Coastguard Worker
190*6777b538SAndroid Build Coastguard Worker // |socket_| is owned by |this| and the callback won't be run once |socket_|
191*6777b538SAndroid Build Coastguard Worker // is gone/closed. Therefore, it is safe to use base::Unretained() here.
192*6777b538SAndroid Build Coastguard Worker CompletionOnceCallback complete_read_callback =
193*6777b538SAndroid Build Coastguard Worker base::BindOnce(&TCPClientSocket::DidCompleteRead, base::Unretained(this));
194*6777b538SAndroid Build Coastguard Worker int result =
195*6777b538SAndroid Build Coastguard Worker read_if_ready
196*6777b538SAndroid Build Coastguard Worker ? socket_->ReadIfReady(buf, buf_len,
197*6777b538SAndroid Build Coastguard Worker std::move(complete_read_callback))
198*6777b538SAndroid Build Coastguard Worker : socket_->Read(buf, buf_len, std::move(complete_read_callback));
199*6777b538SAndroid Build Coastguard Worker if (result == ERR_IO_PENDING) {
200*6777b538SAndroid Build Coastguard Worker read_callback_ = std::move(callback);
201*6777b538SAndroid Build Coastguard Worker } else if (result > 0) {
202*6777b538SAndroid Build Coastguard Worker was_ever_used_ = true;
203*6777b538SAndroid Build Coastguard Worker total_received_bytes_ += result;
204*6777b538SAndroid Build Coastguard Worker }
205*6777b538SAndroid Build Coastguard Worker
206*6777b538SAndroid Build Coastguard Worker return result;
207*6777b538SAndroid Build Coastguard Worker }
208*6777b538SAndroid Build Coastguard Worker
DoConnectLoop(int result)209*6777b538SAndroid Build Coastguard Worker int TCPClientSocket::DoConnectLoop(int result) {
210*6777b538SAndroid Build Coastguard Worker DCHECK_NE(next_connect_state_, CONNECT_STATE_NONE);
211*6777b538SAndroid Build Coastguard Worker
212*6777b538SAndroid Build Coastguard Worker int rv = result;
213*6777b538SAndroid Build Coastguard Worker do {
214*6777b538SAndroid Build Coastguard Worker ConnectState state = next_connect_state_;
215*6777b538SAndroid Build Coastguard Worker next_connect_state_ = CONNECT_STATE_NONE;
216*6777b538SAndroid Build Coastguard Worker switch (state) {
217*6777b538SAndroid Build Coastguard Worker case CONNECT_STATE_CONNECT:
218*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(OK, rv);
219*6777b538SAndroid Build Coastguard Worker rv = DoConnect();
220*6777b538SAndroid Build Coastguard Worker break;
221*6777b538SAndroid Build Coastguard Worker case CONNECT_STATE_CONNECT_COMPLETE:
222*6777b538SAndroid Build Coastguard Worker rv = DoConnectComplete(rv);
223*6777b538SAndroid Build Coastguard Worker break;
224*6777b538SAndroid Build Coastguard Worker default:
225*6777b538SAndroid Build Coastguard Worker NOTREACHED() << "bad state " << state;
226*6777b538SAndroid Build Coastguard Worker rv = ERR_UNEXPECTED;
227*6777b538SAndroid Build Coastguard Worker break;
228*6777b538SAndroid Build Coastguard Worker }
229*6777b538SAndroid Build Coastguard Worker } while (rv != ERR_IO_PENDING && next_connect_state_ != CONNECT_STATE_NONE);
230*6777b538SAndroid Build Coastguard Worker
231*6777b538SAndroid Build Coastguard Worker return rv;
232*6777b538SAndroid Build Coastguard Worker }
233*6777b538SAndroid Build Coastguard Worker
DoConnect()234*6777b538SAndroid Build Coastguard Worker int TCPClientSocket::DoConnect() {
235*6777b538SAndroid Build Coastguard Worker DCHECK_GE(current_address_index_, 0);
236*6777b538SAndroid Build Coastguard Worker DCHECK_LT(current_address_index_, static_cast<int>(addresses_.size()));
237*6777b538SAndroid Build Coastguard Worker
238*6777b538SAndroid Build Coastguard Worker const IPEndPoint& endpoint = addresses_[current_address_index_];
239*6777b538SAndroid Build Coastguard Worker
240*6777b538SAndroid Build Coastguard Worker if (previously_disconnected_) {
241*6777b538SAndroid Build Coastguard Worker was_ever_used_ = false;
242*6777b538SAndroid Build Coastguard Worker previously_disconnected_ = false;
243*6777b538SAndroid Build Coastguard Worker }
244*6777b538SAndroid Build Coastguard Worker
245*6777b538SAndroid Build Coastguard Worker next_connect_state_ = CONNECT_STATE_CONNECT_COMPLETE;
246*6777b538SAndroid Build Coastguard Worker
247*6777b538SAndroid Build Coastguard Worker if (!socket_->IsValid()) {
248*6777b538SAndroid Build Coastguard Worker int result = OpenSocket(endpoint.GetFamily());
249*6777b538SAndroid Build Coastguard Worker if (result != OK)
250*6777b538SAndroid Build Coastguard Worker return result;
251*6777b538SAndroid Build Coastguard Worker
252*6777b538SAndroid Build Coastguard Worker if (bind_address_) {
253*6777b538SAndroid Build Coastguard Worker result = socket_->Bind(*bind_address_);
254*6777b538SAndroid Build Coastguard Worker if (result != OK) {
255*6777b538SAndroid Build Coastguard Worker socket_->Close();
256*6777b538SAndroid Build Coastguard Worker return result;
257*6777b538SAndroid Build Coastguard Worker }
258*6777b538SAndroid Build Coastguard Worker }
259*6777b538SAndroid Build Coastguard Worker }
260*6777b538SAndroid Build Coastguard Worker
261*6777b538SAndroid Build Coastguard Worker if (before_connect_callback_) {
262*6777b538SAndroid Build Coastguard Worker int result = before_connect_callback_.Run();
263*6777b538SAndroid Build Coastguard Worker DCHECK_NE(ERR_IO_PENDING, result);
264*6777b538SAndroid Build Coastguard Worker if (result != net::OK)
265*6777b538SAndroid Build Coastguard Worker return result;
266*6777b538SAndroid Build Coastguard Worker }
267*6777b538SAndroid Build Coastguard Worker
268*6777b538SAndroid Build Coastguard Worker // Notify |socket_performance_watcher_| only if the |socket_| is reused to
269*6777b538SAndroid Build Coastguard Worker // connect to a different IP Address.
270*6777b538SAndroid Build Coastguard Worker if (socket_->socket_performance_watcher() && current_address_index_ != 0)
271*6777b538SAndroid Build Coastguard Worker socket_->socket_performance_watcher()->OnConnectionChanged();
272*6777b538SAndroid Build Coastguard Worker
273*6777b538SAndroid Build Coastguard Worker start_connect_attempt_ = base::TimeTicks::Now();
274*6777b538SAndroid Build Coastguard Worker
275*6777b538SAndroid Build Coastguard Worker // Start a timer to fail the connect attempt if it takes too long.
276*6777b538SAndroid Build Coastguard Worker base::TimeDelta attempt_timeout = GetConnectAttemptTimeout();
277*6777b538SAndroid Build Coastguard Worker if (!attempt_timeout.is_max()) {
278*6777b538SAndroid Build Coastguard Worker DCHECK(!connect_attempt_timer_.IsRunning());
279*6777b538SAndroid Build Coastguard Worker connect_attempt_timer_.Start(
280*6777b538SAndroid Build Coastguard Worker FROM_HERE, attempt_timeout,
281*6777b538SAndroid Build Coastguard Worker base::BindOnce(&TCPClientSocket::OnConnectAttemptTimeout,
282*6777b538SAndroid Build Coastguard Worker base::Unretained(this)));
283*6777b538SAndroid Build Coastguard Worker }
284*6777b538SAndroid Build Coastguard Worker
285*6777b538SAndroid Build Coastguard Worker return ConnectInternal(endpoint);
286*6777b538SAndroid Build Coastguard Worker }
287*6777b538SAndroid Build Coastguard Worker
DoConnectComplete(int result)288*6777b538SAndroid Build Coastguard Worker int TCPClientSocket::DoConnectComplete(int result) {
289*6777b538SAndroid Build Coastguard Worker if (start_connect_attempt_) {
290*6777b538SAndroid Build Coastguard Worker EmitConnectAttemptHistograms(result);
291*6777b538SAndroid Build Coastguard Worker start_connect_attempt_ = std::nullopt;
292*6777b538SAndroid Build Coastguard Worker connect_attempt_timer_.Stop();
293*6777b538SAndroid Build Coastguard Worker }
294*6777b538SAndroid Build Coastguard Worker
295*6777b538SAndroid Build Coastguard Worker if (result == OK)
296*6777b538SAndroid Build Coastguard Worker return OK; // Done!
297*6777b538SAndroid Build Coastguard Worker
298*6777b538SAndroid Build Coastguard Worker // Don't try the next address if entering suspend mode.
299*6777b538SAndroid Build Coastguard Worker if (result == ERR_NETWORK_IO_SUSPENDED)
300*6777b538SAndroid Build Coastguard Worker return result;
301*6777b538SAndroid Build Coastguard Worker
302*6777b538SAndroid Build Coastguard Worker // Close whatever partially connected socket we currently have.
303*6777b538SAndroid Build Coastguard Worker DoDisconnect();
304*6777b538SAndroid Build Coastguard Worker
305*6777b538SAndroid Build Coastguard Worker // Try to fall back to the next address in the list.
306*6777b538SAndroid Build Coastguard Worker if (current_address_index_ + 1 < static_cast<int>(addresses_.size())) {
307*6777b538SAndroid Build Coastguard Worker next_connect_state_ = CONNECT_STATE_CONNECT;
308*6777b538SAndroid Build Coastguard Worker ++current_address_index_;
309*6777b538SAndroid Build Coastguard Worker return OK;
310*6777b538SAndroid Build Coastguard Worker }
311*6777b538SAndroid Build Coastguard Worker
312*6777b538SAndroid Build Coastguard Worker // Otherwise there is nothing to fall back to, so give up.
313*6777b538SAndroid Build Coastguard Worker return result;
314*6777b538SAndroid Build Coastguard Worker }
315*6777b538SAndroid Build Coastguard Worker
OnConnectAttemptTimeout()316*6777b538SAndroid Build Coastguard Worker void TCPClientSocket::OnConnectAttemptTimeout() {
317*6777b538SAndroid Build Coastguard Worker DidCompleteConnect(ERR_TIMED_OUT);
318*6777b538SAndroid Build Coastguard Worker }
319*6777b538SAndroid Build Coastguard Worker
ConnectInternal(const IPEndPoint & endpoint)320*6777b538SAndroid Build Coastguard Worker int TCPClientSocket::ConnectInternal(const IPEndPoint& endpoint) {
321*6777b538SAndroid Build Coastguard Worker // |socket_| is owned by this class and the callback won't be run once
322*6777b538SAndroid Build Coastguard Worker // |socket_| is gone. Therefore, it is safe to use base::Unretained() here.
323*6777b538SAndroid Build Coastguard Worker return socket_->Connect(endpoint,
324*6777b538SAndroid Build Coastguard Worker base::BindOnce(&TCPClientSocket::DidCompleteConnect,
325*6777b538SAndroid Build Coastguard Worker base::Unretained(this)));
326*6777b538SAndroid Build Coastguard Worker }
327*6777b538SAndroid Build Coastguard Worker
Disconnect()328*6777b538SAndroid Build Coastguard Worker void TCPClientSocket::Disconnect() {
329*6777b538SAndroid Build Coastguard Worker DoDisconnect();
330*6777b538SAndroid Build Coastguard Worker current_address_index_ = -1;
331*6777b538SAndroid Build Coastguard Worker bind_address_.reset();
332*6777b538SAndroid Build Coastguard Worker
333*6777b538SAndroid Build Coastguard Worker // Cancel any pending callbacks. Not done in DoDisconnect() because that's
334*6777b538SAndroid Build Coastguard Worker // called on connection failure, when the connect callback will need to be
335*6777b538SAndroid Build Coastguard Worker // invoked.
336*6777b538SAndroid Build Coastguard Worker was_disconnected_on_suspend_ = false;
337*6777b538SAndroid Build Coastguard Worker connect_callback_.Reset();
338*6777b538SAndroid Build Coastguard Worker read_callback_.Reset();
339*6777b538SAndroid Build Coastguard Worker write_callback_.Reset();
340*6777b538SAndroid Build Coastguard Worker }
341*6777b538SAndroid Build Coastguard Worker
DoDisconnect()342*6777b538SAndroid Build Coastguard Worker void TCPClientSocket::DoDisconnect() {
343*6777b538SAndroid Build Coastguard Worker if (start_connect_attempt_) {
344*6777b538SAndroid Build Coastguard Worker EmitConnectAttemptHistograms(ERR_ABORTED);
345*6777b538SAndroid Build Coastguard Worker start_connect_attempt_ = std::nullopt;
346*6777b538SAndroid Build Coastguard Worker connect_attempt_timer_.Stop();
347*6777b538SAndroid Build Coastguard Worker }
348*6777b538SAndroid Build Coastguard Worker
349*6777b538SAndroid Build Coastguard Worker total_received_bytes_ = 0;
350*6777b538SAndroid Build Coastguard Worker
351*6777b538SAndroid Build Coastguard Worker // If connecting or already connected, record that the socket has been
352*6777b538SAndroid Build Coastguard Worker // disconnected.
353*6777b538SAndroid Build Coastguard Worker previously_disconnected_ = socket_->IsValid() && current_address_index_ >= 0;
354*6777b538SAndroid Build Coastguard Worker socket_->Close();
355*6777b538SAndroid Build Coastguard Worker
356*6777b538SAndroid Build Coastguard Worker // Invalidate weak pointers, so if in the middle of a callback in OnSuspend,
357*6777b538SAndroid Build Coastguard Worker // and something destroys this, no other callback is invoked.
358*6777b538SAndroid Build Coastguard Worker weak_ptr_factory_.InvalidateWeakPtrs();
359*6777b538SAndroid Build Coastguard Worker }
360*6777b538SAndroid Build Coastguard Worker
IsConnected() const361*6777b538SAndroid Build Coastguard Worker bool TCPClientSocket::IsConnected() const {
362*6777b538SAndroid Build Coastguard Worker return socket_->IsConnected();
363*6777b538SAndroid Build Coastguard Worker }
364*6777b538SAndroid Build Coastguard Worker
IsConnectedAndIdle() const365*6777b538SAndroid Build Coastguard Worker bool TCPClientSocket::IsConnectedAndIdle() const {
366*6777b538SAndroid Build Coastguard Worker return socket_->IsConnectedAndIdle();
367*6777b538SAndroid Build Coastguard Worker }
368*6777b538SAndroid Build Coastguard Worker
GetPeerAddress(IPEndPoint * address) const369*6777b538SAndroid Build Coastguard Worker int TCPClientSocket::GetPeerAddress(IPEndPoint* address) const {
370*6777b538SAndroid Build Coastguard Worker return socket_->GetPeerAddress(address);
371*6777b538SAndroid Build Coastguard Worker }
372*6777b538SAndroid Build Coastguard Worker
GetLocalAddress(IPEndPoint * address) const373*6777b538SAndroid Build Coastguard Worker int TCPClientSocket::GetLocalAddress(IPEndPoint* address) const {
374*6777b538SAndroid Build Coastguard Worker DCHECK(address);
375*6777b538SAndroid Build Coastguard Worker
376*6777b538SAndroid Build Coastguard Worker if (!socket_->IsValid()) {
377*6777b538SAndroid Build Coastguard Worker if (bind_address_) {
378*6777b538SAndroid Build Coastguard Worker *address = *bind_address_;
379*6777b538SAndroid Build Coastguard Worker return OK;
380*6777b538SAndroid Build Coastguard Worker }
381*6777b538SAndroid Build Coastguard Worker return ERR_SOCKET_NOT_CONNECTED;
382*6777b538SAndroid Build Coastguard Worker }
383*6777b538SAndroid Build Coastguard Worker
384*6777b538SAndroid Build Coastguard Worker return socket_->GetLocalAddress(address);
385*6777b538SAndroid Build Coastguard Worker }
386*6777b538SAndroid Build Coastguard Worker
NetLog() const387*6777b538SAndroid Build Coastguard Worker const NetLogWithSource& TCPClientSocket::NetLog() const {
388*6777b538SAndroid Build Coastguard Worker return socket_->net_log();
389*6777b538SAndroid Build Coastguard Worker }
390*6777b538SAndroid Build Coastguard Worker
WasEverUsed() const391*6777b538SAndroid Build Coastguard Worker bool TCPClientSocket::WasEverUsed() const {
392*6777b538SAndroid Build Coastguard Worker return was_ever_used_;
393*6777b538SAndroid Build Coastguard Worker }
394*6777b538SAndroid Build Coastguard Worker
GetNegotiatedProtocol() const395*6777b538SAndroid Build Coastguard Worker NextProto TCPClientSocket::GetNegotiatedProtocol() const {
396*6777b538SAndroid Build Coastguard Worker return kProtoUnknown;
397*6777b538SAndroid Build Coastguard Worker }
398*6777b538SAndroid Build Coastguard Worker
GetSSLInfo(SSLInfo * ssl_info)399*6777b538SAndroid Build Coastguard Worker bool TCPClientSocket::GetSSLInfo(SSLInfo* ssl_info) {
400*6777b538SAndroid Build Coastguard Worker return false;
401*6777b538SAndroid Build Coastguard Worker }
402*6777b538SAndroid Build Coastguard Worker
Read(IOBuffer * buf,int buf_len,CompletionOnceCallback callback)403*6777b538SAndroid Build Coastguard Worker int TCPClientSocket::Read(IOBuffer* buf,
404*6777b538SAndroid Build Coastguard Worker int buf_len,
405*6777b538SAndroid Build Coastguard Worker CompletionOnceCallback callback) {
406*6777b538SAndroid Build Coastguard Worker return ReadCommon(buf, buf_len, std::move(callback), /*read_if_ready=*/false);
407*6777b538SAndroid Build Coastguard Worker }
408*6777b538SAndroid Build Coastguard Worker
ReadIfReady(IOBuffer * buf,int buf_len,CompletionOnceCallback callback)409*6777b538SAndroid Build Coastguard Worker int TCPClientSocket::ReadIfReady(IOBuffer* buf,
410*6777b538SAndroid Build Coastguard Worker int buf_len,
411*6777b538SAndroid Build Coastguard Worker CompletionOnceCallback callback) {
412*6777b538SAndroid Build Coastguard Worker return ReadCommon(buf, buf_len, std::move(callback), /*read_if_ready=*/true);
413*6777b538SAndroid Build Coastguard Worker }
414*6777b538SAndroid Build Coastguard Worker
CancelReadIfReady()415*6777b538SAndroid Build Coastguard Worker int TCPClientSocket::CancelReadIfReady() {
416*6777b538SAndroid Build Coastguard Worker DCHECK(read_callback_);
417*6777b538SAndroid Build Coastguard Worker read_callback_.Reset();
418*6777b538SAndroid Build Coastguard Worker return socket_->CancelReadIfReady();
419*6777b538SAndroid Build Coastguard Worker }
420*6777b538SAndroid Build Coastguard Worker
Write(IOBuffer * buf,int buf_len,CompletionOnceCallback callback,const NetworkTrafficAnnotationTag & traffic_annotation)421*6777b538SAndroid Build Coastguard Worker int TCPClientSocket::Write(
422*6777b538SAndroid Build Coastguard Worker IOBuffer* buf,
423*6777b538SAndroid Build Coastguard Worker int buf_len,
424*6777b538SAndroid Build Coastguard Worker CompletionOnceCallback callback,
425*6777b538SAndroid Build Coastguard Worker const NetworkTrafficAnnotationTag& traffic_annotation) {
426*6777b538SAndroid Build Coastguard Worker DCHECK(!callback.is_null());
427*6777b538SAndroid Build Coastguard Worker DCHECK(write_callback_.is_null());
428*6777b538SAndroid Build Coastguard Worker
429*6777b538SAndroid Build Coastguard Worker if (was_disconnected_on_suspend_)
430*6777b538SAndroid Build Coastguard Worker return ERR_NETWORK_IO_SUSPENDED;
431*6777b538SAndroid Build Coastguard Worker
432*6777b538SAndroid Build Coastguard Worker // |socket_| is owned by this class and the callback won't be run once
433*6777b538SAndroid Build Coastguard Worker // |socket_| is gone. Therefore, it is safe to use base::Unretained() here.
434*6777b538SAndroid Build Coastguard Worker CompletionOnceCallback complete_write_callback = base::BindOnce(
435*6777b538SAndroid Build Coastguard Worker &TCPClientSocket::DidCompleteWrite, base::Unretained(this));
436*6777b538SAndroid Build Coastguard Worker int result = socket_->Write(buf, buf_len, std::move(complete_write_callback),
437*6777b538SAndroid Build Coastguard Worker traffic_annotation);
438*6777b538SAndroid Build Coastguard Worker if (result == ERR_IO_PENDING) {
439*6777b538SAndroid Build Coastguard Worker write_callback_ = std::move(callback);
440*6777b538SAndroid Build Coastguard Worker } else if (result > 0) {
441*6777b538SAndroid Build Coastguard Worker was_ever_used_ = true;
442*6777b538SAndroid Build Coastguard Worker }
443*6777b538SAndroid Build Coastguard Worker
444*6777b538SAndroid Build Coastguard Worker return result;
445*6777b538SAndroid Build Coastguard Worker }
446*6777b538SAndroid Build Coastguard Worker
SetReceiveBufferSize(int32_t size)447*6777b538SAndroid Build Coastguard Worker int TCPClientSocket::SetReceiveBufferSize(int32_t size) {
448*6777b538SAndroid Build Coastguard Worker return socket_->SetReceiveBufferSize(size);
449*6777b538SAndroid Build Coastguard Worker }
450*6777b538SAndroid Build Coastguard Worker
SetSendBufferSize(int32_t size)451*6777b538SAndroid Build Coastguard Worker int TCPClientSocket::SetSendBufferSize(int32_t size) {
452*6777b538SAndroid Build Coastguard Worker return socket_->SetSendBufferSize(size);
453*6777b538SAndroid Build Coastguard Worker }
454*6777b538SAndroid Build Coastguard Worker
SocketDescriptorForTesting() const455*6777b538SAndroid Build Coastguard Worker SocketDescriptor TCPClientSocket::SocketDescriptorForTesting() const {
456*6777b538SAndroid Build Coastguard Worker return socket_->SocketDescriptorForTesting();
457*6777b538SAndroid Build Coastguard Worker }
458*6777b538SAndroid Build Coastguard Worker
GetTotalReceivedBytes() const459*6777b538SAndroid Build Coastguard Worker int64_t TCPClientSocket::GetTotalReceivedBytes() const {
460*6777b538SAndroid Build Coastguard Worker return total_received_bytes_;
461*6777b538SAndroid Build Coastguard Worker }
462*6777b538SAndroid Build Coastguard Worker
ApplySocketTag(const SocketTag & tag)463*6777b538SAndroid Build Coastguard Worker void TCPClientSocket::ApplySocketTag(const SocketTag& tag) {
464*6777b538SAndroid Build Coastguard Worker socket_->ApplySocketTag(tag);
465*6777b538SAndroid Build Coastguard Worker }
466*6777b538SAndroid Build Coastguard Worker
OnSuspend()467*6777b538SAndroid Build Coastguard Worker void TCPClientSocket::OnSuspend() {
468*6777b538SAndroid Build Coastguard Worker #if defined(TCP_CLIENT_SOCKET_OBSERVES_SUSPEND)
469*6777b538SAndroid Build Coastguard Worker // If the socket is connected, or connecting, act as if current and future
470*6777b538SAndroid Build Coastguard Worker // operations on the socket fail with ERR_NETWORK_IO_SUSPENDED, until the
471*6777b538SAndroid Build Coastguard Worker // socket is reconnected.
472*6777b538SAndroid Build Coastguard Worker
473*6777b538SAndroid Build Coastguard Worker if (next_connect_state_ != CONNECT_STATE_NONE) {
474*6777b538SAndroid Build Coastguard Worker socket_->Close();
475*6777b538SAndroid Build Coastguard Worker DidCompleteConnect(ERR_NETWORK_IO_SUSPENDED);
476*6777b538SAndroid Build Coastguard Worker return;
477*6777b538SAndroid Build Coastguard Worker }
478*6777b538SAndroid Build Coastguard Worker
479*6777b538SAndroid Build Coastguard Worker // Nothing to do. Use IsValid() rather than IsConnected() because it results
480*6777b538SAndroid Build Coastguard Worker // in more testable code, as when calling OnSuspend mode on two sockets
481*6777b538SAndroid Build Coastguard Worker // connected to each other will otherwise cause two sockets to behave
482*6777b538SAndroid Build Coastguard Worker // differently from each other.
483*6777b538SAndroid Build Coastguard Worker if (!socket_->IsValid())
484*6777b538SAndroid Build Coastguard Worker return;
485*6777b538SAndroid Build Coastguard Worker
486*6777b538SAndroid Build Coastguard Worker // Use Close() rather than Disconnect() / DoDisconnect() to avoid mutating
487*6777b538SAndroid Build Coastguard Worker // state, which more closely matches normal read/write error behavior.
488*6777b538SAndroid Build Coastguard Worker socket_->Close();
489*6777b538SAndroid Build Coastguard Worker
490*6777b538SAndroid Build Coastguard Worker was_disconnected_on_suspend_ = true;
491*6777b538SAndroid Build Coastguard Worker
492*6777b538SAndroid Build Coastguard Worker // Grab a weak pointer just in case calling read callback results in |this|
493*6777b538SAndroid Build Coastguard Worker // being destroyed, or disconnected. In either case, should not run the write
494*6777b538SAndroid Build Coastguard Worker // callback.
495*6777b538SAndroid Build Coastguard Worker base::WeakPtr<TCPClientSocket> weak_this = weak_ptr_factory_.GetWeakPtr();
496*6777b538SAndroid Build Coastguard Worker
497*6777b538SAndroid Build Coastguard Worker // Have to grab the write callback now, as it's theoretically possible for the
498*6777b538SAndroid Build Coastguard Worker // read callback to reconnects the socket, that reconnection to complete
499*6777b538SAndroid Build Coastguard Worker // synchronously, and then for it to start a new write. That also means this
500*6777b538SAndroid Build Coastguard Worker // code can't use DidCompleteWrite().
501*6777b538SAndroid Build Coastguard Worker CompletionOnceCallback write_callback = std::move(write_callback_);
502*6777b538SAndroid Build Coastguard Worker if (read_callback_)
503*6777b538SAndroid Build Coastguard Worker DidCompleteRead(ERR_NETWORK_IO_SUSPENDED);
504*6777b538SAndroid Build Coastguard Worker if (weak_this && write_callback)
505*6777b538SAndroid Build Coastguard Worker std::move(write_callback).Run(ERR_NETWORK_IO_SUSPENDED);
506*6777b538SAndroid Build Coastguard Worker #endif // defined(TCP_CLIENT_SOCKET_OBSERVES_SUSPEND)
507*6777b538SAndroid Build Coastguard Worker }
508*6777b538SAndroid Build Coastguard Worker
DidCompleteConnect(int result)509*6777b538SAndroid Build Coastguard Worker void TCPClientSocket::DidCompleteConnect(int result) {
510*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(next_connect_state_, CONNECT_STATE_CONNECT_COMPLETE);
511*6777b538SAndroid Build Coastguard Worker DCHECK_NE(result, ERR_IO_PENDING);
512*6777b538SAndroid Build Coastguard Worker DCHECK(!connect_callback_.is_null());
513*6777b538SAndroid Build Coastguard Worker
514*6777b538SAndroid Build Coastguard Worker result = DoConnectLoop(result);
515*6777b538SAndroid Build Coastguard Worker if (result != ERR_IO_PENDING) {
516*6777b538SAndroid Build Coastguard Worker socket_->EndLoggingMultipleConnectAttempts(result);
517*6777b538SAndroid Build Coastguard Worker std::move(connect_callback_).Run(result);
518*6777b538SAndroid Build Coastguard Worker }
519*6777b538SAndroid Build Coastguard Worker }
520*6777b538SAndroid Build Coastguard Worker
DidCompleteRead(int result)521*6777b538SAndroid Build Coastguard Worker void TCPClientSocket::DidCompleteRead(int result) {
522*6777b538SAndroid Build Coastguard Worker DCHECK(!read_callback_.is_null());
523*6777b538SAndroid Build Coastguard Worker
524*6777b538SAndroid Build Coastguard Worker if (result > 0)
525*6777b538SAndroid Build Coastguard Worker total_received_bytes_ += result;
526*6777b538SAndroid Build Coastguard Worker DidCompleteReadWrite(std::move(read_callback_), result);
527*6777b538SAndroid Build Coastguard Worker }
528*6777b538SAndroid Build Coastguard Worker
DidCompleteWrite(int result)529*6777b538SAndroid Build Coastguard Worker void TCPClientSocket::DidCompleteWrite(int result) {
530*6777b538SAndroid Build Coastguard Worker DCHECK(!write_callback_.is_null());
531*6777b538SAndroid Build Coastguard Worker
532*6777b538SAndroid Build Coastguard Worker DidCompleteReadWrite(std::move(write_callback_), result);
533*6777b538SAndroid Build Coastguard Worker }
534*6777b538SAndroid Build Coastguard Worker
DidCompleteReadWrite(CompletionOnceCallback callback,int result)535*6777b538SAndroid Build Coastguard Worker void TCPClientSocket::DidCompleteReadWrite(CompletionOnceCallback callback,
536*6777b538SAndroid Build Coastguard Worker int result) {
537*6777b538SAndroid Build Coastguard Worker if (result > 0)
538*6777b538SAndroid Build Coastguard Worker was_ever_used_ = true;
539*6777b538SAndroid Build Coastguard Worker std::move(callback).Run(result);
540*6777b538SAndroid Build Coastguard Worker }
541*6777b538SAndroid Build Coastguard Worker
OpenSocket(AddressFamily family)542*6777b538SAndroid Build Coastguard Worker int TCPClientSocket::OpenSocket(AddressFamily family) {
543*6777b538SAndroid Build Coastguard Worker DCHECK(!socket_->IsValid());
544*6777b538SAndroid Build Coastguard Worker
545*6777b538SAndroid Build Coastguard Worker int result = socket_->Open(family);
546*6777b538SAndroid Build Coastguard Worker if (result != OK)
547*6777b538SAndroid Build Coastguard Worker return result;
548*6777b538SAndroid Build Coastguard Worker
549*6777b538SAndroid Build Coastguard Worker if (network_ != handles::kInvalidNetworkHandle) {
550*6777b538SAndroid Build Coastguard Worker result = socket_->BindToNetwork(network_);
551*6777b538SAndroid Build Coastguard Worker if (result != OK) {
552*6777b538SAndroid Build Coastguard Worker socket_->Close();
553*6777b538SAndroid Build Coastguard Worker return result;
554*6777b538SAndroid Build Coastguard Worker }
555*6777b538SAndroid Build Coastguard Worker }
556*6777b538SAndroid Build Coastguard Worker
557*6777b538SAndroid Build Coastguard Worker socket_->SetDefaultOptionsForClient();
558*6777b538SAndroid Build Coastguard Worker
559*6777b538SAndroid Build Coastguard Worker return OK;
560*6777b538SAndroid Build Coastguard Worker }
561*6777b538SAndroid Build Coastguard Worker
EmitConnectAttemptHistograms(int result)562*6777b538SAndroid Build Coastguard Worker void TCPClientSocket::EmitConnectAttemptHistograms(int result) {
563*6777b538SAndroid Build Coastguard Worker // This should only be called in response to completing a connect attempt.
564*6777b538SAndroid Build Coastguard Worker DCHECK(start_connect_attempt_);
565*6777b538SAndroid Build Coastguard Worker
566*6777b538SAndroid Build Coastguard Worker base::TimeDelta duration =
567*6777b538SAndroid Build Coastguard Worker base::TimeTicks::Now() - start_connect_attempt_.value();
568*6777b538SAndroid Build Coastguard Worker
569*6777b538SAndroid Build Coastguard Worker // Histogram the total time the connect attempt took, grouped by success and
570*6777b538SAndroid Build Coastguard Worker // failure. Note that failures also include cases when the connect attempt
571*6777b538SAndroid Build Coastguard Worker // was cancelled by the client before the handshake completed.
572*6777b538SAndroid Build Coastguard Worker if (result == OK) {
573*6777b538SAndroid Build Coastguard Worker UMA_HISTOGRAM_MEDIUM_TIMES("Net.TcpConnectAttempt.Latency.Success",
574*6777b538SAndroid Build Coastguard Worker duration);
575*6777b538SAndroid Build Coastguard Worker } else {
576*6777b538SAndroid Build Coastguard Worker UMA_HISTOGRAM_MEDIUM_TIMES("Net.TcpConnectAttempt.Latency.Error", duration);
577*6777b538SAndroid Build Coastguard Worker }
578*6777b538SAndroid Build Coastguard Worker }
579*6777b538SAndroid Build Coastguard Worker
GetConnectAttemptTimeout()580*6777b538SAndroid Build Coastguard Worker base::TimeDelta TCPClientSocket::GetConnectAttemptTimeout() {
581*6777b538SAndroid Build Coastguard Worker if (!base::FeatureList::IsEnabled(features::kTimeoutTcpConnectAttempt))
582*6777b538SAndroid Build Coastguard Worker return base::TimeDelta::Max();
583*6777b538SAndroid Build Coastguard Worker
584*6777b538SAndroid Build Coastguard Worker std::optional<base::TimeDelta> transport_rtt = std::nullopt;
585*6777b538SAndroid Build Coastguard Worker if (network_quality_estimator_)
586*6777b538SAndroid Build Coastguard Worker transport_rtt = network_quality_estimator_->GetTransportRTT();
587*6777b538SAndroid Build Coastguard Worker
588*6777b538SAndroid Build Coastguard Worker base::TimeDelta min_timeout = features::kTimeoutTcpConnectAttemptMin.Get();
589*6777b538SAndroid Build Coastguard Worker base::TimeDelta max_timeout = features::kTimeoutTcpConnectAttemptMax.Get();
590*6777b538SAndroid Build Coastguard Worker
591*6777b538SAndroid Build Coastguard Worker if (!transport_rtt)
592*6777b538SAndroid Build Coastguard Worker return max_timeout;
593*6777b538SAndroid Build Coastguard Worker
594*6777b538SAndroid Build Coastguard Worker base::TimeDelta adaptive_timeout =
595*6777b538SAndroid Build Coastguard Worker transport_rtt.value() *
596*6777b538SAndroid Build Coastguard Worker features::kTimeoutTcpConnectAttemptRTTMultiplier.Get();
597*6777b538SAndroid Build Coastguard Worker
598*6777b538SAndroid Build Coastguard Worker if (adaptive_timeout <= min_timeout)
599*6777b538SAndroid Build Coastguard Worker return min_timeout;
600*6777b538SAndroid Build Coastguard Worker
601*6777b538SAndroid Build Coastguard Worker if (adaptive_timeout >= max_timeout)
602*6777b538SAndroid Build Coastguard Worker return max_timeout;
603*6777b538SAndroid Build Coastguard Worker
604*6777b538SAndroid Build Coastguard Worker return adaptive_timeout;
605*6777b538SAndroid Build Coastguard Worker }
606*6777b538SAndroid Build Coastguard Worker
607*6777b538SAndroid Build Coastguard Worker } // namespace net
608