Home | History | Annotate | Download | only in socket
      1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "net/socket/client_socket_handle.h"
      6 
      7 #include "base/compiler_specific.h"
      8 #include "base/metrics/histogram.h"
      9 #include "base/logging.h"
     10 #include "net/base/net_errors.h"
     11 #include "net/socket/client_socket_pool.h"
     12 #include "net/socket/client_socket_pool_histograms.h"
     13 
     14 namespace net {
     15 
     16 ClientSocketHandle::ClientSocketHandle()
     17     : is_initialized_(false),
     18       is_reused_(false),
     19       ALLOW_THIS_IN_INITIALIZER_LIST(
     20           callback_(this, &ClientSocketHandle::OnIOComplete)),
     21       is_ssl_error_(false) {}
     22 
     23 ClientSocketHandle::~ClientSocketHandle() {
     24   Reset();
     25 }
     26 
     27 void ClientSocketHandle::Reset() {
     28   ResetInternal(true);
     29   ResetErrorState();
     30 }
     31 
     32 void ClientSocketHandle::ResetInternal(bool cancel) {
     33   if (group_name_.empty())  // Was Init called?
     34     return;
     35   if (is_initialized()) {
     36     // Because of http://crbug.com/37810 we may not have a pool, but have
     37     // just a raw socket.
     38     socket_->NetLog().EndEvent(NetLog::TYPE_SOCKET_IN_USE, NULL);
     39     if (pool_)
     40       // If we've still got a socket, release it back to the ClientSocketPool so
     41       // it can be deleted or reused.
     42       pool_->ReleaseSocket(group_name_, release_socket(), pool_id_);
     43   } else if (cancel) {
     44     // If we did not get initialized yet, we've got a socket request pending.
     45     // Cancel it.
     46     pool_->CancelRequest(group_name_, this);
     47   }
     48   is_initialized_ = false;
     49   group_name_.clear();
     50   is_reused_ = false;
     51   user_callback_ = NULL;
     52   pool_ = NULL;
     53   idle_time_ = base::TimeDelta();
     54   init_time_ = base::TimeTicks();
     55   setup_time_ = base::TimeDelta();
     56   pool_id_ = -1;
     57 }
     58 
     59 void ClientSocketHandle::ResetErrorState() {
     60   is_ssl_error_ = false;
     61   ssl_error_response_info_ = HttpResponseInfo();
     62   pending_http_proxy_connection_.reset();
     63 }
     64 
     65 LoadState ClientSocketHandle::GetLoadState() const {
     66   CHECK(!is_initialized());
     67   CHECK(!group_name_.empty());
     68   // Because of http://crbug.com/37810  we may not have a pool, but have
     69   // just a raw socket.
     70   if (!pool_)
     71     return LOAD_STATE_IDLE;
     72   return pool_->GetLoadState(group_name_, this);
     73 }
     74 
     75 void ClientSocketHandle::OnIOComplete(int result) {
     76   CompletionCallback* callback = user_callback_;
     77   user_callback_ = NULL;
     78   HandleInitCompletion(result);
     79   callback->Run(result);
     80 }
     81 
     82 void ClientSocketHandle::HandleInitCompletion(int result) {
     83   CHECK_NE(ERR_IO_PENDING, result);
     84   if (result != OK) {
     85     if (!socket_.get())
     86       ResetInternal(false);  // Nothing to cancel since the request failed.
     87     else
     88       is_initialized_ = true;
     89     return;
     90   }
     91   is_initialized_ = true;
     92   CHECK_NE(-1, pool_id_) << "Pool should have set |pool_id_| to a valid value.";
     93   setup_time_ = base::TimeTicks::Now() - init_time_;
     94 
     95   ClientSocketPoolHistograms* histograms = pool_->histograms();
     96   histograms->AddSocketType(reuse_type());
     97   switch (reuse_type()) {
     98     case ClientSocketHandle::UNUSED:
     99       histograms->AddRequestTime(setup_time());
    100       break;
    101     case ClientSocketHandle::UNUSED_IDLE:
    102       histograms->AddUnusedIdleTime(idle_time());
    103       break;
    104     case ClientSocketHandle::REUSED_IDLE:
    105       histograms->AddReusedIdleTime(idle_time());
    106       break;
    107     default:
    108       NOTREACHED();
    109       break;
    110   }
    111 
    112   // Broadcast that the socket has been acquired.
    113   // TODO(eroman): This logging is not complete, in particular set_socket() and
    114   // release() socket. It ends up working though, since those methods are being
    115   // used to layer sockets (and the destination sources are the same).
    116   DCHECK(socket_.get());
    117   socket_->NetLog().BeginEvent(
    118       NetLog::TYPE_SOCKET_IN_USE,
    119       make_scoped_refptr(new NetLogSourceParameter(
    120           "source_dependency", requesting_source_)));
    121 }
    122 
    123 }  // namespace net
    124