// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef NET_SOCKET_SSL_CLIENT_SOCKET_POOL_H_
#define NET_SOCKET_SSL_CLIENT_SOCKET_POOL_H_

#include <map>
#include <string>
#include <vector>

#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
#include "net/base/privacy_mode.h"
#include "net/http/http_response_info.h"
#include "net/socket/client_socket_pool.h"
#include "net/socket/client_socket_pool_base.h"
#include "net/socket/client_socket_pool_histograms.h"
#include "net/socket/ssl_client_socket.h"
#include "net/ssl/ssl_config_service.h"

namespace net {

class CertPolicyEnforcer;
class CertVerifier;
class ClientSocketFactory;
class ConnectJobFactory;
class CTVerifier;
class HostPortPair;
class HttpProxyClientSocketPool;
class HttpProxySocketParams;
class SOCKSClientSocketPool;
class SOCKSSocketParams;
class SSLClientSocket;
class TransportClientSocketPool;
class TransportSecurityState;
class TransportSocketParams;

class NET_EXPORT_PRIVATE SSLSocketParams
    : public base::RefCounted<SSLSocketParams> {
 public:
  enum ConnectionType { DIRECT, SOCKS_PROXY, HTTP_PROXY };

  // Exactly one of |direct_params|, |socks_proxy_params|, and
  // |http_proxy_params| must be non-NULL.
  SSLSocketParams(
      const scoped_refptr<TransportSocketParams>& direct_params,
      const scoped_refptr<SOCKSSocketParams>& socks_proxy_params,
      const scoped_refptr<HttpProxySocketParams>& http_proxy_params,
      const HostPortPair& host_and_port,
      const SSLConfig& ssl_config,
      PrivacyMode privacy_mode,
      int load_flags,
      bool force_spdy_over_ssl,
      bool want_spdy_over_npn);

  // Returns the type of the underlying connection.
  ConnectionType GetConnectionType() const;

  // Must be called only when GetConnectionType() returns DIRECT.
  const scoped_refptr<TransportSocketParams>&
      GetDirectConnectionParams() const;

  // Must be called only when GetConnectionType() returns SOCKS_PROXY.
  const scoped_refptr<SOCKSSocketParams>&
      GetSocksProxyConnectionParams() const;

  // Must be called only when GetConnectionType() returns HTTP_PROXY.
  const scoped_refptr<HttpProxySocketParams>&
      GetHttpProxyConnectionParams() const;

  const HostPortPair& host_and_port() const { return host_and_port_; }
  const SSLConfig& ssl_config() const { return ssl_config_; }
  PrivacyMode privacy_mode() const { return privacy_mode_; }
  int load_flags() const { return load_flags_; }
  bool force_spdy_over_ssl() const { return force_spdy_over_ssl_; }
  bool want_spdy_over_npn() const { return want_spdy_over_npn_; }
  bool ignore_limits() const { return ignore_limits_; }

 private:
  friend class base::RefCounted<SSLSocketParams>;
  ~SSLSocketParams();

  const scoped_refptr<TransportSocketParams> direct_params_;
  const scoped_refptr<SOCKSSocketParams> socks_proxy_params_;
  const scoped_refptr<HttpProxySocketParams> http_proxy_params_;
  const HostPortPair host_and_port_;
  const SSLConfig ssl_config_;
  const PrivacyMode privacy_mode_;
  const int load_flags_;
  const bool force_spdy_over_ssl_;
  const bool want_spdy_over_npn_;
  bool ignore_limits_;

  DISALLOW_COPY_AND_ASSIGN(SSLSocketParams);
};

// SSLConnectJobMessenger handles communication between concurrent
// SSLConnectJobs that share the same SSL session cache key.
//
// SSLConnectJobMessengers tell the session cache when a certain
// connection should be monitored for success or failure, and
// tell SSLConnectJobs when to pause or resume their connections.
class SSLConnectJobMessenger {
 public:
  struct SocketAndCallback {
    SocketAndCallback(SSLClientSocket* ssl_socket,
                      const base::Closure& job_resumption_callback);
    ~SocketAndCallback();

    SSLClientSocket* socket;
    base::Closure callback;
  };

  typedef std::vector<SocketAndCallback> SSLPendingSocketsAndCallbacks;

  // |messenger_finished_callback| is run when a connection monitored by the
  // SSLConnectJobMessenger has completed and we are finished with the
  // SSLConnectJobMessenger.
  explicit SSLConnectJobMessenger(
      const base::Closure& messenger_finished_callback);
  ~SSLConnectJobMessenger();

  // Removes |socket| from the set of sockets being monitored. This
  // guarantees that |job_resumption_callback| will not be called for
  // the socket.
  void RemovePendingSocket(SSLClientSocket* ssl_socket);

  // Returns true if |ssl_socket|'s Connect() method should be called.
  bool CanProceed(SSLClientSocket* ssl_socket);

  // Configures the SSLConnectJobMessenger to begin monitoring |ssl_socket|'s
  // connection status. After a successful connection, or an error,
  // the messenger will determine which sockets that have been added
  // via AddPendingSocket() to allow to proceed.
  void MonitorConnectionResult(SSLClientSocket* ssl_socket);

  // Adds |socket| to the list of sockets waiting to Connect(). When
  // the messenger has determined that it's an appropriate time for |socket|
  // to connect, it will invoke |callback|.
  //
  // Note: It is an error to call AddPendingSocket() without having first
  // called MonitorConnectionResult() and configuring a socket that WILL
  // have Connect() called on it.
  void AddPendingSocket(SSLClientSocket* ssl_socket,
                        const base::Closure& callback);

 private:
  // Processes pending callbacks when a socket completes its SSL handshake --
  // either successfully or unsuccessfully.
  void OnSSLHandshakeCompleted();

  // Runs all callbacks stored in |pending_sockets_and_callbacks_|.
  void RunAllCallbacks(
      const SSLPendingSocketsAndCallbacks& pending_socket_and_callbacks);

  SSLPendingSocketsAndCallbacks pending_sockets_and_callbacks_;
  // Note: this field is a vector to allow for future design changes. Currently,
  // this vector should only ever have one entry.
  std::vector<SSLClientSocket*> connecting_sockets_;

  base::Closure messenger_finished_callback_;

  base::WeakPtrFactory<SSLConnectJobMessenger> weak_factory_;
};

// SSLConnectJob handles the SSL handshake after setting up the underlying
// connection as specified in the params.
class SSLConnectJob : public ConnectJob {
 public:
  // Callback to allow the SSLConnectJob to obtain an SSLConnectJobMessenger to
  // coordinate connecting. The SSLConnectJob will supply a unique identifer
  // (ex: the SSL session cache key), with the expectation that the same
  // Messenger will be returned for all such ConnectJobs.
  //
  // Note: It will only be called for situations where the SSL session cache
  // does not already have a candidate session to resume.
  typedef base::Callback<SSLConnectJobMessenger*(const std::string&)>
      GetMessengerCallback;

  // Note: the SSLConnectJob does not own |messenger| so it must outlive the
  // job.
  SSLConnectJob(const std::string& group_name,
                RequestPriority priority,
                const scoped_refptr<SSLSocketParams>& params,
                const base::TimeDelta& timeout_duration,
                TransportClientSocketPool* transport_pool,
                SOCKSClientSocketPool* socks_pool,
                HttpProxyClientSocketPool* http_proxy_pool,
                ClientSocketFactory* client_socket_factory,
                const SSLClientSocketContext& context,
                const GetMessengerCallback& get_messenger_callback,
                Delegate* delegate,
                NetLog* net_log);
  ~SSLConnectJob() override;

  // ConnectJob methods.
  LoadState GetLoadState() const override;

  void GetAdditionalErrorState(ClientSocketHandle* handle) override;

 private:
  enum State {
    STATE_TRANSPORT_CONNECT,
    STATE_TRANSPORT_CONNECT_COMPLETE,
    STATE_SOCKS_CONNECT,
    STATE_SOCKS_CONNECT_COMPLETE,
    STATE_TUNNEL_CONNECT,
    STATE_TUNNEL_CONNECT_COMPLETE,
    STATE_CREATE_SSL_SOCKET,
    STATE_CHECK_FOR_RESUME,
    STATE_SSL_CONNECT,
    STATE_SSL_CONNECT_COMPLETE,
    STATE_NONE,
  };

  void OnIOComplete(int result);

  // Runs the state transition loop.
  int DoLoop(int result);

  int DoTransportConnect();
  int DoTransportConnectComplete(int result);
  int DoSOCKSConnect();
  int DoSOCKSConnectComplete(int result);
  int DoTunnelConnect();
  int DoTunnelConnectComplete(int result);
  int DoCreateSSLSocket();
  int DoCheckForResume();
  int DoSSLConnect();
  int DoSSLConnectComplete(int result);

  // Tells a waiting SSLConnectJob to resume its SSL connection.
  void ResumeSSLConnection();

  // Returns the initial state for the state machine based on the
  // |connection_type|.
  static State GetInitialState(SSLSocketParams::ConnectionType connection_type);

  // Starts the SSL connection process.  Returns OK on success and
  // ERR_IO_PENDING if it cannot immediately service the request.
  // Otherwise, it returns a net error code.
  int ConnectInternal() override;

  scoped_refptr<SSLSocketParams> params_;
  TransportClientSocketPool* const transport_pool_;
  SOCKSClientSocketPool* const socks_pool_;
  HttpProxyClientSocketPool* const http_proxy_pool_;
  ClientSocketFactory* const client_socket_factory_;

  const SSLClientSocketContext context_;

  State next_state_;
  CompletionCallback io_callback_;
  scoped_ptr<ClientSocketHandle> transport_socket_handle_;
  scoped_ptr<SSLClientSocket> ssl_socket_;

  SSLConnectJobMessenger* messenger_;
  HttpResponseInfo error_response_info_;

  GetMessengerCallback get_messenger_callback_;

  base::WeakPtrFactory<SSLConnectJob> weak_factory_;

  DISALLOW_COPY_AND_ASSIGN(SSLConnectJob);
};

class NET_EXPORT_PRIVATE SSLClientSocketPool
    : public ClientSocketPool,
      public HigherLayeredPool,
      public SSLConfigService::Observer {
 public:
  typedef SSLSocketParams SocketParams;

  // Only the pools that will be used are required. i.e. if you never
  // try to create an SSL over SOCKS socket, |socks_pool| may be NULL.
  SSLClientSocketPool(int max_sockets,
                      int max_sockets_per_group,
                      ClientSocketPoolHistograms* histograms,
                      CertVerifier* cert_verifier,
                      ChannelIDService* channel_id_service,
                      TransportSecurityState* transport_security_state,
                      CTVerifier* cert_transparency_verifier,
                      CertPolicyEnforcer* cert_policy_enforcer,
                      const std::string& ssl_session_cache_shard,
                      ClientSocketFactory* client_socket_factory,
                      TransportClientSocketPool* transport_pool,
                      SOCKSClientSocketPool* socks_pool,
                      HttpProxyClientSocketPool* http_proxy_pool,
                      SSLConfigService* ssl_config_service,
                      bool enable_ssl_connect_job_waiting,
                      NetLog* net_log);

  ~SSLClientSocketPool() override;

  // ClientSocketPool implementation.
  int RequestSocket(const std::string& group_name,
                    const void* connect_params,
                    RequestPriority priority,
                    ClientSocketHandle* handle,
                    const CompletionCallback& callback,
                    const BoundNetLog& net_log) override;

  void RequestSockets(const std::string& group_name,
                      const void* params,
                      int num_sockets,
                      const BoundNetLog& net_log) override;

  void CancelRequest(const std::string& group_name,
                     ClientSocketHandle* handle) override;

  void ReleaseSocket(const std::string& group_name,
                     scoped_ptr<StreamSocket> socket,
                     int id) override;

  void FlushWithError(int error) override;

  void CloseIdleSockets() override;

  int IdleSocketCount() const override;

  int IdleSocketCountInGroup(const std::string& group_name) const override;

  LoadState GetLoadState(const std::string& group_name,
                         const ClientSocketHandle* handle) const override;

  base::DictionaryValue* GetInfoAsValue(
      const std::string& name,
      const std::string& type,
      bool include_nested_pools) const override;

  base::TimeDelta ConnectionTimeout() const override;

  ClientSocketPoolHistograms* histograms() const override;

  // LowerLayeredPool implementation.
  bool IsStalled() const override;

  void AddHigherLayeredPool(HigherLayeredPool* higher_pool) override;

  void RemoveHigherLayeredPool(HigherLayeredPool* higher_pool) override;

  // HigherLayeredPool implementation.
  bool CloseOneIdleConnection() override;

  // Gets the SSLConnectJobMessenger for the given ssl session |cache_key|. If
  // none exits, it creates one and stores it in |messenger_map_|.
  SSLConnectJobMessenger* GetOrCreateSSLConnectJobMessenger(
      const std::string& cache_key);
  void DeleteSSLConnectJobMessenger(const std::string& cache_key);

 private:
  typedef ClientSocketPoolBase<SSLSocketParams> PoolBase;
  // Maps SSLConnectJob cache keys to SSLConnectJobMessenger objects.
  typedef std::map<std::string, SSLConnectJobMessenger*> MessengerMap;

  // SSLConfigService::Observer implementation.

  // When the user changes the SSL config, we flush all idle sockets so they
  // won't get re-used.
  void OnSSLConfigChanged() override;

  class SSLConnectJobFactory : public PoolBase::ConnectJobFactory {
   public:
    SSLConnectJobFactory(
        TransportClientSocketPool* transport_pool,
        SOCKSClientSocketPool* socks_pool,
        HttpProxyClientSocketPool* http_proxy_pool,
        ClientSocketFactory* client_socket_factory,
        const SSLClientSocketContext& context,
        const SSLConnectJob::GetMessengerCallback& get_messenger_callback,
        NetLog* net_log);

    ~SSLConnectJobFactory() override;

    // ClientSocketPoolBase::ConnectJobFactory methods.
    scoped_ptr<ConnectJob> NewConnectJob(
        const std::string& group_name,
        const PoolBase::Request& request,
        ConnectJob::Delegate* delegate) const override;

    base::TimeDelta ConnectionTimeout() const override;

   private:
    TransportClientSocketPool* const transport_pool_;
    SOCKSClientSocketPool* const socks_pool_;
    HttpProxyClientSocketPool* const http_proxy_pool_;
    ClientSocketFactory* const client_socket_factory_;
    const SSLClientSocketContext context_;
    base::TimeDelta timeout_;
    SSLConnectJob::GetMessengerCallback get_messenger_callback_;
    NetLog* net_log_;

    DISALLOW_COPY_AND_ASSIGN(SSLConnectJobFactory);
  };

  TransportClientSocketPool* const transport_pool_;
  SOCKSClientSocketPool* const socks_pool_;
  HttpProxyClientSocketPool* const http_proxy_pool_;
  PoolBase base_;
  const scoped_refptr<SSLConfigService> ssl_config_service_;
  MessengerMap messenger_map_;
  bool enable_ssl_connect_job_waiting_;

  DISALLOW_COPY_AND_ASSIGN(SSLClientSocketPool);
};

}  // namespace net

#endif  // NET_SOCKET_SSL_CLIENT_SOCKET_POOL_H_
