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

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "net/base/net_errors.h"
#include "net/socket/client_socket_pool.h"

namespace net {

ClientSocketHandle::ClientSocketHandle()
    : is_initialized_(false),
      pool_(NULL),
      higher_pool_(NULL),
      reuse_type_(ClientSocketHandle::UNUSED),
      callback_(base::Bind(&ClientSocketHandle::OnIOComplete,
                           base::Unretained(this))),
      is_ssl_error_(false),
      ssl_failure_state_(SSL_FAILURE_NONE) {
}

ClientSocketHandle::~ClientSocketHandle() {
  Reset();
}

void ClientSocketHandle::Reset() {
  ResetInternal(true);
  ResetErrorState();
}

void ClientSocketHandle::ResetInternal(bool cancel) {
  // Was Init called?
  if (!group_name_.empty()) {
    // If so, we must have a pool.
    CHECK(pool_);
    if (is_initialized()) {
      if (socket_) {
        socket_->NetLog().EndEvent(NetLog::TYPE_SOCKET_IN_USE);
        // Release the socket back to the ClientSocketPool so it can be
        // deleted or reused.
        pool_->ReleaseSocket(group_name_, socket_.Pass(), pool_id_);
      } else {
        // If the handle has been initialized, we should still have a
        // socket.
        NOTREACHED();
      }
    } else if (cancel) {
      // If we did not get initialized yet and we have a socket
      // request pending, cancel it.
      pool_->CancelRequest(group_name_, this);
    }
  }
  is_initialized_ = false;
  socket_.reset();
  group_name_.clear();
  reuse_type_ = ClientSocketHandle::UNUSED;
  user_callback_.Reset();
  if (higher_pool_)
    RemoveHigherLayeredPool(higher_pool_);
  pool_ = NULL;
  idle_time_ = base::TimeDelta();
  init_time_ = base::TimeTicks();
  setup_time_ = base::TimeDelta();
  connect_timing_ = LoadTimingInfo::ConnectTiming();
  pool_id_ = -1;
}

void ClientSocketHandle::ResetErrorState() {
  is_ssl_error_ = false;
  ssl_error_response_info_ = HttpResponseInfo();
  ssl_failure_state_ = SSL_FAILURE_NONE;
  pending_http_proxy_connection_.reset();
}

LoadState ClientSocketHandle::GetLoadState() const {
  CHECK(!is_initialized());
  CHECK(!group_name_.empty());
  // Because of http://crbug.com/37810  we may not have a pool, but have
  // just a raw socket.
  if (!pool_)
    return LOAD_STATE_IDLE;
  return pool_->GetLoadState(group_name_, this);
}

bool ClientSocketHandle::IsPoolStalled() const {
  if (!pool_)
    return false;
  return pool_->IsStalled();
}

void ClientSocketHandle::AddHigherLayeredPool(HigherLayeredPool* higher_pool) {
  CHECK(higher_pool);
  CHECK(!higher_pool_);
  // TODO(mmenke):  |pool_| should only be NULL in tests.  Maybe stop doing that
  // so this be be made into a DCHECK, and the same can be done in
  // RemoveHigherLayeredPool?
  if (pool_) {
    pool_->AddHigherLayeredPool(higher_pool);
    higher_pool_ = higher_pool;
  }
}

void ClientSocketHandle::RemoveHigherLayeredPool(
    HigherLayeredPool* higher_pool) {
  CHECK(higher_pool_);
  CHECK_EQ(higher_pool_, higher_pool);
  if (pool_) {
    pool_->RemoveHigherLayeredPool(higher_pool);
    higher_pool_ = NULL;
  }
}

bool ClientSocketHandle::GetLoadTimingInfo(
    bool is_reused,
    LoadTimingInfo* load_timing_info) const {
  // Only return load timing information when there's a socket.
  if (!socket_)
    return false;

  load_timing_info->socket_log_id = socket_->NetLog().source().id;
  load_timing_info->socket_reused = is_reused;

  // No times if the socket is reused.
  if (is_reused)
    return true;

  load_timing_info->connect_timing = connect_timing_;
  return true;
}

void ClientSocketHandle::SetSocket(scoped_ptr<StreamSocket> s) {
  socket_ = s.Pass();
}

void ClientSocketHandle::OnIOComplete(int result) {
  CompletionCallback callback = user_callback_;
  user_callback_.Reset();
  HandleInitCompletion(result);
  callback.Run(result);
}

scoped_ptr<StreamSocket> ClientSocketHandle::PassSocket() {
  return socket_.Pass();
}

void ClientSocketHandle::HandleInitCompletion(int result) {
  CHECK_NE(ERR_IO_PENDING, result);
  if (result != OK) {
    if (!socket_.get())
      ResetInternal(false);  // Nothing to cancel since the request failed.
    else
      is_initialized_ = true;
    return;
  }
  is_initialized_ = true;
  CHECK_NE(-1, pool_id_) << "Pool should have set |pool_id_| to a valid value.";
  setup_time_ = base::TimeTicks::Now() - init_time_;

  // Broadcast that the socket has been acquired.
  // TODO(eroman): This logging is not complete, in particular set_socket() and
  // release() socket. It ends up working though, since those methods are being
  // used to layer sockets (and the destination sources are the same).
  DCHECK(socket_.get());
  socket_->NetLog().BeginEvent(
      NetLog::TYPE_SOCKET_IN_USE,
      requesting_source_.ToEventParametersCallback());
}

}  // namespace net
