// Copyright 2018 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_CONNECT_JOB_H_
#define NET_SOCKET_CONNECT_JOB_H_

#include <memory>
#include <string>

#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/optional.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "net/base/address_list.h"
#include "net/base/load_states.h"
#include "net/base/load_timing_info.h"
#include "net/base/net_export.h"
#include "net/base/privacy_mode.h"
#include "net/base/request_priority.h"
#include "net/log/net_log_with_source.h"
#include "net/socket/connection_attempts.h"
#include "net/socket/socket_tag.h"
#include "net/socket/ssl_client_socket.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"

namespace net {

class ClientSocketFactory;
class HostPortPair;
class HostResolver;
class HttpAuthCache;
class HttpAuthController;
class HttpAuthHandlerFactory;
class HttpResponseInfo;
class HttpUserAgentSettings;
class NetLog;
class NetLogWithSource;
class NetworkQualityEstimator;
struct NetworkTrafficAnnotationTag;
class ProxyDelegate;
class ProxyServer;
class SocketPerformanceWatcherFactory;
struct SSLConfig;
class StreamSocket;
class WebSocketEndpointLockManager;
class QuicStreamFactory;
class SocketTag;
class SpdySessionPool;
class SSLCertRequestInfo;

// Immutable socket parameters intended for shared use by all ConnectJob types.
// Excludes priority because it can be modified over the lifetime of a
// ConnectJob. Excludes connection timeout and NetLogWithSource because
// ConnectJobs that wrap other ConnectJobs typically have different values for
// those.
struct NET_EXPORT_PRIVATE CommonConnectJobParams {
  CommonConnectJobParams(
      ClientSocketFactory* client_socket_factory,
      HostResolver* host_resolver,
      HttpAuthCache* http_auth_cache,
      HttpAuthHandlerFactory* http_auth_handler_factory,
      SpdySessionPool* spdy_session_pool,
      const quic::ParsedQuicVersionVector* quic_supported_versions,
      QuicStreamFactory* quic_stream_factory,
      ProxyDelegate* proxy_delegate,
      const HttpUserAgentSettings* http_user_agent_settings,
      const SSLClientSocketContext& ssl_client_socket_context,
      const SSLClientSocketContext& ssl_client_socket_context_privacy_mode,
      SocketPerformanceWatcherFactory* socket_performance_watcher_factory,
      NetworkQualityEstimator* network_quality_estimator,
      NetLog* net_log,
      WebSocketEndpointLockManager* websocket_endpoint_lock_manager);
  CommonConnectJobParams(const CommonConnectJobParams& other);
  ~CommonConnectJobParams();

  CommonConnectJobParams& operator=(const CommonConnectJobParams& other);

  ClientSocketFactory* client_socket_factory;
  HostResolver* host_resolver;
  HttpAuthCache* http_auth_cache;
  HttpAuthHandlerFactory* http_auth_handler_factory;
  SpdySessionPool* spdy_session_pool;
  const quic::ParsedQuicVersionVector* quic_supported_versions;
  QuicStreamFactory* quic_stream_factory;
  ProxyDelegate* proxy_delegate;
  const HttpUserAgentSettings* http_user_agent_settings;
  SSLClientSocketContext ssl_client_socket_context;
  SSLClientSocketContext ssl_client_socket_context_privacy_mode;
  SocketPerformanceWatcherFactory* socket_performance_watcher_factory;
  NetworkQualityEstimator* network_quality_estimator;
  NetLog* net_log;

  // This must only be non-null for WebSockets.
  WebSocketEndpointLockManager* websocket_endpoint_lock_manager;
};

// When a host resolution completes, OnHostResolutionCallback() is invoked. If
// it returns |kContinue|, the ConnectJob can continue immediately. If it
// returns |kMayBeDeletedAsync|, the ConnectJob may be slated for asychronous
// destruction, so should post a task before continuing, in case it will be
// deleted. The purpose of kMayBeDeletedAsync is to avoid needlessly creating
// and connecting a socket when it might not be needed.
enum class OnHostResolutionCallbackResult {
  kContinue,
  kMayBeDeletedAsync,
};

// If non-null, invoked when host resolution completes. May not destroy the
// ConnectJob synchronously, but may signal the ConnectJob may be destroyed
// asynchronously. See OnHostResolutionCallbackResult above.
//
// |address_list| is the list of addresses the host being connected to was
// resolved to, with the port fields populated to the port being connected to.
using OnHostResolutionCallback =
    base::RepeatingCallback<OnHostResolutionCallbackResult(
        const HostPortPair& host_port_pair,
        const AddressList& address_list)>;

// ConnectJob provides an abstract interface for "connecting" a socket.
// The connection may involve host resolution, tcp connection, ssl connection,
// etc.
class NET_EXPORT_PRIVATE ConnectJob {
 public:
  // Alerts the delegate that the connection completed. |job| must be destroyed
  // by the delegate. A std::unique_ptr<> isn't used because the caller of this
  // function doesn't own |job|.
  class NET_EXPORT_PRIVATE Delegate {
   public:
    Delegate() {}
    virtual ~Delegate() {}

    // Alerts the delegate that the connection completed. |job| must be
    // destroyed by the delegate. A std::unique_ptr<> isn't used because the
    // caller of this function doesn't own |job|.
    virtual void OnConnectJobComplete(int result, ConnectJob* job) = 0;

    // Invoked when an HTTP proxy returns an HTTP auth challenge during tunnel
    // establishment. Always invoked asynchronously. The caller should use
    // |auth_controller| to set challenge response information and then invoke
    // |restart_with_auth_callback| to continue establishing a connection, or
    // delete the ConnectJob if it doesn't want to respond to the challenge.
    //
    // Will only be called once at a time. Neither OnConnectJobComplete() nor
    // OnNeedsProxyAuth() will be called synchronously when
    // |restart_with_auth_callback| is invoked. Will not be called after
    // OnConnectJobComplete() has been invoked.
    virtual void OnNeedsProxyAuth(const HttpResponseInfo& response,
                                  HttpAuthController* auth_controller,
                                  base::OnceClosure restart_with_auth_callback,
                                  ConnectJob* job) = 0;

   private:
    DISALLOW_COPY_AND_ASSIGN(Delegate);
  };

  // A |timeout_duration| of 0 corresponds to no timeout.
  //
  // If |net_log| is non-NULL, the ConnectJob will use it for logging.
  // Otherwise, a new one will be created of type |net_log_source_type|.
  //
  // |net_log_connect_event_type| is the NetLog event type logged on Connect()
  // and connect completion.
  ConnectJob(RequestPriority priority,
             const SocketTag& socket_tag,
             base::TimeDelta timeout_duration,
             const CommonConnectJobParams* common_connect_job_params,
             Delegate* delegate,
             const NetLogWithSource* net_log,
             NetLogSourceType net_log_source_type,
             NetLogEventType net_log_connect_event_type);
  virtual ~ConnectJob();

  // Creates a ConnectJob with the specified parameters.
  // |common_connect_job_params| and |delegate| must outlive the returned
  // ConnectJob.
  static std::unique_ptr<ConnectJob> CreateConnectJob(
      bool using_ssl,
      const HostPortPair& endpoint,
      const ProxyServer& proxy_server,
      const base::Optional<NetworkTrafficAnnotationTag>& proxy_annotation_tag,
      const SSLConfig* ssl_config_for_origin,
      const SSLConfig* ssl_config_for_proxy,
      bool force_tunnel,
      PrivacyMode privacy_mode,
      const OnHostResolutionCallback& resolution_callback,
      RequestPriority request_priority,
      SocketTag socket_tag,
      const CommonConnectJobParams* common_connect_job_params,
      ConnectJob::Delegate* delegate);

  // Accessors
  const NetLogWithSource& net_log() { return net_log_; }
  RequestPriority priority() const { return priority_; }

  // Releases ownership of the underlying socket to the caller. Returns the
  // released socket, or nullptr if there was a connection error.
  std::unique_ptr<StreamSocket> PassSocket();

  // Returns the connected socket, or nullptr if PassSocket() has already been
  // called. Used to query the socket state. May only be called after the
  // ConnectJob completes.
  StreamSocket* socket() { return socket_.get(); }

  void ChangePriority(RequestPriority priority);

  // Begins connecting the socket.  Returns OK on success, ERR_IO_PENDING if it
  // cannot complete synchronously without blocking, or another net error code
  // on error.  In asynchronous completion, the ConnectJob will notify
  // |delegate_| via OnConnectJobComplete.  In both asynchronous and synchronous
  // completion, ReleaseSocket() can be called to acquire the connected socket
  // if it succeeded.
  //
  // On completion, the ConnectJob must be destroyed synchronously, since it
  // doesn't bother to stop its timer when complete.
  // TODO(mmenke): Can that be fixed?
  int Connect();

  // Returns the current LoadState of the ConnectJob. Each ConnectJob class must
  // start (optionally) with a LOAD_STATE_RESOLVING_HOST followed by
  // LOAD_STATE_CONNECTING, and never return to LOAD_STATE_CONNECTING. This
  // behavior is needed for backup ConnectJobs to function correctly.
  //
  // TODO(mmenke): Can something better be done here?
  virtual LoadState GetLoadState() const = 0;

  // Returns true if the ConnectJob has ever successfully established a TCP
  // connection. Used solely for deciding if a backup job is needed. Once it
  // starts returning true, must always return true when called in the future.
  // Not safe to call after NotifyComplete() is invoked.
  virtual bool HasEstablishedConnection() const = 0;

  // If the ConnectJobFailed, this method returns a list of failed attempts to
  // connect to the destination server. Returns an empty list if connecting to a
  // proxy.
  virtual ConnectionAttempts GetConnectionAttempts() const;

  // If the ConnectJob failed, returns true if the failure occurred after SSL
  // negotiation started. If the ConnectJob succeeded, the returned value is
  // undefined.
  virtual bool IsSSLError() const;

  // If the ConnectJob failed with ERR_SSL_CLIENT_AUTH_CERT_NEEDED, returns the
  // SSLCertRequestInfo received. Otherwise, returns nullptr.
  virtual scoped_refptr<SSLCertRequestInfo> GetCertRequestInfo();

  const LoadTimingInfo::ConnectTiming& connect_timing() const {
    return connect_timing_;
  }

  const NetLogWithSource& net_log() const { return net_log_; }

 protected:
  const SocketTag& socket_tag() const { return socket_tag_; }
  ClientSocketFactory* client_socket_factory() {
    return common_connect_job_params_->client_socket_factory;
  }
  HostResolver* host_resolver() {
    return common_connect_job_params_->host_resolver;
  }
  const HttpUserAgentSettings* http_user_agent_settings() const {
    return common_connect_job_params_->http_user_agent_settings;
  }
  const SSLClientSocketContext& ssl_client_socket_context() {
    return common_connect_job_params_->ssl_client_socket_context;
  }
  const SSLClientSocketContext& ssl_client_socket_context_privacy_mode() {
    return common_connect_job_params_->ssl_client_socket_context_privacy_mode;
  }
  SocketPerformanceWatcherFactory* socket_performance_watcher_factory() {
    return common_connect_job_params_->socket_performance_watcher_factory;
  }
  NetworkQualityEstimator* network_quality_estimator() {
    return common_connect_job_params_->network_quality_estimator;
  }
  WebSocketEndpointLockManager* websocket_endpoint_lock_manager() {
    return common_connect_job_params_->websocket_endpoint_lock_manager;
  }
  const CommonConnectJobParams* common_connect_job_params() {
    return common_connect_job_params_;
  }

  void SetSocket(std::unique_ptr<StreamSocket> socket);
  void NotifyDelegateOfCompletion(int rv);
  void NotifyDelegateOfProxyAuth(const HttpResponseInfo& response,
                                 HttpAuthController* auth_controller,
                                 base::OnceClosure restart_with_auth_callback);

  // If |remaining_time| is base::TimeDelta(), stops the timeout timer, if it's
  // running. Otherwise, Starts / restarts the timeout timer to trigger in the
  // specified amount of time.
  void ResetTimer(base::TimeDelta remaining_time);

  // Returns whether or not the timeout timer is running. Only intended for use
  // by DCHECKs.
  bool TimerIsRunning() const;

  // Connection establishment timing information.
  // TODO(mmenke): This should be private.
  LoadTimingInfo::ConnectTiming connect_timing_;

 private:
  virtual int ConnectInternal() = 0;

  virtual void ChangePriorityInternal(RequestPriority priority) = 0;

  void LogConnectStart();
  void LogConnectCompletion(int net_error);

  // Alerts the delegate that the ConnectJob has timed out.
  void OnTimeout();

  // Invoked to notify subclasses that the has request timed out.
  virtual void OnTimedOutInternal();

  const base::TimeDelta timeout_duration_;
  RequestPriority priority_;
  const SocketTag socket_tag_;
  const CommonConnectJobParams* common_connect_job_params_;
  // Timer to abort jobs that take too long.
  base::OneShotTimer timer_;
  Delegate* delegate_;
  std::unique_ptr<StreamSocket> socket_;
  // Indicates if this is the topmost ConnectJob. The topmost ConnectJob logs an
  // extra begin and end event, to allow callers to log extra data before the
  // ConnectJob has started / after it has completed.
  const bool top_level_job_;
  NetLogWithSource net_log_;
  const NetLogEventType net_log_connect_event_type_;

  DISALLOW_COPY_AND_ASSIGN(ConnectJob);
};

}  // namespace net

#endif  // NET_SOCKET_CONNECT_JOB_H_
