| Index: net/socket/ssl_client_socket_pool.cc
|
| diff --git a/net/socket/ssl_client_socket_pool.cc b/net/socket/ssl_client_socket_pool.cc
|
| index 2c704658820bc06a8404679c2f796be269657387..1b7b44390990953827a142ab852e425109089e2d 100644
|
| --- a/net/socket/ssl_client_socket_pool.cc
|
| +++ b/net/socket/ssl_client_socket_pool.cc
|
| @@ -94,6 +94,57 @@ SSLSocketParams::GetHttpProxyConnectionParams() const {
|
| return http_proxy_params_;
|
| }
|
|
|
| +bool SSLConnectJobMessenger::CanProceed(SSLClientSocket* ssl_socket) {
|
| + // If the session is in the session cache, or there are no connecting
|
| + // sockets allow the connection to proceed.
|
| + if (ssl_socket->InSessionCache() || connecting_sockets_.empty()) {
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +void SSLConnectJobMessenger::MonitorConnectionResult(
|
| + SSLClientSocket* ssl_socket) {
|
| + connecting_sockets_.push_back(ssl_socket);
|
| + ssl_socket->SetIsLeader();
|
| + ssl_socket->SetSocketFailureCallback(
|
| + base::Bind(&SSLConnectJobMessenger::OnJobFailed, base::Unretained(this)));
|
| + ssl_socket->WatchSessionForCompletion(base::Bind(
|
| + &SSLConnectJobMessenger::OnJobSucceeded, base::Unretained(this)));
|
| +}
|
| +
|
| +void SSLConnectJobMessenger::AddPendingSocket(SSLClientSocket* socket,
|
| + const base::Closure& callback) {
|
| + pending_sockets_and_callbacks_.push_back(SocketAndCallback(socket, callback));
|
| +}
|
| +
|
| +void SSLConnectJobMessenger::OnJobSucceeded() {
|
| + SSLPendingSocketsAndCallbacks temp_list = pending_sockets_and_callbacks_;
|
| + pending_sockets_and_callbacks_.clear();
|
| + connecting_sockets_.clear();
|
| + RunAllJobs(temp_list);
|
| +}
|
| +
|
| +void SSLConnectJobMessenger::OnJobFailed() {
|
| + if (pending_sockets_and_callbacks_.empty())
|
| + return;
|
| + base::Closure callback = pending_sockets_and_callbacks_[0].callback;
|
| + connecting_sockets_.erase(connecting_sockets_.begin());
|
| + SSLClientSocket* ssl_socket = pending_sockets_and_callbacks_[0].socket;
|
| + pending_sockets_and_callbacks_.erase(pending_sockets_and_callbacks_.begin());
|
| + MonitorConnectionResult(ssl_socket);
|
| + callback.Run();
|
| +}
|
| +
|
| +void SSLConnectJobMessenger::RunAllJobs(
|
| + std::vector<SocketAndCallback>& pending_sockets_and_callbacks) {
|
| + for (std::vector<SocketAndCallback>::const_iterator it =
|
| + pending_sockets_and_callbacks.begin();
|
| + it != pending_sockets_and_callbacks.end();
|
| + ++it)
|
| + it->callback.Run();
|
| +}
|
| +
|
| // Timeout for the SSL handshake portion of the connect.
|
| static const int kSSLHandshakeTimeoutInSeconds = 30;
|
|
|
| @@ -107,6 +158,7 @@ SSLConnectJob::SSLConnectJob(const std::string& group_name,
|
| ClientSocketFactory* client_socket_factory,
|
| HostResolver* host_resolver,
|
| const SSLClientSocketContext& context,
|
| + SSLConnectJobMessenger* messenger,
|
| Delegate* delegate,
|
| NetLog* net_log)
|
| : ConnectJob(group_name,
|
| @@ -127,8 +179,11 @@ SSLConnectJob::SSLConnectJob(const std::string& group_name,
|
| (params->privacy_mode() == PRIVACY_MODE_ENABLED
|
| ? "pm/" + context.ssl_session_cache_shard
|
| : context.ssl_session_cache_shard)),
|
| - callback_(base::Bind(&SSLConnectJob::OnIOComplete,
|
| - base::Unretained(this))) {}
|
| + io_callback_(
|
| + base::Bind(&SSLConnectJob::OnIOComplete, base::Unretained(this))),
|
| + messenger_(messenger),
|
| + weak_factory_(this) {
|
| +}
|
|
|
| SSLConnectJob::~SSLConnectJob() {}
|
|
|
| @@ -144,6 +199,8 @@ LoadState SSLConnectJob::GetLoadState() const {
|
| case STATE_SOCKS_CONNECT_COMPLETE:
|
| case STATE_TUNNEL_CONNECT:
|
| return transport_socket_handle_->GetLoadState();
|
| + case STATE_CREATE_SSL_SOCKET:
|
| + case STATE_CHECK_FOR_RESUME:
|
| case STATE_SSL_CONNECT:
|
| case STATE_SSL_CONNECT_COMPLETE:
|
| return LOAD_STATE_SSL_HANDSHAKE;
|
| @@ -200,6 +257,12 @@ int SSLConnectJob::DoLoop(int result) {
|
| case STATE_TUNNEL_CONNECT_COMPLETE:
|
| rv = DoTunnelConnectComplete(rv);
|
| break;
|
| + case STATE_CREATE_SSL_SOCKET:
|
| + rv = DoCreateSSLSocket();
|
| + break;
|
| + case STATE_CHECK_FOR_RESUME:
|
| + rv = DoCheckForResume();
|
| + break;
|
| case STATE_SSL_CONNECT:
|
| DCHECK_EQ(OK, rv);
|
| rv = DoSSLConnect();
|
| @@ -227,14 +290,16 @@ int SSLConnectJob::DoTransportConnect() {
|
| return transport_socket_handle_->Init(group_name(),
|
| direct_params,
|
| priority(),
|
| - callback_,
|
| + io_callback_,
|
| transport_pool_,
|
| net_log());
|
| }
|
|
|
| int SSLConnectJob::DoTransportConnectComplete(int result) {
|
| - if (result == OK)
|
| - next_state_ = STATE_SSL_CONNECT;
|
| + if (result != OK)
|
| + return result;
|
| +
|
| + next_state_ = STATE_CREATE_SSL_SOCKET;
|
|
|
| return result;
|
| }
|
| @@ -248,14 +313,16 @@ int SSLConnectJob::DoSOCKSConnect() {
|
| return transport_socket_handle_->Init(group_name(),
|
| socks_proxy_params,
|
| priority(),
|
| - callback_,
|
| + io_callback_,
|
| socks_pool_,
|
| net_log());
|
| }
|
|
|
| int SSLConnectJob::DoSOCKSConnectComplete(int result) {
|
| - if (result == OK)
|
| - next_state_ = STATE_SSL_CONNECT;
|
| + if (result != OK)
|
| + return result;
|
| +
|
| + next_state_ = STATE_CREATE_SSL_SOCKET;
|
|
|
| return result;
|
| }
|
| @@ -270,7 +337,7 @@ int SSLConnectJob::DoTunnelConnect() {
|
| return transport_socket_handle_->Init(group_name(),
|
| http_proxy_params,
|
| priority(),
|
| - callback_,
|
| + io_callback_,
|
| http_proxy_pool_,
|
| net_log());
|
| }
|
| @@ -291,12 +358,15 @@ int SSLConnectJob::DoTunnelConnectComplete(int result) {
|
| if (result < 0)
|
| return result;
|
|
|
| - next_state_ = STATE_SSL_CONNECT;
|
| + next_state_ = STATE_CREATE_SSL_SOCKET;
|
| return result;
|
| }
|
|
|
| -int SSLConnectJob::DoSSLConnect() {
|
| - next_state_ = STATE_SSL_CONNECT_COMPLETE;
|
| +int SSLConnectJob::DoCreateSSLSocket() {
|
| + if (SSLClientSocket::GetEnableConnectJobWaiting())
|
| + next_state_ = STATE_CHECK_FOR_RESUME;
|
| + else
|
| + next_state_ = STATE_SSL_CONNECT;
|
| // Reset the timeout to just the time allowed for the SSL handshake.
|
| ResetTimer(base::TimeDelta::FromSeconds(kSSLHandshakeTimeoutInSeconds));
|
|
|
| @@ -314,19 +384,43 @@ int SSLConnectJob::DoSSLConnect() {
|
| connect_timing_.dns_end = socket_connect_timing.dns_end;
|
| }
|
|
|
| - connect_timing_.ssl_start = base::TimeTicks::Now();
|
| -
|
| ssl_socket_ = client_socket_factory_->CreateSSLClientSocket(
|
| transport_socket_handle_.Pass(),
|
| params_->host_and_port(),
|
| params_->ssl_config(),
|
| context_);
|
| - return ssl_socket_->Connect(callback_);
|
| + return OK;
|
| +}
|
| +
|
| +int SSLConnectJob::DoCheckForResume() {
|
| + next_state_ = STATE_SSL_CONNECT;
|
| + if (messenger_->CanProceed(ssl_socket_.get())) {
|
| + if (ssl_socket_->InSessionCache())
|
| + return OK;
|
| + messenger_->MonitorConnectionResult(ssl_socket_.get());
|
| + return OK;
|
| + }
|
| + messenger_->AddPendingSocket(
|
| + ssl_socket_.get(),
|
| + base::Bind(&net::SSLConnectJob::ResumeSSLConnection,
|
| + weak_factory_.GetWeakPtr()));
|
| + return ERR_IO_PENDING;
|
| +}
|
| +
|
| +int SSLConnectJob::DoSSLConnect() {
|
| + next_state_ = STATE_SSL_CONNECT_COMPLETE;
|
| +
|
| + connect_timing_.ssl_start = base::TimeTicks::Now();
|
| +
|
| + return ssl_socket_->Connect(io_callback_);
|
| }
|
|
|
| int SSLConnectJob::DoSSLConnectComplete(int result) {
|
| connect_timing_.ssl_end = base::TimeTicks::Now();
|
|
|
| + if (result != OK && SSLClientSocket::GetEnableConnectJobWaiting())
|
| + messenger_->OnJobFailed();
|
| +
|
| SSLClientSocket::NextProtoStatus status =
|
| SSLClientSocket::kNextProtoUnsupported;
|
| std::string proto;
|
| @@ -411,9 +505,9 @@ int SSLConnectJob::DoSSLConnectComplete(int result) {
|
| }
|
|
|
| const std::string& host = params_->host_and_port().host();
|
| - bool is_google = host == "google.com" ||
|
| - (host.size() > 11 &&
|
| - host.rfind(".google.com") == host.size() - 11);
|
| + bool is_google =
|
| + host == "google.com" ||
|
| + (host.size() > 11 && host.rfind(".google.com") == host.size() - 11);
|
| if (is_google) {
|
| UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_Google2",
|
| connect_duration,
|
| @@ -449,6 +543,11 @@ int SSLConnectJob::DoSSLConnectComplete(int result) {
|
| return result;
|
| }
|
|
|
| +void SSLConnectJob::ResumeSSLConnection() {
|
| + DCHECK_EQ(next_state_, STATE_SSL_CONNECT);
|
| + OnIOComplete(OK);
|
| +}
|
| +
|
| SSLConnectJob::State SSLConnectJob::GetInitialState(
|
| SSLSocketParams::ConnectionType connection_type) {
|
| switch (connection_type) {
|
| @@ -482,7 +581,8 @@ SSLClientSocketPool::SSLConnectJobFactory::SSLConnectJobFactory(
|
| client_socket_factory_(client_socket_factory),
|
| host_resolver_(host_resolver),
|
| context_(context),
|
| - net_log_(net_log) {
|
| + net_log_(net_log),
|
| + messenger_map_(new MessengerMap) {
|
| base::TimeDelta max_transport_timeout = base::TimeDelta();
|
| base::TimeDelta pool_timeout;
|
| if (transport_pool_)
|
| @@ -520,21 +620,24 @@ SSLClientSocketPool::SSLClientSocketPool(
|
| : transport_pool_(transport_pool),
|
| socks_pool_(socks_pool),
|
| http_proxy_pool_(http_proxy_pool),
|
| - base_(this, max_sockets, max_sockets_per_group, histograms,
|
| + base_(this,
|
| + max_sockets,
|
| + max_sockets_per_group,
|
| + histograms,
|
| ClientSocketPool::unused_idle_socket_timeout(),
|
| ClientSocketPool::used_idle_socket_timeout(),
|
| - new SSLConnectJobFactory(transport_pool,
|
| - socks_pool,
|
| - http_proxy_pool,
|
| - client_socket_factory,
|
| - host_resolver,
|
| - SSLClientSocketContext(
|
| - cert_verifier,
|
| - server_bound_cert_service,
|
| - transport_security_state,
|
| - cert_transparency_verifier,
|
| - ssl_session_cache_shard),
|
| - net_log)),
|
| + new SSLConnectJobFactory(
|
| + transport_pool,
|
| + socks_pool,
|
| + http_proxy_pool,
|
| + client_socket_factory,
|
| + host_resolver,
|
| + SSLClientSocketContext(cert_verifier,
|
| + server_bound_cert_service,
|
| + transport_security_state,
|
| + cert_transparency_verifier,
|
| + ssl_session_cache_shard),
|
| + net_log)),
|
| ssl_config_service_(ssl_config_service) {
|
| if (ssl_config_service_.get())
|
| ssl_config_service_->AddObserver(this);
|
| @@ -556,11 +659,35 @@ SSLClientSocketPool::SSLConnectJobFactory::NewConnectJob(
|
| const std::string& group_name,
|
| const PoolBase::Request& request,
|
| ConnectJob::Delegate* delegate) const {
|
| - return scoped_ptr<ConnectJob>(
|
| - new SSLConnectJob(group_name, request.priority(), request.params(),
|
| - ConnectionTimeout(), transport_pool_, socks_pool_,
|
| - http_proxy_pool_, client_socket_factory_,
|
| - host_resolver_, context_, delegate, net_log_));
|
| + SSLConnectJobMessenger* messenger;
|
| + std::string cache_key = SSLClientSocket::FormatSessionCacheKey(
|
| + request.params()->host_and_port().ToString(),
|
| + context_.ssl_session_cache_shard);
|
| + if (SSLClientSocket::GetEnableConnectJobWaiting()) {
|
| + MessengerMap::const_iterator it = messenger_map_->find(cache_key);
|
| + if (it == messenger_map_->end()) {
|
| + std::pair<MessengerMap::iterator, bool> iter = messenger_map_->insert(
|
| + MessengerMap::value_type(cache_key, new SSLConnectJobMessenger()));
|
| + it = iter.first;
|
| + }
|
| + messenger = it->second;
|
| + } else {
|
| + messenger = NULL;
|
| + }
|
| +
|
| + return scoped_ptr<ConnectJob>(new SSLConnectJob(group_name,
|
| + request.priority(),
|
| + request.params(),
|
| + ConnectionTimeout(),
|
| + transport_pool_,
|
| + socks_pool_,
|
| + http_proxy_pool_,
|
| + client_socket_factory_,
|
| + host_resolver_,
|
| + context_,
|
| + messenger,
|
| + delegate,
|
| + net_log_));
|
| }
|
|
|
| base::TimeDelta
|
|
|