blob: e368a5baba92a68f56aeef96f26e8b09c261c1d3 [file] [log] [blame]
[email protected]d245c342012-02-23 20:49:151// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]aea80602009-09-18 00:55:082// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Bence Béky94658bf2018-05-11 19:22:585#include "net/spdy/spdy_session_pool.h"
[email protected]aea80602009-09-18 00:55:086
Bence Béky3ba8c332017-12-11 20:19:247#include <algorithm>
Eric Orthac661912022-01-10 21:44:178#include <set>
dchengc7eeda422015-12-26 03:56:489#include <utility>
10
Eric Orthc1fc6912019-02-15 19:33:0811#include "base/bind.h"
Hans Wennborg0924470b2020-04-27 21:08:0512#include "base/check_op.h"
Lei Zhangde197672021-04-29 08:11:2413#include "base/containers/contains.h"
asvitkinec3c93722015-06-17 14:48:3714#include "base/metrics/histogram_macros.h"
Bence Béky4e83f492018-05-13 23:14:2515#include "base/strings/stringprintf.h"
Lei Zhang52637ed2019-02-20 01:38:3716#include "base/threading/thread_task_runner_handle.h"
ssid6d6b40102016-04-05 18:59:5617#include "base/trace_event/trace_event.h"
[email protected]1ce7b66b2010-10-12 20:32:4418#include "base/values.h"
Bence Béky3ba8c332017-12-11 20:19:2419#include "build/build_config.h"
[email protected]ab739042011-04-07 15:22:2820#include "net/base/address_list.h"
xunjieli0b7f5b62016-12-06 20:43:4821#include "net/base/trace_constants.h"
Cammie Smith Barnes5191037b72021-03-01 22:06:5322#include "net/dns/dns_alias_utility.h"
Eric Orthc1fc6912019-02-15 19:33:0823#include "net/dns/host_resolver.h"
Matt Menke991dd7e2021-07-22 17:31:5124#include "net/dns/public/host_resolver_source.h"
[email protected]f4580332010-09-25 21:20:2725#include "net/http/http_network_session.h"
[email protected]53bfa31c2011-11-15 19:20:3126#include "net/http/http_server_properties.h"
Bence Béky6b44abf2018-04-11 10:32:5127#include "net/http/http_stream_request.h"
mikecirone8b85c432016-09-08 19:11:0028#include "net/log/net_log_event_type.h"
mikecironef22f9812016-10-04 03:40:1929#include "net/log/net_log_source.h"
30#include "net/log/net_log_with_source.h"
Matt Menke3c5581752019-03-27 01:19:1831#include "net/socket/client_socket_handle.h"
Bence Béky94658bf2018-05-11 19:22:5832#include "net/spdy/spdy_session.h"
Ryan Hamiltonea4fa192022-04-12 18:30:4933#include "net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_constants.h"
34#include "net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_static_table.h"
[email protected]aea80602009-09-18 00:55:0835
36namespace net {
37
[email protected]8b114dd72011-03-25 05:33:0238namespace {
39
40enum SpdySessionGetTypes {
41 CREATED_NEW = 0,
42 FOUND_EXISTING = 1,
43 FOUND_EXISTING_FROM_IP_POOL = 2,
44 IMPORTED_FROM_SOCKET = 3,
45 SPDY_SESSION_GET_MAX = 4
46};
47
[email protected]41d64e82013-07-03 22:44:2648} // namespace
[email protected]aea80602009-09-18 00:55:0849
Matt Menke9bcb57b2019-04-12 19:09:3450SpdySessionPool::SpdySessionRequest::Delegate::Delegate() = default;
51SpdySessionPool::SpdySessionRequest::Delegate::~Delegate() = default;
52
53SpdySessionPool::SpdySessionRequest::SpdySessionRequest(
54 const SpdySessionKey& key,
Matt Menke2ab5fe792019-04-18 18:14:1355 bool enable_ip_based_pooling,
Matt Menke77173952019-04-18 17:42:1456 bool is_websocket,
Matt Menke9338c3792019-04-19 19:16:4957 bool is_blocking_request_for_session,
Matt Menke9bcb57b2019-04-12 19:09:3458 Delegate* delegate,
59 SpdySessionPool* spdy_session_pool)
Matt Menke77173952019-04-18 17:42:1460 : key_(key),
Matt Menke2ab5fe792019-04-18 18:14:1361 enable_ip_based_pooling_(enable_ip_based_pooling),
Matt Menke77173952019-04-18 17:42:1462 is_websocket_(is_websocket),
Matt Menke9338c3792019-04-19 19:16:4963 is_blocking_request_for_session_(is_blocking_request_for_session),
Matt Menke77173952019-04-18 17:42:1464 delegate_(delegate),
65 spdy_session_pool_(spdy_session_pool) {}
Matt Menke9bcb57b2019-04-12 19:09:3466
67SpdySessionPool::SpdySessionRequest::~SpdySessionRequest() {
68 if (spdy_session_pool_)
69 spdy_session_pool_->RemoveRequestForSpdySession(this);
70}
71
72void SpdySessionPool::SpdySessionRequest::OnRemovedFromPool() {
73 DCHECK(spdy_session_pool_);
74 spdy_session_pool_ = nullptr;
75}
76
[email protected]61b4efc2012-04-27 18:12:5077SpdySessionPool::SpdySessionPool(
78 HostResolver* resolver,
David Benjamin151ec6b2019-08-02 19:38:5279 SSLClientContext* ssl_client_context,
bnc525e175a2016-06-20 12:36:4080 HttpServerProperties* http_server_properties,
[email protected]5db452202014-08-19 05:22:1581 TransportSecurityState* transport_security_state,
Nick Harper23290b82019-05-02 00:02:5682 const quic::ParsedQuicVersionVector& quic_supported_versions,
[email protected]f9cf5572012-12-04 15:52:0983 bool enable_ping_based_connection_checking,
Ryan Hamilton0246af92019-08-30 19:28:5684 bool is_http2_enabled,
85 bool is_quic_enabled,
bnc8f0f3b62015-04-08 04:37:2386 size_t session_max_recv_window_size,
David Schinazi410676a2019-08-13 22:31:0587 int session_max_queued_capped_frames,
Ryan Hamilton0239aac2018-05-19 00:03:1388 const spdy::SettingsMap& initial_settings,
Bence Békyd228fb22021-10-29 14:45:5189 bool enable_http2_settings_grease,
Anton Bikineev068d2912021-05-15 20:43:5290 const absl::optional<GreasedHttp2Frame>& greased_http2_frame,
Bence Békycb4be9e2020-07-09 11:18:1491 bool http2_end_stream_with_data_frame,
Bence Békye84179d2021-01-13 14:36:1692 bool enable_priority_update,
Stefano Duo76e1f8402021-10-25 10:27:5393 bool go_away_on_ip_change,
Tarun Bansal647b30d2018-10-19 21:21:4794 SpdySessionPool::TimeFunc time_func,
Stefano Duoe0b077d2022-02-03 11:16:5995 NetworkQualityEstimator* network_quality_estimator,
96 bool cleanup_sessions_on_ip_address_changed)
[email protected]53bfa31c2011-11-15 19:20:3197 : http_server_properties_(http_server_properties),
[email protected]5db452202014-08-19 05:22:1598 transport_security_state_(transport_security_state),
David Benjamin151ec6b2019-08-02 19:38:5299 ssl_client_context_(ssl_client_context),
[email protected]b9ec6882011-07-01 07:40:26100 resolver_(resolver),
zhongyi8ac630d2017-06-26 19:46:33101 quic_supported_versions_(quic_supported_versions),
[email protected]b40f7fa2013-08-01 16:13:05102 enable_sending_initial_data_(true),
[email protected]f9cf5572012-12-04 15:52:09103 enable_ping_based_connection_checking_(
104 enable_ping_based_connection_checking),
Ryan Hamilton0246af92019-08-30 19:28:56105 is_http2_enabled_(is_http2_enabled),
106 is_quic_enabled_(is_quic_enabled),
bnc8f0f3b62015-04-08 04:37:23107 session_max_recv_window_size_(session_max_recv_window_size),
David Schinazi410676a2019-08-13 22:31:05108 session_max_queued_capped_frames_(session_max_queued_capped_frames),
bnc3171a2432016-12-28 18:40:26109 initial_settings_(initial_settings),
Bence Békyd228fb22021-10-29 14:45:51110 enable_http2_settings_grease_(enable_http2_settings_grease),
Bence Béky6a070bcd2018-09-06 15:02:43111 greased_http2_frame_(greased_http2_frame),
Bence Békycb4be9e2020-07-09 11:18:14112 http2_end_stream_with_data_frame_(http2_end_stream_with_data_frame),
Bence Békye84179d2021-01-13 14:36:16113 enable_priority_update_(enable_priority_update),
Stefano Duo76e1f8402021-10-25 10:27:53114 go_away_on_ip_change_(go_away_on_ip_change),
[email protected]f9cf5572012-12-04 15:52:09115 time_func_(time_func),
Tarun Bansal647b30d2018-10-19 21:21:47116 push_delegate_(nullptr),
Stefano Duoe0b077d2022-02-03 11:16:59117 network_quality_estimator_(network_quality_estimator),
118 cleanup_sessions_on_ip_address_changed_(
119 cleanup_sessions_on_ip_address_changed) {
120 if (cleanup_sessions_on_ip_address_changed_)
121 NetworkChangeNotifier::AddIPAddressObserver(this);
David Benjamin151ec6b2019-08-02 19:38:52122 if (ssl_client_context_)
123 ssl_client_context_->AddObserver(this);
[email protected]b846acd2010-06-07 18:13:10124}
125
[email protected]955fc2e72010-02-08 20:37:30126SpdySessionPool::~SpdySessionPool() {
Matt Menkea6f2e8f2019-05-29 22:54:35127#if DCHECK_IS_ON()
128 for (const auto& request_info : spdy_session_request_map_) {
129 // The should be no pending SpdySessionRequests on destruction, though there
130 // may be callbacks waiting to be invoked, since they use weak pointers and
131 // there's no API to unregister them.
132 DCHECK(request_info.second.request_set.empty());
133 }
134#endif // DCHECK_IS_ON()
135
Bence Béky3ba8c332017-12-11 20:19:24136 // TODO(bnc): CloseAllSessions() is also called in HttpNetworkSession
137 // destructor, one of the two calls should be removed.
[email protected]d1eda932009-11-04 01:03:10138 CloseAllSessions();
[email protected]b846acd2010-06-07 18:13:10139
[email protected]975da41a2014-06-05 03:36:24140 while (!sessions_.empty()) {
141 // Destroy sessions to enforce that lifetime is scoped to SpdySessionPool.
142 // Write callbacks queued upon session drain are not invoked.
143 RemoveUnavailableSession((*sessions_.begin())->GetWeakPtr());
144 }
145
David Benjamin151ec6b2019-08-02 19:38:52146 if (ssl_client_context_)
147 ssl_client_context_->RemoveObserver(this);
Stefano Duoe0b077d2022-02-03 11:16:59148 if (cleanup_sessions_on_ip_address_changed_)
149 NetworkChangeNotifier::RemoveIPAddressObserver(this);
[email protected]d1eda932009-11-04 01:03:10150}
[email protected]aea80602009-09-18 00:55:08151
Bence Béky01d4c232021-03-23 03:09:17152int SpdySessionPool::CreateAvailableSessionFromSocketHandle(
Matt Menkee1d8fe92019-02-07 05:30:54153 const SpdySessionKey& key,
Matt Menkee1d8fe92019-02-07 05:30:54154 std::unique_ptr<ClientSocketHandle> client_socket_handle,
Bence Béky01d4c232021-03-23 03:09:17155 const NetLogWithSource& net_log,
156 base::WeakPtr<SpdySession>* session) {
Matt Menkee1d8fe92019-02-07 05:30:54157 TRACE_EVENT0(NetTracingCategory(),
158 "SpdySessionPool::CreateAvailableSessionFromSocketHandle");
159
160 std::unique_ptr<SpdySession> new_session =
Eric Orthfc0583b2021-05-18 19:13:59161 CreateSession(key, net_log.net_log());
Eric Orthac661912022-01-10 21:44:17162 std::set<std::string> dns_aliases =
Cammie Smith Barnes5191037b72021-03-01 22:06:53163 client_socket_handle->socket()->GetDnsAliases();
164
Matt Menkee1d8fe92019-02-07 05:30:54165 new_session->InitializeWithSocketHandle(std::move(client_socket_handle),
166 this);
Bence Béky01d4c232021-03-23 03:09:17167 *session = InsertSession(key, std::move(new_session), net_log,
168 std::move(dns_aliases));
169
170 if (!(*session)->HasAcceptableTransportSecurity()) {
171 (*session)->CloseSessionOnError(ERR_HTTP2_INADEQUATE_TRANSPORT_SECURITY,
172 "");
173 return ERR_HTTP2_INADEQUATE_TRANSPORT_SECURITY;
174 }
175
Bence Béky78b542c2021-03-25 19:30:37176 int rv = (*session)->ParseAlps();
177 if (rv != OK) {
178 DCHECK_NE(ERR_IO_PENDING, rv);
179 // ParseAlps() already closed the connection on error.
180 return rv;
181 }
182
Bence Béky01d4c232021-03-23 03:09:17183 return OK;
Matt Menkee1d8fe92019-02-07 05:30:54184}
185
[email protected]09356c652014-03-25 15:36:10186base::WeakPtr<SpdySession> SpdySessionPool::CreateAvailableSessionFromSocket(
[email protected]04644d42013-07-08 04:29:59187 const SpdySessionKey& key,
Matt Menkee1d8fe92019-02-07 05:30:54188 std::unique_ptr<StreamSocket> socket_stream,
189 const LoadTimingInfo::ConnectTiming& connect_timing,
Bence Béky0ef1556e2017-06-30 19:52:52190 const NetLogWithSource& net_log) {
Alexandr Ilin33126632018-11-14 14:48:17191 TRACE_EVENT0(NetTracingCategory(),
xunjieli0b7f5b62016-12-06 20:43:48192 "SpdySessionPool::CreateAvailableSessionFromSocket");
[email protected]88a332622013-07-30 07:13:32193
Matt Menkee1d8fe92019-02-07 05:30:54194 std::unique_ptr<SpdySession> new_session =
Eric Orthfc0583b2021-05-18 19:13:59195 CreateSession(key, net_log.net_log());
Eric Orthac661912022-01-10 21:44:17196 std::set<std::string> dns_aliases = socket_stream->GetDnsAliases();
[email protected]04644d42013-07-08 04:29:59197
Matt Menkee1d8fe92019-02-07 05:30:54198 new_session->InitializeWithSocket(std::move(socket_stream), connect_timing,
199 this);
[email protected]04644d42013-07-08 04:29:59200
Cammie Smith Barnes5191037b72021-03-01 22:06:53201 return InsertSession(key, std::move(new_session), net_log,
202 std::move(dns_aliases));
[email protected]04644d42013-07-08 04:29:59203}
204
[email protected]795cbf82013-07-22 09:37:27205base::WeakPtr<SpdySession> SpdySessionPool::FindAvailableSession(
[email protected]04644d42013-07-08 04:29:59206 const SpdySessionKey& key,
bnc9ead3ae2017-03-16 00:48:15207 bool enable_ip_based_pooling,
Bence Békyd885b2b2018-02-03 00:58:31208 bool is_websocket,
tfarina428341112016-09-22 13:38:20209 const NetLogWithSource& net_log) {
jdoerrie22a91d8b92018-10-05 08:43:26210 auto it = LookupAvailableSessionByKey(key);
Matt Menkeea6c5b42019-05-02 17:21:16211 if (it == available_sessions_.end() ||
212 (is_websocket && !it->second->support_websocket())) {
Bence Béky53a5aef2018-03-29 21:54:12213 return base::WeakPtr<SpdySession>();
[email protected]41d64e82013-07-03 22:44:26214 }
215
Matt Menkeea6c5b42019-05-02 17:21:16216 if (key == it->second->spdy_session_key()) {
217 UMA_HISTOGRAM_ENUMERATION("Net.SpdySessionGet", FOUND_EXISTING,
218 SPDY_SESSION_GET_MAX);
Eric Roman06bd9742019-07-13 15:19:13219 net_log.AddEventReferencingSource(
Matt Menkeea6c5b42019-05-02 17:21:16220 NetLogEventType::HTTP2_SESSION_POOL_FOUND_EXISTING_SESSION,
Eric Roman06bd9742019-07-13 15:19:13221 it->second->net_log().source());
Matt Menkeea6c5b42019-05-02 17:21:16222 return it->second;
223 }
bnc9ead3ae2017-03-16 00:48:15224
Matt Menkeea6c5b42019-05-02 17:21:16225 if (enable_ip_based_pooling) {
226 UMA_HISTOGRAM_ENUMERATION("Net.SpdySessionGet", FOUND_EXISTING_FROM_IP_POOL,
227 SPDY_SESSION_GET_MAX);
Eric Roman06bd9742019-07-13 15:19:13228 net_log.AddEventReferencingSource(
Matt Menkeea6c5b42019-05-02 17:21:16229 NetLogEventType::HTTP2_SESSION_POOL_FOUND_EXISTING_SESSION_FROM_IP_POOL,
Eric Roman06bd9742019-07-13 15:19:13230 it->second->net_log().source());
Matt Menkeea6c5b42019-05-02 17:21:16231 return it->second;
[email protected]6cd3bd202010-08-30 05:23:06232 }
[email protected]aea80602009-09-18 00:55:08233
[email protected]795cbf82013-07-22 09:37:27234 return base::WeakPtr<SpdySession>();
[email protected]aea80602009-09-18 00:55:08235}
236
Fan Yangf7faef322022-04-29 01:42:42237bool SpdySessionPool::HasAvailableSession(const SpdySessionKey& key,
238 bool is_websocket) const {
239 const auto it = available_sessions_.find(key);
240 return it != available_sessions_.end() &&
241 (!is_websocket || it->second->support_websocket());
242}
243
Matt Menkecd55e922019-04-15 16:25:08244base::WeakPtr<SpdySession> SpdySessionPool::RequestSession(
245 const SpdySessionKey& key,
246 bool enable_ip_based_pooling,
247 bool is_websocket,
248 const NetLogWithSource& net_log,
Matt Menke9338c3792019-04-19 19:16:49249 base::RepeatingClosure on_blocking_request_destroyed_callback,
Matt Menkecd55e922019-04-15 16:25:08250 SpdySessionRequest::Delegate* delegate,
251 std::unique_ptr<SpdySessionRequest>* spdy_session_request,
Matt Menke9338c3792019-04-19 19:16:49252 bool* is_blocking_request_for_session) {
Matt Menkecd55e922019-04-15 16:25:08253 DCHECK(delegate);
254
255 base::WeakPtr<SpdySession> spdy_session =
256 FindAvailableSession(key, enable_ip_based_pooling, is_websocket, net_log);
257 if (spdy_session) {
258 // This value doesn't really matter, but best to always populate it, for
259 // consistency.
Matt Menke9338c3792019-04-19 19:16:49260 *is_blocking_request_for_session = true;
Matt Menkecd55e922019-04-15 16:25:08261 return spdy_session;
262 }
263
Matt Menke9338c3792019-04-19 19:16:49264 RequestInfoForKey* request_info = &spdy_session_request_map_[key];
265 *is_blocking_request_for_session = !request_info->has_blocking_request;
Matt Menke2ab5fe792019-04-18 18:14:13266 *spdy_session_request = std::make_unique<SpdySessionRequest>(
Matt Menke9338c3792019-04-19 19:16:49267 key, enable_ip_based_pooling, is_websocket,
268 *is_blocking_request_for_session, delegate, this);
269 request_info->request_set.insert(spdy_session_request->get());
Matt Menkecd55e922019-04-15 16:25:08270
Matt Menke9338c3792019-04-19 19:16:49271 if (*is_blocking_request_for_session) {
272 request_info->has_blocking_request = true;
273 } else if (on_blocking_request_destroyed_callback) {
274 request_info->deferred_callbacks.push_back(
275 on_blocking_request_destroyed_callback);
Matt Menkecd55e922019-04-15 16:25:08276 }
277 return nullptr;
278}
279
Matt Menke5062be22019-05-01 17:50:24280OnHostResolutionCallbackResult SpdySessionPool::OnHostResolutionComplete(
281 const SpdySessionKey& key,
282 bool is_websocket,
283 const AddressList& addresses) {
284 // If there are no pending requests for that alias, nothing to do.
285 if (spdy_session_request_map_.find(key) == spdy_session_request_map_.end())
286 return OnHostResolutionCallbackResult::kContinue;
287
288 // Check if there's already a matching session. If so, there may already
289 // be a pending task to inform consumers of the alias. In this case, do
290 // nothing, but inform the caller to wait for such a task to run.
291 auto existing_session_it = LookupAvailableSessionByKey(key);
292 if (existing_session_it != available_sessions_.end()) {
Adam Ricebeaae322021-06-30 23:56:29293 if (is_websocket && !existing_session_it->second->support_websocket()) {
294 // We don't look for aliased sessions because it would not be possible to
295 // add them to the available_sessions_ map. See https://crbug.com/1220771.
296 return OnHostResolutionCallbackResult::kContinue;
297 }
Matt Menke5062be22019-05-01 17:50:24298
Adam Ricebeaae322021-06-30 23:56:29299 return OnHostResolutionCallbackResult::kMayBeDeletedAsync;
Matt Menke5062be22019-05-01 17:50:24300 }
Matt Menke5062be22019-05-01 17:50:24301 for (const auto& address : addresses) {
302 auto range = aliases_.equal_range(address);
303 for (auto alias_it = range.first; alias_it != range.second; ++alias_it) {
304 // We found a potential alias.
305 const SpdySessionKey& alias_key = alias_it->second;
306
307 auto available_session_it = LookupAvailableSessionByKey(alias_key);
308 // It shouldn't be in the aliases table if it doesn't exist!
309 DCHECK(available_session_it != available_sessions_.end());
310
Matt Menkedf93ff72020-07-16 02:23:03311 SpdySessionKey::CompareForAliasingResult compare_result =
312 alias_key.CompareForAliasing(key);
313 // Keys must be aliasable.
314 if (!compare_result.is_potentially_aliasable)
Matt Menke5062be22019-05-01 17:50:24315 continue;
Matt Menke5062be22019-05-01 17:50:24316
317 if (is_websocket && !available_session_it->second->support_websocket())
318 continue;
319
320 // Make copy of WeakPtr as call to UnmapKey() will delete original.
321 const base::WeakPtr<SpdySession> available_session =
322 available_session_it->second;
323
324 // Need to verify that the server is authenticated to serve traffic for
325 // |host_port_proxy_pair| too.
326 if (!available_session->VerifyDomainAuthentication(
327 key.host_port_pair().host())) {
328 UMA_HISTOGRAM_ENUMERATION("Net.SpdyIPPoolDomainMatch", 0, 2);
329 continue;
330 }
331
332 UMA_HISTOGRAM_ENUMERATION("Net.SpdyIPPoolDomainMatch", 1, 2);
333
334 bool adding_pooled_alias = true;
335
336 // If socket tags differ, see if session's socket tag can be changed.
Matt Menkedf93ff72020-07-16 02:23:03337 if (!compare_result.is_socket_tag_match) {
Matt Menke5062be22019-05-01 17:50:24338 SpdySessionKey old_key = available_session->spdy_session_key();
339 SpdySessionKey new_key(old_key.host_port_pair(), old_key.proxy_server(),
340 old_key.privacy_mode(),
Matt Menkeae58eeb2019-05-24 21:09:50341 old_key.is_proxy_session(), key.socket_tag(),
dalyka92863972019-10-14 20:25:58342 old_key.network_isolation_key(),
Ben Schwartz3ff4dc1e62021-04-27 21:15:23343 old_key.secure_dns_policy());
Matt Menke5062be22019-05-01 17:50:24344
345 // If there is already a session with |new_key|, skip this one.
346 // It will be found in |aliases_| in a future iteration.
347 if (available_sessions_.find(new_key) != available_sessions_.end())
348 continue;
349
350 if (!available_session->ChangeSocketTag(key.socket_tag()))
351 continue;
352
353 DCHECK(available_session->spdy_session_key() == new_key);
354
355 // If this isn't a pooled alias, but the actual session that needs to
356 // have its socket tag change, there's no need to add an alias.
357 if (new_key == key)
358 adding_pooled_alias = false;
359
360 // Remap main session key.
Eric Orthac661912022-01-10 21:44:17361 std::set<std::string> main_session_old_dns_aliases =
Cammie Smith Barnes5191037b72021-03-01 22:06:53362 GetDnsAliasesForSessionKey(old_key);
Matt Menke5062be22019-05-01 17:50:24363 UnmapKey(old_key);
Cammie Smith Barnes5191037b72021-03-01 22:06:53364 MapKeyToAvailableSession(new_key, available_session,
365 std::move(main_session_old_dns_aliases));
Matt Menke5062be22019-05-01 17:50:24366
367 // Remap alias. From this point on |alias_it| is invalid, so no more
368 // iterations of the loop should be allowed.
369 aliases_.insert(AliasMap::value_type(alias_it->first, new_key));
370 aliases_.erase(alias_it);
371
372 // Remap pooled session keys.
373 const auto& aliases = available_session->pooled_aliases();
374 for (auto it = aliases.begin(); it != aliases.end();) {
375 // Ignore aliases this loop is inserting.
376 if (it->socket_tag() == key.socket_tag()) {
377 ++it;
378 continue;
379 }
Matt Menkeae58eeb2019-05-24 21:09:50380
Eric Orthac661912022-01-10 21:44:17381 std::set<std::string> pooled_alias_old_dns_aliases =
Cammie Smith Barnes5191037b72021-03-01 22:06:53382 GetDnsAliasesForSessionKey(*it);
Matt Menke5062be22019-05-01 17:50:24383 UnmapKey(*it);
dalyka92863972019-10-14 20:25:58384 SpdySessionKey new_pool_alias_key = SpdySessionKey(
385 it->host_port_pair(), it->proxy_server(), it->privacy_mode(),
386 it->is_proxy_session(), key.socket_tag(),
Ben Schwartz3ff4dc1e62021-04-27 21:15:23387 it->network_isolation_key(), it->secure_dns_policy());
Cammie Smith Barnes5191037b72021-03-01 22:06:53388 MapKeyToAvailableSession(new_pool_alias_key, available_session,
389 std::move(pooled_alias_old_dns_aliases));
Matt Menke5062be22019-05-01 17:50:24390 auto old_it = it;
391 ++it;
392 available_session->RemovePooledAlias(*old_it);
393 available_session->AddPooledAlias(new_pool_alias_key);
394
395 // If this is desired key, no need to add an alias for the desired key
396 // at the end of this method.
397 if (new_pool_alias_key == key)
398 adding_pooled_alias = false;
399 }
400 }
401
402 if (adding_pooled_alias) {
Cammie Smith Barnes5191037b72021-03-01 22:06:53403 // Sanitize DNS aliases so that they can be added to the DNS alias map.
Eric Orthac661912022-01-10 21:44:17404 std::set<std::string> fixed_dns_aliases =
405 dns_alias_utility::FixUpDnsAliases(
406 std::set<std::string>(addresses.dns_aliases().begin(),
407 addresses.dns_aliases().end()));
Cammie Smith Barnes5191037b72021-03-01 22:06:53408
Matt Menke5062be22019-05-01 17:50:24409 // Add this session to the map so that we can find it next time.
Cammie Smith Barnes5191037b72021-03-01 22:06:53410 MapKeyToAvailableSession(key, available_session,
Eric Orthac661912022-01-10 21:44:17411 std::move(fixed_dns_aliases));
Matt Menke5062be22019-05-01 17:50:24412 available_session->AddPooledAlias(key);
413 }
414
415 // Post task to inform pending requests for session for |key| that a
416 // matching session is now available.
417 base::ThreadTaskRunnerHandle::Get()->PostTask(
418 FROM_HERE, base::BindOnce(&SpdySessionPool::UpdatePendingRequests,
419 weak_ptr_factory_.GetWeakPtr(), key));
420
421 // Inform the caller that the Callback may be deleted if the consumer is
422 // switched over to the newly aliased session. It's not guaranteed to be
423 // deleted, as the session may be closed, or taken by yet another pending
424 // request with a different SocketTag before the the request can try and
425 // use the session.
426 return OnHostResolutionCallbackResult::kMayBeDeletedAsync;
427 }
428 }
429 return OnHostResolutionCallbackResult::kContinue;
430}
431
[email protected]04644d42013-07-08 04:29:59432void SpdySessionPool::MakeSessionUnavailable(
[email protected]795cbf82013-07-22 09:37:27433 const base::WeakPtr<SpdySession>& available_session) {
[email protected]04644d42013-07-08 04:29:59434 UnmapKey(available_session->spdy_session_key());
435 RemoveAliases(available_session->spdy_session_key());
436 const std::set<SpdySessionKey>& aliases = available_session->pooled_aliases();
jdoerrie22a91d8b92018-10-05 08:43:26437 for (auto it = aliases.begin(); it != aliases.end(); ++it) {
[email protected]04644d42013-07-08 04:29:59438 UnmapKey(*it);
439 RemoveAliases(*it);
[email protected]46da33be2011-07-19 21:58:04440 }
[email protected]04644d42013-07-08 04:29:59441 DCHECK(!IsSessionAvailable(available_session));
442}
[email protected]46da33be2011-07-19 21:58:04443
[email protected]04644d42013-07-08 04:29:59444void SpdySessionPool::RemoveUnavailableSession(
[email protected]795cbf82013-07-22 09:37:27445 const base::WeakPtr<SpdySession>& unavailable_session) {
[email protected]04644d42013-07-08 04:29:59446 DCHECK(!IsSessionAvailable(unavailable_session));
447
448 unavailable_session->net_log().AddEvent(
bncd4365542017-04-14 18:33:17449 NetLogEventType::HTTP2_SESSION_POOL_REMOVE_SESSION);
[email protected]04644d42013-07-08 04:29:59450
jdoerrie22a91d8b92018-10-05 08:43:26451 auto it = sessions_.find(unavailable_session.get());
[email protected]04644d42013-07-08 04:29:59452 CHECK(it != sessions_.end());
danakjaee3e1ec2016-04-16 00:23:18453 std::unique_ptr<SpdySession> owned_session(*it);
[email protected]04644d42013-07-08 04:29:59454 sessions_.erase(it);
[email protected]9f7c4fd2009-11-24 18:50:15455}
456
[email protected]41d64e82013-07-03 22:44:26457// Make a copy of |sessions_| in the Close* functions below to avoid
[email protected]04644d42013-07-08 04:29:59458// reentrancy problems. Since arbitrary functions get called by close
459// handlers, it doesn't suffice to simply increment the iterator
460// before closing.
[email protected]8b114dd72011-03-25 05:33:02461
ttuttle859dc7a2015-04-23 19:42:29462void SpdySessionPool::CloseCurrentSessions(Error error) {
[email protected]04644d42013-07-08 04:29:59463 CloseCurrentSessionsHelper(error, "Closing current sessions.",
464 false /* idle_only */);
[email protected]41d64e82013-07-03 22:44:26465}
466
Nick Harper1f5bf272020-10-29 11:22:35467void SpdySessionPool::CloseCurrentIdleSessions(const std::string& description) {
468 CloseCurrentSessionsHelper(ERR_ABORTED, description, true /* idle_only */);
[email protected]41d64e82013-07-03 22:44:26469}
470
471void SpdySessionPool::CloseAllSessions() {
Bence Béky3ba8c332017-12-11 20:19:24472 auto is_draining = [](const SpdySession* s) { return s->IsDraining(); };
473 // Repeat until every SpdySession owned by |this| is draining.
474 while (!std::all_of(sessions_.begin(), sessions_.end(), is_draining)) {
[email protected]04644d42013-07-08 04:29:59475 CloseCurrentSessionsHelper(ERR_ABORTED, "Closing all sessions.",
476 false /* idle_only */);
[email protected]6cbfa852012-03-14 06:35:54477 }
478}
479
danakjaee3e1ec2016-04-16 00:23:18480std::unique_ptr<base::Value> SpdySessionPool::SpdySessionPoolInfoToValue()
481 const {
Jeremy Roman0579ed62017-08-29 15:56:19482 auto list = std::make_unique<base::ListValue>();
[email protected]1ce7b66b2010-10-12 20:32:44483
jdoerrie22a91d8b92018-10-05 08:43:26484 for (auto it = available_sessions_.begin(); it != available_sessions_.end();
485 ++it) {
[email protected]41d64e82013-07-03 22:44:26486 // Only add the session if the key in the map matches the main
487 // host_port_proxy_pair (not an alias).
488 const SpdySessionKey& key = it->first;
489 const SpdySessionKey& session_key = it->second->spdy_session_key();
Bence Békya12c7702017-12-06 21:07:28490 if (key == session_key)
Jan Wilken Dörrieba777f32019-09-10 20:31:40491 list->Append(it->second->GetInfoAsValue());
[email protected]1ce7b66b2010-10-12 20:32:44492 }
dchengc7eeda422015-12-26 03:56:48493 return std::move(list);
[email protected]1ce7b66b2010-10-12 20:32:44494}
495
[email protected]66761b952010-06-25 21:30:38496void SpdySessionPool::OnIPAddressChanged() {
Stefano Duoe0b077d2022-02-03 11:16:59497 DCHECK(cleanup_sessions_on_ip_address_changed_);
[email protected]d9a2e412014-02-06 11:02:58498 WeakSessionList current_sessions = GetCurrentSessions();
499 for (WeakSessionList::const_iterator it = current_sessions.begin();
500 it != current_sessions.end(); ++it) {
501 if (!*it)
502 continue;
503
Stefano Duo76e1f8402021-10-25 10:27:53504 if (go_away_on_ip_change_) {
505 (*it)->MakeUnavailable();
506 (*it)->StartGoingAway(kLastStreamId, ERR_NETWORK_CHANGED);
507 (*it)->MaybeFinishGoingAway();
508 } else {
509 (*it)->CloseSessionOnError(ERR_NETWORK_CHANGED,
510 "Closing current sessions.");
511 DCHECK((*it)->IsDraining());
512 }
[email protected]d9a2e412014-02-06 11:02:58513 DCHECK(!IsSessionAvailable(*it));
514 }
[email protected]66761b952010-06-25 21:30:38515}
516
David Benjamin247f1ee2019-08-02 21:52:13517void SpdySessionPool::OnSSLConfigChanged(bool is_cert_database_change) {
518 CloseCurrentSessions(is_cert_database_change ? ERR_CERT_DATABASE_CHANGED
519 : ERR_NETWORK_CHANGED);
[email protected]62635c72011-03-10 04:16:25520}
521
David Benjaminbac8dff2019-08-07 01:30:41522void SpdySessionPool::OnSSLConfigForServerChanged(const HostPortPair& server) {
523 WeakSessionList current_sessions = GetCurrentSessions();
524 for (base::WeakPtr<SpdySession>& session : current_sessions) {
525 if (!session)
526 continue;
527
528 const ProxyServer& proxy_server =
529 session->spdy_session_key().proxy_server();
530 if (session->host_port_pair() == server ||
531 (proxy_server.is_http_like() && !proxy_server.is_http() &&
532 proxy_server.host_port_pair() == server)) {
533 session->MakeUnavailable();
David Benjamina68a7952021-05-26 23:26:15534 // Note this call preserves active streams but fails any streams that are
535 // waiting on a stream ID.
536 // TODO(https://crbug.com/1213609): This is not ideal, but SpdySession
537 // does not have a state that supports this.
538 session->StartGoingAway(kLastStreamId, ERR_NETWORK_CHANGED);
David Benjaminbac8dff2019-08-07 01:30:41539 session->MaybeFinishGoingAway();
540 DCHECK(!IsSessionAvailable(session));
541 }
542 }
543}
544
Eric Orthac661912022-01-10 21:44:17545std::set<std::string> SpdySessionPool::GetDnsAliasesForSessionKey(
Cammie Smith Barnes5191037b72021-03-01 22:06:53546 const SpdySessionKey& key) const {
547 auto it = dns_aliases_by_session_key_.find(key);
548 if (it == dns_aliases_by_session_key_.end())
549 return {};
550
551 return it->second;
552}
553
Matt Menke9bcb57b2019-04-12 19:09:34554void SpdySessionPool::RemoveRequestForSpdySession(SpdySessionRequest* request) {
555 DCHECK_EQ(this, request->spdy_session_pool());
556
Matt Menke9338c3792019-04-19 19:16:49557 auto iter = spdy_session_request_map_.find(request->key());
558 DCHECK(iter != spdy_session_request_map_.end());
559
560 // Resume all pending requests if it is the blocking request, which is either
561 // being canceled, or has completed.
562 if (request->is_blocking_request_for_session() &&
563 !iter->second.deferred_callbacks.empty()) {
Matt Menke66e502a72019-04-15 13:34:38564 base::ThreadTaskRunnerHandle::Get()->PostTask(
565 FROM_HERE,
566 base::BindOnce(&SpdySessionPool::UpdatePendingRequests,
Matt Menke9338c3792019-04-19 19:16:49567 weak_ptr_factory_.GetWeakPtr(), request->key()));
Matt Menke66e502a72019-04-15 13:34:38568 }
xunjielia9972092017-06-15 15:57:05569
Jan Wilken Dörrie21f9de72019-06-07 10:41:53570 DCHECK(base::Contains(iter->second.request_set, request));
Matt Menke9338c3792019-04-19 19:16:49571 RemoveRequestInternal(iter, iter->second.request_set.find(request));
xunjieli87258b72017-06-08 14:19:52572}
573
Matt Menke9338c3792019-04-19 19:16:49574SpdySessionPool::RequestInfoForKey::RequestInfoForKey() = default;
575SpdySessionPool::RequestInfoForKey::~RequestInfoForKey() = default;
576
[email protected]04644d42013-07-08 04:29:59577bool SpdySessionPool::IsSessionAvailable(
[email protected]795cbf82013-07-22 09:37:27578 const base::WeakPtr<SpdySession>& session) const {
jdoerrie22a91d8b92018-10-05 08:43:26579 for (auto it = available_sessions_.begin(); it != available_sessions_.end();
580 ++it) {
[email protected]795cbf82013-07-22 09:37:27581 if (it->second.get() == session.get())
[email protected]04644d42013-07-08 04:29:59582 return true;
583 }
584 return false;
585}
586
[email protected]04644d42013-07-08 04:29:59587void SpdySessionPool::MapKeyToAvailableSession(
588 const SpdySessionKey& key,
Cammie Smith Barnes5191037b72021-03-01 22:06:53589 const base::WeakPtr<SpdySession>& session,
Eric Orthac661912022-01-10 21:44:17590 std::set<std::string> dns_aliases) {
Jan Wilken Dörrie21f9de72019-06-07 10:41:53591 DCHECK(base::Contains(sessions_, session.get()));
[email protected]04644d42013-07-08 04:29:59592 std::pair<AvailableSessionMap::iterator, bool> result =
rchebf12982015-04-10 01:15:00593 available_sessions_.insert(std::make_pair(key, session));
[email protected]41d64e82013-07-03 22:44:26594 CHECK(result.second);
Cammie Smith Barnes5191037b72021-03-01 22:06:53595
596 dns_aliases_by_session_key_[key] = std::move(dns_aliases);
[email protected]aea80602009-09-18 00:55:08597}
598
[email protected]04644d42013-07-08 04:29:59599SpdySessionPool::AvailableSessionMap::iterator
600SpdySessionPool::LookupAvailableSessionByKey(
601 const SpdySessionKey& key) {
rchebf12982015-04-10 01:15:00602 return available_sessions_.find(key);
[email protected]d1eda932009-11-04 01:03:10603}
604
[email protected]04644d42013-07-08 04:29:59605void SpdySessionPool::UnmapKey(const SpdySessionKey& key) {
jdoerrie22a91d8b92018-10-05 08:43:26606 auto it = LookupAvailableSessionByKey(key);
[email protected]04644d42013-07-08 04:29:59607 CHECK(it != available_sessions_.end());
608 available_sessions_.erase(it);
Cammie Smith Barnes5191037b72021-03-01 22:06:53609 dns_aliases_by_session_key_.erase(key);
[email protected]8b114dd72011-03-25 05:33:02610}
611
[email protected]04644d42013-07-08 04:29:59612void SpdySessionPool::RemoveAliases(const SpdySessionKey& key) {
[email protected]8b114dd72011-03-25 05:33:02613 // Walk the aliases map, find references to this pair.
614 // TODO(mbelshe): Figure out if this is too expensive.
jdoerrie22a91d8b92018-10-05 08:43:26615 for (auto it = aliases_.begin(); it != aliases_.end();) {
Bence Békya12c7702017-12-06 21:07:28616 if (it->second == key) {
jdoerrie22a91d8b92018-10-05 08:43:26617 auto old_it = it;
[email protected]04644d42013-07-08 04:29:59618 ++it;
619 aliases_.erase(old_it);
620 } else {
621 ++it;
[email protected]8b114dd72011-03-25 05:33:02622 }
[email protected]04644d42013-07-08 04:29:59623 }
624}
625
[email protected]676438e2013-07-22 11:07:33626SpdySessionPool::WeakSessionList SpdySessionPool::GetCurrentSessions() const {
627 WeakSessionList current_sessions;
jdoerrie22a91d8b92018-10-05 08:43:26628 for (auto it = sessions_.begin(); it != sessions_.end(); ++it) {
[email protected]676438e2013-07-22 11:07:33629 current_sessions.push_back((*it)->GetWeakPtr());
630 }
631 return current_sessions;
632}
633
diannahu401e364c2017-04-07 01:17:47634void SpdySessionPool::CloseCurrentSessionsHelper(Error error,
Bence Béky4e83f492018-05-13 23:14:25635 const std::string& description,
diannahu401e364c2017-04-07 01:17:47636 bool idle_only) {
[email protected]676438e2013-07-22 11:07:33637 WeakSessionList current_sessions = GetCurrentSessions();
Bence Béky3ba8c332017-12-11 20:19:24638 for (base::WeakPtr<SpdySession>& session : current_sessions) {
639 if (!session)
[email protected]04644d42013-07-08 04:29:59640 continue;
641
Bence Béky3ba8c332017-12-11 20:19:24642 if (idle_only && session->is_active())
[email protected]04644d42013-07-08 04:29:59643 continue;
644
Bence Béky3ba8c332017-12-11 20:19:24645 if (session->IsDraining())
646 continue;
647
648 session->CloseSessionOnError(error, description);
649
650 DCHECK(!IsSessionAvailable(session));
651 DCHECK(!session || session->IsDraining());
[email protected]8b114dd72011-03-25 05:33:02652 }
[email protected]aea80602009-09-18 00:55:08653}
654
Matt Menkee1d8fe92019-02-07 05:30:54655std::unique_ptr<SpdySession> SpdySessionPool::CreateSession(
656 const SpdySessionKey& key,
Matt Menkee1d8fe92019-02-07 05:30:54657 NetLog* net_log) {
658 UMA_HISTOGRAM_ENUMERATION("Net.SpdySessionGet", IMPORTED_FROM_SOCKET,
659 SPDY_SESSION_GET_MAX);
660
Matt Menke5062be22019-05-01 17:50:24661 // If there's a pre-existing matching session, it has to be an alias. Remove
662 // the alias.
663 auto it = LookupAvailableSessionByKey(key);
664 if (it != available_sessions_.end()) {
665 DCHECK(key != it->second->spdy_session_key());
666
667 // Remove session from available sessions and from aliases, and remove
668 // key from the session's pooled alias set, so that a new session can be
669 // created with this |key|.
670 it->second->RemovePooledAlias(key);
671 UnmapKey(key);
672 RemoveAliases(key);
673 }
674
Matt Menkee1d8fe92019-02-07 05:30:54675 return std::make_unique<SpdySession>(
676 key, http_server_properties_, transport_security_state_,
David Benjamin151ec6b2019-08-02 19:38:52677 ssl_client_context_ ? ssl_client_context_->ssl_config_service() : nullptr,
678 quic_supported_versions_, enable_sending_initial_data_,
Ryan Hamilton0246af92019-08-30 19:28:56679 enable_ping_based_connection_checking_, is_http2_enabled_,
Eric Orthfc0583b2021-05-18 19:13:59680 is_quic_enabled_, session_max_recv_window_size_,
Ryan Hamiltonf01aaef52019-09-30 23:00:51681 session_max_queued_capped_frames_, initial_settings_,
Bence Békyd228fb22021-10-29 14:45:51682 enable_http2_settings_grease_, greased_http2_frame_,
683 http2_end_stream_with_data_frame_, enable_priority_update_, time_func_,
684 push_delegate_, network_quality_estimator_, net_log);
Matt Menkee1d8fe92019-02-07 05:30:54685}
686
687base::WeakPtr<SpdySession> SpdySessionPool::InsertSession(
688 const SpdySessionKey& key,
689 std::unique_ptr<SpdySession> new_session,
Cammie Smith Barnes5191037b72021-03-01 22:06:53690 const NetLogWithSource& source_net_log,
Eric Orthac661912022-01-10 21:44:17691 std::set<std::string> dns_aliases) {
Matt Menkee1d8fe92019-02-07 05:30:54692 base::WeakPtr<SpdySession> available_session = new_session->GetWeakPtr();
693 sessions_.insert(new_session.release());
Cammie Smith Barnes5191037b72021-03-01 22:06:53694 MapKeyToAvailableSession(key, available_session, std::move(dns_aliases));
Matt Menkee1d8fe92019-02-07 05:30:54695
Matt Menke66e502a72019-04-15 13:34:38696 base::ThreadTaskRunnerHandle::Get()->PostTask(
697 FROM_HERE, base::BindOnce(&SpdySessionPool::UpdatePendingRequests,
698 weak_ptr_factory_.GetWeakPtr(), key));
699
Eric Roman06bd9742019-07-13 15:19:13700 source_net_log.AddEventReferencingSource(
Matt Menkee1d8fe92019-02-07 05:30:54701 NetLogEventType::HTTP2_SESSION_POOL_IMPORTED_SESSION_FROM_SOCKET,
Eric Roman06bd9742019-07-13 15:19:13702 available_session->net_log().source());
Matt Menkee1d8fe92019-02-07 05:30:54703
704 // Look up the IP address for this session so that we can match
705 // future sessions (potentially to different domains) which can
706 // potentially be pooled with this one. Because GetPeerAddress()
707 // reports the proxy's address instead of the origin server, check
708 // to see if this is a direct connection.
709 if (key.proxy_server().is_direct()) {
710 IPEndPoint address;
711 if (available_session->GetPeerAddress(&address) == OK)
712 aliases_.insert(AliasMap::value_type(address, key));
713 }
714
715 return available_session;
716}
717
Matt Menke66e502a72019-04-15 13:34:38718void SpdySessionPool::UpdatePendingRequests(const SpdySessionKey& key) {
Matt Menke66e502a72019-04-15 13:34:38719 auto it = LookupAvailableSessionByKey(key);
720 if (it != available_sessions_.end()) {
721 base::WeakPtr<SpdySession> new_session = it->second->GetWeakPtr();
Matt Menke2ab5fe792019-04-18 18:14:13722 bool is_pooled = (key != new_session->spdy_session_key());
Matt Menke66e502a72019-04-15 13:34:38723 while (new_session && new_session->IsAvailable()) {
724 // Each iteration may empty out the RequestSet for |spdy_session_key| in
725 // |spdy_session_request_map_|. So each time, check for RequestSet and use
726 // the first one. Could just keep track if the last iteration removed the
727 // final request, but it's possible that responding to one request will
728 // result in cancelling another one.
729 //
730 // TODO(willchan): If it's important, switch RequestSet out for a FIFO
731 // queue (Order by priority first, then FIFO within same priority).
732 // Unclear that it matters here.
733 auto iter = spdy_session_request_map_.find(key);
734 if (iter == spdy_session_request_map_.end())
735 break;
Matt Menke9338c3792019-04-19 19:16:49736 RequestSet* request_set = &iter->second.request_set;
Matt Menke77173952019-04-18 17:42:14737 // Find a request that can use the socket, if any.
738 RequestSet::iterator request;
739 for (request = request_set->begin(); request != request_set->end();
740 ++request) {
741 // If the request is for use with websockets, and the session doesn't
742 // support websockets, skip over the request.
743 if ((*request)->is_websocket() && !new_session->support_websocket())
744 continue;
Matt Menke2ab5fe792019-04-18 18:14:13745 // Don't use IP pooled session if not allowed.
746 if (!(*request)->enable_ip_based_pooling() && is_pooled)
747 continue;
Matt Menke77173952019-04-18 17:42:14748 break;
749 }
750 if (request == request_set->end())
751 break;
752
Matt Menke66e502a72019-04-15 13:34:38753 SpdySessionRequest::Delegate* delegate = (*request)->delegate();
Matt Menke66e502a72019-04-15 13:34:38754 RemoveRequestInternal(iter, request);
Matt Menke66e502a72019-04-15 13:34:38755 delegate->OnSpdySessionAvailable(new_session);
756 }
757 }
758
Matt Menke9338c3792019-04-19 19:16:49759 auto iter = spdy_session_request_map_.find(key);
760 if (iter == spdy_session_request_map_.end())
Matt Menkecd55e922019-04-15 16:25:08761 return;
762 // Remove all pending requests, if there are any. As a result, if one of these
763 // callbacks triggers a new RequestSession() call,
Matt Menke9338c3792019-04-19 19:16:49764 // |is_blocking_request_for_session| will be true.
765 std::list<base::RepeatingClosure> deferred_requests =
766 std::move(iter->second.deferred_callbacks);
Matt Menkecd55e922019-04-15 16:25:08767
Matt Menke9338c3792019-04-19 19:16:49768 // Delete the RequestMap if there are no SpdySessionRequests, and no deferred
769 // requests.
770 if (iter->second.request_set.empty())
771 spdy_session_request_map_.erase(iter);
772
773 // Resume any deferred requests. This needs to be after the
Matt Menke66e502a72019-04-15 13:34:38774 // OnSpdySessionAvailable() calls, to prevent requests from calling into the
775 // socket pools in cases where that's not necessary.
Matt Menke9338c3792019-04-19 19:16:49776 for (auto callback : deferred_requests) {
Matt Menke66e502a72019-04-15 13:34:38777 callback.Run();
Matt Menkecd55e922019-04-15 16:25:08778 }
Matt Menke66e502a72019-04-15 13:34:38779}
780
781void SpdySessionPool::RemoveRequestInternal(
782 SpdySessionRequestMap::iterator request_map_iterator,
783 RequestSet::iterator request_set_iterator) {
784 SpdySessionRequest* request = *request_set_iterator;
Matt Menke9338c3792019-04-19 19:16:49785 request_map_iterator->second.request_set.erase(request_set_iterator);
786 if (request->is_blocking_request_for_session()) {
787 DCHECK(request_map_iterator->second.has_blocking_request);
788 request_map_iterator->second.has_blocking_request = false;
789 }
790
791 // If both lists of requests are empty, can now remove the entry from the map.
792 if (request_map_iterator->second.request_set.empty() &&
793 request_map_iterator->second.deferred_callbacks.empty()) {
Matt Menke66e502a72019-04-15 13:34:38794 spdy_session_request_map_.erase(request_map_iterator);
Matt Menke9338c3792019-04-19 19:16:49795 }
Matt Menke66e502a72019-04-15 13:34:38796 request->OnRemovedFromPool();
797}
798
[email protected]aea80602009-09-18 00:55:08799} // namespace net