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