HttpStreamPool: Fix checking available SpdySession
AttemptManager has CHECK to ensure there is no available SpdySession when attempting a TCP-based connection. It used SpdySessionPool::HasAvailableSession() for the check. However, the method didn't consider whether to enable or disable IP-based pooling. The method could return true when there was an aliased SpdySession, even when we disabled IP-based pooling, resulting in hitting CHECK failure. This CL modifies HasAvailableSession() to take a flag that indicate whether IP-based pooling is enabled or disabled. The method returns false if IP-based pooling is disabled even when there is an aliased SpdySession, in a way similar to FindAvailableSession(). Update HttpNetworkTransactionTest.RetryWithoutConnectionPooling test to keep the first SpdySession to cover this case (Previously the first SpdySession was closed before the second SpdySession was created). Also use some actual NetLog sources so that we can see NetLog events when `--log-net-log` command line flag is specified (useful for debugging). Bug: 397322724 Change-Id: Id52495d297661d2acce19c19057f6c5b25920fa8 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6284467 Reviewed-by: mmenke <mmenke@chromium.org> Commit-Queue: Kenichi Ishibashi <bashi@chromium.org> Cr-Commit-Position: refs/heads/main@{#1424264}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
fbd60a65b8
commit
cf6f56623e
@ -464,7 +464,7 @@ class HttpNetworkTransactionTestBase : public PlatformTest,
|
||||
/*ssl_client_context=*/nullptr,
|
||||
/*socket_performance_watcher_factory=*/nullptr,
|
||||
/*network_quality_estimator=*/nullptr,
|
||||
/*net_log=*/nullptr,
|
||||
/*net_log=*/NetLog::Get(),
|
||||
/*websocket_endpoint_lock_manager=*/nullptr,
|
||||
/*http_server_properties=*/nullptr,
|
||||
/*alpn_protos=*/nullptr,
|
||||
@ -20870,7 +20870,7 @@ TEST_P(HttpNetworkTransactionTest, RetryWithoutConnectionPooling) {
|
||||
|
||||
std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
|
||||
|
||||
// Two requests on the first connection.
|
||||
// Two requests on the first H2 connection.
|
||||
spdy::SpdySerializedFrame req1(
|
||||
spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
|
||||
spdy_util_.UpdateWithStreamDestruction(1);
|
||||
@ -20884,7 +20884,8 @@ TEST_P(HttpNetworkTransactionTest, RetryWithoutConnectionPooling) {
|
||||
CreateMockWrite(rst, 6),
|
||||
};
|
||||
|
||||
// The first one succeeds, the second gets error 421 Misdirected Request.
|
||||
// The first request succeeds, the second request gets error 421 Misdirected
|
||||
// Request. The first H2 connection remains available after getting 421.
|
||||
spdy::SpdySerializedFrame resp1(
|
||||
spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
|
||||
spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
|
||||
@ -20892,8 +20893,10 @@ TEST_P(HttpNetworkTransactionTest, RetryWithoutConnectionPooling) {
|
||||
response_headers[spdy::kHttp2StatusHeader] = "421";
|
||||
spdy::SpdySerializedFrame resp2(
|
||||
spdy_util_.ConstructSpdyReply(3, std::move(response_headers)));
|
||||
MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
|
||||
CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
|
||||
MockRead reads1[] = {
|
||||
CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
|
||||
CreateMockRead(resp2, 4),
|
||||
MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5) /* stalls forever */};
|
||||
|
||||
MockConnect connect1(ASYNC, OK, peer_addr);
|
||||
SequencedSocketData data1(connect1, reads1, writes1);
|
||||
@ -20901,7 +20904,7 @@ TEST_P(HttpNetworkTransactionTest, RetryWithoutConnectionPooling) {
|
||||
|
||||
AddSSLSocketData();
|
||||
|
||||
// Retry the second request on a second connection.
|
||||
// Retry the second request on the second H2 connection.
|
||||
SpdyTestUtil spdy_util2(/*use_priority_header=*/true);
|
||||
spdy::SpdySerializedFrame req3(
|
||||
spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
|
||||
@ -20936,7 +20939,8 @@ TEST_P(HttpNetworkTransactionTest, RetryWithoutConnectionPooling) {
|
||||
HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
|
||||
|
||||
TestCompletionCallback callback;
|
||||
rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
|
||||
rv = trans1.Start(&request1, callback.callback(),
|
||||
NetLogWithSource::Make(NetLogSourceType::URL_REQUEST));
|
||||
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
|
||||
rv = callback.WaitForResult();
|
||||
EXPECT_THAT(rv, IsOk());
|
||||
@ -20961,7 +20965,7 @@ TEST_P(HttpNetworkTransactionTest, RetryWithoutConnectionPooling) {
|
||||
|
||||
RecordingNetLogObserver net_log_observer;
|
||||
rv = trans2.Start(&request2, callback.callback(),
|
||||
NetLogWithSource::Make(NetLogSourceType::NONE));
|
||||
NetLogWithSource::Make(NetLogSourceType::URL_REQUEST));
|
||||
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
|
||||
rv = callback.WaitForResult();
|
||||
EXPECT_THAT(rv, IsOk());
|
||||
|
@ -311,8 +311,9 @@ void HttpStreamFactory::Job::SetPriority(RequestPriority priority) {
|
||||
|
||||
bool HttpStreamFactory::Job::HasAvailableSpdySession() const {
|
||||
return !using_quic_ && CanUseExistingSpdySession() &&
|
||||
session_->spdy_session_pool()->HasAvailableSession(spdy_session_key_,
|
||||
is_websocket_);
|
||||
session_->spdy_session_pool()->HasAvailableSession(
|
||||
spdy_session_key_,
|
||||
/*enable_ip_based_pooling=*/true, is_websocket_);
|
||||
}
|
||||
|
||||
bool HttpStreamFactory::Job::HasAvailableQuicSession() const {
|
||||
|
@ -1739,8 +1739,8 @@ void HttpStreamPool::AttemptManager::CreateTextBasedStreamAndNotify(
|
||||
}
|
||||
|
||||
bool HttpStreamPool::AttemptManager::HasAvailableSpdySession() const {
|
||||
return spdy_session_pool()->HasAvailableSession(spdy_session_key(),
|
||||
/*is_websocket=*/false);
|
||||
return spdy_session_pool()->HasAvailableSession(
|
||||
spdy_session_key(), IsIpBasedPoolingEnabled(), /*is_websocket=*/false);
|
||||
}
|
||||
|
||||
void HttpStreamPool::AttemptManager::CreateSpdyStreamAndNotify(
|
||||
@ -1943,7 +1943,6 @@ void HttpStreamPool::AttemptManager::OnInFlightAttemptComplete(
|
||||
|
||||
const auto reuse_type = StreamSocketHandle::SocketReuseType::kUnused;
|
||||
if (stream_socket->GetNegotiatedProtocol() == NextProto::kProtoHTTP2) {
|
||||
CHECK(!HasAvailableSpdySession());
|
||||
std::unique_ptr<HttpStreamPoolHandle> handle = group_->CreateHandle(
|
||||
std::move(stream_socket), reuse_type, std::move(connect_timing));
|
||||
base::WeakPtr<SpdySession> spdy_session;
|
||||
|
@ -524,8 +524,10 @@ class HttpStreamPoolAttemptManagerTest : public TestWithTaskEnvironment {
|
||||
const HttpStreamKey& stream_key,
|
||||
IPEndPoint peer_addr = IPEndPoint(IPAddress(192, 0, 2, 1), 443)) {
|
||||
Group& group = pool().GetOrCreateGroupForTesting(stream_key);
|
||||
CHECK(!spdy_session_pool()->HasAvailableSession(group.spdy_session_key(),
|
||||
/*is_websocket=*/false));
|
||||
CHECK(!spdy_session_pool()->HasAvailableSession(
|
||||
group.spdy_session_key(),
|
||||
/*enable_ip_based_pooling=*/true,
|
||||
/*is_websocket=*/false));
|
||||
auto socket = FakeStreamSocket::CreateForSpdy();
|
||||
socket->set_peer_addr(peer_addr);
|
||||
auto handle = group.CreateHandle(
|
||||
@ -2854,7 +2856,9 @@ TEST_F(HttpStreamPoolAttemptManagerTest, RequireHttp11AfterSpdySessionCreated) {
|
||||
requester1.WaitForResult();
|
||||
EXPECT_THAT(requester1.result(), Optional(IsOk()));
|
||||
ASSERT_TRUE(spdy_session_pool()->HasAvailableSession(
|
||||
stream_key.CalculateSpdySessionKey(), /*is_websocket=*/false));
|
||||
stream_key.CalculateSpdySessionKey(),
|
||||
/*enable_ip_based_pooling=*/true,
|
||||
/*is_websocket=*/false));
|
||||
|
||||
// Disable HTTP/2.
|
||||
http_server_properties()->SetHTTP11Required(
|
||||
@ -2862,7 +2866,8 @@ TEST_F(HttpStreamPoolAttemptManagerTest, RequireHttp11AfterSpdySessionCreated) {
|
||||
// At this point, the SPDY session is still available because it becomes
|
||||
// unavailable after the next request is made.
|
||||
ASSERT_TRUE(spdy_session_pool()->HasAvailableSession(
|
||||
stream_key.CalculateSpdySessionKey(), /*is_websocket=*/false));
|
||||
stream_key.CalculateSpdySessionKey(), /*enable_ip_based_pooling=*/true,
|
||||
/*is_websocket=*/false));
|
||||
|
||||
// Request a stream again. The second request is paused because the first
|
||||
// request is still alive and the corresponding attempt manager is still
|
||||
@ -2873,7 +2878,8 @@ TEST_F(HttpStreamPoolAttemptManagerTest, RequireHttp11AfterSpdySessionCreated) {
|
||||
ASSERT_FALSE(requester2.result().has_value());
|
||||
// The SPDY session should become unavailable.
|
||||
ASSERT_FALSE(spdy_session_pool()->HasAvailableSession(
|
||||
stream_key.CalculateSpdySessionKey(), /*is_websocket=*/false));
|
||||
stream_key.CalculateSpdySessionKey(), /*enable_ip_based_pooling=*/true,
|
||||
/*is_websocket=*/false));
|
||||
|
||||
// Destroy the first request. It should resume the paused request.
|
||||
requester1.ResetRequest();
|
||||
@ -2902,7 +2908,8 @@ TEST_F(HttpStreamPoolAttemptManagerTest,
|
||||
RunUntilIdle();
|
||||
EXPECT_THAT(requester1.result(), Optional(IsOk()));
|
||||
ASSERT_TRUE(spdy_session_pool()->HasAvailableSession(
|
||||
stream_key.CalculateSpdySessionKey(), /*is_websocket=*/false));
|
||||
stream_key.CalculateSpdySessionKey(), /*enable_ip_based_pooling=*/true,
|
||||
/*is_websocket=*/false));
|
||||
|
||||
// Disable HTTP/2.
|
||||
http_server_properties()->SetHTTP11Required(
|
||||
@ -2910,7 +2917,8 @@ TEST_F(HttpStreamPoolAttemptManagerTest,
|
||||
// At this point, the SPDY session is still available because it becomes
|
||||
// unavailable after the next request is made.
|
||||
ASSERT_TRUE(spdy_session_pool()->HasAvailableSession(
|
||||
stream_key.CalculateSpdySessionKey(), /*is_websocket=*/false));
|
||||
stream_key.CalculateSpdySessionKey(), /*enable_ip_based_pooling=*/true,
|
||||
/*is_websocket=*/false));
|
||||
|
||||
// Destroy the first request.
|
||||
requester1.ResetRequest();
|
||||
@ -2932,7 +2940,8 @@ TEST_F(HttpStreamPoolAttemptManagerTest,
|
||||
RunUntilIdle();
|
||||
EXPECT_THAT(requester2.result(), Optional(IsOk()));
|
||||
ASSERT_FALSE(spdy_session_pool()->HasAvailableSession(
|
||||
stream_key.CalculateSpdySessionKey(), /*is_websocket=*/false));
|
||||
stream_key.CalculateSpdySessionKey(), /*enable_ip_based_pooling=*/true,
|
||||
/*is_websocket=*/false));
|
||||
}
|
||||
|
||||
TEST_F(HttpStreamPoolAttemptManagerTest, DoNotUseSpdySessionForHttpRequest) {
|
||||
@ -2959,7 +2968,8 @@ TEST_F(HttpStreamPoolAttemptManagerTest, DoNotUseSpdySessionForHttpRequest) {
|
||||
EXPECT_THAT(requester_https.result(), Optional(IsOk()));
|
||||
EXPECT_EQ(requester_https.negotiated_protocol(), NextProto::kProtoHTTP2);
|
||||
ASSERT_TRUE(spdy_session_pool()->HasAvailableSession(
|
||||
stream_key.CalculateSpdySessionKey(), /*is_websocket=*/false));
|
||||
stream_key.CalculateSpdySessionKey(), /*enable_ip_based_pooling=*/true,
|
||||
/*is_websocket=*/false));
|
||||
|
||||
// Request a stream for http (not https). The second request should use
|
||||
// HTTP/1.1 and should not use the existing SPDY session.
|
||||
@ -2993,7 +3003,8 @@ TEST_F(HttpStreamPoolAttemptManagerTest, CloseIdleSpdySessionWhenPoolStalled) {
|
||||
StreamKeyBuilder().set_destination(kDestinationA).Build();
|
||||
CreateFakeSpdySession(stream_key_a);
|
||||
ASSERT_TRUE(spdy_session_pool()->HasAvailableSession(
|
||||
stream_key_a.CalculateSpdySessionKey(), /*is_websocket=*/false));
|
||||
stream_key_a.CalculateSpdySessionKey(), /*enable_ip_based_pooling=*/true,
|
||||
/*is_websocket=*/false));
|
||||
|
||||
resolver()
|
||||
->AddFakeRequest()
|
||||
@ -3015,9 +3026,11 @@ TEST_F(HttpStreamPoolAttemptManagerTest, CloseIdleSpdySessionWhenPoolStalled) {
|
||||
EXPECT_EQ(requester_b.negotiated_protocol(), NextProto::kProtoHTTP2);
|
||||
ASSERT_TRUE(spdy_session_pool()->HasAvailableSession(
|
||||
requester_b.GetStreamKey().CalculateSpdySessionKey(),
|
||||
/*enable_ip_based_pooling=*/true,
|
||||
/*is_websocket=*/false));
|
||||
ASSERT_FALSE(spdy_session_pool()->HasAvailableSession(
|
||||
stream_key_a.CalculateSpdySessionKey(), /*is_websocket=*/false));
|
||||
stream_key_a.CalculateSpdySessionKey(), /*enable_ip_based_pooling=*/true,
|
||||
/*is_websocket=*/false));
|
||||
}
|
||||
|
||||
TEST_F(HttpStreamPoolAttemptManagerTest, SpdySessionBecomeUnavailable) {
|
||||
@ -3139,7 +3152,8 @@ TEST_F(HttpStreamPoolAttemptManagerTest,
|
||||
RunUntilIdle();
|
||||
EXPECT_THAT(preconnector1.result(), Optional(IsOk()));
|
||||
ASSERT_TRUE(spdy_session_pool()->HasAvailableSession(
|
||||
stream_key.CalculateSpdySessionKey(), /*is_websocket=*/false));
|
||||
stream_key.CalculateSpdySessionKey(), /*enable_ip_based_pooling=*/true,
|
||||
/*is_websocket=*/false));
|
||||
|
||||
// Disable HTTP/2.
|
||||
http_server_properties()->SetHTTP11Required(
|
||||
@ -3162,7 +3176,8 @@ TEST_F(HttpStreamPoolAttemptManagerTest,
|
||||
EXPECT_THAT(rv, IsError(ERR_HTTP_1_1_REQUIRED));
|
||||
RunUntilIdle();
|
||||
ASSERT_FALSE(spdy_session_pool()->HasAvailableSession(
|
||||
stream_key.CalculateSpdySessionKey(), /*is_websocket=*/false));
|
||||
stream_key.CalculateSpdySessionKey(), /*enable_ip_based_pooling=*/true,
|
||||
/*is_websocket=*/false));
|
||||
}
|
||||
|
||||
TEST_F(HttpStreamPoolAttemptManagerTest, SpdyReachedPoolLimit) {
|
||||
@ -3325,8 +3340,8 @@ TEST_F(HttpStreamPoolAttemptManagerTest,
|
||||
// The session was already closed so it's not available.
|
||||
ASSERT_FALSE(spdy_session_pool()->FindAvailableSession(
|
||||
requester_b.GetStreamKey().CalculateSpdySessionKey(),
|
||||
/*enable_ip_based_pooling=*/true, /*is_websocket=*/false,
|
||||
NetLogWithSource()));
|
||||
/*enable_ip_based_pooling=*/true,
|
||||
/*is_websocket=*/false, NetLogWithSource()));
|
||||
}
|
||||
|
||||
TEST_F(HttpStreamPoolAttemptManagerTest, SpdyPreconnectMatchingIpSession) {
|
||||
@ -3931,7 +3946,8 @@ TEST_F(HttpStreamPoolAttemptManagerTest, PreconnectMultipleStreamsHttp2) {
|
||||
EXPECT_THAT(preconnector.result(), Optional(IsOk()));
|
||||
ASSERT_EQ(group.IdleStreamSocketCount(), 0u);
|
||||
ASSERT_TRUE(spdy_session_pool()->HasAvailableSession(
|
||||
stream_key.CalculateSpdySessionKey(), false));
|
||||
stream_key.CalculateSpdySessionKey(), /*enable_ip_based_pooling=*/true,
|
||||
/*is_websocket=*/false));
|
||||
}
|
||||
|
||||
TEST_F(HttpStreamPoolAttemptManagerTest, PreconnectRequireHttp1) {
|
||||
@ -3972,7 +3988,8 @@ TEST_F(HttpStreamPoolAttemptManagerTest, PreconnectRequireHttp1) {
|
||||
EXPECT_THAT(preconnector.result(), Optional(IsOk()));
|
||||
ASSERT_EQ(group.IdleStreamSocketCount(), 2u);
|
||||
ASSERT_FALSE(spdy_session_pool()->HasAvailableSession(
|
||||
stream_key.CalculateSpdySessionKey(), false));
|
||||
stream_key.CalculateSpdySessionKey(), /*enable_ip_based_pooling=*/true,
|
||||
/*is_websocket=*/false));
|
||||
}
|
||||
|
||||
TEST_F(HttpStreamPoolAttemptManagerTest, PreconnectMultipleStreamsOkAndFail) {
|
||||
|
@ -249,7 +249,8 @@ int HttpStreamPool::JobController::Preconnect(
|
||||
SpdySessionKey spdy_session_key =
|
||||
origin_stream_key_.CalculateSpdySessionKey();
|
||||
bool had_spdy_session = spdy_session_pool()->HasAvailableSession(
|
||||
spdy_session_key, /*is_websocket=*/false);
|
||||
spdy_session_key, /*enable_ip_based_pooling=*/true,
|
||||
/*is_websocket=*/false);
|
||||
if (pool_->FindAvailableSpdySession(origin_stream_key_, spdy_session_key,
|
||||
/*enable_ip_based_pooling=*/true)) {
|
||||
net_log_.AddEvent(
|
||||
|
@ -4253,11 +4253,13 @@ TEST_P(SpdyNetworkTransactionTest, GracefulGoaway) {
|
||||
SecureDnsPolicy::kAllow,
|
||||
/*disable_cert_verification_network_fetches=*/false);
|
||||
EXPECT_TRUE(
|
||||
spdy_session_pool->HasAvailableSession(key, /* is_websocket = */ false));
|
||||
spdy_session_pool->HasAvailableSession(key,
|
||||
/*enable_ip_based_pooling=*/true,
|
||||
/*is_websocket=*/false));
|
||||
base::WeakPtr<SpdySession> spdy_session =
|
||||
spdy_session_pool->FindAvailableSession(
|
||||
key, /* enable_ip_based_pooling = */ true,
|
||||
/* is_websocket = */ false, log_);
|
||||
spdy_session_pool->FindAvailableSession(key,
|
||||
/*enable_ip_based_pooling=*/true,
|
||||
/*is_websocket=*/false, log_);
|
||||
EXPECT_TRUE(spdy_session);
|
||||
|
||||
// Start second transaction.
|
||||
@ -4290,7 +4292,9 @@ TEST_P(SpdyNetworkTransactionTest, GracefulGoaway) {
|
||||
|
||||
// Graceful GOAWAY was received, SpdySession should be unavailable.
|
||||
EXPECT_FALSE(
|
||||
spdy_session_pool->HasAvailableSession(key, /* is_websocket = */ false));
|
||||
spdy_session_pool->HasAvailableSession(key,
|
||||
/*enable_ip_based_pooling=*/true,
|
||||
/*is_websocket=*/false));
|
||||
spdy_session = spdy_session_pool->FindAvailableSession(
|
||||
key, /* enable_ip_based_pooling = */ true,
|
||||
/* is_websocket = */ false, log_);
|
||||
@ -7564,7 +7568,7 @@ TEST_P(SpdyNetworkTransactionTest,
|
||||
NetworkAnonymizationKey(), SecureDnsPolicy::kAllow,
|
||||
/*disable_cert_verification_network_fetches=*/false);
|
||||
EXPECT_TRUE(helper.session()->spdy_session_pool()->HasAvailableSession(
|
||||
key1, /* is_websocket = */ false));
|
||||
key1, /*enable_ip_based_pooling=*/true, /*is_websocket=*/false));
|
||||
base::WeakPtr<SpdySession> spdy_session1 =
|
||||
helper.session()->spdy_session_pool()->FindAvailableSession(
|
||||
key1, /* enable_ip_based_pooling = */ true,
|
||||
@ -7582,7 +7586,9 @@ TEST_P(SpdyNetworkTransactionTest,
|
||||
NetworkAnonymizationKey(), SecureDnsPolicy::kAllow,
|
||||
/*disable_cert_verification_network_fetches=*/false);
|
||||
EXPECT_TRUE(helper.session()->spdy_session_pool()->HasAvailableSession(
|
||||
key2, /* is_websocket = */ true));
|
||||
key2, /*enable_ip_based_pooling=*/true, /*is_websocket=*/true));
|
||||
EXPECT_FALSE(helper.session()->spdy_session_pool()->HasAvailableSession(
|
||||
key2, /*enable_ip_based_pooling=*/false, /*is_websocket=*/false));
|
||||
base::WeakPtr<SpdySession> spdy_session2 =
|
||||
helper.session()->spdy_session_pool()->FindAvailableSession(
|
||||
key1, /* enable_ip_based_pooling = */ true,
|
||||
|
@ -235,7 +235,8 @@ SpdySessionPool::FindMatchingIpSessionForServiceEndpoint(
|
||||
const SpdySessionKey& key,
|
||||
const ServiceEndpoint& service_endpoint,
|
||||
const std::set<std::string>& dns_aliases) {
|
||||
CHECK(!HasAvailableSession(key, /*is_websocket=*/false));
|
||||
CHECK(!HasAvailableSession(key, /*enable_ip_based_pooling=*/true,
|
||||
/*is_websocket=*/false));
|
||||
CHECK(key.socket_tag() == SocketTag());
|
||||
|
||||
base::WeakPtr<SpdySession> session =
|
||||
@ -248,10 +249,15 @@ SpdySessionPool::FindMatchingIpSessionForServiceEndpoint(
|
||||
}
|
||||
|
||||
bool SpdySessionPool::HasAvailableSession(const SpdySessionKey& key,
|
||||
bool enable_ip_based_pooling,
|
||||
bool is_websocket) const {
|
||||
const auto it = available_sessions_.find(key);
|
||||
return it != available_sessions_.end() &&
|
||||
(!is_websocket || it->second->support_websocket());
|
||||
auto it = available_sessions_.find(key);
|
||||
if (it == available_sessions_.end() ||
|
||||
(is_websocket && !it->second->support_websocket())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return enable_ip_based_pooling ? true : key == it->second->spdy_session_key();
|
||||
}
|
||||
|
||||
base::WeakPtr<SpdySession> SpdySessionPool::RequestSession(
|
||||
|
@ -214,8 +214,12 @@ class NET_EXPORT SpdySessionPool
|
||||
const ServiceEndpoint& service_endpoint,
|
||||
const std::set<std::string>& dns_aliases);
|
||||
|
||||
// Returns true if there is an available session for |key|.
|
||||
bool HasAvailableSession(const SpdySessionKey& key, bool is_websocket) const;
|
||||
// Returns true if there is an available session for `key`. Otherwise, if
|
||||
// there is a session to pool to based on IP address, returns true if
|
||||
// `enable_ip_based_pooling` is true. Otherwise returns false.
|
||||
bool HasAvailableSession(const SpdySessionKey& key,
|
||||
bool enable_ip_based_pooling,
|
||||
bool is_websocket) const;
|
||||
|
||||
// Just like FindAvailableSession.
|
||||
//
|
||||
|
@ -3400,22 +3400,29 @@ TEST_F(SpdySessionTest, CloseOneIdleConnectionWithAlias) {
|
||||
ClientSocketPool* pool = http_session_->GetSocketPool(
|
||||
HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyChain::Direct());
|
||||
|
||||
// Create an idle SPDY session.
|
||||
SpdySessionKey key1(HostPortPair("www.example.org", 80),
|
||||
PRIVACY_MODE_DISABLED, ProxyChain::Direct(),
|
||||
SessionUsage::kDestination, SocketTag(),
|
||||
NetworkAnonymizationKey(), SecureDnsPolicy::kAllow,
|
||||
/*disable_cert_verification_network_fetches=*/false);
|
||||
base::WeakPtr<SpdySession> session1 =
|
||||
::net::CreateSpdySession(http_session_.get(), key1, NetLogWithSource());
|
||||
EXPECT_FALSE(pool->IsStalled());
|
||||
|
||||
// Set up an alias for the idle SPDY session, increasing its ref count to 2.
|
||||
SpdySessionKey key2(HostPortPair("mail.example.org", 80),
|
||||
PRIVACY_MODE_DISABLED, ProxyChain::Direct(),
|
||||
SessionUsage::kDestination, SocketTag(),
|
||||
NetworkAnonymizationKey(), SecureDnsPolicy::kAllow,
|
||||
/*disable_cert_verification_network_fetches=*/false);
|
||||
|
||||
// Create an idle SPDY session.
|
||||
base::WeakPtr<SpdySession> session1 =
|
||||
::net::CreateSpdySession(http_session_.get(), key1, NetLogWithSource());
|
||||
EXPECT_FALSE(pool->IsStalled());
|
||||
EXPECT_TRUE(http_session_->spdy_session_pool()->HasAvailableSession(
|
||||
key1, /*enable_ip_based_pooling=*/true, /*is_websocket=*/false));
|
||||
EXPECT_FALSE(http_session_->spdy_session_pool()->HasAvailableSession(
|
||||
key2, /*enable_ip_based_pooling=*/true, /*is_websocket=*/false));
|
||||
EXPECT_FALSE(http_session_->spdy_session_pool()->HasAvailableSession(
|
||||
key2, /*enable_ip_based_pooling=*/false, /*is_websocket=*/false));
|
||||
|
||||
// Set up an alias for the idle SPDY session, increasing its ref count to 2.
|
||||
std::unique_ptr<SpdySessionPool::SpdySessionRequest> request;
|
||||
bool is_blocking_request_for_session = false;
|
||||
SpdySessionRequestDelegate request_delegate;
|
||||
@ -3442,6 +3449,12 @@ TEST_F(SpdySessionTest, CloseOneIdleConnectionWithAlias) {
|
||||
EXPECT_TRUE(session2);
|
||||
ASSERT_EQ(session1.get(), session2.get());
|
||||
EXPECT_FALSE(pool->IsStalled());
|
||||
EXPECT_TRUE(http_session_->spdy_session_pool()->HasAvailableSession(
|
||||
key1, /*enable_ip_based_pooling=*/true, /*is_websocket=*/false));
|
||||
EXPECT_TRUE(http_session_->spdy_session_pool()->HasAvailableSession(
|
||||
key2, /*enable_ip_based_pooling=*/true, /*is_websocket=*/false));
|
||||
EXPECT_FALSE(http_session_->spdy_session_pool()->HasAvailableSession(
|
||||
key2, /*enable_ip_based_pooling=*/false, /*is_websocket=*/false));
|
||||
|
||||
// Trying to create a new connection should cause the pool to be stalled, and
|
||||
// post a task asynchronously to try and close the session.
|
||||
@ -3468,6 +3481,12 @@ TEST_F(SpdySessionTest, CloseOneIdleConnectionWithAlias) {
|
||||
EXPECT_FALSE(pool->IsStalled());
|
||||
EXPECT_FALSE(session1);
|
||||
EXPECT_FALSE(session2);
|
||||
EXPECT_FALSE(http_session_->spdy_session_pool()->HasAvailableSession(
|
||||
key1, /*enable_ip_based_pooling=*/true, /*is_websocket=*/false));
|
||||
EXPECT_FALSE(http_session_->spdy_session_pool()->HasAvailableSession(
|
||||
key2, /*enable_ip_based_pooling=*/true, /*is_websocket=*/false));
|
||||
EXPECT_FALSE(http_session_->spdy_session_pool()->HasAvailableSession(
|
||||
key2, /*enable_ip_based_pooling=*/false, /*is_websocket=*/false));
|
||||
}
|
||||
|
||||
// Tests that when a SPDY session becomes idle, it closes itself if there is
|
||||
|
Reference in New Issue
Block a user