• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
ClientSocketHandle()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 
~ClientSocketHandle()23 ClientSocketHandle::~ClientSocketHandle() {
24   Reset();
25 }
26 
Reset()27 void ClientSocketHandle::Reset() {
28   ResetInternal(true);
29   ResetErrorState();
30 }
31 
ResetInternal(bool cancel)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 
ResetErrorState()59 void ClientSocketHandle::ResetErrorState() {
60   is_ssl_error_ = false;
61   ssl_error_response_info_ = HttpResponseInfo();
62   pending_http_proxy_connection_.reset();
63 }
64 
GetLoadState() const65 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 
OnIOComplete(int result)75 void ClientSocketHandle::OnIOComplete(int result) {
76   CompletionCallback* callback = user_callback_;
77   user_callback_ = NULL;
78   HandleInitCompletion(result);
79   callback->Run(result);
80 }
81 
HandleInitCompletion(int result)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