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