Index: net/socket/sctp_client_socket_pool.cc |
=================================================================== |
--- net/socket/sctp_client_socket_pool.cc (revision 0) |
+++ net/socket/sctp_client_socket_pool.cc (revision 0) |
@@ -0,0 +1,310 @@ |
+// Copyright (c) 2011 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/sctp_client_socket_pool.h" |
+ |
+#include "base/compiler_specific.h" |
+#include "base/logging.h" |
+#include "base/message_loop.h" |
+#include "base/metrics/histogram.h" |
+#include "base/string_util.h" |
+#include "base/time.h" |
+#include "net/base/net_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/sctp_client_socket.h" |
+ |
+using base::TimeDelta; |
+ |
+namespace net { |
+ |
+SCTPSocketParams::SCTPSocketParams(const HostPortPair& host_port_pair, |
+ RequestPriority priority, |
+ const GURL& referrer, |
+ bool disable_resolver_cache, |
+ bool ignore_limits) |
+ : destination_(host_port_pair), ignore_limits_(ignore_limits) { |
+ Initialize(priority, referrer, disable_resolver_cache); |
+} |
+ |
+SCTPSocketParams::~SCTPSocketParams() {} |
+ |
+void SCTPSocketParams::Initialize(RequestPriority priority, |
+ const GURL& referrer, |
+ bool disable_resolver_cache) { |
+ // The referrer is used by the DNS prefetch system to correlate resolutions |
+ // with the page that triggered them. It doesn't impact the actual addresses |
+ // that we resolve to. |
+ destination_.set_referrer(referrer); |
+ destination_.set_priority(priority); |
+ if (disable_resolver_cache) |
+ destination_.set_allow_cached_response(false); |
+} |
+ |
+// SCTPConnectJobs will time out after this many seconds. Note this is the |
+// total time, including both host resolution and SCTP connect() times. |
+// |
+// TODO(eroman): The use of this constant needs to be re-evaluated. The time |
+// needed for SCTPClientSocketXXX::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 kSCTPConnectJobTimeoutInSeconds = 240; // 4 minutes. |
+ |
+SCTPConnectJob::SCTPConnectJob( |
+ const std::string& group_name, |
+ const scoped_refptr<SCTPSocketParams>& params, |
+ base::TimeDelta timeout_duration, |
+ ClientSocketFactory* client_socket_factory, |
+ HostResolver* host_resolver, |
+ Delegate* delegate, |
+ NetLog* net_log) |
+ : ConnectJob(group_name, timeout_duration, delegate, |
+ BoundNetLog::Make(net_log, NetLog::SOURCE_CONNECT_JOB)), |
+ params_(params), |
+ client_socket_factory_(client_socket_factory), |
+ ALLOW_THIS_IN_INITIALIZER_LIST( |
+ callback_(this, |
+ &SCTPConnectJob::OnIOComplete)), |
+ resolver_(host_resolver) {} |
+ |
+SCTPConnectJob::~SCTPConnectJob() { |
+ // We don't worry about cancelling the host resolution and SCTP connect, since |
+ // ~SingleRequestHostResolver and ~ClientSocket will take care of it. |
+} |
+ |
+LoadState SCTPConnectJob::GetLoadState() const { |
+ switch (next_state_) { |
+ case STATE_RESOLVE_HOST: |
+ case STATE_RESOLVE_HOST_COMPLETE: |
+ return LOAD_STATE_RESOLVING_HOST; |
+ case STATE_SCTP_CONNECT: |
+ case STATE_SCTP_CONNECT_COMPLETE: |
+ return LOAD_STATE_CONNECTING; |
+ default: |
+ NOTREACHED(); |
+ return LOAD_STATE_IDLE; |
+ } |
+} |
+ |
+void SCTPConnectJob::OnIOComplete(int result) { |
+ int rv = DoLoop(result); |
+ if (rv != ERR_IO_PENDING) |
+ NotifyDelegateOfCompletion(rv); // Deletes |this| |
+} |
+ |
+int SCTPConnectJob::DoLoop(int result) { |
+ DCHECK_NE(next_state_, STATE_NONE); |
+ |
+ int rv = result; |
+ do { |
+ State state = next_state_; |
+ next_state_ = STATE_NONE; |
+ switch (state) { |
+ case STATE_RESOLVE_HOST: |
+ DCHECK_EQ(OK, rv); |
+ rv = DoResolveHost(); |
+ break; |
+ case STATE_RESOLVE_HOST_COMPLETE: |
+ rv = DoResolveHostComplete(rv); |
+ break; |
+ case STATE_SCTP_CONNECT: |
+ DCHECK_EQ(OK, rv); |
+ rv = DoSCTPConnect(); |
+ break; |
+ case STATE_SCTP_CONNECT_COMPLETE: |
+ rv = DoSCTPConnectComplete(rv); |
+ break; |
+ default: |
+ NOTREACHED(); |
+ rv = ERR_FAILED; |
+ break; |
+ } |
+ } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); |
+ |
+ return rv; |
+} |
+ |
+int SCTPConnectJob::DoResolveHost() { |
+ next_state_ = STATE_RESOLVE_HOST_COMPLETE; |
+ return resolver_.Resolve(params_->destination(), &addresses_, &callback_, |
+ net_log()); |
+} |
+ |
+int SCTPConnectJob::DoResolveHostComplete(int result) { |
+ if (result == OK) |
+ next_state_ = STATE_SCTP_CONNECT; |
+ return result; |
+} |
+ |
+int SCTPConnectJob::DoSCTPConnect() { |
+ next_state_ = STATE_SCTP_CONNECT_COMPLETE; |
+ set_socket(client_socket_factory_->CreateSCTPClientSocket( |
+ addresses_, net_log().net_log(), net_log().source())); |
+ connect_start_time_ = base::TimeTicks::Now(); |
+ return socket()->Connect(&callback_); |
+} |
+ |
+int SCTPConnectJob::DoSCTPConnectComplete(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_SCTP_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.SCTP_Connection_Latency", |
+ connect_duration, |
+ base::TimeDelta::FromMilliseconds(1), |
+ base::TimeDelta::FromMinutes(10), |
+ 100); |
+ } else { |
+ // Delete the socket on error. |
+ set_socket(NULL); |
+ } |
+ |
+ return result; |
+} |
+ |
+int SCTPConnectJob::ConnectInternal() { |
+ next_state_ = STATE_RESOLVE_HOST; |
+ start_time_ = base::TimeTicks::Now(); |
+ return DoLoop(OK); |
+} |
+ |
+ConnectJob* SCTPClientSocketPool::SCTPConnectJobFactory::NewConnectJob( |
+ const std::string& group_name, |
+ const PoolBase::Request& request, |
+ ConnectJob::Delegate* delegate) const { |
+ return new SCTPConnectJob(group_name, request.params(), ConnectionTimeout(), |
+ client_socket_factory_, host_resolver_, delegate, |
+ net_log_); |
+} |
+ |
+base::TimeDelta |
+ SCTPClientSocketPool::SCTPConnectJobFactory::ConnectionTimeout() const { |
+ return base::TimeDelta::FromSeconds(kSCTPConnectJobTimeoutInSeconds); |
+} |
+ |
+SCTPClientSocketPool::SCTPClientSocketPool( |
+ int max_sockets, |
+ int max_sockets_per_group, |
+ ClientSocketPoolHistograms* histograms, |
+ HostResolver* host_resolver, |
+ ClientSocketFactory* client_socket_factory, |
+ NetLog* net_log) |
+ : base_(max_sockets, max_sockets_per_group, histograms, |
+ base::TimeDelta::FromSeconds( |
+ ClientSocketPool::unused_idle_socket_timeout()), |
+ base::TimeDelta::FromSeconds(kUsedIdleSocketTimeout), |
+ new SCTPConnectJobFactory(client_socket_factory, |
+ host_resolver, net_log)) { |
+ base_.EnableConnectBackupJobs(); |
+} |
+ |
+SCTPClientSocketPool::~SCTPClientSocketPool() {} |
+ |
+int SCTPClientSocketPool::RequestSocket( |
+ const std::string& group_name, |
+ const void* params, |
+ RequestPriority priority, |
+ ClientSocketHandle* handle, |
+ CompletionCallback* callback, |
+ const BoundNetLog& net_log) { |
+ const scoped_refptr<SCTPSocketParams>* casted_params = |
+ static_cast<const scoped_refptr<SCTPSocketParams>*>(params); |
+ |
+ if (net_log.IsLoggingAllEvents()) { |
+ // TODO(eroman): Split out the host and port parameters. |
+ net_log.AddEvent( |
+ NetLog::TYPE_SCTP_CLIENT_SOCKET_POOL_REQUESTED_SOCKET, |
+ make_scoped_refptr(new NetLogStringParameter( |
+ "host_and_port", |
+ casted_params->get()->destination().host_port_pair().ToString()))); |
+ } |
+ |
+ return base_.RequestSocket(group_name, *casted_params, priority, handle, |
+ callback, net_log); |
+} |
+ |
+void SCTPClientSocketPool::RequestSockets( |
+ const std::string& group_name, |
+ const void* params, |
+ int num_sockets, |
+ const BoundNetLog& net_log) { |
+ const scoped_refptr<SCTPSocketParams>* casted_params = |
+ static_cast<const scoped_refptr<SCTPSocketParams>*>(params); |
+ |
+ if (net_log.IsLoggingAllEvents()) { |
+ // TODO(eroman): Split out the host and port parameters. |
+ net_log.AddEvent( |
+ NetLog::TYPE_SCTP_CLIENT_SOCKET_POOL_REQUESTED_SOCKETS, |
+ make_scoped_refptr(new NetLogStringParameter( |
+ "host_and_port", |
+ casted_params->get()->destination().host_port_pair().ToString()))); |
+ } |
+ |
+ base_.RequestSockets(group_name, *casted_params, num_sockets, net_log); |
+} |
+ |
+void SCTPClientSocketPool::CancelRequest( |
+ const std::string& group_name, |
+ ClientSocketHandle* handle) { |
+ base_.CancelRequest(group_name, handle); |
+} |
+ |
+void SCTPClientSocketPool::ReleaseSocket( |
+ const std::string& group_name, |
+ ClientSocket* socket, |
+ int id) { |
+ base_.ReleaseSocket(group_name, socket, id); |
+} |
+ |
+void SCTPClientSocketPool::Flush() { |
+ base_.Flush(); |
+} |
+ |
+void SCTPClientSocketPool::CloseIdleSockets() { |
+ base_.CloseIdleSockets(); |
+} |
+ |
+int SCTPClientSocketPool::IdleSocketCount() const { |
+ return base_.idle_socket_count(); |
+} |
+ |
+int SCTPClientSocketPool::IdleSocketCountInGroup( |
+ const std::string& group_name) const { |
+ return base_.IdleSocketCountInGroup(group_name); |
+} |
+ |
+LoadState SCTPClientSocketPool::GetLoadState( |
+ const std::string& group_name, const ClientSocketHandle* handle) const { |
+ return base_.GetLoadState(group_name, handle); |
+} |
+ |
+DictionaryValue* SCTPClientSocketPool::GetInfoAsValue( |
+ const std::string& name, |
+ const std::string& type, |
+ bool include_nested_pools) const { |
+ return base_.GetInfoAsValue(name, type); |
+} |
+ |
+base::TimeDelta SCTPClientSocketPool::ConnectionTimeout() const { |
+ return base_.ConnectionTimeout(); |
+} |
+ |
+ClientSocketPoolHistograms* SCTPClientSocketPool::histograms() const { |
+ return base_.histograms(); |
+} |
+ |
+} // namespace net |
Property changes on: net/socket/sctp_client_socket_pool.cc |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |