// 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_client_socket_pool.h"

#include <algorithm>

#include "base/compiler_specific.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.h"
#include "base/profiler/scoped_tracker.h"
#include "base/strings/string_util.h"
#include "base/synchronization/lock.h"
#include "base/time/time.h"
#include "base/values.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
#include "net/log/net_log.h"
#include "net/socket/client_socket_factory.h"
#include "net/socket/client_socket_handle.h"
#include "net/socket/client_socket_pool_base.h"
#include "net/socket/socket_net_log_params.h"
#include "net/socket/tcp_client_socket.h"

using base::TimeDelta;

namespace net {

// 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 TransportConnectJobHelper::kIPv6FallbackTimerInMs = 300;

namespace {

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

}  // namespace

// This lock protects |g_last_connect_time|.
static base::LazyInstance<base::Lock>::Leaky
    g_last_connect_time_lock = LAZY_INSTANCE_INITIALIZER;

// |g_last_connect_time| has the last time a connect() call is made.
static base::LazyInstance<base::TimeTicks>::Leaky
    g_last_connect_time = LAZY_INSTANCE_INITIALIZER;

TransportSocketParams::TransportSocketParams(
    const HostPortPair& host_port_pair,
    bool disable_resolver_cache,
    bool ignore_limits,
    const OnHostResolutionCallback& host_resolution_callback,
    CombineConnectAndWritePolicy combine_connect_and_write_if_supported)
    : destination_(host_port_pair),
      ignore_limits_(ignore_limits),
      host_resolution_callback_(host_resolution_callback),
      combine_connect_and_write_(combine_connect_and_write_if_supported) {
  if (disable_resolver_cache)
    destination_.set_allow_cached_response(false);
  // combine_connect_and_write currently translates to TCP FastOpen.
  // Enable TCP FastOpen if user wants it.
  if (combine_connect_and_write_ == COMBINE_CONNECT_AND_WRITE_DEFAULT) {
    IsTCPFastOpenUserEnabled() ? combine_connect_and_write_ =
        COMBINE_CONNECT_AND_WRITE_DESIRED :
        COMBINE_CONNECT_AND_WRITE_PROHIBITED;
  }
}

TransportSocketParams::~TransportSocketParams() {}

// TransportConnectJobs will time out after this many seconds.  Note this is
// the total time, including both host resolution and TCP connect() times.
//
// 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.
static const int kTransportConnectJobTimeoutInSeconds = 240;  // 4 minutes.

TransportConnectJobHelper::TransportConnectJobHelper(
    const scoped_refptr<TransportSocketParams>& params,
    ClientSocketFactory* client_socket_factory,
    HostResolver* host_resolver,
    LoadTimingInfo::ConnectTiming* connect_timing)
    : params_(params),
      client_socket_factory_(client_socket_factory),
      resolver_(host_resolver),
      next_state_(STATE_NONE),
      connect_timing_(connect_timing) {}

TransportConnectJobHelper::~TransportConnectJobHelper() {}

int TransportConnectJobHelper::DoResolveHost(RequestPriority priority,
                                             const BoundNetLog& net_log) {
  next_state_ = STATE_RESOLVE_HOST_COMPLETE;
  connect_timing_->dns_start = base::TimeTicks::Now();

  return resolver_.Resolve(
      params_->destination(), priority, &addresses_, on_io_complete_, net_log);
}

int TransportConnectJobHelper::DoResolveHostComplete(
    int result,
    const BoundNetLog& net_log) {
  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;

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

    if (result == OK)
      next_state_ = STATE_TRANSPORT_CONNECT;
  }
  return result;
}

base::TimeDelta TransportConnectJobHelper::HistogramDuration(
    ConnectionLatencyHistogram 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 CONNECTION_LATENCY_IPV4_WINS_RACE:
      UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv4_Wins_Race",
                                 connect_duration,
                                 base::TimeDelta::FromMilliseconds(1),
                                 base::TimeDelta::FromMinutes(10),
                                 100);
      break;

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

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

    case CONNECTION_LATENCY_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;
  }

  return connect_duration;
}

TransportConnectJob::TransportConnectJob(
    const std::string& group_name,
    RequestPriority priority,
    const scoped_refptr<TransportSocketParams>& params,
    base::TimeDelta timeout_duration,
    ClientSocketFactory* client_socket_factory,
    HostResolver* host_resolver,
    Delegate* delegate,
    NetLog* net_log)
    : ConnectJob(group_name,
                 timeout_duration,
                 priority,
                 delegate,
                 BoundNetLog::Make(net_log, NetLog::SOURCE_CONNECT_JOB)),
      helper_(params, client_socket_factory, host_resolver, &connect_timing_),
      interval_between_connects_(CONNECT_INTERVAL_GT_20MS),
      resolve_result_(OK) {
  helper_.SetOnIOComplete(this);
}

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

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

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_EQ(0u, helper_.addresses().size());
    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 (AddressList::iterator i = list->begin(); i != list->end(); ++i) {
    if (i->GetFamily() == ADDRESS_FAMILY_IPV4) {
      std::rotate(list->begin(), i, list->end());
      break;
    }
  }
}

int TransportConnectJob::DoResolveHost() {
  // TODO(ricea): Remove ScopedTracker below once crbug.com/436634 is fixed.
  tracked_objects::ScopedTracker tracking_profile(
      FROM_HERE_WITH_EXPLICIT_FUNCTION(
          "436634 TransportConnectJob::DoResolveHost"));

  return helper_.DoResolveHost(priority(), net_log());
}

int TransportConnectJob::DoResolveHostComplete(int result) {
  resolve_result_ = result;
  return helper_.DoResolveHostComplete(result, net_log());
}

int TransportConnectJob::DoTransportConnect() {
  base::TimeTicks now = base::TimeTicks::Now();
  base::TimeTicks last_connect_time;
  {
    base::AutoLock lock(g_last_connect_time_lock.Get());
    last_connect_time = g_last_connect_time.Get();
    *g_last_connect_time.Pointer() = now;
  }
  if (last_connect_time.is_null()) {
    interval_between_connects_ = CONNECT_INTERVAL_GT_20MS;
  } else {
    int64 interval = (now - last_connect_time).InMilliseconds();
    if (interval <= 10)
      interval_between_connects_ = CONNECT_INTERVAL_LE_10MS;
    else if (interval <= 20)
      interval_between_connects_ = CONNECT_INTERVAL_LE_20MS;
    else
      interval_between_connects_ = CONNECT_INTERVAL_GT_20MS;
  }

  helper_.set_next_state(
      TransportConnectJobHelper::STATE_TRANSPORT_CONNECT_COMPLETE);
  transport_socket_ =
      helper_.client_socket_factory()->CreateTransportClientSocket(
          helper_.addresses(), net_log().net_log(), net_log().source());

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

  // Enable TCP FastOpen if indicated by transport socket params.
  // Note: We currently do not turn on TCP FastOpen for destinations where
  // we try a TCP connect over IPv6 with fallback to IPv4.
  if (!try_ipv6_connect_with_ipv4_fallback &&
      helper_.params()->combine_connect_and_write() ==
          TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DESIRED) {
    transport_socket_->EnableTCPFastOpenIfSupported();
  }

  int rv = transport_socket_->Connect(helper_.on_io_complete());
  if (rv == ERR_IO_PENDING && try_ipv6_connect_with_ipv4_fallback) {
    fallback_timer_.Start(
        FROM_HERE,
        base::TimeDelta::FromMilliseconds(
            TransportConnectJobHelper::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 =
        helper_.addresses().front().GetFamily() == ADDRESS_FAMILY_IPV4;
    TransportConnectJobHelper::ConnectionLatencyHistogram race_result =
        TransportConnectJobHelper::CONNECTION_LATENCY_UNKNOWN;
    if (is_ipv4) {
      race_result = TransportConnectJobHelper::CONNECTION_LATENCY_IPV4_NO_RACE;
    } else {
      if (AddressListOnlyContainsIPv6(helper_.addresses())) {
        race_result = TransportConnectJobHelper::CONNECTION_LATENCY_IPV6_SOLO;
      } else {
        race_result =
            TransportConnectJobHelper::CONNECTION_LATENCY_IPV6_RACEABLE;
      }
    }
    base::TimeDelta connect_duration = helper_.HistogramDuration(race_result);
    switch (interval_between_connects_) {
      case CONNECT_INTERVAL_LE_10MS:
        UMA_HISTOGRAM_CUSTOM_TIMES(
            "Net.TCP_Connection_Latency_Interval_LessThanOrEqual_10ms",
            connect_duration,
            base::TimeDelta::FromMilliseconds(1),
            base::TimeDelta::FromMinutes(10),
            100);
        break;
      case CONNECT_INTERVAL_LE_20MS:
        UMA_HISTOGRAM_CUSTOM_TIMES(
            "Net.TCP_Connection_Latency_Interval_LessThanOrEqual_20ms",
            connect_duration,
            base::TimeDelta::FromMilliseconds(1),
            base::TimeDelta::FromMinutes(10),
            100);
        break;
      case CONNECT_INTERVAL_GT_20MS:
        UMA_HISTOGRAM_CUSTOM_TIMES(
            "Net.TCP_Connection_Latency_Interval_GreaterThan_20ms",
            connect_duration,
            base::TimeDelta::FromMilliseconds(1),
            base::TimeDelta::FromMinutes(10),
            100);
        break;
      default:
        NOTREACHED();
        break;
    }

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

    // Be a bit paranoid and kill off the fallback members to prevent reuse.
    fallback_transport_socket_.reset();
    fallback_addresses_.reset();
  }

  // N.B.: The owner of the ConnectJob will delete it after the callback is
  // called, so the fallback socket, if any, won't stick around for long.

  return result;
}

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

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

  fallback_addresses_.reset(new AddressList(helper_.addresses()));
  MakeAddressListStartWithIPv4(fallback_addresses_.get());
  fallback_transport_socket_ =
      helper_.client_socket_factory()->CreateTransportClientSocket(
          *fallback_addresses_, net_log().net_log(), net_log().source());
  fallback_connect_start_time_ = base::TimeTicks::Now();
  int rv = fallback_transport_socket_->Connect(
      base::Bind(
          &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 (helper_.next_state() !=
      TransportConnectJobHelper::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_;
    helper_.HistogramDuration(
        TransportConnectJobHelper::CONNECTION_LATENCY_IPV4_WINS_RACE);
    SetSocket(fallback_transport_socket_.Pass());
    helper_.set_next_state(TransportConnectJobHelper::STATE_NONE);
    transport_socket_.reset();
  } else {
    // Failure will be returned via |GetAdditionalErrorState|, so save
    // connection attempts from both sockets for use there.
    CopyConnectionAttemptsFromSockets();

    // Be a bit paranoid and kill off the fallback members to prevent reuse.
    fallback_transport_socket_.reset();
    fallback_addresses_.reset();
  }

  // N.B.: The owner of the ConnectJob will delete it after the callback is
  // called, so the main socket, if any, won't stick around for long.

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

int TransportConnectJob::ConnectInternal() {
  return helper_.DoConnectInternal(this);
}

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

scoped_ptr<ConnectJob>
TransportClientSocketPool::TransportConnectJobFactory::NewConnectJob(
    const std::string& group_name,
    const PoolBase::Request& request,
    ConnectJob::Delegate* delegate) const {
  return scoped_ptr<ConnectJob>(
      new TransportConnectJob(group_name,
                              request.priority(),
                              request.params(),
                              ConnectionTimeout(),
                              client_socket_factory_,
                              host_resolver_,
                              delegate,
                              net_log_));
}

base::TimeDelta
    TransportClientSocketPool::TransportConnectJobFactory::ConnectionTimeout()
    const {
  return base::TimeDelta::FromSeconds(kTransportConnectJobTimeoutInSeconds);
}

TransportClientSocketPool::TransportClientSocketPool(
    int max_sockets,
    int max_sockets_per_group,
    HostResolver* host_resolver,
    ClientSocketFactory* client_socket_factory,
    NetLog* net_log)
    : base_(NULL,
            max_sockets,
            max_sockets_per_group,
            ClientSocketPool::unused_idle_socket_timeout(),
            ClientSocketPool::used_idle_socket_timeout(),
            new TransportConnectJobFactory(client_socket_factory,
                                           host_resolver,
                                           net_log)) {
  base_.EnableConnectBackupJobs();
}

TransportClientSocketPool::~TransportClientSocketPool() {}

int TransportClientSocketPool::RequestSocket(
    const std::string& group_name,
    const void* params,
    RequestPriority priority,
    ClientSocketHandle* handle,
    const CompletionCallback& callback,
    const BoundNetLog& net_log) {
  const scoped_refptr<TransportSocketParams>* casted_params =
      static_cast<const scoped_refptr<TransportSocketParams>*>(params);

  NetLogTcpClientSocketPoolRequestedSocket(net_log, casted_params);

  return base_.RequestSocket(group_name, *casted_params, priority, handle,
                             callback, net_log);
}

void TransportClientSocketPool::NetLogTcpClientSocketPoolRequestedSocket(
    const BoundNetLog& net_log,
    const scoped_refptr<TransportSocketParams>* casted_params) {
  if (net_log.IsCapturing()) {
    // TODO(eroman): Split out the host and port parameters.
    net_log.AddEvent(
        NetLog::TYPE_TCP_CLIENT_SOCKET_POOL_REQUESTED_SOCKET,
        CreateNetLogHostPortPairCallback(
            &casted_params->get()->destination().host_port_pair()));
  }
}

void TransportClientSocketPool::RequestSockets(
    const std::string& group_name,
    const void* params,
    int num_sockets,
    const BoundNetLog& net_log) {
  const scoped_refptr<TransportSocketParams>* casted_params =
      static_cast<const scoped_refptr<TransportSocketParams>*>(params);

  if (net_log.IsCapturing()) {
    // TODO(eroman): Split out the host and port parameters.
    net_log.AddEvent(
        NetLog::TYPE_TCP_CLIENT_SOCKET_POOL_REQUESTED_SOCKETS,
        CreateNetLogHostPortPairCallback(
            &casted_params->get()->destination().host_port_pair()));
  }

  base_.RequestSockets(group_name, *casted_params, num_sockets, net_log);
}

void TransportClientSocketPool::CancelRequest(
    const std::string& group_name,
    ClientSocketHandle* handle) {
  base_.CancelRequest(group_name, handle);
}

void TransportClientSocketPool::ReleaseSocket(
    const std::string& group_name,
    scoped_ptr<StreamSocket> socket,
    int id) {
  base_.ReleaseSocket(group_name, socket.Pass(), id);
}

void TransportClientSocketPool::FlushWithError(int error) {
  base_.FlushWithError(error);
}

void TransportClientSocketPool::CloseIdleSockets() {
  base_.CloseIdleSockets();
}

int TransportClientSocketPool::IdleSocketCount() const {
  return base_.idle_socket_count();
}

int TransportClientSocketPool::IdleSocketCountInGroup(
    const std::string& group_name) const {
  return base_.IdleSocketCountInGroup(group_name);
}

LoadState TransportClientSocketPool::GetLoadState(
    const std::string& group_name, const ClientSocketHandle* handle) const {
  return base_.GetLoadState(group_name, handle);
}

base::DictionaryValue* TransportClientSocketPool::GetInfoAsValue(
    const std::string& name,
    const std::string& type,
    bool include_nested_pools) const {
  return base_.GetInfoAsValue(name, type);
}

base::TimeDelta TransportClientSocketPool::ConnectionTimeout() const {
  return base_.ConnectionTimeout();
}

bool TransportClientSocketPool::IsStalled() const {
  return base_.IsStalled();
}

void TransportClientSocketPool::AddHigherLayeredPool(
    HigherLayeredPool* higher_pool) {
  base_.AddHigherLayeredPool(higher_pool);
}

void TransportClientSocketPool::RemoveHigherLayeredPool(
    HigherLayeredPool* higher_pool) {
  base_.RemoveHigherLayeredPool(higher_pool);
}

}  // namespace net
