xref: /aosp_15_r20/external/cronet/net/socket/client_socket_handle.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 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/client_socket_handle.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <utility>
8*6777b538SAndroid Build Coastguard Worker 
9*6777b538SAndroid Build Coastguard Worker #include "base/check_op.h"
10*6777b538SAndroid Build Coastguard Worker #include "base/compiler_specific.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/notreached.h"
14*6777b538SAndroid Build Coastguard Worker #include "net/base/net_errors.h"
15*6777b538SAndroid Build Coastguard Worker #include "net/base/trace_constants.h"
16*6777b538SAndroid Build Coastguard Worker #include "net/base/tracing.h"
17*6777b538SAndroid Build Coastguard Worker #include "net/log/net_log_event_type.h"
18*6777b538SAndroid Build Coastguard Worker #include "net/socket/client_socket_pool.h"
19*6777b538SAndroid Build Coastguard Worker #include "net/socket/connect_job.h"
20*6777b538SAndroid Build Coastguard Worker 
21*6777b538SAndroid Build Coastguard Worker namespace net {
22*6777b538SAndroid Build Coastguard Worker 
ClientSocketHandle()23*6777b538SAndroid Build Coastguard Worker ClientSocketHandle::ClientSocketHandle()
24*6777b538SAndroid Build Coastguard Worker     : resolve_error_info_(ResolveErrorInfo(OK)) {}
25*6777b538SAndroid Build Coastguard Worker 
~ClientSocketHandle()26*6777b538SAndroid Build Coastguard Worker ClientSocketHandle::~ClientSocketHandle() {
27*6777b538SAndroid Build Coastguard Worker   weak_factory_.InvalidateWeakPtrs();
28*6777b538SAndroid Build Coastguard Worker   Reset();
29*6777b538SAndroid Build Coastguard Worker }
30*6777b538SAndroid Build Coastguard Worker 
Init(const ClientSocketPool::GroupId & group_id,scoped_refptr<ClientSocketPool::SocketParams> socket_params,const std::optional<NetworkTrafficAnnotationTag> & proxy_annotation_tag,RequestPriority priority,const SocketTag & socket_tag,ClientSocketPool::RespectLimits respect_limits,CompletionOnceCallback callback,const ClientSocketPool::ProxyAuthCallback & proxy_auth_callback,ClientSocketPool * pool,const NetLogWithSource & net_log)31*6777b538SAndroid Build Coastguard Worker int ClientSocketHandle::Init(
32*6777b538SAndroid Build Coastguard Worker     const ClientSocketPool::GroupId& group_id,
33*6777b538SAndroid Build Coastguard Worker     scoped_refptr<ClientSocketPool::SocketParams> socket_params,
34*6777b538SAndroid Build Coastguard Worker     const std::optional<NetworkTrafficAnnotationTag>& proxy_annotation_tag,
35*6777b538SAndroid Build Coastguard Worker     RequestPriority priority,
36*6777b538SAndroid Build Coastguard Worker     const SocketTag& socket_tag,
37*6777b538SAndroid Build Coastguard Worker     ClientSocketPool::RespectLimits respect_limits,
38*6777b538SAndroid Build Coastguard Worker     CompletionOnceCallback callback,
39*6777b538SAndroid Build Coastguard Worker     const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback,
40*6777b538SAndroid Build Coastguard Worker     ClientSocketPool* pool,
41*6777b538SAndroid Build Coastguard Worker     const NetLogWithSource& net_log) {
42*6777b538SAndroid Build Coastguard Worker   requesting_source_ = net_log.source();
43*6777b538SAndroid Build Coastguard Worker 
44*6777b538SAndroid Build Coastguard Worker   CHECK(group_id.destination().IsValid());
45*6777b538SAndroid Build Coastguard Worker   ResetInternal(true /* cancel */, false /* cancel_connect_job */);
46*6777b538SAndroid Build Coastguard Worker   ResetErrorState();
47*6777b538SAndroid Build Coastguard Worker   pool_ = pool;
48*6777b538SAndroid Build Coastguard Worker   group_id_ = group_id;
49*6777b538SAndroid Build Coastguard Worker   CompletionOnceCallback io_complete_callback =
50*6777b538SAndroid Build Coastguard Worker       base::BindOnce(&ClientSocketHandle::OnIOComplete, base::Unretained(this));
51*6777b538SAndroid Build Coastguard Worker   int rv = pool_->RequestSocket(
52*6777b538SAndroid Build Coastguard Worker       group_id, std::move(socket_params), proxy_annotation_tag, priority,
53*6777b538SAndroid Build Coastguard Worker       socket_tag, respect_limits, this, std::move(io_complete_callback),
54*6777b538SAndroid Build Coastguard Worker       proxy_auth_callback, net_log);
55*6777b538SAndroid Build Coastguard Worker   if (rv == ERR_IO_PENDING) {
56*6777b538SAndroid Build Coastguard Worker     callback_ = std::move(callback);
57*6777b538SAndroid Build Coastguard Worker   } else {
58*6777b538SAndroid Build Coastguard Worker     HandleInitCompletion(rv);
59*6777b538SAndroid Build Coastguard Worker   }
60*6777b538SAndroid Build Coastguard Worker   return rv;
61*6777b538SAndroid Build Coastguard Worker }
62*6777b538SAndroid Build Coastguard Worker 
SetPriority(RequestPriority priority)63*6777b538SAndroid Build Coastguard Worker void ClientSocketHandle::SetPriority(RequestPriority priority) {
64*6777b538SAndroid Build Coastguard Worker   if (socket_) {
65*6777b538SAndroid Build Coastguard Worker     // The priority of the handle is no longer relevant to the socket pool;
66*6777b538SAndroid Build Coastguard Worker     // just return.
67*6777b538SAndroid Build Coastguard Worker     return;
68*6777b538SAndroid Build Coastguard Worker   }
69*6777b538SAndroid Build Coastguard Worker 
70*6777b538SAndroid Build Coastguard Worker   if (pool_)
71*6777b538SAndroid Build Coastguard Worker     pool_->SetPriority(group_id_, this, priority);
72*6777b538SAndroid Build Coastguard Worker }
73*6777b538SAndroid Build Coastguard Worker 
Reset()74*6777b538SAndroid Build Coastguard Worker void ClientSocketHandle::Reset() {
75*6777b538SAndroid Build Coastguard Worker   ResetInternal(true /* cancel */, false /* cancel_connect_job */);
76*6777b538SAndroid Build Coastguard Worker   ResetErrorState();
77*6777b538SAndroid Build Coastguard Worker }
78*6777b538SAndroid Build Coastguard Worker 
ResetAndCloseSocket()79*6777b538SAndroid Build Coastguard Worker void ClientSocketHandle::ResetAndCloseSocket() {
80*6777b538SAndroid Build Coastguard Worker   if (is_initialized() && socket_)
81*6777b538SAndroid Build Coastguard Worker     socket_->Disconnect();
82*6777b538SAndroid Build Coastguard Worker   ResetInternal(true /* cancel */, true /* cancel_connect_job */);
83*6777b538SAndroid Build Coastguard Worker   ResetErrorState();
84*6777b538SAndroid Build Coastguard Worker }
85*6777b538SAndroid Build Coastguard Worker 
GetLoadState() const86*6777b538SAndroid Build Coastguard Worker LoadState ClientSocketHandle::GetLoadState() const {
87*6777b538SAndroid Build Coastguard Worker   CHECK(!is_initialized());
88*6777b538SAndroid Build Coastguard Worker   CHECK(group_id_.destination().IsValid());
89*6777b538SAndroid Build Coastguard Worker   // Because of http://crbug.com/37810  we may not have a pool, but have
90*6777b538SAndroid Build Coastguard Worker   // just a raw socket.
91*6777b538SAndroid Build Coastguard Worker   if (!pool_)
92*6777b538SAndroid Build Coastguard Worker     return LOAD_STATE_IDLE;
93*6777b538SAndroid Build Coastguard Worker   return pool_->GetLoadState(group_id_, this);
94*6777b538SAndroid Build Coastguard Worker }
95*6777b538SAndroid Build Coastguard Worker 
IsPoolStalled() const96*6777b538SAndroid Build Coastguard Worker bool ClientSocketHandle::IsPoolStalled() const {
97*6777b538SAndroid Build Coastguard Worker   if (!pool_)
98*6777b538SAndroid Build Coastguard Worker     return false;
99*6777b538SAndroid Build Coastguard Worker   return pool_->IsStalled();
100*6777b538SAndroid Build Coastguard Worker }
101*6777b538SAndroid Build Coastguard Worker 
AddHigherLayeredPool(HigherLayeredPool * higher_pool)102*6777b538SAndroid Build Coastguard Worker void ClientSocketHandle::AddHigherLayeredPool(HigherLayeredPool* higher_pool) {
103*6777b538SAndroid Build Coastguard Worker   CHECK(higher_pool);
104*6777b538SAndroid Build Coastguard Worker   CHECK(!higher_pool_);
105*6777b538SAndroid Build Coastguard Worker   // TODO(mmenke):  |pool_| should only be NULL in tests.  Maybe stop doing that
106*6777b538SAndroid Build Coastguard Worker   // so this be be made into a DCHECK, and the same can be done in
107*6777b538SAndroid Build Coastguard Worker   // RemoveHigherLayeredPool?
108*6777b538SAndroid Build Coastguard Worker   if (pool_) {
109*6777b538SAndroid Build Coastguard Worker     pool_->AddHigherLayeredPool(higher_pool);
110*6777b538SAndroid Build Coastguard Worker     higher_pool_ = higher_pool;
111*6777b538SAndroid Build Coastguard Worker   }
112*6777b538SAndroid Build Coastguard Worker }
113*6777b538SAndroid Build Coastguard Worker 
RemoveHigherLayeredPool(HigherLayeredPool * higher_pool)114*6777b538SAndroid Build Coastguard Worker void ClientSocketHandle::RemoveHigherLayeredPool(
115*6777b538SAndroid Build Coastguard Worker     HigherLayeredPool* higher_pool) {
116*6777b538SAndroid Build Coastguard Worker   CHECK(higher_pool_);
117*6777b538SAndroid Build Coastguard Worker   CHECK_EQ(higher_pool_, higher_pool);
118*6777b538SAndroid Build Coastguard Worker   if (pool_) {
119*6777b538SAndroid Build Coastguard Worker     pool_->RemoveHigherLayeredPool(higher_pool);
120*6777b538SAndroid Build Coastguard Worker     higher_pool_ = nullptr;
121*6777b538SAndroid Build Coastguard Worker   }
122*6777b538SAndroid Build Coastguard Worker }
123*6777b538SAndroid Build Coastguard Worker 
CloseIdleSocketsInGroup(const char * net_log_reason_utf8)124*6777b538SAndroid Build Coastguard Worker void ClientSocketHandle::CloseIdleSocketsInGroup(
125*6777b538SAndroid Build Coastguard Worker     const char* net_log_reason_utf8) {
126*6777b538SAndroid Build Coastguard Worker   if (pool_)
127*6777b538SAndroid Build Coastguard Worker     pool_->CloseIdleSocketsInGroup(group_id_, net_log_reason_utf8);
128*6777b538SAndroid Build Coastguard Worker }
129*6777b538SAndroid Build Coastguard Worker 
GetLoadTimingInfo(bool is_reused,LoadTimingInfo * load_timing_info) const130*6777b538SAndroid Build Coastguard Worker bool ClientSocketHandle::GetLoadTimingInfo(
131*6777b538SAndroid Build Coastguard Worker     bool is_reused,
132*6777b538SAndroid Build Coastguard Worker     LoadTimingInfo* load_timing_info) const {
133*6777b538SAndroid Build Coastguard Worker   if (socket_) {
134*6777b538SAndroid Build Coastguard Worker     load_timing_info->socket_log_id = socket_->NetLog().source().id;
135*6777b538SAndroid Build Coastguard Worker   } else {
136*6777b538SAndroid Build Coastguard Worker     // Only return load timing information when there's a socket.
137*6777b538SAndroid Build Coastguard Worker     return false;
138*6777b538SAndroid Build Coastguard Worker   }
139*6777b538SAndroid Build Coastguard Worker 
140*6777b538SAndroid Build Coastguard Worker   load_timing_info->socket_reused = is_reused;
141*6777b538SAndroid Build Coastguard Worker 
142*6777b538SAndroid Build Coastguard Worker   // No times if the socket is reused.
143*6777b538SAndroid Build Coastguard Worker   if (is_reused)
144*6777b538SAndroid Build Coastguard Worker     return true;
145*6777b538SAndroid Build Coastguard Worker 
146*6777b538SAndroid Build Coastguard Worker   load_timing_info->connect_timing = connect_timing_;
147*6777b538SAndroid Build Coastguard Worker   return true;
148*6777b538SAndroid Build Coastguard Worker }
149*6777b538SAndroid Build Coastguard Worker 
SetSocket(std::unique_ptr<StreamSocket> s)150*6777b538SAndroid Build Coastguard Worker void ClientSocketHandle::SetSocket(std::unique_ptr<StreamSocket> s) {
151*6777b538SAndroid Build Coastguard Worker   socket_ = std::move(s);
152*6777b538SAndroid Build Coastguard Worker }
153*6777b538SAndroid Build Coastguard Worker 
SetAdditionalErrorState(ConnectJob * connect_job)154*6777b538SAndroid Build Coastguard Worker void ClientSocketHandle::SetAdditionalErrorState(ConnectJob* connect_job) {
155*6777b538SAndroid Build Coastguard Worker   connection_attempts_ = connect_job->GetConnectionAttempts();
156*6777b538SAndroid Build Coastguard Worker 
157*6777b538SAndroid Build Coastguard Worker   resolve_error_info_ = connect_job->GetResolveErrorInfo();
158*6777b538SAndroid Build Coastguard Worker   is_ssl_error_ = connect_job->IsSSLError();
159*6777b538SAndroid Build Coastguard Worker   ssl_cert_request_info_ = connect_job->GetCertRequestInfo();
160*6777b538SAndroid Build Coastguard Worker }
161*6777b538SAndroid Build Coastguard Worker 
PassSocket()162*6777b538SAndroid Build Coastguard Worker std::unique_ptr<StreamSocket> ClientSocketHandle::PassSocket() {
163*6777b538SAndroid Build Coastguard Worker   return std::move(socket_);
164*6777b538SAndroid Build Coastguard Worker }
165*6777b538SAndroid Build Coastguard Worker 
OnIOComplete(int result)166*6777b538SAndroid Build Coastguard Worker void ClientSocketHandle::OnIOComplete(int result) {
167*6777b538SAndroid Build Coastguard Worker   TRACE_EVENT0(NetTracingCategory(), "ClientSocketHandle::OnIOComplete");
168*6777b538SAndroid Build Coastguard Worker   CompletionOnceCallback callback = std::move(callback_);
169*6777b538SAndroid Build Coastguard Worker   callback_.Reset();
170*6777b538SAndroid Build Coastguard Worker   HandleInitCompletion(result);
171*6777b538SAndroid Build Coastguard Worker   std::move(callback).Run(result);
172*6777b538SAndroid Build Coastguard Worker }
173*6777b538SAndroid Build Coastguard Worker 
HandleInitCompletion(int result)174*6777b538SAndroid Build Coastguard Worker void ClientSocketHandle::HandleInitCompletion(int result) {
175*6777b538SAndroid Build Coastguard Worker   CHECK_NE(ERR_IO_PENDING, result);
176*6777b538SAndroid Build Coastguard Worker   if (result != OK) {
177*6777b538SAndroid Build Coastguard Worker     if (!socket_.get())
178*6777b538SAndroid Build Coastguard Worker       ResetInternal(false /* cancel */,
179*6777b538SAndroid Build Coastguard Worker                     false /* cancel_connect_job */);  // Nothing to cancel since
180*6777b538SAndroid Build Coastguard Worker                                                       // the request failed.
181*6777b538SAndroid Build Coastguard Worker     else
182*6777b538SAndroid Build Coastguard Worker       is_initialized_ = true;
183*6777b538SAndroid Build Coastguard Worker     return;
184*6777b538SAndroid Build Coastguard Worker   }
185*6777b538SAndroid Build Coastguard Worker   is_initialized_ = true;
186*6777b538SAndroid Build Coastguard Worker   CHECK_NE(-1, group_generation_)
187*6777b538SAndroid Build Coastguard Worker       << "Pool should have set |group_generation_| to a valid value.";
188*6777b538SAndroid Build Coastguard Worker 
189*6777b538SAndroid Build Coastguard Worker   // Broadcast that the socket has been acquired.
190*6777b538SAndroid Build Coastguard Worker   // TODO(eroman): This logging is not complete, in particular set_socket() and
191*6777b538SAndroid Build Coastguard Worker   // release() socket. It ends up working though, since those methods are being
192*6777b538SAndroid Build Coastguard Worker   // used to layer sockets (and the destination sources are the same).
193*6777b538SAndroid Build Coastguard Worker   DCHECK(socket_.get());
194*6777b538SAndroid Build Coastguard Worker   socket_->NetLog().BeginEventReferencingSource(NetLogEventType::SOCKET_IN_USE,
195*6777b538SAndroid Build Coastguard Worker                                                 requesting_source_);
196*6777b538SAndroid Build Coastguard Worker }
197*6777b538SAndroid Build Coastguard Worker 
ResetInternal(bool cancel,bool cancel_connect_job)198*6777b538SAndroid Build Coastguard Worker void ClientSocketHandle::ResetInternal(bool cancel, bool cancel_connect_job) {
199*6777b538SAndroid Build Coastguard Worker   DCHECK(cancel || !cancel_connect_job);
200*6777b538SAndroid Build Coastguard Worker 
201*6777b538SAndroid Build Coastguard Worker   // Was Init called?
202*6777b538SAndroid Build Coastguard Worker   if (group_id_.destination().IsValid()) {
203*6777b538SAndroid Build Coastguard Worker     // If so, we must have a pool.
204*6777b538SAndroid Build Coastguard Worker     CHECK(pool_);
205*6777b538SAndroid Build Coastguard Worker     if (is_initialized()) {
206*6777b538SAndroid Build Coastguard Worker       if (socket_) {
207*6777b538SAndroid Build Coastguard Worker         socket_->NetLog().EndEvent(NetLogEventType::SOCKET_IN_USE);
208*6777b538SAndroid Build Coastguard Worker         // Release the socket back to the ClientSocketPool so it can be
209*6777b538SAndroid Build Coastguard Worker         // deleted or reused.
210*6777b538SAndroid Build Coastguard Worker         pool_->ReleaseSocket(group_id_, std::move(socket_), group_generation_);
211*6777b538SAndroid Build Coastguard Worker       } else {
212*6777b538SAndroid Build Coastguard Worker         // If the handle has been initialized, we should still have a
213*6777b538SAndroid Build Coastguard Worker         // socket.
214*6777b538SAndroid Build Coastguard Worker         NOTREACHED();
215*6777b538SAndroid Build Coastguard Worker       }
216*6777b538SAndroid Build Coastguard Worker     } else if (cancel) {
217*6777b538SAndroid Build Coastguard Worker       // If we did not get initialized yet and we have a socket
218*6777b538SAndroid Build Coastguard Worker       // request pending, cancel it.
219*6777b538SAndroid Build Coastguard Worker       pool_->CancelRequest(group_id_, this, cancel_connect_job);
220*6777b538SAndroid Build Coastguard Worker     }
221*6777b538SAndroid Build Coastguard Worker   }
222*6777b538SAndroid Build Coastguard Worker   is_initialized_ = false;
223*6777b538SAndroid Build Coastguard Worker   socket_.reset();
224*6777b538SAndroid Build Coastguard Worker   group_id_ = ClientSocketPool::GroupId();
225*6777b538SAndroid Build Coastguard Worker   reuse_type_ = ClientSocketHandle::UNUSED;
226*6777b538SAndroid Build Coastguard Worker   callback_.Reset();
227*6777b538SAndroid Build Coastguard Worker   if (higher_pool_)
228*6777b538SAndroid Build Coastguard Worker     RemoveHigherLayeredPool(higher_pool_);
229*6777b538SAndroid Build Coastguard Worker   pool_ = nullptr;
230*6777b538SAndroid Build Coastguard Worker   idle_time_ = base::TimeDelta();
231*6777b538SAndroid Build Coastguard Worker   connect_timing_ = LoadTimingInfo::ConnectTiming();
232*6777b538SAndroid Build Coastguard Worker   group_generation_ = -1;
233*6777b538SAndroid Build Coastguard Worker }
234*6777b538SAndroid Build Coastguard Worker 
ResetErrorState()235*6777b538SAndroid Build Coastguard Worker void ClientSocketHandle::ResetErrorState() {
236*6777b538SAndroid Build Coastguard Worker   resolve_error_info_ = ResolveErrorInfo(OK);
237*6777b538SAndroid Build Coastguard Worker   is_ssl_error_ = false;
238*6777b538SAndroid Build Coastguard Worker   ssl_cert_request_info_ = nullptr;
239*6777b538SAndroid Build Coastguard Worker }
240*6777b538SAndroid Build Coastguard Worker 
241*6777b538SAndroid Build Coastguard Worker }  // namespace net
242