[email protected] | e34400c3 | 2012-01-24 02:49:33 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
license.bot | bf09a50 | 2008-08-24 00:55:55 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
initial.commit | 586acc5fe | 2008-07-26 22:42:52 | [diff] [blame] | 4 | |
[email protected] | f7984fc6 | 2009-06-22 23:26:44 | [diff] [blame] | 5 | #include "net/socket/client_socket_handle.h" |
initial.commit | 586acc5fe | 2008-07-26 22:42:52 | [diff] [blame] | 6 | |
dcheng | c7eeda42 | 2015-12-26 03:56:48 | [diff] [blame] | 7 | #include <utility> |
| 8 | |
[email protected] | 49639fa | 2011-12-20 23:22:41 | [diff] [blame] | 9 | #include "base/bind.h" |
danakj | db9ae794 | 2020-11-11 16:01:35 | [diff] [blame] | 10 | #include "base/callback_helpers.h" |
Hans Wennborg | 0924470b | 2020-04-27 21:08:05 | [diff] [blame] | 11 | #include "base/check_op.h" |
[email protected] | d207a5f | 2009-06-04 05:28:40 | [diff] [blame] | 12 | #include "base/compiler_specific.h" |
Hans Wennborg | 0924470b | 2020-04-27 21:08:05 | [diff] [blame] | 13 | #include "base/notreached.h" |
ssid | 6d6b4010 | 2016-04-05 18:59:56 | [diff] [blame] | 14 | #include "base/trace_event/trace_event.h" |
[email protected] | d207a5f | 2009-06-04 05:28:40 | [diff] [blame] | 15 | #include "net/base/net_errors.h" |
xunjieli | 0b7f5b6 | 2016-12-06 20:43:48 | [diff] [blame] | 16 | #include "net/base/trace_constants.h" |
mikecirone | 8b85c43 | 2016-09-08 19:11:00 | [diff] [blame] | 17 | #include "net/log/net_log_event_type.h" |
[email protected] | f7984fc6 | 2009-06-22 23:26:44 | [diff] [blame] | 18 | #include "net/socket/client_socket_pool.h" |
Matt Menke | c1ae1d5 | 2019-04-10 19:28:27 | [diff] [blame] | 19 | #include "net/socket/connect_job.h" |
initial.commit | 586acc5fe | 2008-07-26 22:42:52 | [diff] [blame] | 20 | |
| 21 | namespace net { |
| 22 | |
[email protected] | a512f598 | 2009-08-18 16:01:06 | [diff] [blame] | 23 | ClientSocketHandle::ClientSocketHandle() |
Tsuyoshi Horo | 2ec06e00 | 2022-06-09 01:38:59 | [diff] [blame] | 24 | : pool_(nullptr), |
Raul Tambre | 94493c65 | 2019-03-11 17:18:35 | [diff] [blame] | 25 | higher_pool_(nullptr), |
Tsuyoshi Horo | 2ec06e00 | 2022-06-09 01:38:59 | [diff] [blame] | 26 | resolve_error_info_(ResolveErrorInfo(OK)) {} |
initial.commit | 586acc5fe | 2008-07-26 22:42:52 | [diff] [blame] | 27 | |
[email protected] | e1e0626 | 2008-08-06 23:57:07 | [diff] [blame] | 28 | ClientSocketHandle::~ClientSocketHandle() { |
initial.commit | 586acc5fe | 2008-07-26 22:42:52 | [diff] [blame] | 29 | Reset(); |
| 30 | } |
| 31 | |
Matt Menke | bd12b7e | 2019-03-25 21:12:03 | [diff] [blame] | 32 | int ClientSocketHandle::Init( |
| 33 | const ClientSocketPool::GroupId& group_id, |
| 34 | scoped_refptr<ClientSocketPool::SocketParams> socket_params, |
Anton Bikineev | 068d291 | 2021-05-15 20:43:52 | [diff] [blame] | 35 | const absl::optional<NetworkTrafficAnnotationTag>& proxy_annotation_tag, |
Matt Menke | bd12b7e | 2019-03-25 21:12:03 | [diff] [blame] | 36 | 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 Orth | a2e777321 | 2021-06-22 21:49:55 | [diff] [blame] | 45 | CHECK(group_id.destination().IsValid()); |
Matt Menke | 7eb405e | 2019-04-25 20:48:21 | [diff] [blame] | 46 | ResetInternal(true /* cancel */, false /* cancel_connect_job */); |
Matt Menke | bd12b7e | 2019-03-25 21:12:03 | [diff] [blame] | 47 | 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 Menke | f09e64c | 2019-04-23 22:16:28 | [diff] [blame] | 53 | 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 Menke | bd12b7e | 2019-03-25 21:12:03 | [diff] [blame] | 56 | if (rv == ERR_IO_PENDING) { |
| 57 | callback_ = std::move(callback); |
| 58 | } else { |
| 59 | HandleInitCompletion(rv); |
| 60 | } |
| 61 | return rv; |
| 62 | } |
| 63 | |
rdsmith | 29dbad1 | 2017-02-17 02:22:18 | [diff] [blame] | 64 | void 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 Menke | f6edce75 | 2019-03-19 17:21:56 | [diff] [blame] | 72 | pool_->SetPriority(group_id_, this, priority); |
rdsmith | 29dbad1 | 2017-02-17 02:22:18 | [diff] [blame] | 73 | } |
| 74 | |
[email protected] | e1e0626 | 2008-08-06 23:57:07 | [diff] [blame] | 75 | void ClientSocketHandle::Reset() { |
Matt Menke | 7eb405e | 2019-04-25 20:48:21 | [diff] [blame] | 76 | ResetInternal(true /* cancel */, false /* cancel_connect_job */); |
[email protected] | e60e47a | 2010-07-14 03:37:18 | [diff] [blame] | 77 | ResetErrorState(); |
[email protected] | d207a5f | 2009-06-04 05:28:40 | [diff] [blame] | 78 | } |
| 79 | |
Matt Menke | 7eb405e | 2019-04-25 20:48:21 | [diff] [blame] | 80 | void ClientSocketHandle::ResetAndCloseSocket() { |
| 81 | if (is_initialized() && socket_) |
| 82 | socket_->Disconnect(); |
| 83 | ResetInternal(true /* cancel */, true /* cancel_connect_job */); |
| 84 | ResetErrorState(); |
| 85 | } |
| 86 | |
[email protected] | d207a5f | 2009-06-04 05:28:40 | [diff] [blame] | 87 | LoadState ClientSocketHandle::GetLoadState() const { |
[email protected] | d242d2c | 2009-06-12 01:24:21 | [diff] [blame] | 88 | CHECK(!is_initialized()); |
Eric Orth | a2e777321 | 2021-06-22 21:49:55 | [diff] [blame] | 89 | CHECK(group_id_.destination().IsValid()); |
[email protected] | a796bcec | 2010-03-22 17:17:26 | [diff] [blame] | 90 | // 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 Menke | f6edce75 | 2019-03-19 17:21:56 | [diff] [blame] | 94 | return pool_->GetLoadState(group_id_, this); |
[email protected] | d207a5f | 2009-06-04 05:28:40 | [diff] [blame] | 95 | } |
| 96 | |
[email protected] | 51fdc7c | 2012-04-10 19:19:48 | [diff] [blame] | 97 | bool ClientSocketHandle::IsPoolStalled() const { |
[email protected] | 043b68c8 | 2013-08-22 23:41:52 | [diff] [blame] | 98 | if (!pool_) |
| 99 | return false; |
[email protected] | 51fdc7c | 2012-04-10 19:19:48 | [diff] [blame] | 100 | return pool_->IsStalled(); |
| 101 | } |
| 102 | |
[email protected] | 043b68c8 | 2013-08-22 23:41:52 | [diff] [blame] | 103 | void 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] | 51fdc7c | 2012-04-10 19:19:48 | [diff] [blame] | 109 | if (pool_) { |
[email protected] | 043b68c8 | 2013-08-22 23:41:52 | [diff] [blame] | 110 | pool_->AddHigherLayeredPool(higher_pool); |
| 111 | higher_pool_ = higher_pool; |
[email protected] | 51fdc7c | 2012-04-10 19:19:48 | [diff] [blame] | 112 | } |
| 113 | } |
| 114 | |
[email protected] | 043b68c8 | 2013-08-22 23:41:52 | [diff] [blame] | 115 | void ClientSocketHandle::RemoveHigherLayeredPool( |
| 116 | HigherLayeredPool* higher_pool) { |
| 117 | CHECK(higher_pool_); |
| 118 | CHECK_EQ(higher_pool_, higher_pool); |
[email protected] | 51fdc7c | 2012-04-10 19:19:48 | [diff] [blame] | 119 | if (pool_) { |
[email protected] | 043b68c8 | 2013-08-22 23:41:52 | [diff] [blame] | 120 | pool_->RemoveHigherLayeredPool(higher_pool); |
Raul Tambre | 94493c65 | 2019-03-11 17:18:35 | [diff] [blame] | 121 | higher_pool_ = nullptr; |
[email protected] | 51fdc7c | 2012-04-10 19:19:48 | [diff] [blame] | 122 | } |
| 123 | } |
| 124 | |
Matt Menke | 433de6d | 2020-03-04 00:24:11 | [diff] [blame] | 125 | void ClientSocketHandle::CloseIdleSocketsInGroup( |
| 126 | const char* net_log_reason_utf8) { |
xunjieli | 92feb33 | 2017-03-03 17:19:23 | [diff] [blame] | 127 | if (pool_) |
Matt Menke | 433de6d | 2020-03-04 00:24:11 | [diff] [blame] | 128 | pool_->CloseIdleSocketsInGroup(group_id_, net_log_reason_utf8); |
xunjieli | 92feb33 | 2017-03-03 17:19:23 | [diff] [blame] | 129 | } |
| 130 | |
[email protected] | 034df0f3 | 2013-01-07 23:17:48 | [diff] [blame] | 131 | bool ClientSocketHandle::GetLoadTimingInfo( |
| 132 | bool is_reused, |
| 133 | LoadTimingInfo* load_timing_info) const { |
Matt Menke | aade581 | 2019-03-02 13:38:00 | [diff] [blame] | 134 | if (socket_) { |
| 135 | load_timing_info->socket_log_id = socket_->NetLog().source().id; |
Matt Menke | aade581 | 2019-03-02 13:38:00 | [diff] [blame] | 136 | } else { |
| 137 | // Only return load timing information when there's a socket. |
[email protected] | 034df0f3 | 2013-01-07 23:17:48 | [diff] [blame] | 138 | return false; |
Matt Menke | aade581 | 2019-03-02 13:38:00 | [diff] [blame] | 139 | } |
[email protected] | 034df0f3 | 2013-01-07 23:17:48 | [diff] [blame] | 140 | |
[email protected] | 034df0f3 | 2013-01-07 23:17:48 | [diff] [blame] | 141 | 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 | |
danakj | 655b66c | 2016-04-16 00:51:38 | [diff] [blame] | 151 | void ClientSocketHandle::SetSocket(std::unique_ptr<StreamSocket> s) { |
dcheng | c7eeda42 | 2015-12-26 03:56:48 | [diff] [blame] | 152 | socket_ = std::move(s); |
[email protected] | 18ccfdb | 2013-08-15 00:13:44 | [diff] [blame] | 153 | } |
| 154 | |
Matt Menke | c1ae1d5 | 2019-04-10 19:28:27 | [diff] [blame] | 155 | void ClientSocketHandle::SetAdditionalErrorState(ConnectJob* connect_job) { |
Matt Menke | 6030ed9f | 2019-04-11 20:25:55 | [diff] [blame] | 156 | connection_attempts_ = connect_job->GetConnectionAttempts(); |
Matt Menke | c1ae1d5 | 2019-04-10 19:28:27 | [diff] [blame] | 157 | |
dalyk | edd30d98 | 2019-12-16 15:31:10 | [diff] [blame] | 158 | resolve_error_info_ = connect_job->GetResolveErrorInfo(); |
Matt Menke | 6f84d1f1 | 2019-04-11 19:26:47 | [diff] [blame] | 159 | is_ssl_error_ = connect_job->IsSSLError(); |
| 160 | ssl_cert_request_info_ = connect_job->GetCertRequestInfo(); |
Matt Menke | c1ae1d5 | 2019-04-10 19:28:27 | [diff] [blame] | 161 | } |
| 162 | |
Matt Menke | 9dd8b979 | 2019-04-29 19:42:13 | [diff] [blame] | 163 | std::unique_ptr<StreamSocket> ClientSocketHandle::PassSocket() { |
| 164 | return std::move(socket_); |
| 165 | } |
| 166 | |
[email protected] | d207a5f | 2009-06-04 05:28:40 | [diff] [blame] | 167 | void ClientSocketHandle::OnIOComplete(int result) { |
Alexandr Ilin | 3312663 | 2018-11-14 14:48:17 | [diff] [blame] | 168 | TRACE_EVENT0(NetTracingCategory(), "ClientSocketHandle::OnIOComplete"); |
Bence Béky | a4a5093 | 2018-08-10 13:39:41 | [diff] [blame] | 169 | CompletionOnceCallback callback = std::move(callback_); |
| 170 | callback_.Reset(); |
[email protected] | 3ae8230 | 2009-06-26 06:01:21 | [diff] [blame] | 171 | HandleInitCompletion(result); |
Brad Lassey | 3a81417 | 2018-04-26 03:30:21 | [diff] [blame] | 172 | std::move(callback).Run(result); |
[email protected] | 3ae8230 | 2009-06-26 06:01:21 | [diff] [blame] | 173 | } |
| 174 | |
| 175 | void ClientSocketHandle::HandleInitCompletion(int result) { |
[email protected] | b1f031dd | 2010-03-02 23:19:33 | [diff] [blame] | 176 | CHECK_NE(ERR_IO_PENDING, result); |
[email protected] | a796bcec | 2010-03-22 17:17:26 | [diff] [blame] | 177 | if (result != OK) { |
[email protected] | e772db3f | 2010-07-12 18:11:13 | [diff] [blame] | 178 | if (!socket_.get()) |
Matt Menke | 7eb405e | 2019-04-25 20:48:21 | [diff] [blame] | 179 | ResetInternal(false /* cancel */, |
| 180 | false /* cancel_connect_job */); // Nothing to cancel since |
| 181 | // the request failed. |
[email protected] | 05ea9ff | 2010-07-15 19:08:21 | [diff] [blame] | 182 | else |
| 183 | is_initialized_ = true; |
[email protected] | a796bcec | 2010-03-22 17:17:26 | [diff] [blame] | 184 | return; |
| 185 | } |
[email protected] | 05ea9ff | 2010-07-15 19:08:21 | [diff] [blame] | 186 | is_initialized_ = true; |
Matt Menke | bf3c767d | 2019-04-15 23:28:24 | [diff] [blame] | 187 | CHECK_NE(-1, group_generation_) |
| 188 | << "Pool should have set |group_generation_| to a valid value."; |
[email protected] | a796bcec | 2010-03-22 17:17:26 | [diff] [blame] | 189 | |
[email protected] | 06650c5 | 2010-06-03 00:49:17 | [diff] [blame] | 190 | // 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 Roman | 06bd974 | 2019-07-13 15:19:13 | [diff] [blame] | 195 | socket_->NetLog().BeginEventReferencingSource(NetLogEventType::SOCKET_IN_USE, |
| 196 | requesting_source_); |
initial.commit | 586acc5fe | 2008-07-26 22:42:52 | [diff] [blame] | 197 | } |
| 198 | |
Matt Menke | 9dd8b979 | 2019-04-29 19:42:13 | [diff] [blame] | 199 | void ClientSocketHandle::ResetInternal(bool cancel, bool cancel_connect_job) { |
| 200 | DCHECK(cancel || !cancel_connect_job); |
| 201 | |
| 202 | // Was Init called? |
Eric Orth | a2e777321 | 2021-06-22 21:49:55 | [diff] [blame] | 203 | if (group_id_.destination().IsValid()) { |
Matt Menke | 9dd8b979 | 2019-04-29 19:42:13 | [diff] [blame] | 204 | // 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 | |
| 236 | void ClientSocketHandle::ResetErrorState() { |
dalyk | edd30d98 | 2019-12-16 15:31:10 | [diff] [blame] | 237 | resolve_error_info_ = ResolveErrorInfo(OK); |
Matt Menke | 9dd8b979 | 2019-04-29 19:42:13 | [diff] [blame] | 238 | is_ssl_error_ = false; |
| 239 | ssl_cert_request_info_ = nullptr; |
| 240 | } |
| 241 | |
initial.commit | 586acc5fe | 2008-07-26 22:42:52 | [diff] [blame] | 242 | } // namespace net |