// 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),
      proxy_resolve_request_(nullptr),
      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::ERR_SOCKET_NOT_CONNECTED;
}

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_) {
    network_session_->proxy_resolution_service()->CancelRequest(
        proxy_resolve_request_);
    proxy_resolve_request_ = nullptr;
  }
  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;
  // TODO(xunjieli): Having a null ProxyDelegate is bad. Figure out how to
  // interact with the new interface for proxy delegate.
  // https://crbug.com/793071.
  // 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_, nullptr /*proxy_delegate*/, 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, which doesn't yet support tunneling.
    // TODO(xunjieli): Allow QUIC proxy once it supports tunneling.
    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_,
                                                              nullptr);
  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
