blob: a51fea5109299ae6869fc1d3ba1737141de47291 [file] [log] [blame]
[email protected]e34400c32012-01-24 02:49:331// Copyright (c) 2012 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit586acc5fe2008-07-26 22:42:524
[email protected]f7984fc62009-06-22 23:26:445#include "net/socket/client_socket_handle.h"
initial.commit586acc5fe2008-07-26 22:42:526
dchengc7eeda422015-12-26 03:56:487#include <utility>
8
[email protected]49639fa2011-12-20 23:22:419#include "base/bind.h"
danakjdb9ae7942020-11-11 16:01:3510#include "base/callback_helpers.h"
Hans Wennborg0924470b2020-04-27 21:08:0511#include "base/check_op.h"
[email protected]d207a5f2009-06-04 05:28:4012#include "base/compiler_specific.h"
Hans Wennborg0924470b2020-04-27 21:08:0513#include "base/notreached.h"
ssid6d6b40102016-04-05 18:59:5614#include "base/trace_event/trace_event.h"
[email protected]d207a5f2009-06-04 05:28:4015#include "net/base/net_errors.h"
xunjieli0b7f5b62016-12-06 20:43:4816#include "net/base/trace_constants.h"
mikecirone8b85c432016-09-08 19:11:0017#include "net/log/net_log_event_type.h"
[email protected]f7984fc62009-06-22 23:26:4418#include "net/socket/client_socket_pool.h"
Matt Menkec1ae1d52019-04-10 19:28:2719#include "net/socket/connect_job.h"
initial.commit586acc5fe2008-07-26 22:42:5220
21namespace net {
22
[email protected]a512f5982009-08-18 16:01:0623ClientSocketHandle::ClientSocketHandle()
Tsuyoshi Horo2ec06e002022-06-09 01:38:5924 : pool_(nullptr),
Raul Tambre94493c652019-03-11 17:18:3525 higher_pool_(nullptr),
Tsuyoshi Horo2ec06e002022-06-09 01:38:5926 resolve_error_info_(ResolveErrorInfo(OK)) {}
initial.commit586acc5fe2008-07-26 22:42:5227
[email protected]e1e06262008-08-06 23:57:0728ClientSocketHandle::~ClientSocketHandle() {
initial.commit586acc5fe2008-07-26 22:42:5229 Reset();
30}
31
Matt Menkebd12b7e2019-03-25 21:12:0332int ClientSocketHandle::Init(
33 const ClientSocketPool::GroupId& group_id,
34 scoped_refptr<ClientSocketPool::SocketParams> socket_params,
Anton Bikineev068d2912021-05-15 20:43:5235 const absl::optional<NetworkTrafficAnnotationTag>& proxy_annotation_tag,
Matt Menkebd12b7e2019-03-25 21:12:0336 RequestPriority priority,
37 const SocketTag& socket_tag,
38 ClientSocketPool::RespectLimits respect_limits,
39 CompletionOnceCallback callback,
40 const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback,
41 ClientSocketPool* pool,
42 const NetLogWithSource& net_log) {
43 requesting_source_ = net_log.source();
44
Eric Ortha2e7773212021-06-22 21:49:5545 CHECK(group_id.destination().IsValid());
Matt Menke7eb405e2019-04-25 20:48:2146 ResetInternal(true /* cancel */, false /* cancel_connect_job */);
Matt Menkebd12b7e2019-03-25 21:12:0347 ResetErrorState();
48 pool_ = pool;
49 group_id_ = group_id;
50 CompletionOnceCallback io_complete_callback =
51 base::BindOnce(&ClientSocketHandle::OnIOComplete, base::Unretained(this));
52 int rv = pool_->RequestSocket(
Matt Menkef09e64c2019-04-23 22:16:2853 group_id, std::move(socket_params), proxy_annotation_tag, priority,
54 socket_tag, respect_limits, this, std::move(io_complete_callback),
55 proxy_auth_callback, net_log);
Matt Menkebd12b7e2019-03-25 21:12:0356 if (rv == ERR_IO_PENDING) {
57 callback_ = std::move(callback);
58 } else {
59 HandleInitCompletion(rv);
60 }
61 return rv;
62}
63
rdsmith29dbad12017-02-17 02:22:1864void ClientSocketHandle::SetPriority(RequestPriority priority) {
65 if (socket_) {
66 // The priority of the handle is no longer relevant to the socket pool;
67 // just return.
68 return;
69 }
70
71 if (pool_)
Matt Menkef6edce752019-03-19 17:21:5672 pool_->SetPriority(group_id_, this, priority);
rdsmith29dbad12017-02-17 02:22:1873}
74
[email protected]e1e06262008-08-06 23:57:0775void ClientSocketHandle::Reset() {
Matt Menke7eb405e2019-04-25 20:48:2176 ResetInternal(true /* cancel */, false /* cancel_connect_job */);
[email protected]e60e47a2010-07-14 03:37:1877 ResetErrorState();
[email protected]d207a5f2009-06-04 05:28:4078}
79
Matt Menke7eb405e2019-04-25 20:48:2180void ClientSocketHandle::ResetAndCloseSocket() {
81 if (is_initialized() && socket_)
82 socket_->Disconnect();
83 ResetInternal(true /* cancel */, true /* cancel_connect_job */);
84 ResetErrorState();
85}
86
[email protected]d207a5f2009-06-04 05:28:4087LoadState ClientSocketHandle::GetLoadState() const {
[email protected]d242d2c2009-06-12 01:24:2188 CHECK(!is_initialized());
Eric Ortha2e7773212021-06-22 21:49:5589 CHECK(group_id_.destination().IsValid());
[email protected]a796bcec2010-03-22 17:17:2690 // Because of http://crbug.com/37810 we may not have a pool, but have
91 // just a raw socket.
92 if (!pool_)
93 return LOAD_STATE_IDLE;
Matt Menkef6edce752019-03-19 17:21:5694 return pool_->GetLoadState(group_id_, this);
[email protected]d207a5f2009-06-04 05:28:4095}
96
[email protected]51fdc7c2012-04-10 19:19:4897bool ClientSocketHandle::IsPoolStalled() const {
[email protected]043b68c82013-08-22 23:41:5298 if (!pool_)
99 return false;
[email protected]51fdc7c2012-04-10 19:19:48100 return pool_->IsStalled();
101}
102
[email protected]043b68c82013-08-22 23:41:52103void ClientSocketHandle::AddHigherLayeredPool(HigherLayeredPool* higher_pool) {
104 CHECK(higher_pool);
105 CHECK(!higher_pool_);
106 // TODO(mmenke): |pool_| should only be NULL in tests. Maybe stop doing that
107 // so this be be made into a DCHECK, and the same can be done in
108 // RemoveHigherLayeredPool?
[email protected]51fdc7c2012-04-10 19:19:48109 if (pool_) {
[email protected]043b68c82013-08-22 23:41:52110 pool_->AddHigherLayeredPool(higher_pool);
111 higher_pool_ = higher_pool;
[email protected]51fdc7c2012-04-10 19:19:48112 }
113}
114
[email protected]043b68c82013-08-22 23:41:52115void ClientSocketHandle::RemoveHigherLayeredPool(
116 HigherLayeredPool* higher_pool) {
117 CHECK(higher_pool_);
118 CHECK_EQ(higher_pool_, higher_pool);
[email protected]51fdc7c2012-04-10 19:19:48119 if (pool_) {
[email protected]043b68c82013-08-22 23:41:52120 pool_->RemoveHigherLayeredPool(higher_pool);
Raul Tambre94493c652019-03-11 17:18:35121 higher_pool_ = nullptr;
[email protected]51fdc7c2012-04-10 19:19:48122 }
123}
124
Matt Menke433de6d2020-03-04 00:24:11125void ClientSocketHandle::CloseIdleSocketsInGroup(
126 const char* net_log_reason_utf8) {
xunjieli92feb332017-03-03 17:19:23127 if (pool_)
Matt Menke433de6d2020-03-04 00:24:11128 pool_->CloseIdleSocketsInGroup(group_id_, net_log_reason_utf8);
xunjieli92feb332017-03-03 17:19:23129}
130
[email protected]034df0f32013-01-07 23:17:48131bool ClientSocketHandle::GetLoadTimingInfo(
132 bool is_reused,
133 LoadTimingInfo* load_timing_info) const {
Matt Menkeaade5812019-03-02 13:38:00134 if (socket_) {
135 load_timing_info->socket_log_id = socket_->NetLog().source().id;
Matt Menkeaade5812019-03-02 13:38:00136 } else {
137 // Only return load timing information when there's a socket.
[email protected]034df0f32013-01-07 23:17:48138 return false;
Matt Menkeaade5812019-03-02 13:38:00139 }
[email protected]034df0f32013-01-07 23:17:48140
[email protected]034df0f32013-01-07 23:17:48141 load_timing_info->socket_reused = is_reused;
142
143 // No times if the socket is reused.
144 if (is_reused)
145 return true;
146
147 load_timing_info->connect_timing = connect_timing_;
148 return true;
149}
150
danakj655b66c2016-04-16 00:51:38151void ClientSocketHandle::SetSocket(std::unique_ptr<StreamSocket> s) {
dchengc7eeda422015-12-26 03:56:48152 socket_ = std::move(s);
[email protected]18ccfdb2013-08-15 00:13:44153}
154
Matt Menkec1ae1d52019-04-10 19:28:27155void ClientSocketHandle::SetAdditionalErrorState(ConnectJob* connect_job) {
Matt Menke6030ed9f2019-04-11 20:25:55156 connection_attempts_ = connect_job->GetConnectionAttempts();
Matt Menkec1ae1d52019-04-10 19:28:27157
dalykedd30d982019-12-16 15:31:10158 resolve_error_info_ = connect_job->GetResolveErrorInfo();
Matt Menke6f84d1f12019-04-11 19:26:47159 is_ssl_error_ = connect_job->IsSSLError();
160 ssl_cert_request_info_ = connect_job->GetCertRequestInfo();
Matt Menkec1ae1d52019-04-10 19:28:27161}
162
Matt Menke9dd8b9792019-04-29 19:42:13163std::unique_ptr<StreamSocket> ClientSocketHandle::PassSocket() {
164 return std::move(socket_);
165}
166
[email protected]d207a5f2009-06-04 05:28:40167void ClientSocketHandle::OnIOComplete(int result) {
Alexandr Ilin33126632018-11-14 14:48:17168 TRACE_EVENT0(NetTracingCategory(), "ClientSocketHandle::OnIOComplete");
Bence Békya4a50932018-08-10 13:39:41169 CompletionOnceCallback callback = std::move(callback_);
170 callback_.Reset();
[email protected]3ae82302009-06-26 06:01:21171 HandleInitCompletion(result);
Brad Lassey3a814172018-04-26 03:30:21172 std::move(callback).Run(result);
[email protected]3ae82302009-06-26 06:01:21173}
174
175void ClientSocketHandle::HandleInitCompletion(int result) {
[email protected]b1f031dd2010-03-02 23:19:33176 CHECK_NE(ERR_IO_PENDING, result);
[email protected]a796bcec2010-03-22 17:17:26177 if (result != OK) {
[email protected]e772db3f2010-07-12 18:11:13178 if (!socket_.get())
Matt Menke7eb405e2019-04-25 20:48:21179 ResetInternal(false /* cancel */,
180 false /* cancel_connect_job */); // Nothing to cancel since
181 // the request failed.
[email protected]05ea9ff2010-07-15 19:08:21182 else
183 is_initialized_ = true;
[email protected]a796bcec2010-03-22 17:17:26184 return;
185 }
[email protected]05ea9ff2010-07-15 19:08:21186 is_initialized_ = true;
Matt Menkebf3c767d2019-04-15 23:28:24187 CHECK_NE(-1, group_generation_)
188 << "Pool should have set |group_generation_| to a valid value.";
[email protected]a796bcec2010-03-22 17:17:26189
[email protected]06650c52010-06-03 00:49:17190 // Broadcast that the socket has been acquired.
191 // TODO(eroman): This logging is not complete, in particular set_socket() and
192 // release() socket. It ends up working though, since those methods are being
193 // used to layer sockets (and the destination sources are the same).
194 DCHECK(socket_.get());
Eric Roman06bd9742019-07-13 15:19:13195 socket_->NetLog().BeginEventReferencingSource(NetLogEventType::SOCKET_IN_USE,
196 requesting_source_);
initial.commit586acc5fe2008-07-26 22:42:52197}
198
Matt Menke9dd8b9792019-04-29 19:42:13199void ClientSocketHandle::ResetInternal(bool cancel, bool cancel_connect_job) {
200 DCHECK(cancel || !cancel_connect_job);
201
202 // Was Init called?
Eric Ortha2e7773212021-06-22 21:49:55203 if (group_id_.destination().IsValid()) {
Matt Menke9dd8b9792019-04-29 19:42:13204 // If so, we must have a pool.
205 CHECK(pool_);
206 if (is_initialized()) {
207 if (socket_) {
208 socket_->NetLog().EndEvent(NetLogEventType::SOCKET_IN_USE);
209 // Release the socket back to the ClientSocketPool so it can be
210 // deleted or reused.
211 pool_->ReleaseSocket(group_id_, std::move(socket_), group_generation_);
212 } else {
213 // If the handle has been initialized, we should still have a
214 // socket.
215 NOTREACHED();
216 }
217 } else if (cancel) {
218 // If we did not get initialized yet and we have a socket
219 // request pending, cancel it.
220 pool_->CancelRequest(group_id_, this, cancel_connect_job);
221 }
222 }
223 is_initialized_ = false;
224 socket_.reset();
225 group_id_ = ClientSocketPool::GroupId();
226 reuse_type_ = ClientSocketHandle::UNUSED;
227 callback_.Reset();
228 if (higher_pool_)
229 RemoveHigherLayeredPool(higher_pool_);
230 pool_ = nullptr;
231 idle_time_ = base::TimeDelta();
232 connect_timing_ = LoadTimingInfo::ConnectTiming();
233 group_generation_ = -1;
234}
235
236void ClientSocketHandle::ResetErrorState() {
dalykedd30d982019-12-16 15:31:10237 resolve_error_info_ = ResolveErrorInfo(OK);
Matt Menke9dd8b9792019-04-29 19:42:13238 is_ssl_error_ = false;
239 ssl_cert_request_info_ = nullptr;
240}
241
initial.commit586acc5fe2008-07-26 22:42:52242} // namespace net