// 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.

#include "services/network/proxy_resolving_client_socket.h"

#include <stdint.h>
#include <string>
#include <utility>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/threading/thread_task_runner_handle.h"
#include "net/base/io_buffer.h"
#include "net/base/ip_address.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/http/http_auth_controller.h"
#include "net/http/http_network_session.h"
#include "net/http/http_transaction_factory.h"
#include "net/http/proxy_client_socket.h"
#include "net/http/proxy_fallback.h"
#include "net/log/net_log_source_type.h"
#include "net/socket/client_socket_handle.h"
#include "net/socket/client_socket_pool_manager.h"
#include "net/traffic_annotation/network_traffic_annotation.h"

namespace network {

ProxyResolvingClientSocket::ProxyResolvingClientSocket(
    net::HttpNetworkSession* network_session,
    const net::SSLConfig& ssl_config,
    const GURL& url,
    bool use_tls)
    : network_session_(network_session),
      socket_handle_(std::make_unique<net::ClientSocketHandle>()),
      ssl_config_(ssl_config),
      url_(url),
      use_tls_(use_tls),
      net_log_(net::NetLogWithSource::Make(network_session_->net_log(),
                                           net::NetLogSourceType::SOCKET)),
      next_state_(STATE_NONE),
      weak_factory_(this) {
  // TODO(xunjieli): Handle invalid URLs more gracefully (at mojo API layer
  // or when the request is created).
  DCHECK(url_.is_valid());
}

ProxyResolvingClientSocket::~ProxyResolvingClientSocket() {
  Disconnect();
}

int ProxyResolvingClientSocket::Read(net::IOBuffer* buf,
                                     int buf_len,
                                     net::CompletionOnceCallback callback) {
  if (socket_handle_->socket())
    return socket_handle_->socket()->Read(buf, buf_len, std::move(callback));
  return net::ERR_SOCKET_NOT_CONNECTED;
}

int ProxyResolvingClientSocket::ReadIfReady(
    net::IOBuffer* buf,
    int buf_len,
    net::CompletionOnceCallback callback) {
  if (socket_handle_->socket()) {
    return socket_handle_->socket()->ReadIfReady(buf, buf_len,
                                                 std::move(callback));
  }
  return net::ERR_SOCKET_NOT_CONNECTED;
}

int ProxyResolvingClientSocket::CancelReadIfReady() {
  if (socket_handle_->socket())
    return socket_handle_->socket()->CancelReadIfReady();
  // Return net::OK as ReadIfReady() is canceled when socket is disconnected.
  return net::OK;
}

int ProxyResolvingClientSocket::Write(
    net::IOBuffer* buf,
    int buf_len,
    net::CompletionOnceCallback callback,
    const net::NetworkTrafficAnnotationTag& traffic_annotation) {
  if (socket_handle_->socket()) {
    return socket_handle_->socket()->Write(buf, buf_len, std::move(callback),
                                           traffic_annotation);
  }
  return net::ERR_SOCKET_NOT_CONNECTED;
}

int ProxyResolvingClientSocket::SetReceiveBufferSize(int32_t size) {
  if (socket_handle_->socket())
    return socket_handle_->socket()->SetReceiveBufferSize(size);
  return net::ERR_SOCKET_NOT_CONNECTED;
}

int ProxyResolvingClientSocket::SetSendBufferSize(int32_t size) {
  if (socket_handle_->socket())
    return socket_handle_->socket()->SetSendBufferSize(size);
  return net::ERR_SOCKET_NOT_CONNECTED;
}

int ProxyResolvingClientSocket::Connect(net::CompletionOnceCallback callback) {
  DCHECK(user_connect_callback_.is_null());
  DCHECK(!socket_handle_->socket());

  next_state_ = STATE_PROXY_RESOLVE;
  int result = DoLoop(net::OK);
  if (result == net::ERR_IO_PENDING) {
    user_connect_callback_ = std::move(callback);
  }
  return result;
}

void ProxyResolvingClientSocket::Disconnect() {
  CloseSocket(true /*close_connection*/);
  if (proxy_resolve_request_) {
    proxy_resolve_request_.reset();
  }
  user_connect_callback_.Reset();
}

bool ProxyResolvingClientSocket::IsConnected() const {
  if (!socket_handle_->socket())
    return false;
  return socket_handle_->socket()->IsConnected();
}

bool ProxyResolvingClientSocket::IsConnectedAndIdle() const {
  if (!socket_handle_->socket())
    return false;
  return socket_handle_->socket()->IsConnectedAndIdle();
}

int ProxyResolvingClientSocket::GetPeerAddress(net::IPEndPoint* address) const {
  if (!socket_handle_->socket()) {
    return net::ERR_SOCKET_NOT_CONNECTED;
  }

  if (proxy_info_.is_direct())
    return socket_handle_->socket()->GetPeerAddress(address);

  net::IPAddress ip_address;
  if (!ip_address.AssignFromIPLiteral(url_.HostNoBrackets())) {
    // Do not expose the proxy IP address to the caller.
    return net::ERR_NAME_NOT_RESOLVED;
  }

  *address = net::IPEndPoint(ip_address, url_.EffectiveIntPort());
  return net::OK;
}

int ProxyResolvingClientSocket::GetLocalAddress(
    net::IPEndPoint* address) const {
  if (socket_handle_->socket())
    return socket_handle_->socket()->GetLocalAddress(address);
  return net::ERR_SOCKET_NOT_CONNECTED;
}

const net::NetLogWithSource& ProxyResolvingClientSocket::NetLog() const {
  if (socket_handle_->socket())
    return socket_handle_->socket()->NetLog();
  return net_log_;
}

bool ProxyResolvingClientSocket::WasEverUsed() const {
  if (socket_handle_->socket())
    return socket_handle_->socket()->WasEverUsed();
  return false;
}

bool ProxyResolvingClientSocket::WasAlpnNegotiated() const {
  if (socket_handle_->socket())
    return socket_handle_->socket()->WasAlpnNegotiated();
  return false;
}

net::NextProto ProxyResolvingClientSocket::GetNegotiatedProtocol() const {
  if (socket_handle_->socket())
    return socket_handle_->socket()->GetNegotiatedProtocol();
  return net::kProtoUnknown;
}

bool ProxyResolvingClientSocket::GetSSLInfo(net::SSLInfo* ssl_info) {
  if (socket_handle_->socket())
    return socket_handle_->socket()->GetSSLInfo(ssl_info);
  return false;
}

void ProxyResolvingClientSocket::GetConnectionAttempts(
    net::ConnectionAttempts* out) const {
  out->clear();
}

int64_t ProxyResolvingClientSocket::GetTotalReceivedBytes() const {
  NOTIMPLEMENTED();
  return 0;
}

void ProxyResolvingClientSocket::ApplySocketTag(const net::SocketTag& tag) {
  NOTIMPLEMENTED();
}

void ProxyResolvingClientSocket::OnIOComplete(int result) {
  DCHECK_NE(net::ERR_IO_PENDING, result);
  int net_error = DoLoop(result);
  if (net_error != net::ERR_IO_PENDING)
    std::move(user_connect_callback_).Run(net_error);
}

int ProxyResolvingClientSocket::DoLoop(int result) {
  DCHECK_NE(next_state_, STATE_NONE);
  int rv = result;
  do {
    State state = next_state_;
    next_state_ = STATE_NONE;
    switch (state) {
      case STATE_PROXY_RESOLVE:
        DCHECK_EQ(net::OK, rv);
        rv = DoProxyResolve();
        break;
      case STATE_PROXY_RESOLVE_COMPLETE:
        rv = DoProxyResolveComplete(rv);
        break;
      case STATE_INIT_CONNECTION:
        DCHECK_EQ(net::OK, rv);
        rv = DoInitConnection();
        break;
      case STATE_INIT_CONNECTION_COMPLETE:
        rv = DoInitConnectionComplete(rv);
        break;
      case STATE_RESTART_TUNNEL_AUTH:
        rv = DoRestartTunnelAuth(rv);
        break;
      case STATE_RESTART_TUNNEL_AUTH_COMPLETE:
        rv = DoRestartTunnelAuthComplete(rv);
        break;
      default:
        NOTREACHED() << "bad state";
        rv = net::ERR_FAILED;
        break;
    }
  } while (rv != net::ERR_IO_PENDING && next_state_ != STATE_NONE);
  return rv;
}

int ProxyResolvingClientSocket::DoProxyResolve() {
  next_state_ = STATE_PROXY_RESOLVE_COMPLETE;
  // base::Unretained(this) is safe because resolution request is canceled when
  // |proxy_resolve_request_| is destroyed.
  return network_session_->proxy_resolution_service()->ResolveProxy(
      url_, "POST", &proxy_info_,
      base::BindRepeating(&ProxyResolvingClientSocket::OnIOComplete,
                          base::Unretained(this)),
      &proxy_resolve_request_, net_log_);
}

int ProxyResolvingClientSocket::DoProxyResolveComplete(int result) {
  proxy_resolve_request_ = nullptr;
  if (result == net::OK) {
    // Removes unsupported proxies from the list. Currently, this removes
    // just the SCHEME_QUIC proxy.
    // TODO(crbug.com/876885): Allow QUIC proxy once net::QuicProxyClientSocket
    // supports ReadIfReady() and CancelReadIfReady().
    proxy_info_.RemoveProxiesWithoutScheme(
        net::ProxyServer::SCHEME_DIRECT | net::ProxyServer::SCHEME_HTTP |
        net::ProxyServer::SCHEME_HTTPS | net::ProxyServer::SCHEME_SOCKS4 |
        net::ProxyServer::SCHEME_SOCKS5);

    if (proxy_info_.is_empty()) {
      // No proxies/direct to choose from. This happens when we don't support
      // any of the proxies in the returned list.
      return net::ERR_NO_SUPPORTED_PROXIES;
    }
    next_state_ = STATE_INIT_CONNECTION;
    return net::OK;
  }
  return result;
}

int ProxyResolvingClientSocket::DoInitConnection() {
  DCHECK(!socket_handle_->socket());

  next_state_ = STATE_INIT_CONNECTION_COMPLETE;

  // Now that the proxy is resolved, issue a socket connect.
  net::HostPortPair host_port_pair = net::HostPortPair::FromURL(url_);
  // Ignore socket limit set by socket pool for this type of socket.
  int request_load_flags = net::LOAD_IGNORE_LIMITS;
  net::RequestPriority request_priority = net::MAXIMUM_PRIORITY;

  // base::Unretained(this) is safe because request is canceled when
  // |socket_handle_| is destroyed.
  if (use_tls_) {
    return net::InitSocketHandleForTlsConnect(
        host_port_pair, network_session_, request_load_flags, request_priority,
        proxy_info_, ssl_config_, ssl_config_, net::PRIVACY_MODE_DISABLED,
        net_log_, socket_handle_.get(),
        base::BindRepeating(&ProxyResolvingClientSocket::OnIOComplete,
                            base::Unretained(this)));
  }
  return net::InitSocketHandleForRawConnect(
      host_port_pair, network_session_, request_load_flags, request_priority,
      proxy_info_, ssl_config_, ssl_config_, net::PRIVACY_MODE_DISABLED,
      net_log_, socket_handle_.get(),
      base::BindRepeating(&ProxyResolvingClientSocket::OnIOComplete,
                          base::Unretained(this)));
}

int ProxyResolvingClientSocket::DoInitConnectionComplete(int result) {
  if (result == net::ERR_PROXY_AUTH_REQUESTED) {
    if (use_tls_) {
      // Put the in-progress HttpProxyClientSocket into |socket_handle_| to
      // do tunnel auth. After auth completes, it's important to reset
      // |socket_handle_|, so it doesn't have a HttpProxyClientSocket when the
      // code expects an SSLClientSocket. The tunnel restart code is careful to
      // put it back to the socket pool before returning control to the rest of
      // this class.
      socket_handle_ = socket_handle_->release_pending_http_proxy_connection();
    }
    next_state_ = STATE_RESTART_TUNNEL_AUTH;
    return result;
  }

  if (result != net::OK) {
    // ReconsiderProxyAfterError either returns an error (in which case it is
    // not reconsidering a proxy) or returns ERR_IO_PENDING if it is considering
    // another proxy.
    return ReconsiderProxyAfterError(result);
  }

  network_session_->proxy_resolution_service()->ReportSuccess(proxy_info_);
  return net::OK;
}

int ProxyResolvingClientSocket::DoRestartTunnelAuth(int result) {
  DCHECK_EQ(net::ERR_PROXY_AUTH_REQUESTED, result);

  net::ProxyClientSocket* proxy_socket =
      static_cast<net::ProxyClientSocket*>(socket_handle_->socket());

  if (proxy_socket->GetAuthController() &&
      proxy_socket->GetAuthController()->HaveAuth()) {
    next_state_ = STATE_RESTART_TUNNEL_AUTH_COMPLETE;
    // base::Unretained(this) is safe because |proxy_socket| is owned by this.
    return proxy_socket->RestartWithAuth(base::BindRepeating(
        &ProxyResolvingClientSocket::OnIOComplete, base::Unretained(this)));
  }
  // This socket is unusable if the underlying authentication handler doesn't
  // already have credentials.  It is possible to overcome this hurdle and
  // finish the handshake if this class exposes an interface for an embedder to
  // supply credentials.
  CloseSocket(true /*close_connection*/);
  return result;
}

int ProxyResolvingClientSocket::DoRestartTunnelAuthComplete(int result) {
  if (result == net::ERR_PROXY_AUTH_REQUESTED) {
    // Handle multi-round auth challenge.
    next_state_ = STATE_RESTART_TUNNEL_AUTH;
    return result;
  }
  if (result == net::OK) {
    CloseSocket(false /*close_connection*/);
    // Now that the HttpProxyClientSocket is connected, release it as an idle
    // socket into the pool and start the connection process from the beginning.
    next_state_ = STATE_INIT_CONNECTION;
    return net::OK;
  }
  CloseSocket(true /*close_connection*/);
  return ReconsiderProxyAfterError(result);
}

void ProxyResolvingClientSocket::CloseSocket(bool close_connection) {
  if (close_connection && socket_handle_->socket())
    socket_handle_->socket()->Disconnect();
  socket_handle_->Reset();
}

int ProxyResolvingClientSocket::ReconsiderProxyAfterError(int error) {
  DCHECK(!socket_handle_->socket());
  DCHECK(!proxy_resolve_request_);
  DCHECK_NE(error, net::OK);
  DCHECK_NE(error, net::ERR_IO_PENDING);

  // Check if the error was a proxy failure.
  if (!net::CanFalloverToNextProxy(proxy_info_.proxy_server(), error, &error))
    return error;

  if (proxy_info_.is_https() && ssl_config_.send_client_cert) {
    network_session_->ssl_client_auth_cache()->Remove(
        proxy_info_.proxy_server().host_port_pair());
  }

  // There was nothing left to fall-back to, so fail the transaction
  // with the last connection error we got.
  if (!proxy_info_.Fallback(error, net_log_))
    return error;

  next_state_ = STATE_INIT_CONNECTION;
  return net::OK;
}

}  // namespace network
