// 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 "net/socket/transport_connect_job.h"

#include <algorithm>
#include <utility>

#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_util.h"
#include "base/trace_event/trace_event.h"
#include "base/values.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
#include "net/base/trace_constants.h"
#include "net/log/net_log.h"
#include "net/log/net_log_event_type.h"
#include "net/log/net_log_source_type.h"
#include "net/log/net_log_with_source.h"
#include "net/socket/client_socket_factory.h"
#include "net/socket/client_socket_handle.h"
#include "net/socket/socket_performance_watcher.h"
#include "net/socket/socket_performance_watcher_factory.h"
#include "net/socket/tcp_client_socket.h"
#include "net/socket/websocket_transport_connect_job.h"

namespace net {

namespace {

// Returns true iff all addresses in |list| are in the IPv6 family.
bool AddressListOnlyContainsIPv6(const AddressList& list) {
  DCHECK(!list.empty());
  for (auto iter = list.begin(); iter != list.end(); ++iter) {
    if (iter->GetFamily() != ADDRESS_FAMILY_IPV6)
      return false;
  }
  return true;
}

}  // namespace

TransportSocketParams::TransportSocketParams(
    const HostPortPair& host_port_pair,
    bool disable_resolver_cache,
    const OnHostResolutionCallback& host_resolution_callback)
    : destination_(host_port_pair),
      disable_resolver_cache_(disable_resolver_cache),
      host_resolution_callback_(host_resolution_callback) {}

TransportSocketParams::~TransportSocketParams() = default;

// TODO(eroman): The use of this constant needs to be re-evaluated. The time
// needed for TCPClientSocketXXX::Connect() can be arbitrarily long, since
// the address list may contain many alternatives, and most of those may
// timeout. Even worse, the per-connect timeout threshold varies greatly
// between systems (anywhere from 20 seconds to 190 seconds).
// See comment #12 at http://crbug.com/23364 for specifics.
const int TransportConnectJob::kTimeoutInSeconds = 240;  // 4 minutes.

// TODO(willchan): Base this off RTT instead of statically setting it. Note we
// choose a timeout that is different from the backup connect job timer so they
// don't synchronize.
const int TransportConnectJob::kIPv6FallbackTimerInMs = 300;

std::unique_ptr<ConnectJob> TransportConnectJob::CreateTransportConnectJob(
    scoped_refptr<TransportSocketParams> transport_client_params,
    RequestPriority priority,
    const CommonConnectJobParams& common_connect_job_params,
    ConnectJob::Delegate* delegate) {
  if (!common_connect_job_params.websocket_endpoint_lock_manager) {
    return std::make_unique<TransportConnectJob>(
        priority, common_connect_job_params, transport_client_params, delegate);
  }

  return std::make_unique<WebSocketTransportConnectJob>(
      priority, common_connect_job_params, transport_client_params, delegate);
}

TransportConnectJob::TransportConnectJob(
    RequestPriority priority,
    const CommonConnectJobParams& common_connect_job_params,
    const scoped_refptr<TransportSocketParams>& params,
    Delegate* delegate)
    : ConnectJob(
          priority,
          ConnectionTimeout(),
          common_connect_job_params,
          delegate,
          NetLogWithSource::Make(common_connect_job_params.net_log,
                                 NetLogSourceType::TRANSPORT_CONNECT_JOB)),
      params_(params),
      next_state_(STATE_NONE),
      resolve_result_(OK) {
  // This is only set for WebSockets.
  DCHECK(!common_connect_job_params.websocket_endpoint_lock_manager);
}

TransportConnectJob::~TransportConnectJob() {
  // We don't worry about cancelling the host resolution and TCP connect, since
  // ~HostResolver::Request and ~StreamSocket will take care of it.
}

LoadState TransportConnectJob::GetLoadState() const {
  switch (next_state_) {
    case STATE_RESOLVE_HOST:
    case STATE_RESOLVE_HOST_COMPLETE:
      return LOAD_STATE_RESOLVING_HOST;
    case STATE_TRANSPORT_CONNECT:
    case STATE_TRANSPORT_CONNECT_COMPLETE:
      return LOAD_STATE_CONNECTING;
    case STATE_NONE:
      return LOAD_STATE_IDLE;
  }
  NOTREACHED();
  return LOAD_STATE_IDLE;
}

bool TransportConnectJob::HasEstablishedConnection() const {
  // No need to ever return true, since NotifyComplete() is called as soon as a
  // connection is established.
  return false;
}

void TransportConnectJob::GetAdditionalErrorState(ClientSocketHandle* handle) {
  // If hostname resolution failed, record an empty endpoint and the result.
  // Also record any attempts made on either of the sockets.
  ConnectionAttempts attempts;
  if (resolve_result_ != OK) {
    DCHECK(!request_->GetAddressResults());
    attempts.push_back(ConnectionAttempt(IPEndPoint(), resolve_result_));
  }
  attempts.insert(attempts.begin(), connection_attempts_.begin(),
                  connection_attempts_.end());
  attempts.insert(attempts.begin(), fallback_connection_attempts_.begin(),
                  fallback_connection_attempts_.end());
  handle->set_connection_attempts(attempts);
}

// static
void TransportConnectJob::MakeAddressListStartWithIPv4(AddressList* list) {
  for (auto i = list->begin(); i != list->end(); ++i) {
    if (i->GetFamily() == ADDRESS_FAMILY_IPV4) {
      std::rotate(list->begin(), i, list->end());
      break;
    }
  }
}

// static
void TransportConnectJob::HistogramDuration(
    const LoadTimingInfo::ConnectTiming& connect_timing,
    RaceResult race_result) {
  DCHECK(!connect_timing.connect_start.is_null());
  DCHECK(!connect_timing.dns_start.is_null());
  base::TimeTicks now = base::TimeTicks::Now();
  base::TimeDelta total_duration = now - connect_timing.dns_start;
  UMA_HISTOGRAM_CUSTOM_TIMES("Net.DNS_Resolution_And_TCP_Connection_Latency2",
                             total_duration,
                             base::TimeDelta::FromMilliseconds(1),
                             base::TimeDelta::FromMinutes(10), 100);

  base::TimeDelta connect_duration = now - connect_timing.connect_start;
  UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency", connect_duration,
                             base::TimeDelta::FromMilliseconds(1),
                             base::TimeDelta::FromMinutes(10), 100);

  switch (race_result) {
    case RACE_IPV4_WINS:
      UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv4_Wins_Race",
                                 connect_duration,
                                 base::TimeDelta::FromMilliseconds(1),
                                 base::TimeDelta::FromMinutes(10), 100);
      break;

    case RACE_IPV4_SOLO:
      UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv4_No_Race",
                                 connect_duration,
                                 base::TimeDelta::FromMilliseconds(1),
                                 base::TimeDelta::FromMinutes(10), 100);
      break;

    case RACE_IPV6_WINS:
      UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv6_Raceable",
                                 connect_duration,
                                 base::TimeDelta::FromMilliseconds(1),
                                 base::TimeDelta::FromMinutes(10), 100);
      break;

    case RACE_IPV6_SOLO:
      UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv6_Solo",
                                 connect_duration,
                                 base::TimeDelta::FromMilliseconds(1),
                                 base::TimeDelta::FromMinutes(10), 100);
      break;

    default:
      NOTREACHED();
      break;
  }
}

// static
base::TimeDelta TransportConnectJob::ConnectionTimeout() {
  return base::TimeDelta::FromSeconds(TransportConnectJob::kTimeoutInSeconds);
}

void TransportConnectJob::OnIOComplete(int result) {
  result = DoLoop(result);
  if (result != ERR_IO_PENDING)
    NotifyDelegateOfCompletion(result);  // Deletes |this|
}

int TransportConnectJob::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_RESOLVE_HOST:
        DCHECK_EQ(OK, rv);
        rv = DoResolveHost();
        break;
      case STATE_RESOLVE_HOST_COMPLETE:
        rv = DoResolveHostComplete(rv);
        break;
      case STATE_TRANSPORT_CONNECT:
        DCHECK_EQ(OK, rv);
        rv = DoTransportConnect();
        break;
      case STATE_TRANSPORT_CONNECT_COMPLETE:
        rv = DoTransportConnectComplete(rv);
        break;
      default:
        NOTREACHED();
        rv = ERR_FAILED;
        break;
    }
  } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);

  return rv;
}

int TransportConnectJob::DoResolveHost() {
  next_state_ = STATE_RESOLVE_HOST_COMPLETE;
  connect_timing_.dns_start = base::TimeTicks::Now();

  HostResolver::ResolveHostParameters parameters;
  parameters.initial_priority = priority();
  parameters.cache_usage =
      params_->disable_resolver_cache()
          ? HostResolver::ResolveHostParameters::CacheUsage::DISALLOWED
          : HostResolver::ResolveHostParameters::CacheUsage::ALLOWED;
  request_ = host_resolver()->CreateRequest(params_->destination(), net_log(),
                                            parameters);

  return request_->Start(base::BindOnce(&TransportConnectJob::OnIOComplete,
                                        base::Unretained(this)));
}

int TransportConnectJob::DoResolveHostComplete(int result) {
  TRACE_EVENT0(NetTracingCategory(),
               "TransportConnectJob::DoResolveHostComplete");
  connect_timing_.dns_end = base::TimeTicks::Now();
  // Overwrite connection start time, since for connections that do not go
  // through proxies, |connect_start| should not include dns lookup time.
  connect_timing_.connect_start = connect_timing_.dns_end;
  resolve_result_ = result;

  if (result != OK)
    return result;
  DCHECK(request_->GetAddressResults());

  // Invoke callback, and abort if it fails.
  if (!params_->host_resolution_callback().is_null()) {
    result = params_->host_resolution_callback().Run(
        request_->GetAddressResults().value(), net_log());
    if (result != OK)
      return result;
  }

  next_state_ = STATE_TRANSPORT_CONNECT;
  return result;
}

int TransportConnectJob::DoTransportConnect() {
  next_state_ = STATE_TRANSPORT_CONNECT_COMPLETE;
  // Create a |SocketPerformanceWatcher|, and pass the ownership.
  std::unique_ptr<SocketPerformanceWatcher> socket_performance_watcher;
  if (socket_performance_watcher_factory()) {
    socket_performance_watcher =
        socket_performance_watcher_factory()->CreateSocketPerformanceWatcher(
            SocketPerformanceWatcherFactory::PROTOCOL_TCP,
            request_->GetAddressResults().value());
  }
  transport_socket_ = client_socket_factory()->CreateTransportClientSocket(
      request_->GetAddressResults().value(),
      std::move(socket_performance_watcher), net_log().net_log(),
      net_log().source());

  // If the list contains IPv6 and IPv4 addresses, and the first address
  // is IPv6, the IPv4 addresses will be tried as fallback addresses, per
  // "Happy Eyeballs" (RFC 6555).
  bool try_ipv6_connect_with_ipv4_fallback =
      request_->GetAddressResults().value().front().GetFamily() ==
          ADDRESS_FAMILY_IPV6 &&
      !AddressListOnlyContainsIPv6(request_->GetAddressResults().value());

  transport_socket_->ApplySocketTag(socket_tag());

  int rv = transport_socket_->Connect(base::BindOnce(
      &TransportConnectJob::OnIOComplete, base::Unretained(this)));
  if (rv == ERR_IO_PENDING && try_ipv6_connect_with_ipv4_fallback) {
    fallback_timer_.Start(
        FROM_HERE, base::TimeDelta::FromMilliseconds(kIPv6FallbackTimerInMs),
        this, &TransportConnectJob::DoIPv6FallbackTransportConnect);
  }
  return rv;
}

int TransportConnectJob::DoTransportConnectComplete(int result) {
  if (result == OK) {
    // Success will be returned via the main socket, so also include connection
    // attempts made on the fallback socket up to this point. (Unfortunately,
    // the only simple way to return information in the success case is through
    // the successfully-connected socket.)
    if (fallback_transport_socket_) {
      ConnectionAttempts fallback_attempts;
      fallback_transport_socket_->GetConnectionAttempts(&fallback_attempts);
      transport_socket_->AddConnectionAttempts(fallback_attempts);
    }

    bool is_ipv4 = request_->GetAddressResults().value().front().GetFamily() ==
                   ADDRESS_FAMILY_IPV4;
    RaceResult race_result = RACE_UNKNOWN;
    if (is_ipv4)
      race_result = RACE_IPV4_SOLO;
    else if (AddressListOnlyContainsIPv6(request_->GetAddressResults().value()))
      race_result = RACE_IPV6_SOLO;
    else
      race_result = RACE_IPV6_WINS;
    HistogramDuration(connect_timing_, race_result);

    SetSocket(std::move(transport_socket_));
  } else {
    // Failure will be returned via |GetAdditionalErrorState|, so save
    // connection attempts from both sockets for use there.
    CopyConnectionAttemptsFromSockets();

    transport_socket_.reset();
  }

  fallback_timer_.Stop();
  fallback_transport_socket_.reset();
  fallback_addresses_.reset();

  return result;
}

void TransportConnectJob::DoIPv6FallbackTransportConnect() {
  // The timer should only fire while we're waiting for the main connect to
  // succeed.
  if (next_state_ != STATE_TRANSPORT_CONNECT_COMPLETE) {
    NOTREACHED();
    return;
  }

  DCHECK(!fallback_transport_socket_.get());
  DCHECK(!fallback_addresses_.get());

  fallback_addresses_.reset(
      new AddressList(request_->GetAddressResults().value()));
  MakeAddressListStartWithIPv4(fallback_addresses_.get());

  // Create a |SocketPerformanceWatcher|, and pass the ownership.
  std::unique_ptr<SocketPerformanceWatcher> socket_performance_watcher;
  if (socket_performance_watcher_factory()) {
    socket_performance_watcher =
        socket_performance_watcher_factory()->CreateSocketPerformanceWatcher(
            SocketPerformanceWatcherFactory::PROTOCOL_TCP,
            *fallback_addresses_);
  }

  fallback_transport_socket_ =
      client_socket_factory()->CreateTransportClientSocket(
          *fallback_addresses_, std::move(socket_performance_watcher),
          net_log().net_log(), net_log().source());
  fallback_connect_start_time_ = base::TimeTicks::Now();
  int rv = fallback_transport_socket_->Connect(base::BindOnce(
      &TransportConnectJob::DoIPv6FallbackTransportConnectComplete,
      base::Unretained(this)));
  if (rv != ERR_IO_PENDING)
    DoIPv6FallbackTransportConnectComplete(rv);
}

void TransportConnectJob::DoIPv6FallbackTransportConnectComplete(int result) {
  // This should only happen when we're waiting for the main connect to succeed.
  if (next_state_ != STATE_TRANSPORT_CONNECT_COMPLETE) {
    NOTREACHED();
    return;
  }

  DCHECK_NE(ERR_IO_PENDING, result);
  DCHECK(fallback_transport_socket_.get());
  DCHECK(fallback_addresses_.get());

  if (result == OK) {
    DCHECK(!fallback_connect_start_time_.is_null());

    // Success will be returned via the fallback socket, so also include
    // connection attempts made on the main socket up to this point.
    // (Unfortunately, the only simple way to return information in the success
    // case is through the successfully-connected socket.)
    if (transport_socket_) {
      ConnectionAttempts attempts;
      transport_socket_->GetConnectionAttempts(&attempts);
      fallback_transport_socket_->AddConnectionAttempts(attempts);
    }

    connect_timing_.connect_start = fallback_connect_start_time_;
    HistogramDuration(connect_timing_, RACE_IPV4_WINS);
    SetSocket(std::move(fallback_transport_socket_));
    next_state_ = STATE_NONE;
  } else {
    // Failure will be returned via |GetAdditionalErrorState|, so save
    // connection attempts from both sockets for use there.
    CopyConnectionAttemptsFromSockets();

    fallback_transport_socket_.reset();
    fallback_addresses_.reset();
  }

  transport_socket_.reset();

  NotifyDelegateOfCompletion(result);  // Deletes |this|
}

int TransportConnectJob::ConnectInternal() {
  next_state_ = STATE_RESOLVE_HOST;
  return DoLoop(OK);
}

void TransportConnectJob::ChangePriorityInternal(RequestPriority priority) {
  if (next_state_ == STATE_RESOLVE_HOST_COMPLETE) {
    DCHECK(request_);
    // Change the request priority in the host resolver.
    request_->ChangeRequestPriority(priority);
  }
}

void TransportConnectJob::CopyConnectionAttemptsFromSockets() {
  if (transport_socket_)
    transport_socket_->GetConnectionAttempts(&connection_attempts_);
  if (fallback_transport_socket_) {
    fallback_transport_socket_->GetConnectionAttempts(
        &fallback_connection_attempts_);
  }
}

}  // namespace net
