// 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_STREAM_SOCKET_STREAM_H_
#define NET_SOCKET_STREAM_SOCKET_STREAM_H_

#include <deque>
#include <map>
#include <string>

#include "base/memory/linked_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "net/base/address_list.h"
#include "net/base/completion_callback.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/base/net_export.h"
#include "net/base/net_log.h"
#include "net/base/privacy_mode.h"
#include "net/cookies/cookie_store.h"
#include "net/proxy/proxy_service.h"
#include "net/ssl/ssl_config_service.h"
#include "net/url_request/url_request.h"

namespace net {

class AuthChallengeInfo;
class CertVerifier;
class ChannelIDService;
class ClientSocketFactory;
class ClientSocketHandle;
class CookieOptions;
class HostResolver;
class HttpAuthController;
class SSLInfo;
class SingleRequestHostResolver;
class SocketStreamMetrics;
class TransportSecurityState;
class URLRequestContext;

// SocketStream is used to implement Web Sockets.
// It provides plain full-duplex stream with proxy and SSL support.
// For proxy authentication, only basic mechanisum is supported.  It will try
// authentication identity for proxy URL first.  If server requires proxy
// authentication, it will try authentication identity for realm that server
// requests.
class NET_EXPORT SocketStream
    : public base::RefCountedThreadSafe<SocketStream> {
 public:
  // Derive from this class and add your own data members to associate extra
  // information with a SocketStream.  Use GetUserData(key) and
  // SetUserData(key, data).
  class UserData {
   public:
    UserData() {}
    virtual ~UserData() {}
  };

  class NET_EXPORT Delegate {
   public:
    virtual int OnStartOpenConnection(SocketStream* socket,
                                      const CompletionCallback& callback);

    // Called when a socket stream has been connected.  The socket stream is
    // allowed to buffer pending send data at most |max_pending_send_allowed|
    // bytes.  A client of the socket stream should keep track of how much
    // pending send data it has and must not call SendData() if the pending
    // data goes over |max_pending_send_allowed| bytes.
    virtual void OnConnected(SocketStream* socket,
                             int max_pending_send_allowed) = 0;

    // Called when |amount_sent| bytes of data are sent.
    virtual void OnSentData(SocketStream* socket,
                            int amount_sent) = 0;

    // Called when |len| bytes of |data| are received.
    virtual void OnReceivedData(SocketStream* socket,
                                const char* data, int len) = 0;

    // Called when the socket stream has been closed.
    virtual void OnClose(SocketStream* socket) = 0;

    // Called when proxy authentication required.
    // The delegate should call RestartWithAuth() if credential for |auth_info|
    // is found in password database, or call Close() to close the connection.
    virtual void OnAuthRequired(SocketStream* socket,
                                AuthChallengeInfo* auth_info);

    // Called when using SSL and the server responds with a certificate with an
    // error. The delegate should call CancelBecauseOfCertError() or
    // ContinueDespiteCertError() to resume connection handling.
    virtual void OnSSLCertificateError(SocketStream* socket,
                                       const SSLInfo& ssl_info,
                                       bool fatal);

    // Called when an error occured.
    // This is only for error reporting to the delegate.
    // |error| is net::Error.
    virtual void OnError(const SocketStream* socket, int error) {}

    // Called when reading cookies to allow the delegate to block access to the
    // cookie.
    virtual bool CanGetCookies(SocketStream* socket, const GURL& url);

    // Called when a cookie is set to allow the delegate to block access to the
    // cookie.
    virtual bool CanSetCookie(SocketStream* request,
                              const GURL& url,
                              const std::string& cookie_line,
                              CookieOptions* options);

   protected:
    virtual ~Delegate() {}
  };

  SocketStream(const GURL& url, Delegate* delegate, URLRequestContext* context,
               CookieStore* cookie_store);

  // The user data allows the clients to associate data with this job.
  // Multiple user data values can be stored under different keys.
  // This job will TAKE OWNERSHIP of the given data pointer, and will
  // delete the object if it is changed or the job is destroyed.
  UserData* GetUserData(const void* key) const;
  void SetUserData(const void* key, UserData* data);

  const GURL& url() const { return url_; }
  bool is_secure() const;
  const AddressList& address_list() const { return addresses_; }
  Delegate* delegate() const { return delegate_; }
  int max_pending_send_allowed() const { return max_pending_send_allowed_; }

  URLRequestContext* context() { return context_; }

  const SSLConfig& server_ssl_config() const { return server_ssl_config_; }
  PrivacyMode privacy_mode() const { return privacy_mode_; }
  void CheckPrivacyMode();

  BoundNetLog* net_log() { return &net_log_; }

  // Opens the connection on the IO thread.
  // Once the connection is established, calls delegate's OnConnected.
  virtual void Connect();

  // Buffers |data| of |len| bytes for send and returns true if successful.
  // If size of buffered data exceeds |max_pending_send_allowed_|, sends no
  // data and returns false. |len| must be positive.
  virtual bool SendData(const char* data, int len);

  // Requests to close the connection.
  // Once the connection is closed, calls delegate's OnClose.
  virtual void Close();

  // Restarts with authentication info.
  // Should be used for response of OnAuthRequired.
  virtual void RestartWithAuth(const AuthCredentials& credentials);

  // Detach delegate.  Call before delegate is deleted.
  // Once delegate is detached, close the socket stream and never call delegate
  // back.
  virtual void DetachDelegate();

  // Detach the context.
  virtual void DetachContext();

  const ProxyServer& proxy_server() const;

  // Sets an alternative ClientSocketFactory.  Doesn't take ownership of
  // |factory|.  For testing purposes only.
  void SetClientSocketFactory(ClientSocketFactory* factory);

  // Cancels the connection because of an error.
  // |error| is net::Error which represents the error.
  void CancelWithError(int error);

  // Cancels the connection because of receiving a certificate with an error.
  void CancelWithSSLError(const SSLInfo& ssl_info);

  // Continues to establish the connection in spite of an error. Usually this
  // case happens because users allow certificate with an error by manual
  // actions on alert dialog or browser cached such kinds of user actions.
  void ContinueDespiteError();

  CookieStore* cookie_store() const;

 protected:
  friend class base::RefCountedThreadSafe<SocketStream>;
  virtual ~SocketStream();

  Delegate* delegate_;

 private:
  FRIEND_TEST_ALL_PREFIXES(SocketStreamTest, IOPending);
  FRIEND_TEST_ALL_PREFIXES(SocketStreamTest, SwitchAfterPending);
  FRIEND_TEST_ALL_PREFIXES(SocketStreamTest,
                           NullContextSocketStreamShouldNotCrash);

  friend class WebSocketThrottleTest;

  typedef std::map<const void*, linked_ptr<UserData> > UserDataMap;
  typedef std::deque< scoped_refptr<IOBufferWithSize> > PendingDataQueue;

  class RequestHeaders : public IOBuffer {
   public:
    RequestHeaders() : IOBuffer() {}

    void SetDataOffset(size_t offset) {
      data_ = const_cast<char*>(headers_.data()) + offset;
    }

    std::string headers_;

    private:
     ~RequestHeaders() override;
  };

  class ResponseHeaders : public IOBuffer {
   public:
    ResponseHeaders();

    void SetDataOffset(size_t offset) { data_ = headers_.get() + offset; }
    char* headers() const { return headers_.get(); }
    void Reset() { headers_.reset(); }
    void Realloc(size_t new_size);

   private:
    ~ResponseHeaders() override;

    scoped_ptr<char, base::FreeDeleter> headers_;
  };

  enum State {
    STATE_NONE,
    STATE_BEFORE_CONNECT,
    STATE_BEFORE_CONNECT_COMPLETE,
    STATE_RESOLVE_PROXY,
    STATE_RESOLVE_PROXY_COMPLETE,
    STATE_RESOLVE_HOST,
    STATE_RESOLVE_HOST_COMPLETE,
    STATE_RESOLVE_PROTOCOL,
    STATE_RESOLVE_PROTOCOL_COMPLETE,
    STATE_TCP_CONNECT,
    STATE_TCP_CONNECT_COMPLETE,
    STATE_GENERATE_PROXY_AUTH_TOKEN,
    STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE,
    STATE_WRITE_TUNNEL_HEADERS,
    STATE_WRITE_TUNNEL_HEADERS_COMPLETE,
    STATE_READ_TUNNEL_HEADERS,
    STATE_READ_TUNNEL_HEADERS_COMPLETE,
    STATE_SOCKS_CONNECT,
    STATE_SOCKS_CONNECT_COMPLETE,
    STATE_SECURE_PROXY_CONNECT,
    STATE_SECURE_PROXY_CONNECT_COMPLETE,
    STATE_SECURE_PROXY_HANDLE_CERT_ERROR,
    STATE_SECURE_PROXY_HANDLE_CERT_ERROR_COMPLETE,
    STATE_SSL_CONNECT,
    STATE_SSL_CONNECT_COMPLETE,
    STATE_SSL_HANDLE_CERT_ERROR,
    STATE_SSL_HANDLE_CERT_ERROR_COMPLETE,
    STATE_READ_WRITE,
    STATE_AUTH_REQUIRED,
    STATE_CLOSE,
  };

  enum ProxyMode {
    kDirectConnection,  // If using a direct connection
    kTunnelProxy,  // If using a tunnel (CONNECT method as HTTPS)
    kSOCKSProxy,  // If using a SOCKS proxy
  };

  // Use the same number as HttpNetworkTransaction::kMaxHeaderBufSize.
  enum { kMaxTunnelResponseHeadersSize = 32768 };  // 32 kilobytes.

  // Used for WebSocketThrottleTest.
  void set_addresses(const AddressList& addresses);

  void DoClose();

  // Finishes the job.
  // Calls OnError and OnClose of delegate, and no more
  // notifications will be sent to delegate.
  void Finish(int result);

  int DidEstablishConnection();
  int DidReceiveData(int result);
  // Given the number of bytes sent,
  // - notifies the |delegate_| and |metrics_| of this event.
  // - drains sent data from |current_write_buf_|.
  // - if |current_write_buf_| has been fully sent, sets NULL to
  //   |current_write_buf_| to get ready for next write.
  // and then, returns OK.
  void DidSendData(int result);

  void OnIOCompleted(int result);
  void OnReadCompleted(int result);
  void OnWriteCompleted(int result);

  void DoLoop(int result);

  int DoBeforeConnect();
  int DoBeforeConnectComplete(int result);
  int DoResolveProxy();
  int DoResolveProxyComplete(int result);
  int DoResolveHost();
  int DoResolveHostComplete(int result);
  int DoResolveProtocol(int result);
  int DoResolveProtocolComplete(int result);
  int DoTcpConnect(int result);
  int DoTcpConnectComplete(int result);
  int DoGenerateProxyAuthToken();
  int DoGenerateProxyAuthTokenComplete(int result);
  int DoWriteTunnelHeaders();
  int DoWriteTunnelHeadersComplete(int result);
  int DoReadTunnelHeaders();
  int DoReadTunnelHeadersComplete(int result);
  int DoSOCKSConnect();
  int DoSOCKSConnectComplete(int result);
  int DoSecureProxyConnect();
  int DoSecureProxyConnectComplete(int result);
  int DoSecureProxyHandleCertError(int result);
  int DoSecureProxyHandleCertErrorComplete(int result);
  int DoSSLConnect();
  int DoSSLConnectComplete(int result);
  int DoSSLHandleCertError(int result);
  int DoSSLHandleCertErrorComplete(int result);
  int DoReadWrite(int result);

  GURL ProxyAuthOrigin() const;
  int HandleAuthChallenge(const HttpResponseHeaders* headers);
  int HandleCertificateRequest(int result, SSLConfig* ssl_config);
  void DoAuthRequired();
  void DoRestartWithAuth();

  int HandleCertificateError(int result);
  int AllowCertErrorForReconnection(SSLConfig* ssl_config);

  // Returns the sum of the size of buffers in |pending_write_bufs_|.
  size_t GetTotalSizeOfPendingWriteBufs() const;

  BoundNetLog net_log_;

  GURL url_;
  // The number of bytes allowed to be buffered in this object. If the size of
  // buffered data which is
  //   current_write_buf_.BytesRemaining() +
  //   sum of the size of buffers in |pending_write_bufs_|
  // exceeds this limit, SendData() fails.
  int max_pending_send_allowed_;
  URLRequestContext* context_;

  UserDataMap user_data_;

  State next_state_;
  ClientSocketFactory* factory_;

  ProxyMode proxy_mode_;

  GURL proxy_url_;
  ProxyService::PacRequest* pac_request_;
  ProxyInfo proxy_info_;

  scoped_refptr<HttpAuthController> proxy_auth_controller_;

  scoped_refptr<RequestHeaders> tunnel_request_headers_;
  size_t tunnel_request_headers_bytes_sent_;
  scoped_refptr<ResponseHeaders> tunnel_response_headers_;
  int tunnel_response_headers_capacity_;
  int tunnel_response_headers_len_;

  scoped_ptr<SingleRequestHostResolver> resolver_;
  AddressList addresses_;
  scoped_ptr<ClientSocketHandle> connection_;

  SSLConfig server_ssl_config_;
  SSLConfig proxy_ssl_config_;
  PrivacyMode privacy_mode_;

  CompletionCallback io_callback_;

  scoped_refptr<IOBuffer> read_buf_;
  int read_buf_size_;

  // Buffer to hold data to pass to socket_.
  scoped_refptr<DrainableIOBuffer> current_write_buf_;
  // True iff there's no error and this instance is waiting for completion of
  // Write operation by socket_.
  bool waiting_for_write_completion_;
  PendingDataQueue pending_write_bufs_;

  bool closing_;
  bool server_closed_;

  scoped_ptr<SocketStreamMetrics> metrics_;

  // Cookie store to use for this socket stream.
  scoped_refptr<CookieStore> cookie_store_;

  DISALLOW_COPY_AND_ASSIGN(SocketStream);
};

}  // namespace net

#endif  // NET_SOCKET_STREAM_SOCKET_STREAM_H_
