summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwillchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-10 08:12:22 +0000
committerwillchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-10 08:12:22 +0000
commit1c67ccc3ab473fd54db8aa1d93b5e216edbe1d01 (patch)
tree822ef6b0d4cadc88e6bbecef58de21041735a083
parent72a221c1f159a134671b9f9f12d8216f3527d8f5 (diff)
downloadchromium_src-1c67ccc3ab473fd54db8aa1d93b5e216edbe1d01.zip
chromium_src-1c67ccc3ab473fd54db8aa1d93b5e216edbe1d01.tar.gz
chromium_src-1c67ccc3ab473fd54db8aa1d93b5e216edbe1d01.tar.bz2
Revert "Move much of the TCPClientSocketPool implementation out into ClientSocketPoolBase..."
This reverts r18034. Review URL: http://codereview.chromium.org/119413 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@18046 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--net/base/client_socket_pool_base.cc342
-rw-r--r--net/base/client_socket_pool_base.h177
-rw-r--r--net/base/tcp_client_socket_pool.cc406
-rw-r--r--net/base/tcp_client_socket_pool.h147
-rw-r--r--net/base/tcp_connecting_socket.cc150
-rw-r--r--net/base/tcp_connecting_socket.h80
-rw-r--r--net/net.gyp4
7 files changed, 501 insertions, 805 deletions
diff --git a/net/base/client_socket_pool_base.cc b/net/base/client_socket_pool_base.cc
deleted file mode 100644
index 92bb28d..0000000
--- a/net/base/client_socket_pool_base.cc
+++ /dev/null
@@ -1,342 +0,0 @@
-// Copyright (c) 2009 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/base/client_socket_pool_base.h"
-
-#include "base/logging.h"
-#include "base/message_loop.h"
-#include "base/time.h"
-#include "base/stl_util-inl.h"
-#include "net/base/client_socket_handle.h"
-#include "net/base/net_errors.h"
-#include "net/base/tcp_connecting_socket.h"
-
-using base::TimeDelta;
-
-namespace net {
-
-namespace {
-
-// The timeout value, in seconds, used to clean up idle sockets that can't be
-// reused.
-//
-// Note: It's important to close idle sockets that have received data as soon
-// as possible because the received data may cause BSOD on Windows XP under
-// some conditions. See http://crbug.com/4606.
-const int kCleanupInterval = 10; // DO NOT INCREASE THIS TIMEOUT.
-
-// The maximum duration, in seconds, to keep idle persistent sockets alive.
-const int kIdleTimeout = 300; // 5 minutes.
-
-// InsertRequestIntoQueue inserts the request into the queue based on
-// priority. Highest priorities are closest to the front. Older requests are
-// prioritized over requests of equal priority.
-void InsertRequestIntoQueue(
- const ClientSocketPoolBase::Request& r,
- ClientSocketPoolBase::RequestQueue* pending_requests) {
- ClientSocketPoolBase::RequestQueue::iterator it = pending_requests->begin();
- while (it != pending_requests->end() && r.priority <= it->priority)
- ++it;
- pending_requests->insert(it, r);
-}
-
-} // namespace
-
-ClientSocketPoolBase::ClientSocketPoolBase(
- int max_sockets_per_group,
- const ConnectingSocketFactory* connecting_socket_factory)
- : idle_socket_count_(0),
- max_sockets_per_group_(max_sockets_per_group),
- connecting_socket_factory_(connecting_socket_factory) {}
-
-ClientSocketPoolBase::~ClientSocketPoolBase() {
- // Clean up any idle sockets. Assert that we have no remaining active
- // sockets or pending requests. They should have all been cleaned up prior
- // to the manager being destroyed.
- CleanupIdleSockets(true /* force close all idle sockets */);
- DCHECK(group_map_.empty());
-}
-
-int ClientSocketPoolBase::RequestSocket(const std::string& group_name,
- const Request& request) {
- DCHECK(!request.host.empty());
- DCHECK_GE(request.priority, 0);
- DCHECK(request.callback);
- DCHECK_EQ(LOAD_STATE_IDLE, request.load_state);
-
- Group& group = group_map_[group_name];
-
- // Can we make another active socket now?
- if (group.active_socket_count == max_sockets_per_group_) {
- InsertRequestIntoQueue(request, &group.pending_requests);
- return ERR_IO_PENDING;
- }
-
- // OK, we are going to activate one.
- group.active_socket_count++;
-
- while (!group.idle_sockets.empty()) {
- IdleSocket idle_socket = group.idle_sockets.back();
- group.idle_sockets.pop_back();
- DecrementIdleCount();
- if (idle_socket.socket->IsConnectedAndIdle()) {
- // We found one we can reuse!
- request.handle->set_socket(idle_socket.socket);
- request.handle->set_is_reused(true);
- return OK;
- }
- delete idle_socket.socket;
- }
-
- // We couldn't find a socket to reuse, so allocate and connect a new one.
-
- // First, we need to make sure we aren't already servicing a request for this
- // handle (which could happen if we requested, canceled, and then requested
- // with the same handle).
- if (ContainsKey(connecting_socket_map_, request.handle))
- connecting_socket_map_[request.handle]->Cancel();
-
- group.connecting_requests[request.handle] = request;
- group.connecting_requests[request.handle].load_state =
- LOAD_STATE_RESOLVING_HOST;
-
- TCPConnectingSocket* connecting_socket =
- connecting_socket_factory_->CreateConnectingSocket(group_name, request);
- connecting_socket_map_[request.handle] = connecting_socket;
-
- return connecting_socket->Connect();
-}
-
-void ClientSocketPoolBase::CancelRequest(const std::string& group_name,
- const ClientSocketHandle* handle) {
- DCHECK(ContainsKey(group_map_, group_name));
-
- Group& group = group_map_[group_name];
-
- // Search pending_requests for matching handle.
- RequestQueue::iterator it = group.pending_requests.begin();
- for (; it != group.pending_requests.end(); ++it) {
- if (it->handle == handle) {
- group.pending_requests.erase(it);
- return;
- }
- }
-
- // It's invalid to cancel a non-existent request.
- DCHECK(ContainsKey(group.connecting_requests, handle));
-
- RequestMap::iterator map_it = group.connecting_requests.find(handle);
- if (map_it != group.connecting_requests.end()) {
- group.connecting_requests.erase(map_it);
- group.active_socket_count--;
-
- // Delete group if no longer needed.
- if (group.active_socket_count == 0 && group.idle_sockets.empty()) {
- DCHECK(group.pending_requests.empty());
- DCHECK(group.connecting_requests.empty());
- group_map_.erase(group_name);
- }
- }
-}
-
-void ClientSocketPoolBase::ReleaseSocket(const std::string& group_name,
- ClientSocket* socket) {
- // Run this asynchronously to allow the caller to finish before we let
- // another to begin doing work. This also avoids nasty recursion issues.
- // NOTE: We cannot refer to the handle argument after this method returns.
- MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
- this, &ClientSocketPoolBase::DoReleaseSocket, group_name, socket));
-}
-
-int ClientSocketPoolBase::IdleSocketCountInGroup(
- const std::string& group_name) const {
- GroupMap::const_iterator i = group_map_.find(group_name);
- DCHECK(i != group_map_.end());
-
- return i->second.idle_sockets.size();
-}
-
-LoadState ClientSocketPoolBase::GetLoadState(
- const std::string& group_name,
- const ClientSocketHandle* handle) const {
- DCHECK(ContainsKey(group_map_, group_name)) << group_name;
-
- // Can't use operator[] since it is non-const.
- const Group& group = group_map_.find(group_name)->second;
-
- // Search connecting_requests for matching handle.
- RequestMap::const_iterator map_it = group.connecting_requests.find(handle);
- if (map_it != group.connecting_requests.end()) {
- const LoadState load_state = map_it->second.load_state;
- DCHECK(load_state == LOAD_STATE_RESOLVING_HOST ||
- load_state == LOAD_STATE_CONNECTING);
- return load_state;
- }
-
- // Search pending_requests for matching handle.
- RequestQueue::const_iterator it = group.pending_requests.begin();
- for (; it != group.pending_requests.end(); ++it) {
- if (it->handle == handle) {
- DCHECK_EQ(LOAD_STATE_IDLE, it->load_state);
- // TODO(wtc): Add a state for being on the wait list.
- // See http://www.crbug.com/5077.
- return LOAD_STATE_IDLE;
- }
- }
-
- NOTREACHED();
- return LOAD_STATE_IDLE;
-}
-
-bool ClientSocketPoolBase::IdleSocket::ShouldCleanup(
- base::TimeTicks now) const {
- bool timed_out = (now - start_time) >=
- base::TimeDelta::FromSeconds(kIdleTimeout);
- return timed_out || !socket->IsConnectedAndIdle();
-}
-
-void ClientSocketPoolBase::CleanupIdleSockets(bool force) {
- if (idle_socket_count_ == 0)
- return;
-
- // Current time value. Retrieving it once at the function start rather than
- // inside the inner loop, since it shouldn't change by any meaningful amount.
- base::TimeTicks now = base::TimeTicks::Now();
-
- GroupMap::iterator i = group_map_.begin();
- while (i != group_map_.end()) {
- Group& group = i->second;
-
- std::deque<IdleSocket>::iterator j = group.idle_sockets.begin();
- while (j != group.idle_sockets.end()) {
- if (force || j->ShouldCleanup(now)) {
- delete j->socket;
- j = group.idle_sockets.erase(j);
- DecrementIdleCount();
- } else {
- ++j;
- }
- }
-
- // Delete group if no longer needed.
- if (group.active_socket_count == 0 && group.idle_sockets.empty()) {
- DCHECK(group.pending_requests.empty());
- DCHECK(group.connecting_requests.empty());
- group_map_.erase(i++);
- } else {
- ++i;
- }
- }
-}
-
-ClientSocketPoolBase::Request* ClientSocketPoolBase::GetConnectingRequest(
- const std::string& group_name, const ClientSocketHandle* handle) {
- GroupMap::iterator group_it = group_map_.find(group_name);
- if (group_it == group_map_.end())
- return NULL;
-
- Group& group = group_it->second;
-
- RequestMap* request_map = &group.connecting_requests;
- RequestMap::iterator it = request_map->find(handle);
- if (it == request_map->end())
- return NULL;
-
- return &it->second;
-}
-
-CompletionCallback* ClientSocketPoolBase::OnConnectingRequestComplete(
- const std::string& group_name,
- const ClientSocketHandle* handle,
- bool deactivate,
- ClientSocket* socket) {
- DCHECK((deactivate && !socket) || (!deactivate && socket));
- DCHECK(ContainsKey(group_map_, group_name));
- Group& group = group_map_[group_name];
-
- RequestMap* request_map = &group.connecting_requests;
-
- // TODO(willchan): For decoupling connecting sockets from requests, don't use
- // |handle|. Simply pop the first request from |connecting_requests|. Handle
- // the case where |connecting_requests| is empty by calling DoReleaseSocket().
- DCHECK(ContainsKey(*request_map, handle));
- RequestMap::iterator it = request_map->find(handle);
- Request request = it->second;
- request_map->erase(it);
- DCHECK_EQ(request.handle, handle);
-
- if (deactivate) {
- group.active_socket_count--;
-
- // Delete group if no longer needed.
- if (group.active_socket_count == 0 && group.idle_sockets.empty()) {
- DCHECK(group.pending_requests.empty());
- DCHECK(group.connecting_requests.empty());
- group_map_.erase(group_name);
- }
- } else {
- request.handle->set_socket(socket);
- request.handle->set_is_reused(false);
- }
-
- // TODO(willchan): Don't bother with this when decoupling connecting sockets
- // from requests.
- connecting_socket_map_.erase(handle);
-
- return request.callback;
-}
-
-void ClientSocketPoolBase::IncrementIdleCount() {
- if (++idle_socket_count_ == 1)
- timer_.Start(TimeDelta::FromSeconds(kCleanupInterval), this,
- &ClientSocketPoolBase::OnCleanupTimerFired);
-}
-
-void ClientSocketPoolBase::DecrementIdleCount() {
- if (--idle_socket_count_ == 0)
- timer_.Stop();
-}
-
-void ClientSocketPoolBase::DoReleaseSocket(const std::string& group_name,
- ClientSocket* socket) {
- GroupMap::iterator i = group_map_.find(group_name);
- DCHECK(i != group_map_.end());
-
- Group& group = i->second;
-
- DCHECK_GT(group.active_socket_count, 0);
- group.active_socket_count--;
-
- const bool can_reuse = socket->IsConnectedAndIdle();
- if (can_reuse) {
- IdleSocket idle_socket;
- idle_socket.socket = socket;
- idle_socket.start_time = base::TimeTicks::Now();
-
- group.idle_sockets.push_back(idle_socket);
- IncrementIdleCount();
- } else {
- delete socket;
- }
-
- // Process one pending request.
- if (!group.pending_requests.empty()) {
- Request r = group.pending_requests.front();
- group.pending_requests.pop_front();
-
- int rv = RequestSocket(group_name, r);
- if (rv != ERR_IO_PENDING)
- r.callback->Run(rv);
- return;
- }
-
- // Delete group if no longer needed.
- if (group.active_socket_count == 0 && group.idle_sockets.empty()) {
- DCHECK(group.pending_requests.empty());
- DCHECK(group.connecting_requests.empty());
- group_map_.erase(i);
- }
-}
-
-} // namespace net
diff --git a/net/base/client_socket_pool_base.h b/net/base/client_socket_pool_base.h
deleted file mode 100644
index c18c5b7..0000000
--- a/net/base/client_socket_pool_base.h
+++ /dev/null
@@ -1,177 +0,0 @@
-// Copyright (c) 2009 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.
-//
-// ClientSocketPoolBase is an implementation class for building new
-// ClientSocketPools. New ClientSocketPools should compose
-// ClientSocketPoolBase. ClientSocketPoolBase provides functionality for
-// managing socket reuse and restricting the number of open sockets within a
-// "group". It always returns a connected socket. Clients of
-// ClientSocketPoolBase need to provide a ConnectingSocketFactory to generate
-// ConnectingSockets that actually perform the socket connection.
-
-#ifndef NET_BASE_CLIENT_SOCKET_POOL_BASE_H_
-#define NET_BASE_CLIENT_SOCKET_POOL_BASE_H_
-
-#include <deque>
-#include <map>
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/ref_counted.h"
-#include "base/scoped_ptr.h"
-#include "base/task.h"
-#include "base/timer.h"
-#include "net/base/completion_callback.h"
-#include "net/base/load_states.h"
-
-namespace net {
-
-class ClientSocket;
-class ClientSocketHandle;
-class TCPConnectingSocket;
-
-// A ClientSocketPoolBase is used to restrict the number of sockets open at
-// a time. It also maintains a list of idle persistent sockets.
-class ClientSocketPoolBase : public base::RefCounted<ClientSocketPoolBase> {
- public:
- // A Request is allocated per call to RequestSocket that results in
- // ERR_IO_PENDING.
- struct Request {
- ClientSocketHandle* handle;
- CompletionCallback* callback;
- int priority;
- std::string host;
- int port;
- LoadState load_state;
- };
-
- // Entry for a persistent socket which became idle at time |start_time|.
- struct IdleSocket {
- ClientSocket* socket;
- base::TimeTicks start_time;
-
- // An idle socket should be removed if it can't be reused, or has been idle
- // for too long. |now| is the current time value (TimeTicks::Now()).
- //
- // An idle socket can't be reused if it is disconnected or has received
- // data unexpectedly (hence no longer idle). The unread data would be
- // mistaken for the beginning of the next response if we were to reuse the
- // socket for a new request.
- bool ShouldCleanup(base::TimeTicks now) const;
- };
-
- typedef std::deque<Request> RequestQueue;
- typedef std::map<const ClientSocketHandle*, Request> RequestMap;
-
- // A Group is allocated per group_name when there are idle sockets or pending
- // requests. Otherwise, the Group object is removed from the map.
- struct Group {
- Group() : active_socket_count(0) {}
- std::deque<IdleSocket> idle_sockets;
- RequestQueue pending_requests;
- RequestMap connecting_requests;
- int active_socket_count;
- };
-
- typedef std::map<std::string, Group> GroupMap;
-
- // TODO(willchan): Change the return value of CreateConnectingSocket to be
- // ConnectingSocket*, once I've extracted out an interface for it.
- class ConnectingSocketFactory {
- public:
- ConnectingSocketFactory() {}
- virtual ~ConnectingSocketFactory() {}
-
- // Creates a TCPConnectingSocket. Never returns NULL.
- virtual TCPConnectingSocket* CreateConnectingSocket(
- const std::string& group_name, const Request& request) const = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ConnectingSocketFactory);
- };
-
- ClientSocketPoolBase(
- int max_sockets_per_group,
- const ConnectingSocketFactory* connecting_socket_factory);
- ~ClientSocketPoolBase();
-
- int RequestSocket(const std::string& group_name, const Request& request);
-
- void CancelRequest(const std::string& group_name,
- const ClientSocketHandle* handle);
-
- void ReleaseSocket(const std::string& group_name, ClientSocket* socket);
-
- int idle_socket_count() const { return idle_socket_count_; }
-
- int IdleSocketCountInGroup(const std::string& group_name) const;
-
- LoadState GetLoadState(const std::string& group_name,
- const ClientSocketHandle* handle) const;
-
- // Closes all idle sockets if |force| is true. Else, only closes idle
- // sockets that timed out or can't be reused.
- void CleanupIdleSockets(bool force);
-
- // Used by ConnectingSocket until we remove the coupling between a specific
- // ConnectingSocket and a ClientSocketHandle:
-
- // Returns NULL if not found. Otherwise it returns the Request*
- // corresponding to the ConnectingSocket (keyed by |group_name| and |handle|.
- // Note that this pointer may be invalidated after any call that might mutate
- // the RequestMap or GroupMap, so the user should not hold onto the pointer
- // for long.
- Request* GetConnectingRequest(const std::string& group_name,
- const ClientSocketHandle* handle);
-
- // Handles the completed Request corresponding to the ConnectingSocket (keyed
- // by |group_name| and |handle|. |deactivate| indicates whether or not to
- // deactivate the socket, making the socket slot available for a new socket
- // connection. If |deactivate| is false, then set |socket| into |handle|.
- // Returns the callback to run.
- // TODO(willchan): When we decouple Requests and ConnectingSockets, this will
- // return the callback of the request we select.
- CompletionCallback* OnConnectingRequestComplete(
- const std::string& group_name,
- const ClientSocketHandle* handle,
- bool deactivate,
- ClientSocket* socket);
-
- private:
- // Called when the number of idle sockets changes.
- void IncrementIdleCount();
- void DecrementIdleCount();
-
- // Called via PostTask by ReleaseSocket.
- void DoReleaseSocket(const std::string& group_name, ClientSocket* socket);
-
- // Called when timer_ fires. This method scans the idle sockets removing
- // sockets that timed out or can't be reused.
- void OnCleanupTimerFired() {
- CleanupIdleSockets(false);
- }
-
- GroupMap group_map_;
-
- std::map<const ClientSocketHandle*, TCPConnectingSocket*>
- connecting_socket_map_;
-
- // Timer used to periodically prune idle sockets that timed out or can't be
- // reused.
- base::RepeatingTimer<ClientSocketPoolBase> timer_;
-
- // The total number of idle sockets in the system.
- int idle_socket_count_;
-
- // The maximum number of sockets kept per group.
- const int max_sockets_per_group_;
-
- const ConnectingSocketFactory* const connecting_socket_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBase);
-};
-
-} // namespace net
-
-#endif // NET_BASE_CLIENT_SOCKET_POOL_BASE_H_
diff --git a/net/base/tcp_client_socket_pool.cc b/net/base/tcp_client_socket_pool.cc
index 3f895f7..75875f2 100644
--- a/net/base/tcp_client_socket_pool.cc
+++ b/net/base/tcp_client_socket_pool.cc
@@ -14,20 +14,176 @@
#include "net/base/dns_resolution_observer.h"
#include "net/base/net_errors.h"
#include "net/base/tcp_client_socket.h"
-#include "net/base/tcp_connecting_socket.h"
using base::TimeDelta;
+namespace {
+
+// The timeout value, in seconds, used to clean up idle sockets that can't be
+// reused.
+//
+// Note: It's important to close idle sockets that have received data as soon
+// as possible because the received data may cause BSOD on Windows XP under
+// some conditions. See http://crbug.com/4606.
+const int kCleanupInterval = 10; // DO NOT INCREASE THIS TIMEOUT.
+
+// The maximum duration, in seconds, to keep idle persistent sockets alive.
+const int kIdleTimeout = 300; // 5 minutes.
+
+} // namespace
+
namespace net {
+TCPClientSocketPool::ConnectingSocket::ConnectingSocket(
+ const std::string& group_name,
+ const ClientSocketHandle* handle,
+ ClientSocketFactory* client_socket_factory,
+ TCPClientSocketPool* pool)
+ : group_name_(group_name),
+ handle_(handle),
+ client_socket_factory_(client_socket_factory),
+ ALLOW_THIS_IN_INITIALIZER_LIST(
+ callback_(this,
+ &TCPClientSocketPool::ConnectingSocket::OnIOComplete)),
+ pool_(pool),
+ canceled_(false) {
+ DCHECK(!ContainsKey(pool_->connecting_socket_map_, handle));
+ pool_->connecting_socket_map_[handle] = this;
+}
+
+TCPClientSocketPool::ConnectingSocket::~ConnectingSocket() {
+ if (!canceled_)
+ pool_->connecting_socket_map_.erase(handle_);
+}
+
+int TCPClientSocketPool::ConnectingSocket::Connect(
+ const std::string& host,
+ int port) {
+ DCHECK(!canceled_);
+ DidStartDnsResolution(host, this);
+ int rv = resolver_.Resolve(host, port, &addresses_, &callback_);
+ if (rv != ERR_IO_PENDING)
+ rv = OnIOCompleteInternal(rv, true /* synchronous */);
+ return rv;
+}
+
+void TCPClientSocketPool::ConnectingSocket::OnIOComplete(int result) {
+ OnIOCompleteInternal(result, false /* asynchronous */);
+}
+
+int TCPClientSocketPool::ConnectingSocket::OnIOCompleteInternal(
+ int result, bool synchronous) {
+ DCHECK_NE(result, ERR_IO_PENDING);
+
+ if (canceled_) {
+ // We got canceled, so bail out.
+ delete this;
+ return result;
+ }
+
+ GroupMap::iterator group_it = pool_->group_map_.find(group_name_);
+ if (group_it == pool_->group_map_.end()) {
+ // The request corresponding to this ConnectingSocket has been canceled.
+ // Stop bothering with it.
+ delete this;
+ return result;
+ }
+
+ Group& group = group_it->second;
+
+ RequestMap* request_map = &group.connecting_requests;
+ RequestMap::iterator it = request_map->find(handle_);
+ if (it == request_map->end()) {
+ // The request corresponding to this ConnectingSocket has been canceled.
+ // Stop bothering with it.
+ delete this;
+ return result;
+ }
+
+ if (result == OK && it->second.load_state == LOAD_STATE_RESOLVING_HOST) {
+ it->second.load_state = LOAD_STATE_CONNECTING;
+ socket_.reset(client_socket_factory_->CreateTCPClientSocket(addresses_));
+ connect_start_time_ = base::Time::Now();
+ result = socket_->Connect(&callback_);
+ if (result == ERR_IO_PENDING)
+ return result;
+ }
+
+ if (result == OK) {
+ DCHECK(connect_start_time_ != base::Time());
+ base::TimeDelta connect_duration =
+ base::Time::Now() - connect_start_time_;
+
+ UMA_HISTOGRAM_CLIPPED_TIMES(
+ FieldTrial::MakeName(
+ "Net.TCP_Connection_Latency", "DnsImpact").data(),
+ connect_duration,
+ base::TimeDelta::FromMilliseconds(1),
+ base::TimeDelta::FromMinutes(10),
+ 100);
+ }
+
+ // Now, we either succeeded at Connect()'ing, or we failed at host resolution
+ // or Connect()'ing. Either way, we'll run the callback to alert the client.
+
+ Request request = it->second;
+ request_map->erase(it);
+
+ if (result == OK) {
+ request.handle->set_socket(socket_.release());
+ request.handle->set_is_reused(false);
+ } else {
+ group.active_socket_count--;
+
+ // Delete group if no longer needed.
+ if (group.active_socket_count == 0 && group.idle_sockets.empty()) {
+ DCHECK(group.pending_requests.empty());
+ DCHECK(group.connecting_requests.empty());
+ pool_->group_map_.erase(group_it);
+ }
+ }
+
+ if (!synchronous)
+ request.callback->Run(result);
+ delete this;
+ return result;
+}
+
+void TCPClientSocketPool::ConnectingSocket::Cancel() {
+ DCHECK(!canceled_);
+ DCHECK(ContainsKey(pool_->connecting_socket_map_, handle_));
+ pool_->connecting_socket_map_.erase(handle_);
+ canceled_ = true;
+}
+
TCPClientSocketPool::TCPClientSocketPool(
int max_sockets_per_group,
ClientSocketFactory* client_socket_factory)
- : base_(new ClientSocketPoolBase(max_sockets_per_group,
- &connecting_socket_factory_)),
- connecting_socket_factory_(base_, client_socket_factory) {}
+ : client_socket_factory_(client_socket_factory),
+ idle_socket_count_(0),
+ max_sockets_per_group_(max_sockets_per_group) {
+}
-TCPClientSocketPool::~TCPClientSocketPool() {}
+TCPClientSocketPool::~TCPClientSocketPool() {
+ // Clean up any idle sockets. Assert that we have no remaining active
+ // sockets or pending requests. They should have all been cleaned up prior
+ // to the manager being destroyed.
+ CloseIdleSockets();
+ DCHECK(group_map_.empty());
+}
+
+// InsertRequestIntoQueue inserts the request into the queue based on
+// priority. Highest priorities are closest to the front. Older requests are
+// prioritized over requests of equal priority.
+//
+// static
+void TCPClientSocketPool::InsertRequestIntoQueue(
+ const Request& r, RequestQueue* pending_requests) {
+ RequestQueue::iterator it = pending_requests->begin();
+ while (it != pending_requests->end() && r.priority <= it->priority)
+ ++it;
+ pending_requests->insert(it, r);
+}
int TCPClientSocketPool::RequestSocket(const std::string& group_name,
const std::string& host,
@@ -35,61 +191,241 @@ int TCPClientSocketPool::RequestSocket(const std::string& group_name,
int priority,
ClientSocketHandle* handle,
CompletionCallback* callback) {
- ClientSocketPoolBase::Request request;
- request.host = host;
- request.port = port;
- request.priority = priority;
- request.handle = handle;
- request.callback = callback;
- request.load_state = LOAD_STATE_IDLE;
- return base_->RequestSocket(group_name, request);
+ DCHECK(!host.empty());
+ DCHECK_GE(priority, 0);
+ Group& group = group_map_[group_name];
+
+ // Can we make another active socket now?
+ if (group.active_socket_count == max_sockets_per_group_) {
+ Request r;
+ r.handle = handle;
+ DCHECK(callback);
+ r.callback = callback;
+ r.priority = priority;
+ r.host = host;
+ r.port = port;
+ r.load_state = LOAD_STATE_IDLE;
+ InsertRequestIntoQueue(r, &group.pending_requests);
+ return ERR_IO_PENDING;
+ }
+
+ // OK, we are going to activate one.
+ group.active_socket_count++;
+
+ while (!group.idle_sockets.empty()) {
+ IdleSocket idle_socket = group.idle_sockets.back();
+ group.idle_sockets.pop_back();
+ DecrementIdleCount();
+ if (idle_socket.socket->IsConnectedAndIdle()) {
+ // We found one we can reuse!
+ handle->set_socket(idle_socket.socket);
+ handle->set_is_reused(true);
+ return OK;
+ }
+ delete idle_socket.socket;
+ }
+
+ // We couldn't find a socket to reuse, so allocate and connect a new one.
+
+ // First, we need to make sure we aren't already servicing a request for this
+ // handle (which could happen if we requested, canceled, and then requested
+ // with the same handle).
+ if (ContainsKey(connecting_socket_map_, handle))
+ connecting_socket_map_[handle]->Cancel();
+
+ Request r;
+ r.handle = handle;
+ DCHECK(callback);
+ r.callback = callback;
+ r.priority = priority;
+ r.host = host;
+ r.port = port;
+ r.load_state = LOAD_STATE_RESOLVING_HOST;
+ group_map_[group_name].connecting_requests[handle] = r;
+
+ // connecting_socket will delete itself.
+ ConnectingSocket* connecting_socket =
+ new ConnectingSocket(group_name, handle, client_socket_factory_, this);
+ int rv = connecting_socket->Connect(host, port);
+ return rv;
}
void TCPClientSocketPool::CancelRequest(const std::string& group_name,
const ClientSocketHandle* handle) {
- base_->CancelRequest(group_name, handle);
+ DCHECK(ContainsKey(group_map_, group_name));
+
+ Group& group = group_map_[group_name];
+
+ // Search pending_requests for matching handle.
+ RequestQueue::iterator it = group.pending_requests.begin();
+ for (; it != group.pending_requests.end(); ++it) {
+ if (it->handle == handle) {
+ group.pending_requests.erase(it);
+ return;
+ }
+ }
+
+ // It's invalid to cancel a non-existent request.
+ DCHECK(ContainsKey(group.connecting_requests, handle));
+
+ RequestMap::iterator map_it = group.connecting_requests.find(handle);
+ if (map_it != group.connecting_requests.end()) {
+ group.connecting_requests.erase(map_it);
+ group.active_socket_count--;
+
+ // Delete group if no longer needed.
+ if (group.active_socket_count == 0 && group.idle_sockets.empty()) {
+ DCHECK(group.pending_requests.empty());
+ DCHECK(group.connecting_requests.empty());
+ group_map_.erase(group_name);
+ }
+ }
}
void TCPClientSocketPool::ReleaseSocket(const std::string& group_name,
ClientSocket* socket) {
- base_->ReleaseSocket(group_name, socket);
+ // Run this asynchronously to allow the caller to finish before we let
+ // another to begin doing work. This also avoids nasty recursion issues.
+ // NOTE: We cannot refer to the handle argument after this method returns.
+ MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
+ this, &TCPClientSocketPool::DoReleaseSocket, group_name, socket));
}
void TCPClientSocketPool::CloseIdleSockets() {
- base_->CleanupIdleSockets(true);
+ CleanupIdleSockets(true);
}
int TCPClientSocketPool::IdleSocketCountInGroup(
const std::string& group_name) const {
- return base_->IdleSocketCountInGroup(group_name);
+ GroupMap::const_iterator i = group_map_.find(group_name);
+ DCHECK(i != group_map_.end());
+
+ return i->second.idle_sockets.size();
}
LoadState TCPClientSocketPool::GetLoadState(
const std::string& group_name,
const ClientSocketHandle* handle) const {
- return base_->GetLoadState(group_name, handle);
+ DCHECK(ContainsKey(group_map_, group_name)) << group_name;
+
+ // Can't use operator[] since it is non-const.
+ const Group& group = group_map_.find(group_name)->second;
+
+ // Search connecting_requests for matching handle.
+ RequestMap::const_iterator map_it = group.connecting_requests.find(handle);
+ if (map_it != group.connecting_requests.end()) {
+ const LoadState load_state = map_it->second.load_state;
+ DCHECK(load_state == LOAD_STATE_RESOLVING_HOST ||
+ load_state == LOAD_STATE_CONNECTING);
+ return load_state;
+ }
+
+ // Search pending_requests for matching handle.
+ RequestQueue::const_iterator it = group.pending_requests.begin();
+ for (; it != group.pending_requests.end(); ++it) {
+ if (it->handle == handle) {
+ DCHECK_EQ(LOAD_STATE_IDLE, it->load_state);
+ // TODO(wtc): Add a state for being on the wait list.
+ // See http://www.crbug.com/5077.
+ return LOAD_STATE_IDLE;
+ }
+ }
+
+ NOTREACHED();
+ return LOAD_STATE_IDLE;
}
-TCPClientSocketPool::TCPConnectingSocketFactory::TCPConnectingSocketFactory(
- const scoped_refptr<ClientSocketPoolBase>& base,
- ClientSocketFactory* client_socket_factory)
- : base_(base),
- client_socket_factory_(client_socket_factory) {}
+bool TCPClientSocketPool::IdleSocket::ShouldCleanup(base::TimeTicks now) const {
+ bool timed_out = (now - start_time) >=
+ base::TimeDelta::FromSeconds(kIdleTimeout);
+ return timed_out || !socket->IsConnectedAndIdle();
+}
+
+void TCPClientSocketPool::CleanupIdleSockets(bool force) {
+ if (idle_socket_count_ == 0)
+ return;
+
+ // Current time value. Retrieving it once at the function start rather than
+ // inside the inner loop, since it shouldn't change by any meaningful amount.
+ base::TimeTicks now = base::TimeTicks::Now();
+
+ GroupMap::iterator i = group_map_.begin();
+ while (i != group_map_.end()) {
+ Group& group = i->second;
+
+ std::deque<IdleSocket>::iterator j = group.idle_sockets.begin();
+ while (j != group.idle_sockets.end()) {
+ if (force || j->ShouldCleanup(now)) {
+ delete j->socket;
+ j = group.idle_sockets.erase(j);
+ DecrementIdleCount();
+ } else {
+ ++j;
+ }
+ }
-TCPClientSocketPool::TCPConnectingSocketFactory::~TCPConnectingSocketFactory() {
+ // Delete group if no longer needed.
+ if (group.active_socket_count == 0 && group.idle_sockets.empty()) {
+ DCHECK(group.pending_requests.empty());
+ DCHECK(group.connecting_requests.empty());
+ group_map_.erase(i++);
+ } else {
+ ++i;
+ }
+ }
}
-TCPConnectingSocket*
-TCPClientSocketPool::TCPConnectingSocketFactory::CreateConnectingSocket(
- const std::string& group_name,
- const ClientSocketPoolBase::Request& request) const {
- return new TCPConnectingSocket(group_name,
- request.host,
- request.port,
- request.handle,
- request.callback,
- client_socket_factory_,
- base_);
+void TCPClientSocketPool::IncrementIdleCount() {
+ if (++idle_socket_count_ == 1)
+ timer_.Start(TimeDelta::FromSeconds(kCleanupInterval), this,
+ &TCPClientSocketPool::OnCleanupTimerFired);
+}
+
+void TCPClientSocketPool::DecrementIdleCount() {
+ if (--idle_socket_count_ == 0)
+ timer_.Stop();
+}
+
+void TCPClientSocketPool::DoReleaseSocket(const std::string& group_name,
+ ClientSocket* socket) {
+ GroupMap::iterator i = group_map_.find(group_name);
+ DCHECK(i != group_map_.end());
+
+ Group& group = i->second;
+
+ DCHECK_GT(group.active_socket_count, 0);
+ group.active_socket_count--;
+
+ const bool can_reuse = socket->IsConnectedAndIdle();
+ if (can_reuse) {
+ IdleSocket idle_socket;
+ idle_socket.socket = socket;
+ idle_socket.start_time = base::TimeTicks::Now();
+
+ group.idle_sockets.push_back(idle_socket);
+ IncrementIdleCount();
+ } else {
+ delete socket;
+ }
+
+ // Process one pending request.
+ if (!group.pending_requests.empty()) {
+ Request r = group.pending_requests.front();
+ group.pending_requests.pop_front();
+
+ int rv = RequestSocket(
+ group_name, r.host, r.port, r.priority, r.handle, r.callback);
+ if (rv != ERR_IO_PENDING)
+ r.callback->Run(rv);
+ return;
+ }
+
+ // Delete group if no longer needed.
+ if (group.active_socket_count == 0 && group.idle_sockets.empty()) {
+ DCHECK(group.pending_requests.empty());
+ DCHECK(group.connecting_requests.empty());
+ group_map_.erase(i);
+ }
}
} // namespace net
diff --git a/net/base/tcp_client_socket_pool.h b/net/base/tcp_client_socket_pool.h
index c92a081..8d4a3bd 100644
--- a/net/base/tcp_client_socket_pool.h
+++ b/net/base/tcp_client_socket_pool.h
@@ -5,15 +5,19 @@
#ifndef NET_BASE_TCP_CLIENT_SOCKET_POOL_H_
#define NET_BASE_TCP_CLIENT_SOCKET_POOL_H_
+#include <deque>
+#include <map>
#include <string>
+#include "base/scoped_ptr.h"
+#include "base/timer.h"
+#include "net/base/address_list.h"
#include "net/base/client_socket_pool.h"
-#include "net/base/client_socket_pool_base.h"
+#include "net/base/host_resolver.h"
namespace net {
class ClientSocketFactory;
-class TCPConnectingSocket;
// A TCPClientSocketPool is used to restrict the number of TCP sockets open at
// a time. It also maintains a list of idle persistent sockets.
@@ -40,7 +44,9 @@ class TCPClientSocketPool : public ClientSocketPool {
virtual void CloseIdleSockets();
- virtual int idle_socket_count() const { return base_->idle_socket_count(); }
+ virtual int idle_socket_count() const {
+ return idle_socket_count_;
+ }
virtual int IdleSocketCountInGroup(const std::string& group_name) const;
@@ -48,29 +54,136 @@ class TCPClientSocketPool : public ClientSocketPool {
const ClientSocketHandle* handle) const;
private:
- class TCPConnectingSocketFactory
- : public ClientSocketPoolBase::ConnectingSocketFactory {
- public:
- TCPConnectingSocketFactory(
- const scoped_refptr<ClientSocketPoolBase>& base,
- ClientSocketFactory* factory);
- virtual ~TCPConnectingSocketFactory();
+ // A Request is allocated per call to RequestSocket that results in
+ // ERR_IO_PENDING.
+ struct Request {
+ ClientSocketHandle* handle;
+ CompletionCallback* callback;
+ int priority;
+ std::string host;
+ int port;
+ LoadState load_state;
+ };
+
+ // Entry for a persistent socket which became idle at time |start_time|.
+ struct IdleSocket {
+ ClientSocket* socket;
+ base::TimeTicks start_time;
+
+ // An idle socket should be removed if it can't be reused, or has been idle
+ // for too long. |now| is the current time value (TimeTicks::Now()).
+ //
+ // An idle socket can't be reused if it is disconnected or has received
+ // data unexpectedly (hence no longer idle). The unread data would be
+ // mistaken for the beginning of the next response if we were to reuse the
+ // socket for a new request.
+ bool ShouldCleanup(base::TimeTicks now) const;
+ };
+
+ typedef std::deque<Request> RequestQueue;
+ typedef std::map<const ClientSocketHandle*, Request> RequestMap;
+
+ // A Group is allocated per group_name when there are idle sockets or pending
+ // requests. Otherwise, the Group object is removed from the map.
+ struct Group {
+ Group() : active_socket_count(0) {}
+ std::deque<IdleSocket> idle_sockets;
+ RequestQueue pending_requests;
+ RequestMap connecting_requests;
+ int active_socket_count;
+ };
+
+ typedef std::map<std::string, Group> GroupMap;
- virtual TCPConnectingSocket* CreateConnectingSocket(
- const std::string& group_name,
- const ClientSocketPoolBase::Request& request) const;
+ // ConnectingSocket handles the host resolution necessary for socket creation
+ // and the Connect().
+ class ConnectingSocket {
+ public:
+ enum State {
+ STATE_RESOLVE_HOST,
+ STATE_CONNECT
+ };
+
+ ConnectingSocket(const std::string& group_name,
+ const ClientSocketHandle* handle,
+ ClientSocketFactory* client_socket_factory,
+ TCPClientSocketPool* pool);
+ ~ConnectingSocket();
+
+ // Begins the host resolution and the TCP connect. Returns OK on success
+ // and ERR_IO_PENDING if it cannot immediately service the request.
+ // Otherwise, it returns a net error code.
+ int Connect(const std::string& host, int port);
+
+ // Called by the TCPClientSocketPool to cancel this ConnectingSocket. Only
+ // necessary if a ClientSocketHandle is reused.
+ void Cancel();
private:
- const scoped_refptr<ClientSocketPoolBase> base_;
+ // Handles asynchronous completion of IO. |result| represents the result of
+ // the IO operation.
+ void OnIOComplete(int result);
+
+ // Handles both asynchronous and synchronous completion of IO. |result|
+ // represents the result of the IO operation. |synchronous| indicates
+ // whether or not the previous IO operation completed synchronously or
+ // asynchronously. OnIOCompleteInternal returns the result of the next IO
+ // operation that executes, or just the value of |result|.
+ int OnIOCompleteInternal(int result, bool synchronous);
+
+ const std::string group_name_;
+ const ClientSocketHandle* const handle_;
ClientSocketFactory* const client_socket_factory_;
+ CompletionCallbackImpl<ConnectingSocket> callback_;
+ scoped_ptr<ClientSocket> socket_;
+ scoped_refptr<TCPClientSocketPool> pool_;
+ HostResolver resolver_;
+ AddressList addresses_;
+ bool canceled_;
- DISALLOW_COPY_AND_ASSIGN(TCPConnectingSocketFactory);
+ // The time the Connect() method was called (if it got called).
+ base::Time connect_start_time_;
+
+ DISALLOW_COPY_AND_ASSIGN(ConnectingSocket);
};
virtual ~TCPClientSocketPool();
- const scoped_refptr<ClientSocketPoolBase> base_;
- const TCPConnectingSocketFactory connecting_socket_factory_;
+ static void InsertRequestIntoQueue(const Request& r,
+ RequestQueue* pending_requests);
+
+ // Closes all idle sockets if |force| is true. Else, only closes idle
+ // sockets that timed out or can't be reused.
+ void CleanupIdleSockets(bool force);
+
+ // Called when the number of idle sockets changes.
+ void IncrementIdleCount();
+ void DecrementIdleCount();
+
+ // Called via PostTask by ReleaseSocket.
+ void DoReleaseSocket(const std::string& group_name, ClientSocket* socket);
+
+ // Called when timer_ fires. This method scans the idle sockets removing
+ // sockets that timed out or can't be reused.
+ void OnCleanupTimerFired() {
+ CleanupIdleSockets(false);
+ }
+
+ ClientSocketFactory* const client_socket_factory_;
+
+ GroupMap group_map_;
+
+ std::map<const ClientSocketHandle*, ConnectingSocket*> connecting_socket_map_;
+
+ // Timer used to periodically prune idle sockets that timed out or can't be
+ // reused.
+ base::RepeatingTimer<TCPClientSocketPool> timer_;
+
+ // The total number of idle sockets in the system.
+ int idle_socket_count_;
+
+ // The maximum number of sockets kept per group.
+ const int max_sockets_per_group_;
DISALLOW_COPY_AND_ASSIGN(TCPClientSocketPool);
};
diff --git a/net/base/tcp_connecting_socket.cc b/net/base/tcp_connecting_socket.cc
deleted file mode 100644
index 82e1952..0000000
--- a/net/base/tcp_connecting_socket.cc
+++ /dev/null
@@ -1,150 +0,0 @@
-// Copyright (c) 2006-2008 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/base/tcp_connecting_socket.h"
-
-#include "base/compiler_specific.h"
-#include "base/field_trial.h"
-#include "base/stl_util-inl.h"
-#include "base/time.h"
-#include "net/base/client_socket_factory.h"
-#include "net/base/client_socket_handle.h"
-#include "net/base/client_socket_pool_base.h"
-#include "net/base/dns_resolution_observer.h"
-#include "net/base/net_errors.h"
-#include "net/base/tcp_client_socket.h"
-
-using base::TimeDelta;
-
-namespace {
-
-// The timeout value, in seconds, used to clean up idle sockets that can't be
-// reused.
-//
-// Note: It's important to close idle sockets that have received data as soon
-// as possible because the received data may cause BSOD on Windows XP under
-// some conditions. See http://crbug.com/4606.
-const int kCleanupInterval = 10; // DO NOT INCREASE THIS TIMEOUT.
-
-// The maximum duration, in seconds, to keep idle persistent sockets alive.
-const int kIdleTimeout = 300; // 5 minutes.
-
-} // namespace
-
-namespace net {
-
-TCPConnectingSocket::TCPConnectingSocket(
- const std::string& group_name,
- const std::string& host,
- int port,
- const ClientSocketHandle* handle,
- CompletionCallback* callback,
- ClientSocketFactory* client_socket_factory,
- const scoped_refptr<ClientSocketPoolBase>& pool)
- : group_name_(group_name),
- host_(host),
- port_(port),
- handle_(handle),
- user_callback_(callback),
- client_socket_factory_(client_socket_factory),
- ALLOW_THIS_IN_INITIALIZER_LIST(
- callback_(this,
- &TCPConnectingSocket::OnIOComplete)),
- pool_(pool),
- canceled_(false) {}
-
-TCPConnectingSocket::~TCPConnectingSocket() {}
-
-int TCPConnectingSocket::Connect() {
- DCHECK(!canceled_);
- DidStartDnsResolution(host_, this);
- int rv = resolver_.Resolve(host_, port_, &addresses_, &callback_);
- if (rv == OK) {
- rv = OnIOCompleteInternal(rv, true /* synchronous */);
- }
- return rv;
-}
-
-void TCPConnectingSocket::OnIOComplete(int result) {
- OnIOCompleteInternal(result, false /* asynchronous */);
-}
-
-int TCPConnectingSocket::OnIOCompleteInternal(int result, bool synchronous) {
- DCHECK_NE(result, ERR_IO_PENDING);
-
- if (canceled_) {
- // We got canceled, so bail out.
- delete this;
- return result;
- }
-
- ClientSocketPoolBase::Request* request = pool_->GetConnectingRequest(
- group_name_, handle_);
- if (!request) {
- // The request corresponding to this TCPConnectingSocket has been canceled.
- // Stop bothering with it.
- delete this;
- return result;
- }
-
- if (result == OK && request->load_state == LOAD_STATE_RESOLVING_HOST) {
- request->load_state = LOAD_STATE_CONNECTING;
- socket_.reset(client_socket_factory_->CreateTCPClientSocket(addresses_));
- connect_start_time_ = base::Time::Now();
- result = socket_->Connect(&callback_);
- if (result == ERR_IO_PENDING)
- return result;
- }
-
- if (result == OK) {
- DCHECK_EQ(request->load_state, LOAD_STATE_CONNECTING);
- DCHECK(connect_start_time_ != base::Time());
- base::TimeDelta connect_duration =
- base::Time::Now() - connect_start_time_;
-
- UMA_HISTOGRAM_CLIPPED_TIMES(
- FieldTrial::MakeName(
- "Net.TCP_Connection_Latency", "DnsImpact").data(),
- connect_duration,
- base::TimeDelta::FromMilliseconds(1),
- base::TimeDelta::FromMinutes(10),
- 100);
- }
-
- // Now, we either succeeded at Connect()'ing, or we failed at host resolution
- // or Connect()'ing. Either way, we'll run the callback to alert the client.
-
- CompletionCallback* callback = NULL;
-
- if (result == OK) {
- callback = pool_->OnConnectingRequestComplete(
- group_name_,
- handle_,
- false /* don't deactivate socket */,
- socket_.release());
- } else {
- callback = pool_->OnConnectingRequestComplete(
- group_name_,
- handle_,
- true /* deactivate socket */,
- NULL /* no socket to give */);
- }
-
- // TODO(willchan): Eventually this DCHECK will not be true, once we timeout
- // slow connecting sockets and allocate extra connecting sockets to avoid the
- // 3s timeout.
- DCHECK(callback);
-
- if (!synchronous)
- callback->Run(result);
- delete this;
- return result;
-}
-
-void TCPConnectingSocket::Cancel() {
- DCHECK(!canceled_);
- canceled_ = true;
-}
-
-} // namespace net
diff --git a/net/base/tcp_connecting_socket.h b/net/base/tcp_connecting_socket.h
deleted file mode 100644
index 7096692..0000000
--- a/net/base/tcp_connecting_socket.h
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright (c) 2006-2008 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.
-
-#ifndef NET_BASE_TCP_CONNECTING_SOCKET_H_
-#define NET_BASE_TCP_CONNECTING_SOCKET_H_
-
-#include <deque>
-#include <map>
-#include <string>
-
-#include "base/scoped_ptr.h"
-#include "base/timer.h"
-#include "net/base/address_list.h"
-#include "net/base/client_socket_pool.h"
-#include "net/base/host_resolver.h"
-
-namespace net {
-
-class ClientSocketFactory;
-class ClientSocketPoolBase;
-
-// TCPConnectingSocket handles host resolution and socket connection for a TCP
-// socket.
-class TCPConnectingSocket {
- public:
- TCPConnectingSocket(const std::string& group_name,
- const std::string& host,
- int port,
- const ClientSocketHandle* handle,
- CompletionCallback* callback,
- ClientSocketFactory* client_socket_factory,
- const scoped_refptr<ClientSocketPoolBase>& pool);
- ~TCPConnectingSocket();
-
- // Begins the host resolution and the TCP connect. Returns OK on success
- // and ERR_IO_PENDING if it cannot immediately service the request.
- // Otherwise, it returns a net error code.
- int Connect();
-
- // TODO(willchan): Delete this function once we decouple connecting sockets
- // from requests, since we'll keep around the idle connected socket.
- // Called by the ClientSocketPoolBase to cancel this TCPConnectingSocket.
- // Only necessary if a ClientSocketHandle is reused.
- void Cancel();
-
- private:
- // Handles asynchronous completion of IO. |result| represents the result of
- // the IO operation.
- void OnIOComplete(int result);
-
- // Handles both asynchronous and synchronous completion of IO. |result|
- // represents the result of the IO operation. |synchronous| indicates
- // whether or not the previous IO operation completed synchronously or
- // asynchronously. OnIOCompleteInternal returns the result of the next IO
- // operation that executes, or just the value of |result|.
- int OnIOCompleteInternal(int result, bool synchronous);
-
- const std::string group_name_;
- const std::string host_;
- const int port_;
- const ClientSocketHandle* const handle_;
- CompletionCallback* const user_callback_;
- ClientSocketFactory* const client_socket_factory_;
- CompletionCallbackImpl<TCPConnectingSocket> callback_;
- scoped_ptr<ClientSocket> socket_;
- const scoped_refptr<ClientSocketPoolBase> pool_;
- HostResolver resolver_;
- AddressList addresses_;
- bool canceled_;
-
- // The time the Connect() method was called (if it got called).
- base::Time connect_start_time_;
-
- DISALLOW_COPY_AND_ASSIGN(TCPConnectingSocket);
-};
-
-} // namespace net
-
-#endif // NET_BASE_TCP_CONNECTING_SOCKET_H_
diff --git a/net/net.gyp b/net/net.gyp
index 66f888d..37bc3a7 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -50,8 +50,6 @@
'base/client_socket_handle.cc',
'base/client_socket_handle.h',
'base/client_socket_pool.h',
- 'base/client_socket_pool_base.cc',
- 'base/client_socket_pool_base.h',
'base/completion_callback.h',
'base/connection_type_histograms.cc',
'base/connection_type_histograms.h',
@@ -132,8 +130,6 @@
'base/tcp_client_socket_pool.h',
'base/tcp_client_socket_win.cc',
'base/tcp_client_socket_win.h',
- 'base/tcp_connecting_socket.cc',
- 'base/tcp_connecting_socket.h',
'base/telnet_server.cc',
'base/telnet_server.h',
'base/upload_data.cc',