1 // Copyright (c) 2012 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.
5 #include "net/socket/client_socket_handle.h"
8 #include "base/bind_helpers.h"
9 #include "base/compiler_specific.h"
10 #include "base/metrics/histogram.h"
11 #include "base/logging.h"
12 #include "net/base/net_errors.h"
13 #include "net/socket/client_socket_pool.h"
14 #include "net/socket/client_socket_pool_histograms.h"
18 ClientSocketHandle::ClientSocketHandle()
19 : is_initialized_(false),
23 ALLOW_THIS_IN_INITIALIZER_LIST(callback_(
24 base::Bind(&ClientSocketHandle::OnIOComplete
,
25 base::Unretained(this)))),
26 is_ssl_error_(false) {}
28 ClientSocketHandle::~ClientSocketHandle() {
32 void ClientSocketHandle::Reset() {
37 void ClientSocketHandle::ResetInternal(bool cancel
) {
38 if (group_name_
.empty()) // Was Init called?
40 if (is_initialized()) {
41 // Because of http://crbug.com/37810 we may not have a pool, but have
43 socket_
->NetLog().EndEvent(NetLog::TYPE_SOCKET_IN_USE
);
45 // If we've still got a socket, release it back to the ClientSocketPool so
46 // it can be deleted or reused.
47 pool_
->ReleaseSocket(group_name_
, release_socket(), pool_id_
);
49 // If we did not get initialized yet, we've got a socket request pending.
51 pool_
->CancelRequest(group_name_
, this);
53 is_initialized_
= false;
56 user_callback_
.Reset();
58 pool_
->RemoveLayeredPool(layered_pool_
);
62 idle_time_
= base::TimeDelta();
63 init_time_
= base::TimeTicks();
64 setup_time_
= base::TimeDelta();
65 connect_timing_
= LoadTimingInfo::ConnectTiming();
69 void ClientSocketHandle::ResetErrorState() {
70 is_ssl_error_
= false;
71 ssl_error_response_info_
= HttpResponseInfo();
72 pending_http_proxy_connection_
.reset();
75 LoadState
ClientSocketHandle::GetLoadState() const {
76 CHECK(!is_initialized());
77 CHECK(!group_name_
.empty());
78 // Because of http://crbug.com/37810 we may not have a pool, but have
81 return LOAD_STATE_IDLE
;
82 return pool_
->GetLoadState(group_name_
, this);
85 bool ClientSocketHandle::IsPoolStalled() const {
86 return pool_
->IsStalled();
89 void ClientSocketHandle::AddLayeredPool(LayeredPool
* layered_pool
) {
91 CHECK(!layered_pool_
);
93 pool_
->AddLayeredPool(layered_pool
);
94 layered_pool_
= layered_pool
;
98 void ClientSocketHandle::RemoveLayeredPool(LayeredPool
* layered_pool
) {
100 CHECK(layered_pool_
);
102 pool_
->RemoveLayeredPool(layered_pool
);
103 layered_pool_
= NULL
;
107 bool ClientSocketHandle::GetLoadTimingInfo(
109 LoadTimingInfo
* load_timing_info
) const {
110 // Only return load timing information when there's a socket.
114 load_timing_info
->socket_log_id
= socket_
->NetLog().source().id
;
115 load_timing_info
->socket_reused
= is_reused
;
117 // No times if the socket is reused.
121 load_timing_info
->connect_timing
= connect_timing_
;
125 void ClientSocketHandle::OnIOComplete(int result
) {
126 CompletionCallback callback
= user_callback_
;
127 user_callback_
.Reset();
128 HandleInitCompletion(result
);
129 callback
.Run(result
);
132 void ClientSocketHandle::HandleInitCompletion(int result
) {
133 CHECK_NE(ERR_IO_PENDING
, result
);
134 ClientSocketPoolHistograms
* histograms
= pool_
->histograms();
135 histograms
->AddErrorCode(result
);
138 ResetInternal(false); // Nothing to cancel since the request failed.
140 is_initialized_
= true;
143 is_initialized_
= true;
144 CHECK_NE(-1, pool_id_
) << "Pool should have set |pool_id_| to a valid value.";
145 setup_time_
= base::TimeTicks::Now() - init_time_
;
147 histograms
->AddSocketType(reuse_type());
148 switch (reuse_type()) {
149 case ClientSocketHandle::UNUSED
:
150 histograms
->AddRequestTime(setup_time());
152 case ClientSocketHandle::UNUSED_IDLE
:
153 histograms
->AddUnusedIdleTime(idle_time());
155 case ClientSocketHandle::REUSED_IDLE
:
156 histograms
->AddReusedIdleTime(idle_time());
163 // Broadcast that the socket has been acquired.
164 // TODO(eroman): This logging is not complete, in particular set_socket() and
165 // release() socket. It ends up working though, since those methods are being
166 // used to layer sockets (and the destination sources are the same).
167 DCHECK(socket_
.get());
168 socket_
->NetLog().BeginEvent(
169 NetLog::TYPE_SOCKET_IN_USE
,
170 requesting_source_
.ToEventParametersCallback());