// 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/optional.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/base/network_isolation_key.h"
#include "net/base/privacy_mode.h"
#include "net/http/http_auth_controller.h"
#include "net/http/http_network_session.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/socket_tag.h"
#include "net/traffic_annotation/network_traffic_annotation.h"

namespace network {

ProxyResolvingClientSocket::ProxyResolvingClientSocket(
    net::HttpNetworkSession* network_session,
    const net::CommonConnectJobParams* common_connect_job_params,
    const net::SSLConfig& ssl_config,
    const GURL& url,
    bool use_tls)
    : network_session_(network_session),
      common_connect_job_params_(common_connect_job_params),
      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) {
  // TODO(xunjieli): Handle invalid URLs more gracefully (at mojo API layer
  // or when the request is created).
  DCHECK(url_.is_valid());
}

ProxyResolvingClientSocket::~ProxyResolvingClientSocket() {}

int ProxyResolvingClientSocket::Read(net::IOBuffer* buf,
                                     int buf_len,
                                     net::CompletionOnceCallback callback) {
  if (socket_)
    return 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_)
    return socket_->ReadIfReady(buf, buf_len, std::move(callback));
  return net::ERR_SOCKET_NOT_CONNECTED;
}

int ProxyResolvingClientSocket::CancelReadIfReady() {
  if (socket_)
    return 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_) {
    return socket_->Write(buf, buf_len, std::move(callback),
                          traffic_annotation);
  }
  return net::ERR_SOCKET_NOT_CONNECTED;
}

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

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

int ProxyResolvingClientSocket::Connect(net::CompletionOnceCallback callback) {
  DCHECK(user_connect_callback_.is_null());
  DCHECK(!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() {
  connect_job_.reset();
  socket_.reset();
  if (proxy_resolve_request_)
    proxy_resolve_request_.reset();
  user_connect_callback_.Reset();
}

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

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

int ProxyResolvingClientSocket::GetPeerAddress(net::IPEndPoint* address) const {
  if (!socket_)
    return net::ERR_SOCKET_NOT_CONNECTED;

  if (proxy_info_.is_direct())
    return 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_)
    return socket_->GetLocalAddress(address);
  return net::ERR_SOCKET_NOT_CONNECTED;
}

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

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

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

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

bool ProxyResolvingClientSocket::GetSSLInfo(net::SSLInfo* ssl_info) {
  if (socket_)
    return 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;
      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_);
  // QUIC proxies are currently not supported.
  DCHECK(!proxy_info_.is_quic());

  next_state_ = STATE_INIT_CONNECTION_COMPLETE;

  base::Optional<net::NetworkTrafficAnnotationTag> proxy_annotation_tag =
      proxy_info_.is_direct()
          ? base::nullopt
          : base::Optional<net::NetworkTrafficAnnotationTag>(
                proxy_info_.traffic_annotation());

  // Now that the proxy is resolved, create and start a ConnectJob. Using an
  // empty NetworkIsolationKey means that tunnels over H2 or QUIC proxies will
  // be shared, which may result in privacy leaks, depending on the nature of
  // the consumer.
  //
  // TODO(mmenke): Investigate that.
  connect_job_ = net::ConnectJob::CreateConnectJob(
      use_tls_, net::HostPortPair::FromURL(url_), proxy_info_.proxy_server(),
      proxy_annotation_tag, &ssl_config_, &ssl_config_, true /* force_tunnel */,
      net::PRIVACY_MODE_DISABLED, net::OnHostResolutionCallback(),
      net::MAXIMUM_PRIORITY, net::SocketTag(), net::NetworkIsolationKey(),
      common_connect_job_params_, this);
  return connect_job_->Connect();
}

int ProxyResolvingClientSocket::DoInitConnectionComplete(int result) {
  if (result != net::OK) {
    connect_job_.reset();

    // 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);
  }

  socket_ = connect_job_->PassSocket();
  connect_job_.reset();

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

void ProxyResolvingClientSocket::OnConnectJobComplete(int result,
                                                      net::ConnectJob* job) {
  DCHECK_EQ(next_state_, STATE_INIT_CONNECTION_COMPLETE);
  DCHECK_EQ(connect_job_.get(), job);

  OnIOComplete(result);
}

void ProxyResolvingClientSocket::OnNeedsProxyAuth(
    const net::HttpResponseInfo& response,
    net::HttpAuthController* auth_controller,
    base::OnceClosure restart_with_auth_callback,
    net::ConnectJob* job) {
  DCHECK_EQ(next_state_, STATE_INIT_CONNECTION_COMPLETE);
  DCHECK_EQ(connect_job_.get(), job);

  // If there are credentials available to try and use, use them.
  if (auth_controller->HaveAuth()) {
    std::move(restart_with_auth_callback).Run();
    return;
  }

  // Otherwise, cancel the ConnectJob and continue.
  connect_job_.reset();

  OnIOComplete(net::ERR_PROXY_AUTH_REQUESTED);
}

int ProxyResolvingClientSocket::ReconsiderProxyAfterError(int error) {
  DCHECK(!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
