ssl_client_socket_pool.cc revision 03b57e008b61dfcb1fbad3aea950ae0e001748b0
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "net/socket/ssl_client_socket_pool.h" 6 7#include "base/bind.h" 8#include "base/bind_helpers.h" 9#include "base/metrics/field_trial.h" 10#include "base/metrics/histogram.h" 11#include "base/metrics/sparse_histogram.h" 12#include "base/stl_util.h" 13#include "base/values.h" 14#include "net/base/host_port_pair.h" 15#include "net/base/net_errors.h" 16#include "net/http/http_proxy_client_socket.h" 17#include "net/http/http_proxy_client_socket_pool.h" 18#include "net/socket/client_socket_factory.h" 19#include "net/socket/client_socket_handle.h" 20#include "net/socket/socks_client_socket_pool.h" 21#include "net/socket/ssl_client_socket.h" 22#include "net/socket/transport_client_socket_pool.h" 23#include "net/ssl/ssl_cert_request_info.h" 24#include "net/ssl/ssl_connection_status_flags.h" 25#include "net/ssl/ssl_info.h" 26 27namespace net { 28 29SSLSocketParams::SSLSocketParams( 30 const scoped_refptr<TransportSocketParams>& direct_params, 31 const scoped_refptr<SOCKSSocketParams>& socks_proxy_params, 32 const scoped_refptr<HttpProxySocketParams>& http_proxy_params, 33 const HostPortPair& host_and_port, 34 const SSLConfig& ssl_config, 35 PrivacyMode privacy_mode, 36 int load_flags, 37 bool force_spdy_over_ssl, 38 bool want_spdy_over_npn) 39 : direct_params_(direct_params), 40 socks_proxy_params_(socks_proxy_params), 41 http_proxy_params_(http_proxy_params), 42 host_and_port_(host_and_port), 43 ssl_config_(ssl_config), 44 privacy_mode_(privacy_mode), 45 load_flags_(load_flags), 46 force_spdy_over_ssl_(force_spdy_over_ssl), 47 want_spdy_over_npn_(want_spdy_over_npn), 48 ignore_limits_(false) { 49 if (direct_params_) { 50 DCHECK(!socks_proxy_params_); 51 DCHECK(!http_proxy_params_); 52 ignore_limits_ = direct_params_->ignore_limits(); 53 } else if (socks_proxy_params_) { 54 DCHECK(!http_proxy_params_); 55 ignore_limits_ = socks_proxy_params_->ignore_limits(); 56 } else { 57 DCHECK(http_proxy_params_); 58 ignore_limits_ = http_proxy_params_->ignore_limits(); 59 } 60} 61 62SSLSocketParams::~SSLSocketParams() {} 63 64SSLSocketParams::ConnectionType SSLSocketParams::GetConnectionType() const { 65 if (direct_params_) { 66 DCHECK(!socks_proxy_params_); 67 DCHECK(!http_proxy_params_); 68 return DIRECT; 69 } 70 71 if (socks_proxy_params_) { 72 DCHECK(!http_proxy_params_); 73 return SOCKS_PROXY; 74 } 75 76 DCHECK(http_proxy_params_); 77 return HTTP_PROXY; 78} 79 80const scoped_refptr<TransportSocketParams>& 81SSLSocketParams::GetDirectConnectionParams() const { 82 DCHECK_EQ(GetConnectionType(), DIRECT); 83 return direct_params_; 84} 85 86const scoped_refptr<SOCKSSocketParams>& 87SSLSocketParams::GetSocksProxyConnectionParams() const { 88 DCHECK_EQ(GetConnectionType(), SOCKS_PROXY); 89 return socks_proxy_params_; 90} 91 92const scoped_refptr<HttpProxySocketParams>& 93SSLSocketParams::GetHttpProxyConnectionParams() const { 94 DCHECK_EQ(GetConnectionType(), HTTP_PROXY); 95 return http_proxy_params_; 96} 97 98SSLConnectJobMessenger::SocketAndCallback::SocketAndCallback( 99 SSLClientSocket* ssl_socket, 100 const base::Closure& job_resumption_callback) 101 : socket(ssl_socket), callback(job_resumption_callback) { 102} 103 104SSLConnectJobMessenger::SocketAndCallback::~SocketAndCallback() { 105} 106 107SSLConnectJobMessenger::SSLConnectJobMessenger( 108 const base::Closure& messenger_finished_callback) 109 : messenger_finished_callback_(messenger_finished_callback), 110 weak_factory_(this) { 111} 112 113SSLConnectJobMessenger::~SSLConnectJobMessenger() { 114} 115 116void SSLConnectJobMessenger::RemovePendingSocket(SSLClientSocket* ssl_socket) { 117 // Sockets do not need to be removed from connecting_sockets_ because 118 // OnSSLHandshakeCompleted will do this. 119 for (SSLPendingSocketsAndCallbacks::iterator it = 120 pending_sockets_and_callbacks_.begin(); 121 it != pending_sockets_and_callbacks_.end(); 122 ++it) { 123 if (it->socket == ssl_socket) { 124 pending_sockets_and_callbacks_.erase(it); 125 return; 126 } 127 } 128} 129 130bool SSLConnectJobMessenger::CanProceed(SSLClientSocket* ssl_socket) { 131 // If there are no connecting sockets, allow the connection to proceed. 132 return connecting_sockets_.empty(); 133} 134 135void SSLConnectJobMessenger::MonitorConnectionResult( 136 SSLClientSocket* ssl_socket) { 137 connecting_sockets_.push_back(ssl_socket); 138 ssl_socket->SetHandshakeCompletionCallback( 139 base::Bind(&SSLConnectJobMessenger::OnSSLHandshakeCompleted, 140 weak_factory_.GetWeakPtr())); 141} 142 143void SSLConnectJobMessenger::AddPendingSocket(SSLClientSocket* ssl_socket, 144 const base::Closure& callback) { 145 DCHECK(!connecting_sockets_.empty()); 146 pending_sockets_and_callbacks_.push_back( 147 SocketAndCallback(ssl_socket, callback)); 148} 149 150void SSLConnectJobMessenger::OnSSLHandshakeCompleted() { 151 connecting_sockets_.clear(); 152 SSLPendingSocketsAndCallbacks temp_list; 153 temp_list.swap(pending_sockets_and_callbacks_); 154 base::Closure messenger_finished_callback = messenger_finished_callback_; 155 messenger_finished_callback.Run(); 156 RunAllCallbacks(temp_list); 157} 158 159void SSLConnectJobMessenger::RunAllCallbacks( 160 const SSLPendingSocketsAndCallbacks& pending_sockets_and_callbacks) { 161 for (std::vector<SocketAndCallback>::const_iterator it = 162 pending_sockets_and_callbacks.begin(); 163 it != pending_sockets_and_callbacks.end(); 164 ++it) { 165 it->callback.Run(); 166 } 167} 168 169// Timeout for the SSL handshake portion of the connect. 170static const int kSSLHandshakeTimeoutInSeconds = 30; 171 172SSLConnectJob::SSLConnectJob(const std::string& group_name, 173 RequestPriority priority, 174 const scoped_refptr<SSLSocketParams>& params, 175 const base::TimeDelta& timeout_duration, 176 TransportClientSocketPool* transport_pool, 177 SOCKSClientSocketPool* socks_pool, 178 HttpProxyClientSocketPool* http_proxy_pool, 179 ClientSocketFactory* client_socket_factory, 180 HostResolver* host_resolver, 181 const SSLClientSocketContext& context, 182 const GetMessengerCallback& get_messenger_callback, 183 Delegate* delegate, 184 NetLog* net_log) 185 : ConnectJob(group_name, 186 timeout_duration, 187 priority, 188 delegate, 189 BoundNetLog::Make(net_log, NetLog::SOURCE_CONNECT_JOB)), 190 params_(params), 191 transport_pool_(transport_pool), 192 socks_pool_(socks_pool), 193 http_proxy_pool_(http_proxy_pool), 194 client_socket_factory_(client_socket_factory), 195 host_resolver_(host_resolver), 196 context_(context.cert_verifier, 197 context.channel_id_service, 198 context.transport_security_state, 199 context.cert_transparency_verifier, 200 (params->privacy_mode() == PRIVACY_MODE_ENABLED 201 ? "pm/" + context.ssl_session_cache_shard 202 : context.ssl_session_cache_shard)), 203 io_callback_( 204 base::Bind(&SSLConnectJob::OnIOComplete, base::Unretained(this))), 205 messenger_(NULL), 206 get_messenger_callback_(get_messenger_callback), 207 weak_factory_(this) { 208} 209 210SSLConnectJob::~SSLConnectJob() { 211 if (ssl_socket_.get() && messenger_) 212 messenger_->RemovePendingSocket(ssl_socket_.get()); 213} 214 215LoadState SSLConnectJob::GetLoadState() const { 216 switch (next_state_) { 217 case STATE_TUNNEL_CONNECT_COMPLETE: 218 if (transport_socket_handle_->socket()) 219 return LOAD_STATE_ESTABLISHING_PROXY_TUNNEL; 220 // else, fall through. 221 case STATE_TRANSPORT_CONNECT: 222 case STATE_TRANSPORT_CONNECT_COMPLETE: 223 case STATE_SOCKS_CONNECT: 224 case STATE_SOCKS_CONNECT_COMPLETE: 225 case STATE_TUNNEL_CONNECT: 226 return transport_socket_handle_->GetLoadState(); 227 case STATE_CREATE_SSL_SOCKET: 228 case STATE_CHECK_FOR_RESUME: 229 case STATE_SSL_CONNECT: 230 case STATE_SSL_CONNECT_COMPLETE: 231 return LOAD_STATE_SSL_HANDSHAKE; 232 default: 233 NOTREACHED(); 234 return LOAD_STATE_IDLE; 235 } 236} 237 238void SSLConnectJob::GetAdditionalErrorState(ClientSocketHandle* handle) { 239 // Headers in |error_response_info_| indicate a proxy tunnel setup 240 // problem. See DoTunnelConnectComplete. 241 if (error_response_info_.headers.get()) { 242 handle->set_pending_http_proxy_connection( 243 transport_socket_handle_.release()); 244 } 245 handle->set_ssl_error_response_info(error_response_info_); 246 if (!connect_timing_.ssl_start.is_null()) 247 handle->set_is_ssl_error(true); 248} 249 250void SSLConnectJob::OnIOComplete(int result) { 251 int rv = DoLoop(result); 252 if (rv != ERR_IO_PENDING) 253 NotifyDelegateOfCompletion(rv); // Deletes |this|. 254} 255 256int SSLConnectJob::DoLoop(int result) { 257 DCHECK_NE(next_state_, STATE_NONE); 258 259 int rv = result; 260 do { 261 State state = next_state_; 262 next_state_ = STATE_NONE; 263 switch (state) { 264 case STATE_TRANSPORT_CONNECT: 265 DCHECK_EQ(OK, rv); 266 rv = DoTransportConnect(); 267 break; 268 case STATE_TRANSPORT_CONNECT_COMPLETE: 269 rv = DoTransportConnectComplete(rv); 270 break; 271 case STATE_SOCKS_CONNECT: 272 DCHECK_EQ(OK, rv); 273 rv = DoSOCKSConnect(); 274 break; 275 case STATE_SOCKS_CONNECT_COMPLETE: 276 rv = DoSOCKSConnectComplete(rv); 277 break; 278 case STATE_TUNNEL_CONNECT: 279 DCHECK_EQ(OK, rv); 280 rv = DoTunnelConnect(); 281 break; 282 case STATE_TUNNEL_CONNECT_COMPLETE: 283 rv = DoTunnelConnectComplete(rv); 284 break; 285 case STATE_CREATE_SSL_SOCKET: 286 rv = DoCreateSSLSocket(); 287 break; 288 case STATE_CHECK_FOR_RESUME: 289 rv = DoCheckForResume(); 290 break; 291 case STATE_SSL_CONNECT: 292 DCHECK_EQ(OK, rv); 293 rv = DoSSLConnect(); 294 break; 295 case STATE_SSL_CONNECT_COMPLETE: 296 rv = DoSSLConnectComplete(rv); 297 break; 298 default: 299 NOTREACHED() << "bad state"; 300 rv = ERR_FAILED; 301 break; 302 } 303 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); 304 305 return rv; 306} 307 308int SSLConnectJob::DoTransportConnect() { 309 DCHECK(transport_pool_); 310 311 next_state_ = STATE_TRANSPORT_CONNECT_COMPLETE; 312 transport_socket_handle_.reset(new ClientSocketHandle()); 313 scoped_refptr<TransportSocketParams> direct_params = 314 params_->GetDirectConnectionParams(); 315 return transport_socket_handle_->Init(group_name(), 316 direct_params, 317 priority(), 318 io_callback_, 319 transport_pool_, 320 net_log()); 321} 322 323int SSLConnectJob::DoTransportConnectComplete(int result) { 324 if (result == OK) 325 next_state_ = STATE_CREATE_SSL_SOCKET; 326 327 return result; 328} 329 330int SSLConnectJob::DoSOCKSConnect() { 331 DCHECK(socks_pool_); 332 next_state_ = STATE_SOCKS_CONNECT_COMPLETE; 333 transport_socket_handle_.reset(new ClientSocketHandle()); 334 scoped_refptr<SOCKSSocketParams> socks_proxy_params = 335 params_->GetSocksProxyConnectionParams(); 336 return transport_socket_handle_->Init(group_name(), 337 socks_proxy_params, 338 priority(), 339 io_callback_, 340 socks_pool_, 341 net_log()); 342} 343 344int SSLConnectJob::DoSOCKSConnectComplete(int result) { 345 if (result == OK) 346 next_state_ = STATE_CREATE_SSL_SOCKET; 347 348 return result; 349} 350 351int SSLConnectJob::DoTunnelConnect() { 352 DCHECK(http_proxy_pool_); 353 next_state_ = STATE_TUNNEL_CONNECT_COMPLETE; 354 355 transport_socket_handle_.reset(new ClientSocketHandle()); 356 scoped_refptr<HttpProxySocketParams> http_proxy_params = 357 params_->GetHttpProxyConnectionParams(); 358 return transport_socket_handle_->Init(group_name(), 359 http_proxy_params, 360 priority(), 361 io_callback_, 362 http_proxy_pool_, 363 net_log()); 364} 365 366int SSLConnectJob::DoTunnelConnectComplete(int result) { 367 // Extract the information needed to prompt for appropriate proxy 368 // authentication so that when ClientSocketPoolBaseHelper calls 369 // |GetAdditionalErrorState|, we can easily set the state. 370 if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) { 371 error_response_info_ = transport_socket_handle_->ssl_error_response_info(); 372 } else if (result == ERR_PROXY_AUTH_REQUESTED || 373 result == ERR_HTTPS_PROXY_TUNNEL_RESPONSE) { 374 StreamSocket* socket = transport_socket_handle_->socket(); 375 HttpProxyClientSocket* tunnel_socket = 376 static_cast<HttpProxyClientSocket*>(socket); 377 error_response_info_ = *tunnel_socket->GetConnectResponseInfo(); 378 } 379 if (result < 0) 380 return result; 381 next_state_ = STATE_CREATE_SSL_SOCKET; 382 return result; 383} 384 385int SSLConnectJob::DoCreateSSLSocket() { 386 next_state_ = STATE_CHECK_FOR_RESUME; 387 388 // Reset the timeout to just the time allowed for the SSL handshake. 389 ResetTimer(base::TimeDelta::FromSeconds(kSSLHandshakeTimeoutInSeconds)); 390 391 // If the handle has a fresh socket, get its connect start and DNS times. 392 // This should always be the case. 393 const LoadTimingInfo::ConnectTiming& socket_connect_timing = 394 transport_socket_handle_->connect_timing(); 395 if (!transport_socket_handle_->is_reused() && 396 !socket_connect_timing.connect_start.is_null()) { 397 // Overwriting |connect_start| serves two purposes - it adjusts timing so 398 // |connect_start| doesn't include dns times, and it adjusts the time so 399 // as not to include time spent waiting for an idle socket. 400 connect_timing_.connect_start = socket_connect_timing.connect_start; 401 connect_timing_.dns_start = socket_connect_timing.dns_start; 402 connect_timing_.dns_end = socket_connect_timing.dns_end; 403 } 404 405 ssl_socket_ = client_socket_factory_->CreateSSLClientSocket( 406 transport_socket_handle_.Pass(), 407 params_->host_and_port(), 408 params_->ssl_config(), 409 context_); 410 411 if (!ssl_socket_->InSessionCache()) 412 messenger_ = get_messenger_callback_.Run(ssl_socket_->GetSessionCacheKey()); 413 414 return OK; 415} 416 417int SSLConnectJob::DoCheckForResume() { 418 next_state_ = STATE_SSL_CONNECT; 419 420 if (!messenger_) 421 return OK; 422 423 if (messenger_->CanProceed(ssl_socket_.get())) { 424 messenger_->MonitorConnectionResult(ssl_socket_.get()); 425 // The SSLConnectJob no longer needs access to the messenger after this 426 // point. 427 messenger_ = NULL; 428 return OK; 429 } 430 431 messenger_->AddPendingSocket(ssl_socket_.get(), 432 base::Bind(&SSLConnectJob::ResumeSSLConnection, 433 weak_factory_.GetWeakPtr())); 434 435 return ERR_IO_PENDING; 436} 437 438int SSLConnectJob::DoSSLConnect() { 439 next_state_ = STATE_SSL_CONNECT_COMPLETE; 440 441 connect_timing_.ssl_start = base::TimeTicks::Now(); 442 443 return ssl_socket_->Connect(io_callback_); 444} 445 446int SSLConnectJob::DoSSLConnectComplete(int result) { 447 connect_timing_.ssl_end = base::TimeTicks::Now(); 448 449 SSLClientSocket::NextProtoStatus status = 450 SSLClientSocket::kNextProtoUnsupported; 451 std::string proto; 452 // GetNextProto will fail and and trigger a NOTREACHED if we pass in a socket 453 // that hasn't had SSL_ImportFD called on it. If we get a certificate error 454 // here, then we know that we called SSL_ImportFD. 455 if (result == OK || IsCertificateError(result)) 456 status = ssl_socket_->GetNextProto(&proto); 457 458 // If we want spdy over npn, make sure it succeeded. 459 if (status == SSLClientSocket::kNextProtoNegotiated) { 460 ssl_socket_->set_was_npn_negotiated(true); 461 NextProto protocol_negotiated = 462 SSLClientSocket::NextProtoFromString(proto); 463 ssl_socket_->set_protocol_negotiated(protocol_negotiated); 464 // If we negotiated a SPDY version, it must have been present in 465 // SSLConfig::next_protos. 466 // TODO(mbelshe): Verify this. 467 if (protocol_negotiated >= kProtoSPDYMinimumVersion && 468 protocol_negotiated <= kProtoSPDYMaximumVersion) { 469 ssl_socket_->set_was_spdy_negotiated(true); 470 } 471 } 472 if (params_->want_spdy_over_npn() && !ssl_socket_->was_spdy_negotiated()) 473 return ERR_NPN_NEGOTIATION_FAILED; 474 475 // Spdy might be turned on by default, or it might be over npn. 476 bool using_spdy = params_->force_spdy_over_ssl() || 477 params_->want_spdy_over_npn(); 478 479 if (result == OK || 480 ssl_socket_->IgnoreCertError(result, params_->load_flags())) { 481 DCHECK(!connect_timing_.ssl_start.is_null()); 482 base::TimeDelta connect_duration = 483 connect_timing_.ssl_end - connect_timing_.ssl_start; 484 if (using_spdy) { 485 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SpdyConnectionLatency_2", 486 connect_duration, 487 base::TimeDelta::FromMilliseconds(1), 488 base::TimeDelta::FromMinutes(1), 489 100); 490 } 491#if defined(SPDY_PROXY_AUTH_ORIGIN) 492 bool using_data_reduction_proxy = params_->host_and_port().Equals( 493 HostPortPair::FromURL(GURL(SPDY_PROXY_AUTH_ORIGIN))); 494 if (using_data_reduction_proxy) { 495 UMA_HISTOGRAM_CUSTOM_TIMES( 496 "Net.SSL_Connection_Latency_DataReductionProxy", 497 connect_duration, 498 base::TimeDelta::FromMilliseconds(1), 499 base::TimeDelta::FromMinutes(1), 500 100); 501 } 502#endif 503 504 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_2", 505 connect_duration, 506 base::TimeDelta::FromMilliseconds(1), 507 base::TimeDelta::FromMinutes(1), 508 100); 509 510 SSLInfo ssl_info; 511 ssl_socket_->GetSSLInfo(&ssl_info); 512 513 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SSL_CipherSuite", 514 SSLConnectionStatusToCipherSuite( 515 ssl_info.connection_status)); 516 517 if (ssl_info.handshake_type == SSLInfo::HANDSHAKE_RESUME) { 518 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_Resume_Handshake", 519 connect_duration, 520 base::TimeDelta::FromMilliseconds(1), 521 base::TimeDelta::FromMinutes(1), 522 100); 523 } else if (ssl_info.handshake_type == SSLInfo::HANDSHAKE_FULL) { 524 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_Full_Handshake", 525 connect_duration, 526 base::TimeDelta::FromMilliseconds(1), 527 base::TimeDelta::FromMinutes(1), 528 100); 529 } 530 531 const std::string& host = params_->host_and_port().host(); 532 bool is_google = 533 host == "google.com" || 534 (host.size() > 11 && host.rfind(".google.com") == host.size() - 11); 535 if (is_google) { 536 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_Google2", 537 connect_duration, 538 base::TimeDelta::FromMilliseconds(1), 539 base::TimeDelta::FromMinutes(1), 540 100); 541 if (ssl_info.handshake_type == SSLInfo::HANDSHAKE_RESUME) { 542 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_Google_" 543 "Resume_Handshake", 544 connect_duration, 545 base::TimeDelta::FromMilliseconds(1), 546 base::TimeDelta::FromMinutes(1), 547 100); 548 } else if (ssl_info.handshake_type == SSLInfo::HANDSHAKE_FULL) { 549 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_Google_" 550 "Full_Handshake", 551 connect_duration, 552 base::TimeDelta::FromMilliseconds(1), 553 base::TimeDelta::FromMinutes(1), 554 100); 555 } 556 } 557 } 558 559 if (result == OK || IsCertificateError(result)) { 560 SetSocket(ssl_socket_.PassAs<StreamSocket>()); 561 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) { 562 error_response_info_.cert_request_info = new SSLCertRequestInfo; 563 ssl_socket_->GetSSLCertRequestInfo( 564 error_response_info_.cert_request_info.get()); 565 } 566 567 return result; 568} 569 570void SSLConnectJob::ResumeSSLConnection() { 571 DCHECK_EQ(next_state_, STATE_SSL_CONNECT); 572 messenger_ = NULL; 573 OnIOComplete(OK); 574} 575 576SSLConnectJob::State SSLConnectJob::GetInitialState( 577 SSLSocketParams::ConnectionType connection_type) { 578 switch (connection_type) { 579 case SSLSocketParams::DIRECT: 580 return STATE_TRANSPORT_CONNECT; 581 case SSLSocketParams::HTTP_PROXY: 582 return STATE_TUNNEL_CONNECT; 583 case SSLSocketParams::SOCKS_PROXY: 584 return STATE_SOCKS_CONNECT; 585 } 586 NOTREACHED(); 587 return STATE_NONE; 588} 589 590int SSLConnectJob::ConnectInternal() { 591 next_state_ = GetInitialState(params_->GetConnectionType()); 592 return DoLoop(OK); 593} 594 595SSLClientSocketPool::SSLConnectJobFactory::SSLConnectJobFactory( 596 TransportClientSocketPool* transport_pool, 597 SOCKSClientSocketPool* socks_pool, 598 HttpProxyClientSocketPool* http_proxy_pool, 599 ClientSocketFactory* client_socket_factory, 600 HostResolver* host_resolver, 601 const SSLClientSocketContext& context, 602 const SSLConnectJob::GetMessengerCallback& get_messenger_callback, 603 NetLog* net_log) 604 : transport_pool_(transport_pool), 605 socks_pool_(socks_pool), 606 http_proxy_pool_(http_proxy_pool), 607 client_socket_factory_(client_socket_factory), 608 host_resolver_(host_resolver), 609 context_(context), 610 get_messenger_callback_(get_messenger_callback), 611 net_log_(net_log) { 612 base::TimeDelta max_transport_timeout = base::TimeDelta(); 613 base::TimeDelta pool_timeout; 614 if (transport_pool_) 615 max_transport_timeout = transport_pool_->ConnectionTimeout(); 616 if (socks_pool_) { 617 pool_timeout = socks_pool_->ConnectionTimeout(); 618 if (pool_timeout > max_transport_timeout) 619 max_transport_timeout = pool_timeout; 620 } 621 if (http_proxy_pool_) { 622 pool_timeout = http_proxy_pool_->ConnectionTimeout(); 623 if (pool_timeout > max_transport_timeout) 624 max_transport_timeout = pool_timeout; 625 } 626 timeout_ = max_transport_timeout + 627 base::TimeDelta::FromSeconds(kSSLHandshakeTimeoutInSeconds); 628} 629 630SSLClientSocketPool::SSLConnectJobFactory::~SSLConnectJobFactory() { 631} 632 633SSLClientSocketPool::SSLClientSocketPool( 634 int max_sockets, 635 int max_sockets_per_group, 636 ClientSocketPoolHistograms* histograms, 637 HostResolver* host_resolver, 638 CertVerifier* cert_verifier, 639 ChannelIDService* channel_id_service, 640 TransportSecurityState* transport_security_state, 641 CTVerifier* cert_transparency_verifier, 642 const std::string& ssl_session_cache_shard, 643 ClientSocketFactory* client_socket_factory, 644 TransportClientSocketPool* transport_pool, 645 SOCKSClientSocketPool* socks_pool, 646 HttpProxyClientSocketPool* http_proxy_pool, 647 SSLConfigService* ssl_config_service, 648 bool enable_ssl_connect_job_waiting, 649 NetLog* net_log) 650 : transport_pool_(transport_pool), 651 socks_pool_(socks_pool), 652 http_proxy_pool_(http_proxy_pool), 653 base_(this, 654 max_sockets, 655 max_sockets_per_group, 656 histograms, 657 ClientSocketPool::unused_idle_socket_timeout(), 658 ClientSocketPool::used_idle_socket_timeout(), 659 new SSLConnectJobFactory( 660 transport_pool, 661 socks_pool, 662 http_proxy_pool, 663 client_socket_factory, 664 host_resolver, 665 SSLClientSocketContext(cert_verifier, 666 channel_id_service, 667 transport_security_state, 668 cert_transparency_verifier, 669 ssl_session_cache_shard), 670 base::Bind( 671 &SSLClientSocketPool::GetOrCreateSSLConnectJobMessenger, 672 base::Unretained(this)), 673 net_log)), 674 ssl_config_service_(ssl_config_service), 675 enable_ssl_connect_job_waiting_(enable_ssl_connect_job_waiting) { 676 if (ssl_config_service_.get()) 677 ssl_config_service_->AddObserver(this); 678 if (transport_pool_) 679 base_.AddLowerLayeredPool(transport_pool_); 680 if (socks_pool_) 681 base_.AddLowerLayeredPool(socks_pool_); 682 if (http_proxy_pool_) 683 base_.AddLowerLayeredPool(http_proxy_pool_); 684} 685 686SSLClientSocketPool::~SSLClientSocketPool() { 687 STLDeleteContainerPairSecondPointers(messenger_map_.begin(), 688 messenger_map_.end()); 689 if (ssl_config_service_.get()) 690 ssl_config_service_->RemoveObserver(this); 691} 692 693scoped_ptr<ConnectJob> SSLClientSocketPool::SSLConnectJobFactory::NewConnectJob( 694 const std::string& group_name, 695 const PoolBase::Request& request, 696 ConnectJob::Delegate* delegate) const { 697 return scoped_ptr<ConnectJob>(new SSLConnectJob(group_name, 698 request.priority(), 699 request.params(), 700 ConnectionTimeout(), 701 transport_pool_, 702 socks_pool_, 703 http_proxy_pool_, 704 client_socket_factory_, 705 host_resolver_, 706 context_, 707 get_messenger_callback_, 708 delegate, 709 net_log_)); 710} 711 712base::TimeDelta SSLClientSocketPool::SSLConnectJobFactory::ConnectionTimeout() 713 const { 714 return timeout_; 715} 716 717int SSLClientSocketPool::RequestSocket(const std::string& group_name, 718 const void* socket_params, 719 RequestPriority priority, 720 ClientSocketHandle* handle, 721 const CompletionCallback& callback, 722 const BoundNetLog& net_log) { 723 const scoped_refptr<SSLSocketParams>* casted_socket_params = 724 static_cast<const scoped_refptr<SSLSocketParams>*>(socket_params); 725 726 return base_.RequestSocket(group_name, *casted_socket_params, priority, 727 handle, callback, net_log); 728} 729 730void SSLClientSocketPool::RequestSockets( 731 const std::string& group_name, 732 const void* params, 733 int num_sockets, 734 const BoundNetLog& net_log) { 735 const scoped_refptr<SSLSocketParams>* casted_params = 736 static_cast<const scoped_refptr<SSLSocketParams>*>(params); 737 738 base_.RequestSockets(group_name, *casted_params, num_sockets, net_log); 739} 740 741void SSLClientSocketPool::CancelRequest(const std::string& group_name, 742 ClientSocketHandle* handle) { 743 base_.CancelRequest(group_name, handle); 744} 745 746void SSLClientSocketPool::ReleaseSocket(const std::string& group_name, 747 scoped_ptr<StreamSocket> socket, 748 int id) { 749 base_.ReleaseSocket(group_name, socket.Pass(), id); 750} 751 752void SSLClientSocketPool::FlushWithError(int error) { 753 base_.FlushWithError(error); 754} 755 756void SSLClientSocketPool::CloseIdleSockets() { 757 base_.CloseIdleSockets(); 758} 759 760int SSLClientSocketPool::IdleSocketCount() const { 761 return base_.idle_socket_count(); 762} 763 764int SSLClientSocketPool::IdleSocketCountInGroup( 765 const std::string& group_name) const { 766 return base_.IdleSocketCountInGroup(group_name); 767} 768 769LoadState SSLClientSocketPool::GetLoadState( 770 const std::string& group_name, const ClientSocketHandle* handle) const { 771 return base_.GetLoadState(group_name, handle); 772} 773 774base::DictionaryValue* SSLClientSocketPool::GetInfoAsValue( 775 const std::string& name, 776 const std::string& type, 777 bool include_nested_pools) const { 778 base::DictionaryValue* dict = base_.GetInfoAsValue(name, type); 779 if (include_nested_pools) { 780 base::ListValue* list = new base::ListValue(); 781 if (transport_pool_) { 782 list->Append(transport_pool_->GetInfoAsValue("transport_socket_pool", 783 "transport_socket_pool", 784 false)); 785 } 786 if (socks_pool_) { 787 list->Append(socks_pool_->GetInfoAsValue("socks_pool", 788 "socks_pool", 789 true)); 790 } 791 if (http_proxy_pool_) { 792 list->Append(http_proxy_pool_->GetInfoAsValue("http_proxy_pool", 793 "http_proxy_pool", 794 true)); 795 } 796 dict->Set("nested_pools", list); 797 } 798 return dict; 799} 800 801base::TimeDelta SSLClientSocketPool::ConnectionTimeout() const { 802 return base_.ConnectionTimeout(); 803} 804 805ClientSocketPoolHistograms* SSLClientSocketPool::histograms() const { 806 return base_.histograms(); 807} 808 809bool SSLClientSocketPool::IsStalled() const { 810 return base_.IsStalled(); 811} 812 813void SSLClientSocketPool::AddHigherLayeredPool(HigherLayeredPool* higher_pool) { 814 base_.AddHigherLayeredPool(higher_pool); 815} 816 817void SSLClientSocketPool::RemoveHigherLayeredPool( 818 HigherLayeredPool* higher_pool) { 819 base_.RemoveHigherLayeredPool(higher_pool); 820} 821 822bool SSLClientSocketPool::CloseOneIdleConnection() { 823 if (base_.CloseOneIdleSocket()) 824 return true; 825 return base_.CloseOneIdleConnectionInHigherLayeredPool(); 826} 827 828SSLConnectJobMessenger* SSLClientSocketPool::GetOrCreateSSLConnectJobMessenger( 829 const std::string& cache_key) { 830 if (!enable_ssl_connect_job_waiting_) 831 return NULL; 832 MessengerMap::const_iterator it = messenger_map_.find(cache_key); 833 if (it == messenger_map_.end()) { 834 std::pair<MessengerMap::iterator, bool> iter = 835 messenger_map_.insert(MessengerMap::value_type( 836 cache_key, 837 new SSLConnectJobMessenger( 838 base::Bind(&SSLClientSocketPool::DeleteSSLConnectJobMessenger, 839 base::Unretained(this), 840 cache_key)))); 841 it = iter.first; 842 } 843 return it->second; 844} 845 846void SSLClientSocketPool::DeleteSSLConnectJobMessenger( 847 const std::string& cache_key) { 848 MessengerMap::iterator it = messenger_map_.find(cache_key); 849 CHECK(it != messenger_map_.end()); 850 delete it->second; 851 messenger_map_.erase(it); 852} 853 854void SSLClientSocketPool::OnSSLConfigChanged() { 855 FlushWithError(ERR_NETWORK_CHANGED); 856} 857 858} // namespace net 859