// Copyright 2014 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/websocket_transport_client_socket_pool.h"

#include <algorithm>

#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/string_util.h"
#include "base/time/time.h"
#include "base/values.h"
#include "net/base/net_errors.h"
#include "net/base/net_log.h"
#include "net/socket/client_socket_handle.h"
#include "net/socket/client_socket_pool_base.h"
#include "net/socket/websocket_endpoint_lock_manager.h"
#include "net/socket/websocket_transport_connect_sub_job.h"

namespace net {

namespace {

using base::TimeDelta;

// TODO(ricea): For now, we implement a global timeout for compatability with
// TransportConnectJob. Since WebSocketTransportConnectJob controls the address
// selection process more tightly, it could do something smarter here.
const int kTransportConnectJobTimeoutInSeconds = 240;  // 4 minutes.

}  // namespace

WebSocketTransportConnectJob::WebSocketTransportConnectJob(
    const std::string& group_name,
    RequestPriority priority,
    const scoped_refptr<TransportSocketParams>& params,
    TimeDelta timeout_duration,
    const CompletionCallback& callback,
    ClientSocketFactory* client_socket_factory,
    HostResolver* host_resolver,
    ClientSocketHandle* handle,
    Delegate* delegate,
    NetLog* pool_net_log,
    const BoundNetLog& request_net_log)
    : ConnectJob(group_name,
                 timeout_duration,
                 priority,
                 delegate,
                 BoundNetLog::Make(pool_net_log, NetLog::SOURCE_CONNECT_JOB)),
      helper_(params, client_socket_factory, host_resolver, &connect_timing_),
      race_result_(TransportConnectJobHelper::CONNECTION_LATENCY_UNKNOWN),
      handle_(handle),
      callback_(callback),
      request_net_log_(request_net_log),
      had_ipv4_(false),
      had_ipv6_(false) {
  helper_.SetOnIOComplete(this);
}

WebSocketTransportConnectJob::~WebSocketTransportConnectJob() {}

LoadState WebSocketTransportConnectJob::GetLoadState() const {
  LoadState load_state = LOAD_STATE_RESOLVING_HOST;
  if (ipv6_job_)
    load_state = ipv6_job_->GetLoadState();
  // This method should return LOAD_STATE_CONNECTING in preference to
  // LOAD_STATE_WAITING_FOR_AVAILABLE_SOCKET when possible because "waiting for
  // available socket" implies that nothing is happening.
  if (ipv4_job_ && load_state != LOAD_STATE_CONNECTING)
    load_state = ipv4_job_->GetLoadState();
  return load_state;
}

int WebSocketTransportConnectJob::DoResolveHost() {
  return helper_.DoResolveHost(priority(), net_log());
}

int WebSocketTransportConnectJob::DoResolveHostComplete(int result) {
  return helper_.DoResolveHostComplete(result, net_log());
}

int WebSocketTransportConnectJob::DoTransportConnect() {
  AddressList ipv4_addresses;
  AddressList ipv6_addresses;
  int result = ERR_UNEXPECTED;
  helper_.set_next_state(
      TransportConnectJobHelper::STATE_TRANSPORT_CONNECT_COMPLETE);

  for (AddressList::const_iterator it = helper_.addresses().begin();
       it != helper_.addresses().end();
       ++it) {
    switch (it->GetFamily()) {
      case ADDRESS_FAMILY_IPV4:
        ipv4_addresses.push_back(*it);
        break;

      case ADDRESS_FAMILY_IPV6:
        ipv6_addresses.push_back(*it);
        break;

      default:
        DVLOG(1) << "Unexpected ADDRESS_FAMILY: " << it->GetFamily();
        break;
    }
  }

  if (!ipv4_addresses.empty()) {
    had_ipv4_ = true;
    ipv4_job_.reset(new WebSocketTransportConnectSubJob(
        ipv4_addresses, this, SUB_JOB_IPV4));
  }

  if (!ipv6_addresses.empty()) {
    had_ipv6_ = true;
    ipv6_job_.reset(new WebSocketTransportConnectSubJob(
        ipv6_addresses, this, SUB_JOB_IPV6));
    result = ipv6_job_->Start();
    switch (result) {
      case OK:
        SetSocket(ipv6_job_->PassSocket());
        race_result_ =
            had_ipv4_
                ? TransportConnectJobHelper::CONNECTION_LATENCY_IPV6_RACEABLE
                : TransportConnectJobHelper::CONNECTION_LATENCY_IPV6_SOLO;
        return result;

      case ERR_IO_PENDING:
        if (ipv4_job_) {
          // This use of base::Unretained is safe because |fallback_timer_| is
          // owned by this object.
          fallback_timer_.Start(
              FROM_HERE,
              TimeDelta::FromMilliseconds(
                  TransportConnectJobHelper::kIPv6FallbackTimerInMs),
              base::Bind(&WebSocketTransportConnectJob::StartIPv4JobAsync,
                         base::Unretained(this)));
        }
        return result;

      default:
        ipv6_job_.reset();
    }
  }

  DCHECK(!ipv6_job_);
  if (ipv4_job_) {
    result = ipv4_job_->Start();
    if (result == OK) {
      SetSocket(ipv4_job_->PassSocket());
      race_result_ =
          had_ipv6_
              ? TransportConnectJobHelper::CONNECTION_LATENCY_IPV4_WINS_RACE
              : TransportConnectJobHelper::CONNECTION_LATENCY_IPV4_NO_RACE;
    }
  }

  return result;
}

int WebSocketTransportConnectJob::DoTransportConnectComplete(int result) {
  if (result == OK)
    helper_.HistogramDuration(race_result_);
  return result;
}

void WebSocketTransportConnectJob::OnSubJobComplete(
    int result,
    WebSocketTransportConnectSubJob* job) {
  if (result == OK) {
    switch (job->type()) {
      case SUB_JOB_IPV4:
        race_result_ =
            had_ipv6_
                ? TransportConnectJobHelper::CONNECTION_LATENCY_IPV4_WINS_RACE
                : TransportConnectJobHelper::CONNECTION_LATENCY_IPV4_NO_RACE;
        break;

      case SUB_JOB_IPV6:
        race_result_ =
            had_ipv4_
                ? TransportConnectJobHelper::CONNECTION_LATENCY_IPV6_RACEABLE
                : TransportConnectJobHelper::CONNECTION_LATENCY_IPV6_SOLO;
        break;
    }
    SetSocket(job->PassSocket());

    // Make sure all connections are cancelled even if this object fails to be
    // deleted.
    ipv4_job_.reset();
    ipv6_job_.reset();
  } else {
    switch (job->type()) {
      case SUB_JOB_IPV4:
        ipv4_job_.reset();
        break;

      case SUB_JOB_IPV6:
        ipv6_job_.reset();
        if (ipv4_job_ && !ipv4_job_->started()) {
          fallback_timer_.Stop();
          result = ipv4_job_->Start();
          if (result != ERR_IO_PENDING) {
            OnSubJobComplete(result, ipv4_job_.get());
            return;
          }
        }
        break;
    }
    if (ipv4_job_ || ipv6_job_)
      return;
  }
  helper_.OnIOComplete(this, result);
}

void WebSocketTransportConnectJob::StartIPv4JobAsync() {
  DCHECK(ipv4_job_);
  int result = ipv4_job_->Start();
  if (result != ERR_IO_PENDING)
    OnSubJobComplete(result, ipv4_job_.get());
}

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

WebSocketTransportClientSocketPool::WebSocketTransportClientSocketPool(
    int max_sockets,
    int max_sockets_per_group,
    ClientSocketPoolHistograms* histograms,
    HostResolver* host_resolver,
    ClientSocketFactory* client_socket_factory,
    NetLog* net_log)
    : TransportClientSocketPool(max_sockets,
                                max_sockets_per_group,
                                histograms,
                                host_resolver,
                                client_socket_factory,
                                net_log),
      connect_job_delegate_(this),
      histograms_(histograms),
      pool_net_log_(net_log),
      client_socket_factory_(client_socket_factory),
      host_resolver_(host_resolver),
      max_sockets_(max_sockets),
      handed_out_socket_count_(0),
      flushing_(false),
      weak_factory_(this) {}

WebSocketTransportClientSocketPool::~WebSocketTransportClientSocketPool() {
  // Clean up any pending connect jobs.
  FlushWithError(ERR_ABORTED);
  DCHECK(pending_connects_.empty());
  DCHECK_EQ(0, handed_out_socket_count_);
  DCHECK(stalled_request_queue_.empty());
  DCHECK(stalled_request_map_.empty());
}

// static
void WebSocketTransportClientSocketPool::UnlockEndpoint(
    ClientSocketHandle* handle) {
  DCHECK(handle->is_initialized());
  DCHECK(handle->socket());
  IPEndPoint address;
  if (handle->socket()->GetPeerAddress(&address) == OK)
    WebSocketEndpointLockManager::GetInstance()->UnlockEndpoint(address);
}

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

  NetLogTcpClientSocketPoolRequestedSocket(request_net_log, &casted_params);

  CHECK(!callback.is_null());
  CHECK(handle);

  request_net_log.BeginEvent(NetLog::TYPE_SOCKET_POOL);

  if (ReachedMaxSocketsLimit() && !casted_params->ignore_limits()) {
    request_net_log.AddEvent(NetLog::TYPE_SOCKET_POOL_STALLED_MAX_SOCKETS);
    // TODO(ricea): Use emplace_back when C++11 becomes allowed.
    StalledRequest request(
        casted_params, priority, handle, callback, request_net_log);
    stalled_request_queue_.push_back(request);
    StalledRequestQueue::iterator iterator = stalled_request_queue_.end();
    --iterator;
    DCHECK_EQ(handle, iterator->handle);
    // Because StalledRequestQueue is a std::list, its iterators are guaranteed
    // to remain valid as long as the elements are not removed. As long as
    // stalled_request_queue_ and stalled_request_map_ are updated in sync, it
    // is safe to dereference an iterator in stalled_request_map_ to find the
    // corresponding list element.
    stalled_request_map_.insert(
        StalledRequestMap::value_type(handle, iterator));
    return ERR_IO_PENDING;
  }

  scoped_ptr<WebSocketTransportConnectJob> connect_job(
      new WebSocketTransportConnectJob(group_name,
                                       priority,
                                       casted_params,
                                       ConnectionTimeout(),
                                       callback,
                                       client_socket_factory_,
                                       host_resolver_,
                                       handle,
                                       &connect_job_delegate_,
                                       pool_net_log_,
                                       request_net_log));

  int rv = connect_job->Connect();
  // Regardless of the outcome of |connect_job|, it will always be bound to
  // |handle|, since this pool uses early-binding. So the binding is logged
  // here, without waiting for the result.
  request_net_log.AddEvent(
      NetLog::TYPE_SOCKET_POOL_BOUND_TO_CONNECT_JOB,
      connect_job->net_log().source().ToEventParametersCallback());
  if (rv == OK) {
    HandOutSocket(connect_job->PassSocket(),
                  connect_job->connect_timing(),
                  handle,
                  request_net_log);
    request_net_log.EndEvent(NetLog::TYPE_SOCKET_POOL);
  } else if (rv == ERR_IO_PENDING) {
    // TODO(ricea): Implement backup job timer?
    AddJob(handle, connect_job.Pass());
  } else {
    scoped_ptr<StreamSocket> error_socket;
    connect_job->GetAdditionalErrorState(handle);
    error_socket = connect_job->PassSocket();
    if (error_socket) {
      HandOutSocket(error_socket.Pass(),
                    connect_job->connect_timing(),
                    handle,
                    request_net_log);
    }
  }

  if (rv != ERR_IO_PENDING) {
    request_net_log.EndEventWithNetErrorCode(NetLog::TYPE_SOCKET_POOL, rv);
  }

  return rv;
}

void WebSocketTransportClientSocketPool::RequestSockets(
    const std::string& group_name,
    const void* params,
    int num_sockets,
    const BoundNetLog& net_log) {
  NOTIMPLEMENTED();
}

void WebSocketTransportClientSocketPool::CancelRequest(
    const std::string& group_name,
    ClientSocketHandle* handle) {
  DCHECK(!handle->is_initialized());
  if (DeleteStalledRequest(handle))
    return;
  scoped_ptr<StreamSocket> socket = handle->PassSocket();
  if (socket)
    ReleaseSocket(handle->group_name(), socket.Pass(), handle->id());
  if (!DeleteJob(handle))
    pending_callbacks_.erase(handle);
  if (!ReachedMaxSocketsLimit() && !stalled_request_queue_.empty())
    ActivateStalledRequest();
}

void WebSocketTransportClientSocketPool::ReleaseSocket(
    const std::string& group_name,
    scoped_ptr<StreamSocket> socket,
    int id) {
  WebSocketEndpointLockManager::GetInstance()->UnlockSocket(socket.get());
  CHECK_GT(handed_out_socket_count_, 0);
  --handed_out_socket_count_;
  if (!ReachedMaxSocketsLimit() && !stalled_request_queue_.empty())
    ActivateStalledRequest();
}

void WebSocketTransportClientSocketPool::FlushWithError(int error) {
  // Sockets which are in LOAD_STATE_CONNECTING are in danger of unlocking
  // sockets waiting for the endpoint lock. If they connected synchronously,
  // then OnConnectJobComplete(). The |flushing_| flag tells this object to
  // ignore spurious calls to OnConnectJobComplete(). It is safe to ignore those
  // calls because this method will delete the jobs and call their callbacks
  // anyway.
  flushing_ = true;
  for (PendingConnectsMap::iterator it = pending_connects_.begin();
       it != pending_connects_.end();
       ++it) {
    InvokeUserCallbackLater(
        it->second->handle(), it->second->callback(), error);
    delete it->second, it->second = NULL;
  }
  pending_connects_.clear();
  for (StalledRequestQueue::iterator it = stalled_request_queue_.begin();
       it != stalled_request_queue_.end();
       ++it) {
    InvokeUserCallbackLater(it->handle, it->callback, error);
  }
  stalled_request_map_.clear();
  stalled_request_queue_.clear();
  flushing_ = false;
}

void WebSocketTransportClientSocketPool::CloseIdleSockets() {
  // We have no idle sockets.
}

int WebSocketTransportClientSocketPool::IdleSocketCount() const {
  return 0;
}

int WebSocketTransportClientSocketPool::IdleSocketCountInGroup(
    const std::string& group_name) const {
  return 0;
}

LoadState WebSocketTransportClientSocketPool::GetLoadState(
    const std::string& group_name,
    const ClientSocketHandle* handle) const {
  if (stalled_request_map_.find(handle) != stalled_request_map_.end())
    return LOAD_STATE_WAITING_FOR_AVAILABLE_SOCKET;
  if (pending_callbacks_.count(handle))
    return LOAD_STATE_CONNECTING;
  return LookupConnectJob(handle)->GetLoadState();
}

base::DictionaryValue* WebSocketTransportClientSocketPool::GetInfoAsValue(
    const std::string& name,
    const std::string& type,
    bool include_nested_pools) const {
  base::DictionaryValue* dict = new base::DictionaryValue();
  dict->SetString("name", name);
  dict->SetString("type", type);
  dict->SetInteger("handed_out_socket_count", handed_out_socket_count_);
  dict->SetInteger("connecting_socket_count", pending_connects_.size());
  dict->SetInteger("idle_socket_count", 0);
  dict->SetInteger("max_socket_count", max_sockets_);
  dict->SetInteger("max_sockets_per_group", max_sockets_);
  dict->SetInteger("pool_generation_number", 0);
  return dict;
}

TimeDelta WebSocketTransportClientSocketPool::ConnectionTimeout() const {
  return TimeDelta::FromSeconds(kTransportConnectJobTimeoutInSeconds);
}

ClientSocketPoolHistograms* WebSocketTransportClientSocketPool::histograms()
    const {
  return histograms_;
}

bool WebSocketTransportClientSocketPool::IsStalled() const {
  return !stalled_request_queue_.empty();
}

void WebSocketTransportClientSocketPool::OnConnectJobComplete(
    int result,
    WebSocketTransportConnectJob* job) {
  DCHECK_NE(ERR_IO_PENDING, result);

  scoped_ptr<StreamSocket> socket = job->PassSocket();

  // See comment in FlushWithError.
  if (flushing_) {
    WebSocketEndpointLockManager::GetInstance()->UnlockSocket(socket.get());
    return;
  }

  BoundNetLog request_net_log = job->request_net_log();
  CompletionCallback callback = job->callback();
  LoadTimingInfo::ConnectTiming connect_timing = job->connect_timing();

  ClientSocketHandle* const handle = job->handle();
  bool handed_out_socket = false;

  if (result == OK) {
    DCHECK(socket.get());
    handed_out_socket = true;
    HandOutSocket(socket.Pass(), connect_timing, handle, request_net_log);
    request_net_log.EndEvent(NetLog::TYPE_SOCKET_POOL);
  } else {
    // If we got a socket, it must contain error information so pass that
    // up so that the caller can retrieve it.
    job->GetAdditionalErrorState(handle);
    if (socket.get()) {
      handed_out_socket = true;
      HandOutSocket(socket.Pass(), connect_timing, handle, request_net_log);
    }
    request_net_log.EndEventWithNetErrorCode(NetLog::TYPE_SOCKET_POOL, result);
  }
  bool delete_succeeded = DeleteJob(handle);
  DCHECK(delete_succeeded);
  if (!handed_out_socket && !stalled_request_queue_.empty() &&
      !ReachedMaxSocketsLimit())
    ActivateStalledRequest();
  InvokeUserCallbackLater(handle, callback, result);
}

void WebSocketTransportClientSocketPool::InvokeUserCallbackLater(
    ClientSocketHandle* handle,
    const CompletionCallback& callback,
    int rv) {
  DCHECK(!pending_callbacks_.count(handle));
  pending_callbacks_.insert(handle);
  base::MessageLoop::current()->PostTask(
      FROM_HERE,
      base::Bind(&WebSocketTransportClientSocketPool::InvokeUserCallback,
                 weak_factory_.GetWeakPtr(),
                 handle,
                 callback,
                 rv));
}

void WebSocketTransportClientSocketPool::InvokeUserCallback(
    ClientSocketHandle* handle,
    const CompletionCallback& callback,
    int rv) {
  if (pending_callbacks_.erase(handle))
    callback.Run(rv);
}

bool WebSocketTransportClientSocketPool::ReachedMaxSocketsLimit() const {
  return handed_out_socket_count_ >= max_sockets_ ||
         base::checked_cast<int>(pending_connects_.size()) >=
             max_sockets_ - handed_out_socket_count_;
}

void WebSocketTransportClientSocketPool::HandOutSocket(
    scoped_ptr<StreamSocket> socket,
    const LoadTimingInfo::ConnectTiming& connect_timing,
    ClientSocketHandle* handle,
    const BoundNetLog& net_log) {
  DCHECK(socket);
  handle->SetSocket(socket.Pass());
  DCHECK_EQ(ClientSocketHandle::UNUSED, handle->reuse_type());
  DCHECK_EQ(0, handle->idle_time().InMicroseconds());
  handle->set_pool_id(0);
  handle->set_connect_timing(connect_timing);

  net_log.AddEvent(
      NetLog::TYPE_SOCKET_POOL_BOUND_TO_SOCKET,
      handle->socket()->NetLog().source().ToEventParametersCallback());

  ++handed_out_socket_count_;
}

void WebSocketTransportClientSocketPool::AddJob(
    ClientSocketHandle* handle,
    scoped_ptr<WebSocketTransportConnectJob> connect_job) {
  bool inserted =
      pending_connects_.insert(PendingConnectsMap::value_type(
                                   handle, connect_job.release())).second;
  DCHECK(inserted);
}

bool WebSocketTransportClientSocketPool::DeleteJob(ClientSocketHandle* handle) {
  PendingConnectsMap::iterator it = pending_connects_.find(handle);
  if (it == pending_connects_.end())
    return false;
  // Deleting a ConnectJob which holds an endpoint lock can lead to a different
  // ConnectJob proceeding to connect. If the connect proceeds synchronously
  // (usually because of a failure) then it can trigger that job to be
  // deleted. |it| remains valid because std::map guarantees that erase() does
  // not invalid iterators to other entries.
  delete it->second, it->second = NULL;
  DCHECK(pending_connects_.find(handle) == it);
  pending_connects_.erase(it);
  return true;
}

const WebSocketTransportConnectJob*
WebSocketTransportClientSocketPool::LookupConnectJob(
    const ClientSocketHandle* handle) const {
  PendingConnectsMap::const_iterator it = pending_connects_.find(handle);
  CHECK(it != pending_connects_.end());
  return it->second;
}

void WebSocketTransportClientSocketPool::ActivateStalledRequest() {
  DCHECK(!stalled_request_queue_.empty());
  DCHECK(!ReachedMaxSocketsLimit());
  // Usually we will only be able to activate one stalled request at a time,
  // however if all the connects fail synchronously for some reason, we may be
  // able to clear the whole queue at once.
  while (!stalled_request_queue_.empty() && !ReachedMaxSocketsLimit()) {
    StalledRequest request(stalled_request_queue_.front());
    stalled_request_queue_.pop_front();
    stalled_request_map_.erase(request.handle);
    int rv = RequestSocket("ignored",
                           &request.params,
                           request.priority,
                           request.handle,
                           request.callback,
                           request.net_log);
    // ActivateStalledRequest() never returns synchronously, so it is never
    // called re-entrantly.
    if (rv != ERR_IO_PENDING)
      InvokeUserCallbackLater(request.handle, request.callback, rv);
  }
}

bool WebSocketTransportClientSocketPool::DeleteStalledRequest(
    ClientSocketHandle* handle) {
  StalledRequestMap::iterator it = stalled_request_map_.find(handle);
  if (it == stalled_request_map_.end())
    return false;
  stalled_request_queue_.erase(it->second);
  stalled_request_map_.erase(it);
  return true;
}

WebSocketTransportClientSocketPool::ConnectJobDelegate::ConnectJobDelegate(
    WebSocketTransportClientSocketPool* owner)
    : owner_(owner) {}

WebSocketTransportClientSocketPool::ConnectJobDelegate::~ConnectJobDelegate() {}

void
WebSocketTransportClientSocketPool::ConnectJobDelegate::OnConnectJobComplete(
    int result,
    ConnectJob* job) {
  owner_->OnConnectJobComplete(result,
                               static_cast<WebSocketTransportConnectJob*>(job));
}

WebSocketTransportClientSocketPool::StalledRequest::StalledRequest(
    const scoped_refptr<TransportSocketParams>& params,
    RequestPriority priority,
    ClientSocketHandle* handle,
    const CompletionCallback& callback,
    const BoundNetLog& net_log)
    : params(params),
      priority(priority),
      handle(handle),
      callback(callback),
      net_log(net_log) {}

WebSocketTransportClientSocketPool::StalledRequest::~StalledRequest() {}

}  // namespace net
