| 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
|
|
|
|
|