summaryrefslogtreecommitdiffstats
path: root/net/socket/tcp_client_socket_pool.cc
diff options
context:
space:
mode:
authorPatrick Scott <phanna@android.com>2010-02-04 10:37:17 -0500
committerPatrick Scott <phanna@android.com>2010-02-04 10:39:42 -0500
commitc7f5f8508d98d5952d42ed7648c2a8f30a4da156 (patch)
treedd51dbfbf6670daa61279b3a19e7b1835b301dbf /net/socket/tcp_client_socket_pool.cc
parent139d8152182f9093f03d9089822b688e49fa7667 (diff)
downloadexternal_chromium-c7f5f8508d98d5952d42ed7648c2a8f30a4da156.zip
external_chromium-c7f5f8508d98d5952d42ed7648c2a8f30a4da156.tar.gz
external_chromium-c7f5f8508d98d5952d42ed7648c2a8f30a4da156.tar.bz2
Initial source checkin.
The source files were determined by building net_unittests in chromium's source tree. Some of the obvious libraries were left out (v8, gmock, gtest). The Android.mk file has all the sources (minus unittests and tools) that were used during net_unittests compilation. Nothing builds yet because of STL but that is the next task. The .cpp files will most likely not compile anyways because of the LOCAL_CPP_EXTENSION mod. I will have to break this into multiple projects to get around that limitation.
Diffstat (limited to 'net/socket/tcp_client_socket_pool.cc')
-rw-r--r--net/socket/tcp_client_socket_pool.cc231
1 files changed, 231 insertions, 0 deletions
diff --git a/net/socket/tcp_client_socket_pool.cc b/net/socket/tcp_client_socket_pool.cc
new file mode 100644
index 0000000..3ea6700
--- /dev/null
+++ b/net/socket/tcp_client_socket_pool.cc
@@ -0,0 +1,231 @@
+// 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/socket/tcp_client_socket_pool.h"
+
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "base/string_util.h"
+#include "base/time.h"
+#include "net/base/load_log.h"
+#include "net/base/net_errors.h"
+#include "net/socket/client_socket_factory.h"
+#include "net/socket/client_socket_handle.h"
+#include "net/socket/client_socket_pool_base.h"
+#include "net/socket/tcp_client_socket.h"
+
+using base::TimeDelta;
+
+namespace net {
+
+// TCPConnectJobs will time out after this many seconds. Note this is the total
+// time, including both host resolution and TCP connect() times.
+//
+// TODO(eroman): The use of this constant needs to be re-evaluated. The time
+// needed for TCPClientSocketXXX::Connect() can be arbitrarily long, since
+// the address list may contain many alternatives, and most of those may
+// timeout. Even worse, the per-connect timeout threshold varies greatly
+// between systems (anywhere from 20 seconds to 190 seconds).
+// See comment #12 at http://crbug.com/23364 for specifics.
+static const int kTCPConnectJobTimeoutInSeconds = 240; // 4 minutes.
+
+TCPConnectJob::TCPConnectJob(
+ const std::string& group_name,
+ const HostResolver::RequestInfo& resolve_info,
+ base::TimeDelta timeout_duration,
+ ClientSocketFactory* client_socket_factory,
+ HostResolver* host_resolver,
+ Delegate* delegate,
+ LoadLog* load_log)
+ : ConnectJob(group_name, timeout_duration, delegate, load_log),
+ resolve_info_(resolve_info),
+ client_socket_factory_(client_socket_factory),
+ ALLOW_THIS_IN_INITIALIZER_LIST(
+ callback_(this,
+ &TCPConnectJob::OnIOComplete)),
+ resolver_(host_resolver) {}
+
+TCPConnectJob::~TCPConnectJob() {
+ // We don't worry about cancelling the host resolution and TCP connect, since
+ // ~SingleRequestHostResolver and ~ClientSocket will take care of it.
+}
+
+LoadState TCPConnectJob::GetLoadState() const {
+ switch (next_state_) {
+ case kStateResolveHost:
+ case kStateResolveHostComplete:
+ return LOAD_STATE_RESOLVING_HOST;
+ case kStateTCPConnect:
+ case kStateTCPConnectComplete:
+ return LOAD_STATE_CONNECTING;
+ default:
+ NOTREACHED();
+ return LOAD_STATE_IDLE;
+ }
+}
+
+int TCPConnectJob::ConnectInternal() {
+ next_state_ = kStateResolveHost;
+ start_time_ = base::TimeTicks::Now();
+ return DoLoop(OK);
+}
+
+void TCPConnectJob::OnIOComplete(int result) {
+ int rv = DoLoop(result);
+ if (rv != ERR_IO_PENDING)
+ NotifyDelegateOfCompletion(rv); // Deletes |this|
+}
+
+int TCPConnectJob::DoLoop(int result) {
+ DCHECK_NE(next_state_, kStateNone);
+
+ int rv = result;
+ do {
+ State state = next_state_;
+ next_state_ = kStateNone;
+ switch (state) {
+ case kStateResolveHost:
+ DCHECK_EQ(OK, rv);
+ rv = DoResolveHost();
+ break;
+ case kStateResolveHostComplete:
+ rv = DoResolveHostComplete(rv);
+ break;
+ case kStateTCPConnect:
+ DCHECK_EQ(OK, rv);
+ rv = DoTCPConnect();
+ break;
+ case kStateTCPConnectComplete:
+ rv = DoTCPConnectComplete(rv);
+ break;
+ default:
+ NOTREACHED();
+ rv = ERR_FAILED;
+ break;
+ }
+ } while (rv != ERR_IO_PENDING && next_state_ != kStateNone);
+
+ return rv;
+}
+
+int TCPConnectJob::DoResolveHost() {
+ next_state_ = kStateResolveHostComplete;
+ return resolver_.Resolve(resolve_info_, &addresses_, &callback_, load_log());
+}
+
+int TCPConnectJob::DoResolveHostComplete(int result) {
+ if (result == OK)
+ next_state_ = kStateTCPConnect;
+ return result;
+}
+
+int TCPConnectJob::DoTCPConnect() {
+ next_state_ = kStateTCPConnectComplete;
+ set_socket(client_socket_factory_->CreateTCPClientSocket(addresses_));
+ connect_start_time_ = base::TimeTicks::Now();
+ return socket()->Connect(&callback_, load_log());
+}
+
+int TCPConnectJob::DoTCPConnectComplete(int result) {
+ if (result == OK) {
+ DCHECK(connect_start_time_ != base::TimeTicks());
+ DCHECK(start_time_ != base::TimeTicks());
+ base::TimeTicks now = base::TimeTicks::Now();
+ base::TimeDelta total_duration = now - start_time_;
+ UMA_HISTOGRAM_CUSTOM_TIMES(
+ "Net.DNS_Resolution_And_TCP_Connection_Latency2",
+ total_duration,
+ base::TimeDelta::FromMilliseconds(1),
+ base::TimeDelta::FromMinutes(10),
+ 100);
+
+ base::TimeDelta connect_duration = now - connect_start_time_;
+ UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency",
+ connect_duration,
+ base::TimeDelta::FromMilliseconds(1),
+ base::TimeDelta::FromMinutes(10),
+ 100);
+ } else {
+ // Delete the socket on error.
+ set_socket(NULL);
+ }
+
+ return result;
+}
+
+ConnectJob* TCPClientSocketPool::TCPConnectJobFactory::NewConnectJob(
+ const std::string& group_name,
+ const PoolBase::Request& request,
+ ConnectJob::Delegate* delegate,
+ LoadLog* load_log) const {
+ return new TCPConnectJob(
+ group_name, request.params(),
+ base::TimeDelta::FromSeconds(kTCPConnectJobTimeoutInSeconds),
+ client_socket_factory_, host_resolver_, delegate, load_log);
+}
+
+TCPClientSocketPool::TCPClientSocketPool(
+ int max_sockets,
+ int max_sockets_per_group,
+ HostResolver* host_resolver,
+ ClientSocketFactory* client_socket_factory,
+ NetworkChangeNotifier* network_change_notifier)
+ : base_(max_sockets, max_sockets_per_group,
+ base::TimeDelta::FromSeconds(kUnusedIdleSocketTimeout),
+ base::TimeDelta::FromSeconds(kUsedIdleSocketTimeout),
+ new TCPConnectJobFactory(client_socket_factory, host_resolver),
+ network_change_notifier) {}
+
+TCPClientSocketPool::~TCPClientSocketPool() {}
+
+int TCPClientSocketPool::RequestSocket(
+ const std::string& group_name,
+ const void* resolve_info,
+ RequestPriority priority,
+ ClientSocketHandle* handle,
+ CompletionCallback* callback,
+ LoadLog* load_log) {
+ const HostResolver::RequestInfo* casted_resolve_info =
+ static_cast<const HostResolver::RequestInfo*>(resolve_info);
+
+ if (LoadLog::IsUnbounded(load_log)) {
+ LoadLog::AddString(
+ load_log,
+ StringPrintf("Requested TCP socket to: %s [port %d]",
+ casted_resolve_info->hostname().c_str(),
+ casted_resolve_info->port()));
+ }
+
+ return base_.RequestSocket(
+ group_name, *casted_resolve_info, priority, handle, callback, load_log);
+}
+
+void TCPClientSocketPool::CancelRequest(
+ const std::string& group_name,
+ const ClientSocketHandle* handle) {
+ base_.CancelRequest(group_name, handle);
+}
+
+void TCPClientSocketPool::ReleaseSocket(
+ const std::string& group_name,
+ ClientSocket* socket) {
+ base_.ReleaseSocket(group_name, socket);
+}
+
+void TCPClientSocketPool::CloseIdleSockets() {
+ base_.CloseIdleSockets();
+}
+
+int TCPClientSocketPool::IdleSocketCountInGroup(
+ const std::string& group_name) const {
+ return base_.IdleSocketCountInGroup(group_name);
+}
+
+LoadState TCPClientSocketPool::GetLoadState(
+ const std::string& group_name, const ClientSocketHandle* handle) const {
+ return base_.GetLoadState(group_name, handle);
+}
+
+} // namespace net