xref: /aosp_15_r20/external/cronet/net/socket/tcp_client_socket.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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