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_.get()) { 50 DCHECK(!socks_proxy_params_.get()); 51 DCHECK(!http_proxy_params_.get()); 52 ignore_limits_ = direct_params_->ignore_limits(); 53 } else if (socks_proxy_params_.get()) { 54 DCHECK(!http_proxy_params_.get()); 55 ignore_limits_ = socks_proxy_params_->ignore_limits(); 56 } else { 57 DCHECK(http_proxy_params_.get()); 58 ignore_limits_ = http_proxy_params_->ignore_limits(); 59 } 60} 61 62SSLSocketParams::~SSLSocketParams() {} 63 64SSLSocketParams::ConnectionType SSLSocketParams::GetConnectionType() const { 65 if (direct_params_.get()) { 66 DCHECK(!socks_proxy_params_.get()); 67 DCHECK(!http_proxy_params_.get()); 68 return DIRECT; 69 } 70 71 if (socks_proxy_params_.get()) { 72 DCHECK(!http_proxy_params_.get()); 73 return SOCKS_PROXY; 74 } 75 76 DCHECK(http_proxy_params_.get()); 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 492 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_2", 493 connect_duration, 494 base::TimeDelta::FromMilliseconds(1), 495 base::TimeDelta::FromMinutes(1), 496 100); 497 498 SSLInfo ssl_info; 499 ssl_socket_->GetSSLInfo(&ssl_info); 500 501 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SSL_CipherSuite", 502 SSLConnectionStatusToCipherSuite( 503 ssl_info.connection_status)); 504 505 UMA_HISTOGRAM_BOOLEAN( 506 "Net.RenegotiationExtensionSupported", 507 (ssl_info.connection_status & 508 SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION) == 0); 509 510 if (ssl_info.handshake_type == SSLInfo::HANDSHAKE_RESUME) { 511 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_Resume_Handshake", 512 connect_duration, 513 base::TimeDelta::FromMilliseconds(1), 514 base::TimeDelta::FromMinutes(1), 515 100); 516 } else if (ssl_info.handshake_type == SSLInfo::HANDSHAKE_FULL) { 517 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_Full_Handshake", 518 connect_duration, 519 base::TimeDelta::FromMilliseconds(1), 520 base::TimeDelta::FromMinutes(1), 521 100); 522 } 523 524 const std::string& host = params_->host_and_port().host(); 525 bool is_google = 526 host == "google.com" || 527 (host.size() > 11 && host.rfind(".google.com") == host.size() - 11); 528 if (is_google) { 529 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_Google2", 530 connect_duration, 531 base::TimeDelta::FromMilliseconds(1), 532 base::TimeDelta::FromMinutes(1), 533 100); 534 if (ssl_info.handshake_type == SSLInfo::HANDSHAKE_RESUME) { 535 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_Google_" 536 "Resume_Handshake", 537 connect_duration, 538 base::TimeDelta::FromMilliseconds(1), 539 base::TimeDelta::FromMinutes(1), 540 100); 541 } else if (ssl_info.handshake_type == SSLInfo::HANDSHAKE_FULL) { 542 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_Google_" 543 "Full_Handshake", 544 connect_duration, 545 base::TimeDelta::FromMilliseconds(1), 546 base::TimeDelta::FromMinutes(1), 547 100); 548 } 549 } 550 } 551 552 if (result == OK || IsCertificateError(result)) { 553 SetSocket(ssl_socket_.PassAs<StreamSocket>()); 554 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) { 555 error_response_info_.cert_request_info = new SSLCertRequestInfo; 556 ssl_socket_->GetSSLCertRequestInfo( 557 error_response_info_.cert_request_info.get()); 558 } 559 560 return result; 561} 562 563void SSLConnectJob::ResumeSSLConnection() { 564 DCHECK_EQ(next_state_, STATE_SSL_CONNECT); 565 messenger_ = NULL; 566 OnIOComplete(OK); 567} 568 569SSLConnectJob::State SSLConnectJob::GetInitialState( 570 SSLSocketParams::ConnectionType connection_type) { 571 switch (connection_type) { 572 case SSLSocketParams::DIRECT: 573 return STATE_TRANSPORT_CONNECT; 574 case SSLSocketParams::HTTP_PROXY: 575 return STATE_TUNNEL_CONNECT; 576 case SSLSocketParams::SOCKS_PROXY: 577 return STATE_SOCKS_CONNECT; 578 } 579 NOTREACHED(); 580 return STATE_NONE; 581} 582 583int SSLConnectJob::ConnectInternal() { 584 next_state_ = GetInitialState(params_->GetConnectionType()); 585 return DoLoop(OK); 586} 587 588SSLClientSocketPool::SSLConnectJobFactory::SSLConnectJobFactory( 589 TransportClientSocketPool* transport_pool, 590 SOCKSClientSocketPool* socks_pool, 591 HttpProxyClientSocketPool* http_proxy_pool, 592 ClientSocketFactory* client_socket_factory, 593 HostResolver* host_resolver, 594 const SSLClientSocketContext& context, 595 const SSLConnectJob::GetMessengerCallback& get_messenger_callback, 596 NetLog* net_log) 597 : transport_pool_(transport_pool), 598 socks_pool_(socks_pool), 599 http_proxy_pool_(http_proxy_pool), 600 client_socket_factory_(client_socket_factory), 601 host_resolver_(host_resolver), 602 context_(context), 603 get_messenger_callback_(get_messenger_callback), 604 net_log_(net_log) { 605 base::TimeDelta max_transport_timeout = base::TimeDelta(); 606 base::TimeDelta pool_timeout; 607 if (transport_pool_) 608 max_transport_timeout = transport_pool_->ConnectionTimeout(); 609 if (socks_pool_) { 610 pool_timeout = socks_pool_->ConnectionTimeout(); 611 if (pool_timeout > max_transport_timeout) 612 max_transport_timeout = pool_timeout; 613 } 614 if (http_proxy_pool_) { 615 pool_timeout = http_proxy_pool_->ConnectionTimeout(); 616 if (pool_timeout > max_transport_timeout) 617 max_transport_timeout = pool_timeout; 618 } 619 timeout_ = max_transport_timeout + 620 base::TimeDelta::FromSeconds(kSSLHandshakeTimeoutInSeconds); 621} 622 623SSLClientSocketPool::SSLConnectJobFactory::~SSLConnectJobFactory() { 624} 625 626SSLClientSocketPool::SSLClientSocketPool( 627 int max_sockets, 628 int max_sockets_per_group, 629 ClientSocketPoolHistograms* histograms, 630 HostResolver* host_resolver, 631 CertVerifier* cert_verifier, 632 ChannelIDService* channel_id_service, 633 TransportSecurityState* transport_security_state, 634 CTVerifier* cert_transparency_verifier, 635 const std::string& ssl_session_cache_shard, 636 ClientSocketFactory* client_socket_factory, 637 TransportClientSocketPool* transport_pool, 638 SOCKSClientSocketPool* socks_pool, 639 HttpProxyClientSocketPool* http_proxy_pool, 640 SSLConfigService* ssl_config_service, 641 bool enable_ssl_connect_job_waiting, 642 NetLog* net_log) 643 : transport_pool_(transport_pool), 644 socks_pool_(socks_pool), 645 http_proxy_pool_(http_proxy_pool), 646 base_(this, 647 max_sockets, 648 max_sockets_per_group, 649 histograms, 650 ClientSocketPool::unused_idle_socket_timeout(), 651 ClientSocketPool::used_idle_socket_timeout(), 652 new SSLConnectJobFactory( 653 transport_pool, 654 socks_pool, 655 http_proxy_pool, 656 client_socket_factory, 657 host_resolver, 658 SSLClientSocketContext(cert_verifier, 659 channel_id_service, 660 transport_security_state, 661 cert_transparency_verifier, 662 ssl_session_cache_shard), 663 base::Bind( 664 &SSLClientSocketPool::GetOrCreateSSLConnectJobMessenger, 665 base::Unretained(this)), 666 net_log)), 667 ssl_config_service_(ssl_config_service), 668 enable_ssl_connect_job_waiting_(enable_ssl_connect_job_waiting) { 669 if (ssl_config_service_.get()) 670 ssl_config_service_->AddObserver(this); 671 if (transport_pool_) 672 base_.AddLowerLayeredPool(transport_pool_); 673 if (socks_pool_) 674 base_.AddLowerLayeredPool(socks_pool_); 675 if (http_proxy_pool_) 676 base_.AddLowerLayeredPool(http_proxy_pool_); 677} 678 679SSLClientSocketPool::~SSLClientSocketPool() { 680 STLDeleteContainerPairSecondPointers(messenger_map_.begin(), 681 messenger_map_.end()); 682 if (ssl_config_service_.get()) 683 ssl_config_service_->RemoveObserver(this); 684} 685 686scoped_ptr<ConnectJob> SSLClientSocketPool::SSLConnectJobFactory::NewConnectJob( 687 const std::string& group_name, 688 const PoolBase::Request& request, 689 ConnectJob::Delegate* delegate) const { 690 return scoped_ptr<ConnectJob>(new SSLConnectJob(group_name, 691 request.priority(), 692 request.params(), 693 ConnectionTimeout(), 694 transport_pool_, 695 socks_pool_, 696 http_proxy_pool_, 697 client_socket_factory_, 698 host_resolver_, 699 context_, 700 get_messenger_callback_, 701 delegate, 702 net_log_)); 703} 704 705base::TimeDelta SSLClientSocketPool::SSLConnectJobFactory::ConnectionTimeout() 706 const { 707 return timeout_; 708} 709 710int SSLClientSocketPool::RequestSocket(const std::string& group_name, 711 const void* socket_params, 712 RequestPriority priority, 713 ClientSocketHandle* handle, 714 const CompletionCallback& callback, 715 const BoundNetLog& net_log) { 716 const scoped_refptr<SSLSocketParams>* casted_socket_params = 717 static_cast<const scoped_refptr<SSLSocketParams>*>(socket_params); 718 719 return base_.RequestSocket(group_name, *casted_socket_params, priority, 720 handle, callback, net_log); 721} 722 723void SSLClientSocketPool::RequestSockets( 724 const std::string& group_name, 725 const void* params, 726 int num_sockets, 727 const BoundNetLog& net_log) { 728 const scoped_refptr<SSLSocketParams>* casted_params = 729 static_cast<const scoped_refptr<SSLSocketParams>*>(params); 730 731 base_.RequestSockets(group_name, *casted_params, num_sockets, net_log); 732} 733 734void SSLClientSocketPool::CancelRequest(const std::string& group_name, 735 ClientSocketHandle* handle) { 736 base_.CancelRequest(group_name, handle); 737} 738 739void SSLClientSocketPool::ReleaseSocket(const std::string& group_name, 740 scoped_ptr<StreamSocket> socket, 741 int id) { 742 base_.ReleaseSocket(group_name, socket.Pass(), id); 743} 744 745void SSLClientSocketPool::FlushWithError(int error) { 746 base_.FlushWithError(error); 747} 748 749void SSLClientSocketPool::CloseIdleSockets() { 750 base_.CloseIdleSockets(); 751} 752 753int SSLClientSocketPool::IdleSocketCount() const { 754 return base_.idle_socket_count(); 755} 756 757int SSLClientSocketPool::IdleSocketCountInGroup( 758 const std::string& group_name) const { 759 return base_.IdleSocketCountInGroup(group_name); 760} 761 762LoadState SSLClientSocketPool::GetLoadState( 763 const std::string& group_name, const ClientSocketHandle* handle) const { 764 return base_.GetLoadState(group_name, handle); 765} 766 767base::DictionaryValue* SSLClientSocketPool::GetInfoAsValue( 768 const std::string& name, 769 const std::string& type, 770 bool include_nested_pools) const { 771 base::DictionaryValue* dict = base_.GetInfoAsValue(name, type); 772 if (include_nested_pools) { 773 base::ListValue* list = new base::ListValue(); 774 if (transport_pool_) { 775 list->Append(transport_pool_->GetInfoAsValue("transport_socket_pool", 776 "transport_socket_pool", 777 false)); 778 } 779 if (socks_pool_) { 780 list->Append(socks_pool_->GetInfoAsValue("socks_pool", 781 "socks_pool", 782 true)); 783 } 784 if (http_proxy_pool_) { 785 list->Append(http_proxy_pool_->GetInfoAsValue("http_proxy_pool", 786 "http_proxy_pool", 787 true)); 788 } 789 dict->Set("nested_pools", list); 790 } 791 return dict; 792} 793 794base::TimeDelta SSLClientSocketPool::ConnectionTimeout() const { 795 return base_.ConnectionTimeout(); 796} 797 798ClientSocketPoolHistograms* SSLClientSocketPool::histograms() const { 799 return base_.histograms(); 800} 801 802bool SSLClientSocketPool::IsStalled() const { 803 return base_.IsStalled(); 804} 805 806void SSLClientSocketPool::AddHigherLayeredPool(HigherLayeredPool* higher_pool) { 807 base_.AddHigherLayeredPool(higher_pool); 808} 809 810void SSLClientSocketPool::RemoveHigherLayeredPool( 811 HigherLayeredPool* higher_pool) { 812 base_.RemoveHigherLayeredPool(higher_pool); 813} 814 815bool SSLClientSocketPool::CloseOneIdleConnection() { 816 if (base_.CloseOneIdleSocket()) 817 return true; 818 return base_.CloseOneIdleConnectionInHigherLayeredPool(); 819} 820 821SSLConnectJobMessenger* SSLClientSocketPool::GetOrCreateSSLConnectJobMessenger( 822 const std::string& cache_key) { 823 if (!enable_ssl_connect_job_waiting_) 824 return NULL; 825 MessengerMap::const_iterator it = messenger_map_.find(cache_key); 826 if (it == messenger_map_.end()) { 827 std::pair<MessengerMap::iterator, bool> iter = 828 messenger_map_.insert(MessengerMap::value_type( 829 cache_key, 830 new SSLConnectJobMessenger( 831 base::Bind(&SSLClientSocketPool::DeleteSSLConnectJobMessenger, 832 base::Unretained(this), 833 cache_key)))); 834 it = iter.first; 835 } 836 return it->second; 837} 838 839void SSLClientSocketPool::DeleteSSLConnectJobMessenger( 840 const std::string& cache_key) { 841 MessengerMap::iterator it = messenger_map_.find(cache_key); 842 CHECK(it != messenger_map_.end()); 843 delete it->second; 844 messenger_map_.erase(it); 845} 846 847void SSLClientSocketPool::OnSSLConfigChanged() { 848 FlushWithError(ERR_NETWORK_CHANGED); 849} 850 851} // namespace net 852