Home | History | Annotate | Download | only in socket
      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/values.h"
     13 #include "net/base/host_port_pair.h"
     14 #include "net/base/net_errors.h"
     15 #include "net/http/http_proxy_client_socket.h"
     16 #include "net/http/http_proxy_client_socket_pool.h"
     17 #include "net/socket/client_socket_factory.h"
     18 #include "net/socket/client_socket_handle.h"
     19 #include "net/socket/socks_client_socket_pool.h"
     20 #include "net/socket/ssl_client_socket.h"
     21 #include "net/socket/transport_client_socket_pool.h"
     22 #include "net/ssl/ssl_cert_request_info.h"
     23 #include "net/ssl/ssl_connection_status_flags.h"
     24 #include "net/ssl/ssl_info.h"
     25 
     26 namespace net {
     27 
     28 SSLSocketParams::SSLSocketParams(
     29     const scoped_refptr<TransportSocketParams>& transport_params,
     30     const scoped_refptr<SOCKSSocketParams>& socks_params,
     31     const scoped_refptr<HttpProxySocketParams>& http_proxy_params,
     32     ProxyServer::Scheme proxy,
     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     : transport_params_(transport_params),
     40       http_proxy_params_(http_proxy_params),
     41       socks_params_(socks_params),
     42       proxy_(proxy),
     43       host_and_port_(host_and_port),
     44       ssl_config_(ssl_config),
     45       privacy_mode_(privacy_mode),
     46       load_flags_(load_flags),
     47       force_spdy_over_ssl_(force_spdy_over_ssl),
     48       want_spdy_over_npn_(want_spdy_over_npn),
     49       ignore_limits_(false) {
     50   switch (proxy_) {
     51     case ProxyServer::SCHEME_DIRECT:
     52       DCHECK(transport_params_.get() != NULL);
     53       DCHECK(http_proxy_params_.get() == NULL);
     54       DCHECK(socks_params_.get() == NULL);
     55       ignore_limits_ = transport_params_->ignore_limits();
     56       break;
     57     case ProxyServer::SCHEME_HTTP:
     58     case ProxyServer::SCHEME_HTTPS:
     59       DCHECK(transport_params_.get() == NULL);
     60       DCHECK(http_proxy_params_.get() != NULL);
     61       DCHECK(socks_params_.get() == NULL);
     62       ignore_limits_ = http_proxy_params_->ignore_limits();
     63       break;
     64     case ProxyServer::SCHEME_SOCKS4:
     65     case ProxyServer::SCHEME_SOCKS5:
     66       DCHECK(transport_params_.get() == NULL);
     67       DCHECK(http_proxy_params_.get() == NULL);
     68       DCHECK(socks_params_.get() != NULL);
     69       ignore_limits_ = socks_params_->ignore_limits();
     70       break;
     71     default:
     72       LOG(DFATAL) << "unknown proxy type";
     73       break;
     74   }
     75 }
     76 
     77 SSLSocketParams::~SSLSocketParams() {}
     78 
     79 // Timeout for the SSL handshake portion of the connect.
     80 static const int kSSLHandshakeTimeoutInSeconds = 30;
     81 
     82 SSLConnectJob::SSLConnectJob(const std::string& group_name,
     83                              const scoped_refptr<SSLSocketParams>& params,
     84                              const base::TimeDelta& timeout_duration,
     85                              TransportClientSocketPool* transport_pool,
     86                              SOCKSClientSocketPool* socks_pool,
     87                              HttpProxyClientSocketPool* http_proxy_pool,
     88                              ClientSocketFactory* client_socket_factory,
     89                              HostResolver* host_resolver,
     90                              const SSLClientSocketContext& context,
     91                              Delegate* delegate,
     92                              NetLog* net_log)
     93     : ConnectJob(group_name,
     94                  timeout_duration,
     95                  delegate,
     96                  BoundNetLog::Make(net_log, NetLog::SOURCE_CONNECT_JOB)),
     97       params_(params),
     98       transport_pool_(transport_pool),
     99       socks_pool_(socks_pool),
    100       http_proxy_pool_(http_proxy_pool),
    101       client_socket_factory_(client_socket_factory),
    102       host_resolver_(host_resolver),
    103       context_(context.cert_verifier,
    104                context.server_bound_cert_service,
    105                context.transport_security_state,
    106                (params->privacy_mode() == kPrivacyModeEnabled
    107                     ? "pm/" + context.ssl_session_cache_shard
    108                     : context.ssl_session_cache_shard)),
    109       callback_(base::Bind(&SSLConnectJob::OnIOComplete,
    110                            base::Unretained(this))) {}
    111 
    112 SSLConnectJob::~SSLConnectJob() {}
    113 
    114 LoadState SSLConnectJob::GetLoadState() const {
    115   switch (next_state_) {
    116     case STATE_TUNNEL_CONNECT_COMPLETE:
    117       if (transport_socket_handle_->socket())
    118         return LOAD_STATE_ESTABLISHING_PROXY_TUNNEL;
    119       // else, fall through.
    120     case STATE_TRANSPORT_CONNECT:
    121     case STATE_TRANSPORT_CONNECT_COMPLETE:
    122     case STATE_SOCKS_CONNECT:
    123     case STATE_SOCKS_CONNECT_COMPLETE:
    124     case STATE_TUNNEL_CONNECT:
    125       return transport_socket_handle_->GetLoadState();
    126     case STATE_SSL_CONNECT:
    127     case STATE_SSL_CONNECT_COMPLETE:
    128       return LOAD_STATE_SSL_HANDSHAKE;
    129     default:
    130       NOTREACHED();
    131       return LOAD_STATE_IDLE;
    132   }
    133 }
    134 
    135 void SSLConnectJob::GetAdditionalErrorState(ClientSocketHandle* handle) {
    136   // Headers in |error_response_info_| indicate a proxy tunnel setup
    137   // problem. See DoTunnelConnectComplete.
    138   if (error_response_info_.headers.get()) {
    139     handle->set_pending_http_proxy_connection(
    140         transport_socket_handle_.release());
    141   }
    142   handle->set_ssl_error_response_info(error_response_info_);
    143   if (!connect_timing_.ssl_start.is_null())
    144     handle->set_is_ssl_error(true);
    145 }
    146 
    147 void SSLConnectJob::OnIOComplete(int result) {
    148   int rv = DoLoop(result);
    149   if (rv != ERR_IO_PENDING)
    150     NotifyDelegateOfCompletion(rv);  // Deletes |this|.
    151 }
    152 
    153 int SSLConnectJob::DoLoop(int result) {
    154   DCHECK_NE(next_state_, STATE_NONE);
    155 
    156   int rv = result;
    157   do {
    158     State state = next_state_;
    159     next_state_ = STATE_NONE;
    160     switch (state) {
    161       case STATE_TRANSPORT_CONNECT:
    162         DCHECK_EQ(OK, rv);
    163         rv = DoTransportConnect();
    164         break;
    165       case STATE_TRANSPORT_CONNECT_COMPLETE:
    166         rv = DoTransportConnectComplete(rv);
    167         break;
    168       case STATE_SOCKS_CONNECT:
    169         DCHECK_EQ(OK, rv);
    170         rv = DoSOCKSConnect();
    171         break;
    172       case STATE_SOCKS_CONNECT_COMPLETE:
    173         rv = DoSOCKSConnectComplete(rv);
    174         break;
    175       case STATE_TUNNEL_CONNECT:
    176         DCHECK_EQ(OK, rv);
    177         rv = DoTunnelConnect();
    178         break;
    179       case STATE_TUNNEL_CONNECT_COMPLETE:
    180         rv = DoTunnelConnectComplete(rv);
    181         break;
    182       case STATE_SSL_CONNECT:
    183         DCHECK_EQ(OK, rv);
    184         rv = DoSSLConnect();
    185         break;
    186       case STATE_SSL_CONNECT_COMPLETE:
    187         rv = DoSSLConnectComplete(rv);
    188         break;
    189       default:
    190         NOTREACHED() << "bad state";
    191         rv = ERR_FAILED;
    192         break;
    193     }
    194   } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
    195 
    196   return rv;
    197 }
    198 
    199 int SSLConnectJob::DoTransportConnect() {
    200   DCHECK(transport_pool_);
    201 
    202   next_state_ = STATE_TRANSPORT_CONNECT_COMPLETE;
    203   transport_socket_handle_.reset(new ClientSocketHandle());
    204   scoped_refptr<TransportSocketParams> transport_params =
    205       params_->transport_params();
    206   return transport_socket_handle_->Init(
    207       group_name(), transport_params,
    208       transport_params->destination().priority(), callback_, transport_pool_,
    209       net_log());
    210 }
    211 
    212 int SSLConnectJob::DoTransportConnectComplete(int result) {
    213   if (result == OK)
    214     next_state_ = STATE_SSL_CONNECT;
    215 
    216   return result;
    217 }
    218 
    219 int SSLConnectJob::DoSOCKSConnect() {
    220   DCHECK(socks_pool_);
    221   next_state_ = STATE_SOCKS_CONNECT_COMPLETE;
    222   transport_socket_handle_.reset(new ClientSocketHandle());
    223   scoped_refptr<SOCKSSocketParams> socks_params = params_->socks_params();
    224   return transport_socket_handle_->Init(
    225       group_name(), socks_params, socks_params->destination().priority(),
    226       callback_, socks_pool_, net_log());
    227 }
    228 
    229 int SSLConnectJob::DoSOCKSConnectComplete(int result) {
    230   if (result == OK)
    231     next_state_ = STATE_SSL_CONNECT;
    232 
    233   return result;
    234 }
    235 
    236 int SSLConnectJob::DoTunnelConnect() {
    237   DCHECK(http_proxy_pool_);
    238   next_state_ = STATE_TUNNEL_CONNECT_COMPLETE;
    239 
    240   transport_socket_handle_.reset(new ClientSocketHandle());
    241   scoped_refptr<HttpProxySocketParams> http_proxy_params =
    242       params_->http_proxy_params();
    243   return transport_socket_handle_->Init(
    244       group_name(), http_proxy_params,
    245       http_proxy_params->destination().priority(), callback_, http_proxy_pool_,
    246       net_log());
    247 }
    248 
    249 int SSLConnectJob::DoTunnelConnectComplete(int result) {
    250   // Extract the information needed to prompt for appropriate proxy
    251   // authentication so that when ClientSocketPoolBaseHelper calls
    252   // |GetAdditionalErrorState|, we can easily set the state.
    253   if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
    254     error_response_info_ = transport_socket_handle_->ssl_error_response_info();
    255   } else if (result == ERR_PROXY_AUTH_REQUESTED ||
    256              result == ERR_HTTPS_PROXY_TUNNEL_RESPONSE) {
    257     StreamSocket* socket = transport_socket_handle_->socket();
    258     HttpProxyClientSocket* tunnel_socket =
    259         static_cast<HttpProxyClientSocket*>(socket);
    260     error_response_info_ = *tunnel_socket->GetConnectResponseInfo();
    261   }
    262   if (result < 0)
    263     return result;
    264 
    265   next_state_ = STATE_SSL_CONNECT;
    266   return result;
    267 }
    268 
    269 int SSLConnectJob::DoSSLConnect() {
    270   next_state_ = STATE_SSL_CONNECT_COMPLETE;
    271   // Reset the timeout to just the time allowed for the SSL handshake.
    272   ResetTimer(base::TimeDelta::FromSeconds(kSSLHandshakeTimeoutInSeconds));
    273 
    274   // If the handle has a fresh socket, get its connect start and DNS times.
    275   // This should always be the case.
    276   const LoadTimingInfo::ConnectTiming& socket_connect_timing =
    277       transport_socket_handle_->connect_timing();
    278   if (!transport_socket_handle_->is_reused() &&
    279       !socket_connect_timing.connect_start.is_null()) {
    280     // Overwriting |connect_start| serves two purposes - it adjusts timing so
    281     // |connect_start| doesn't include dns times, and it adjusts the time so
    282     // as not to include time spent waiting for an idle socket.
    283     connect_timing_.connect_start = socket_connect_timing.connect_start;
    284     connect_timing_.dns_start = socket_connect_timing.dns_start;
    285     connect_timing_.dns_end = socket_connect_timing.dns_end;
    286   }
    287 
    288   connect_timing_.ssl_start = base::TimeTicks::Now();
    289 
    290   ssl_socket_.reset(client_socket_factory_->CreateSSLClientSocket(
    291       transport_socket_handle_.release(),
    292       params_->host_and_port(),
    293       params_->ssl_config(),
    294       context_));
    295   return ssl_socket_->Connect(callback_);
    296 }
    297 
    298 int SSLConnectJob::DoSSLConnectComplete(int result) {
    299   connect_timing_.ssl_end = base::TimeTicks::Now();
    300 
    301   SSLClientSocket::NextProtoStatus status =
    302       SSLClientSocket::kNextProtoUnsupported;
    303   std::string proto;
    304   std::string server_protos;
    305   // GetNextProto will fail and and trigger a NOTREACHED if we pass in a socket
    306   // that hasn't had SSL_ImportFD called on it. If we get a certificate error
    307   // here, then we know that we called SSL_ImportFD.
    308   if (result == OK || IsCertificateError(result))
    309     status = ssl_socket_->GetNextProto(&proto, &server_protos);
    310 
    311   // If we want spdy over npn, make sure it succeeded.
    312   if (status == SSLClientSocket::kNextProtoNegotiated) {
    313     ssl_socket_->set_was_npn_negotiated(true);
    314     NextProto protocol_negotiated =
    315         SSLClientSocket::NextProtoFromString(proto);
    316     ssl_socket_->set_protocol_negotiated(protocol_negotiated);
    317     // If we negotiated a SPDY version, it must have been present in
    318     // SSLConfig::next_protos.
    319     // TODO(mbelshe): Verify this.
    320     if (protocol_negotiated >= kProtoSPDYMinimumVersion &&
    321         protocol_negotiated <= kProtoSPDYMaximumVersion) {
    322       ssl_socket_->set_was_spdy_negotiated(true);
    323     }
    324   }
    325   if (params_->want_spdy_over_npn() && !ssl_socket_->was_spdy_negotiated())
    326     return ERR_NPN_NEGOTIATION_FAILED;
    327 
    328   // Spdy might be turned on by default, or it might be over npn.
    329   bool using_spdy = params_->force_spdy_over_ssl() ||
    330       params_->want_spdy_over_npn();
    331 
    332   if (result == OK ||
    333       ssl_socket_->IgnoreCertError(result, params_->load_flags())) {
    334     DCHECK(!connect_timing_.ssl_start.is_null());
    335     base::TimeDelta connect_duration =
    336         connect_timing_.ssl_end - connect_timing_.ssl_start;
    337     if (using_spdy) {
    338       UMA_HISTOGRAM_CUSTOM_TIMES("Net.SpdyConnectionLatency_2",
    339                                  connect_duration,
    340                                  base::TimeDelta::FromMilliseconds(1),
    341                                  base::TimeDelta::FromMinutes(1),
    342                                  100);
    343     }
    344 #if defined(SPDY_PROXY_AUTH_ORIGIN)
    345     bool using_data_reduction_proxy = params_->host_and_port().Equals(
    346         HostPortPair::FromURL(GURL(SPDY_PROXY_AUTH_ORIGIN)));
    347     if (using_data_reduction_proxy) {
    348       UMA_HISTOGRAM_CUSTOM_TIMES(
    349           "Net.SSL_Connection_Latency_DataReductionProxy",
    350           connect_duration,
    351           base::TimeDelta::FromMilliseconds(1),
    352           base::TimeDelta::FromMinutes(1),
    353           100);
    354     }
    355 #endif
    356 
    357     UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_2",
    358                                connect_duration,
    359                                base::TimeDelta::FromMilliseconds(1),
    360                                base::TimeDelta::FromMinutes(1),
    361                                100);
    362 
    363     SSLInfo ssl_info;
    364     ssl_socket_->GetSSLInfo(&ssl_info);
    365 
    366     UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SSL_CipherSuite",
    367                                 SSLConnectionStatusToCipherSuite(
    368                                     ssl_info.connection_status));
    369 
    370     if (ssl_info.handshake_type == SSLInfo::HANDSHAKE_RESUME) {
    371       UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_Resume_Handshake",
    372                                  connect_duration,
    373                                  base::TimeDelta::FromMilliseconds(1),
    374                                  base::TimeDelta::FromMinutes(1),
    375                                  100);
    376     } else if (ssl_info.handshake_type == SSLInfo::HANDSHAKE_FULL) {
    377       UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_Full_Handshake",
    378                                  connect_duration,
    379                                  base::TimeDelta::FromMilliseconds(1),
    380                                  base::TimeDelta::FromMinutes(1),
    381                                  100);
    382     }
    383 
    384     const std::string& host = params_->host_and_port().host();
    385     bool is_google = host == "google.com" ||
    386                      (host.size() > 11 &&
    387                       host.rfind(".google.com") == host.size() - 11);
    388     if (is_google) {
    389       UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_Google2",
    390                                  connect_duration,
    391                                  base::TimeDelta::FromMilliseconds(1),
    392                                  base::TimeDelta::FromMinutes(1),
    393                                  100);
    394       if (ssl_info.handshake_type == SSLInfo::HANDSHAKE_RESUME) {
    395         UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_Google_"
    396                                        "Resume_Handshake",
    397                                    connect_duration,
    398                                    base::TimeDelta::FromMilliseconds(1),
    399                                    base::TimeDelta::FromMinutes(1),
    400                                    100);
    401       } else if (ssl_info.handshake_type == SSLInfo::HANDSHAKE_FULL) {
    402         UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_Google_"
    403                                        "Full_Handshake",
    404                                    connect_duration,
    405                                    base::TimeDelta::FromMilliseconds(1),
    406                                    base::TimeDelta::FromMinutes(1),
    407                                    100);
    408       }
    409     }
    410   }
    411 
    412   if (result == OK || IsCertificateError(result)) {
    413     set_socket(ssl_socket_.release());
    414   } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
    415     error_response_info_.cert_request_info = new SSLCertRequestInfo;
    416     ssl_socket_->GetSSLCertRequestInfo(
    417         error_response_info_.cert_request_info.get());
    418   }
    419 
    420   return result;
    421 }
    422 
    423 int SSLConnectJob::ConnectInternal() {
    424   switch (params_->proxy()) {
    425     case ProxyServer::SCHEME_DIRECT:
    426       next_state_ = STATE_TRANSPORT_CONNECT;
    427       break;
    428     case ProxyServer::SCHEME_HTTP:
    429     case ProxyServer::SCHEME_HTTPS:
    430       next_state_ = STATE_TUNNEL_CONNECT;
    431       break;
    432     case ProxyServer::SCHEME_SOCKS4:
    433     case ProxyServer::SCHEME_SOCKS5:
    434       next_state_ = STATE_SOCKS_CONNECT;
    435       break;
    436     default:
    437       NOTREACHED() << "unknown proxy type";
    438       break;
    439   }
    440   return DoLoop(OK);
    441 }
    442 
    443 SSLClientSocketPool::SSLConnectJobFactory::SSLConnectJobFactory(
    444     TransportClientSocketPool* transport_pool,
    445     SOCKSClientSocketPool* socks_pool,
    446     HttpProxyClientSocketPool* http_proxy_pool,
    447     ClientSocketFactory* client_socket_factory,
    448     HostResolver* host_resolver,
    449     const SSLClientSocketContext& context,
    450     NetLog* net_log)
    451     : transport_pool_(transport_pool),
    452       socks_pool_(socks_pool),
    453       http_proxy_pool_(http_proxy_pool),
    454       client_socket_factory_(client_socket_factory),
    455       host_resolver_(host_resolver),
    456       context_(context),
    457       net_log_(net_log) {
    458   base::TimeDelta max_transport_timeout = base::TimeDelta();
    459   base::TimeDelta pool_timeout;
    460   if (transport_pool_)
    461     max_transport_timeout = transport_pool_->ConnectionTimeout();
    462   if (socks_pool_) {
    463     pool_timeout = socks_pool_->ConnectionTimeout();
    464     if (pool_timeout > max_transport_timeout)
    465       max_transport_timeout = pool_timeout;
    466   }
    467   if (http_proxy_pool_) {
    468     pool_timeout = http_proxy_pool_->ConnectionTimeout();
    469     if (pool_timeout > max_transport_timeout)
    470       max_transport_timeout = pool_timeout;
    471   }
    472   timeout_ = max_transport_timeout +
    473       base::TimeDelta::FromSeconds(kSSLHandshakeTimeoutInSeconds);
    474 }
    475 
    476 SSLClientSocketPool::SSLClientSocketPool(
    477     int max_sockets,
    478     int max_sockets_per_group,
    479     ClientSocketPoolHistograms* histograms,
    480     HostResolver* host_resolver,
    481     CertVerifier* cert_verifier,
    482     ServerBoundCertService* server_bound_cert_service,
    483     TransportSecurityState* transport_security_state,
    484     const std::string& ssl_session_cache_shard,
    485     ClientSocketFactory* client_socket_factory,
    486     TransportClientSocketPool* transport_pool,
    487     SOCKSClientSocketPool* socks_pool,
    488     HttpProxyClientSocketPool* http_proxy_pool,
    489     SSLConfigService* ssl_config_service,
    490     NetLog* net_log)
    491     : transport_pool_(transport_pool),
    492       socks_pool_(socks_pool),
    493       http_proxy_pool_(http_proxy_pool),
    494       base_(max_sockets, max_sockets_per_group, histograms,
    495             ClientSocketPool::unused_idle_socket_timeout(),
    496             ClientSocketPool::used_idle_socket_timeout(),
    497             new SSLConnectJobFactory(transport_pool,
    498                                      socks_pool,
    499                                      http_proxy_pool,
    500                                      client_socket_factory,
    501                                      host_resolver,
    502                                      SSLClientSocketContext(
    503                                          cert_verifier,
    504                                          server_bound_cert_service,
    505                                          transport_security_state,
    506                                          ssl_session_cache_shard),
    507                                      net_log)),
    508       ssl_config_service_(ssl_config_service) {
    509   if (ssl_config_service_.get())
    510     ssl_config_service_->AddObserver(this);
    511   if (transport_pool_)
    512     transport_pool_->AddLayeredPool(this);
    513   if (socks_pool_)
    514     socks_pool_->AddLayeredPool(this);
    515   if (http_proxy_pool_)
    516     http_proxy_pool_->AddLayeredPool(this);
    517 }
    518 
    519 SSLClientSocketPool::~SSLClientSocketPool() {
    520   if (http_proxy_pool_)
    521     http_proxy_pool_->RemoveLayeredPool(this);
    522   if (socks_pool_)
    523     socks_pool_->RemoveLayeredPool(this);
    524   if (transport_pool_)
    525     transport_pool_->RemoveLayeredPool(this);
    526   if (ssl_config_service_.get())
    527     ssl_config_service_->RemoveObserver(this);
    528 }
    529 
    530 ConnectJob* SSLClientSocketPool::SSLConnectJobFactory::NewConnectJob(
    531     const std::string& group_name,
    532     const PoolBase::Request& request,
    533     ConnectJob::Delegate* delegate) const {
    534   return new SSLConnectJob(group_name, request.params(), ConnectionTimeout(),
    535                            transport_pool_, socks_pool_, http_proxy_pool_,
    536                            client_socket_factory_, host_resolver_,
    537                            context_, delegate, net_log_);
    538 }
    539 
    540 base::TimeDelta
    541 SSLClientSocketPool::SSLConnectJobFactory::ConnectionTimeout() const {
    542   return timeout_;
    543 }
    544 
    545 int SSLClientSocketPool::RequestSocket(const std::string& group_name,
    546                                        const void* socket_params,
    547                                        RequestPriority priority,
    548                                        ClientSocketHandle* handle,
    549                                        const CompletionCallback& callback,
    550                                        const BoundNetLog& net_log) {
    551   const scoped_refptr<SSLSocketParams>* casted_socket_params =
    552       static_cast<const scoped_refptr<SSLSocketParams>*>(socket_params);
    553 
    554   return base_.RequestSocket(group_name, *casted_socket_params, priority,
    555                              handle, callback, net_log);
    556 }
    557 
    558 void SSLClientSocketPool::RequestSockets(
    559     const std::string& group_name,
    560     const void* params,
    561     int num_sockets,
    562     const BoundNetLog& net_log) {
    563   const scoped_refptr<SSLSocketParams>* casted_params =
    564       static_cast<const scoped_refptr<SSLSocketParams>*>(params);
    565 
    566   base_.RequestSockets(group_name, *casted_params, num_sockets, net_log);
    567 }
    568 
    569 void SSLClientSocketPool::CancelRequest(const std::string& group_name,
    570                                         ClientSocketHandle* handle) {
    571   base_.CancelRequest(group_name, handle);
    572 }
    573 
    574 void SSLClientSocketPool::ReleaseSocket(const std::string& group_name,
    575                                         StreamSocket* socket, int id) {
    576   base_.ReleaseSocket(group_name, socket, id);
    577 }
    578 
    579 void SSLClientSocketPool::FlushWithError(int error) {
    580   base_.FlushWithError(error);
    581 }
    582 
    583 bool SSLClientSocketPool::IsStalled() const {
    584   return base_.IsStalled() ||
    585       (transport_pool_ && transport_pool_->IsStalled()) ||
    586       (socks_pool_ && socks_pool_->IsStalled()) ||
    587       (http_proxy_pool_ && http_proxy_pool_->IsStalled());
    588 }
    589 
    590 void SSLClientSocketPool::CloseIdleSockets() {
    591   base_.CloseIdleSockets();
    592 }
    593 
    594 int SSLClientSocketPool::IdleSocketCount() const {
    595   return base_.idle_socket_count();
    596 }
    597 
    598 int SSLClientSocketPool::IdleSocketCountInGroup(
    599     const std::string& group_name) const {
    600   return base_.IdleSocketCountInGroup(group_name);
    601 }
    602 
    603 LoadState SSLClientSocketPool::GetLoadState(
    604     const std::string& group_name, const ClientSocketHandle* handle) const {
    605   return base_.GetLoadState(group_name, handle);
    606 }
    607 
    608 void SSLClientSocketPool::AddLayeredPool(LayeredPool* layered_pool) {
    609   base_.AddLayeredPool(layered_pool);
    610 }
    611 
    612 void SSLClientSocketPool::RemoveLayeredPool(LayeredPool* layered_pool) {
    613   base_.RemoveLayeredPool(layered_pool);
    614 }
    615 
    616 base::DictionaryValue* SSLClientSocketPool::GetInfoAsValue(
    617     const std::string& name,
    618     const std::string& type,
    619     bool include_nested_pools) const {
    620   base::DictionaryValue* dict = base_.GetInfoAsValue(name, type);
    621   if (include_nested_pools) {
    622     base::ListValue* list = new base::ListValue();
    623     if (transport_pool_) {
    624       list->Append(transport_pool_->GetInfoAsValue("transport_socket_pool",
    625                                                    "transport_socket_pool",
    626                                                    false));
    627     }
    628     if (socks_pool_) {
    629       list->Append(socks_pool_->GetInfoAsValue("socks_pool",
    630                                                "socks_pool",
    631                                                true));
    632     }
    633     if (http_proxy_pool_) {
    634       list->Append(http_proxy_pool_->GetInfoAsValue("http_proxy_pool",
    635                                                     "http_proxy_pool",
    636                                                     true));
    637     }
    638     dict->Set("nested_pools", list);
    639   }
    640   return dict;
    641 }
    642 
    643 base::TimeDelta SSLClientSocketPool::ConnectionTimeout() const {
    644   return base_.ConnectionTimeout();
    645 }
    646 
    647 ClientSocketPoolHistograms* SSLClientSocketPool::histograms() const {
    648   return base_.histograms();
    649 }
    650 
    651 void SSLClientSocketPool::OnSSLConfigChanged() {
    652   FlushWithError(ERR_NETWORK_CHANGED);
    653 }
    654 
    655 bool SSLClientSocketPool::CloseOneIdleConnection() {
    656   if (base_.CloseOneIdleSocket())
    657     return true;
    658   return base_.CloseOneIdleConnectionInLayeredPool();
    659 }
    660 
    661 }  // namespace net
    662