Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(405)

Unified Diff: net/socket/transport_client_socket_pool.cc

Issue 7029049: Merge 84251, 85083, 85188, 85375. (Closed) Base URL: svn://svn.chromium.org/chrome/branches/742/src/
Patch Set: Upload before checkin Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/socket/transport_client_socket_pool.h ('k') | net/socket/transport_client_socket_pool_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/socket/transport_client_socket_pool.cc
===================================================================
--- net/socket/transport_client_socket_pool.cc (revision 85841)
+++ net/socket/transport_client_socket_pool.cc (working copy)
@@ -10,8 +10,10 @@
#include "base/metrics/histogram.h"
#include "base/string_util.h"
#include "base/time.h"
+#include "net/base/ip_endpoint.h"
#include "net/base/net_log.h"
#include "net/base/net_errors.h"
+#include "net/base/sys_addrinfo.h"
#include "net/socket/client_socket_factory.h"
#include "net/socket/client_socket_handle.h"
#include "net/socket/client_socket_pool_base.h"
@@ -21,10 +23,46 @@
namespace net {
-TransportSocketParams::TransportSocketParams(const HostPortPair& host_port_pair,
- RequestPriority priority, const GURL& referrer,
- bool disable_resolver_cache,
- bool ignore_limits)
+// TODO(willchan): Base this off RTT instead of statically setting it. Note we
+// choose a timeout that is different from the backup connect job timer so they
+// don't synchronize.
+const int TransportConnectJob::kIPv6FallbackTimerInMs = 300;
+
+namespace {
+
+bool AddressListStartsWithIPv6AndHasAnIPv4Addr(const AddressList& addrlist) {
+ const struct addrinfo* ai = addrlist.head();
+ if (ai->ai_family != AF_INET6)
+ return false;
+
+ ai = ai->ai_next;
+ while (ai) {
+ if (ai->ai_family != AF_INET6)
+ return true;
+ ai = ai->ai_next;
+ }
+
+ return false;
+}
+
+bool AddressListOnlyContainsIPv6Addresses(const AddressList& addrlist) {
+ DCHECK(addrlist.head());
+ for (const struct addrinfo* ai = addrlist.head(); ai; ai = ai->ai_next) {
+ if (ai->ai_family != AF_INET6)
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace
+
+TransportSocketParams::TransportSocketParams(
+ 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);
}
@@ -32,8 +70,8 @@
TransportSocketParams::~TransportSocketParams() {}
void TransportSocketParams::Initialize(RequestPriority priority,
- const GURL& referrer,
- bool disable_resolver_cache) {
+ 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.
@@ -69,7 +107,11 @@
ALLOW_THIS_IN_INITIALIZER_LIST(
callback_(this,
&TransportConnectJob::OnIOComplete)),
- resolver_(host_resolver) {}
+ resolver_(host_resolver),
+ ALLOW_THIS_IN_INITIALIZER_LIST(
+ fallback_callback_(
+ this,
+ &TransportConnectJob::DoIPv6FallbackTransportConnectComplete)) {}
TransportConnectJob::~TransportConnectJob() {
// We don't worry about cancelling the host resolution and TCP connect, since
@@ -90,6 +132,38 @@
}
}
+// static
+void TransportConnectJob::MakeAddrListStartWithIPv4(AddressList* addrlist) {
+ if (addrlist->head()->ai_family != AF_INET6)
+ return;
+ bool has_ipv4 = false;
+ for (const struct addrinfo* ai = addrlist->head(); ai; ai = ai->ai_next) {
+ if (ai->ai_family != AF_INET6) {
+ has_ipv4 = true;
+ break;
+ }
+ }
+ if (!has_ipv4)
+ return;
+
+ struct addrinfo* head = CreateCopyOfAddrinfo(addrlist->head(), true);
+ struct addrinfo* tail = head;
+ while (tail->ai_next)
+ tail = tail->ai_next;
+ char* canonname = head->ai_canonname;
+ head->ai_canonname = NULL;
+ while (head->ai_family == AF_INET6) {
+ tail->ai_next = head;
+ tail = head;
+ head = head->ai_next;
+ tail->ai_next = NULL;
+ }
+ head->ai_canonname = canonname;
+
+ addrlist->Copy(head, true);
+ FreeCopyOfAddrinfo(head);
+}
+
void TransportConnectJob::OnIOComplete(int result) {
int rv = DoLoop(result);
if (rv != ERR_IO_PENDING)
@@ -142,14 +216,22 @@
int TransportConnectJob::DoTransportConnect() {
next_state_ = STATE_TRANSPORT_CONNECT_COMPLETE;
- set_socket(client_socket_factory_->CreateTransportClientSocket(
+ transport_socket_.reset(client_socket_factory_->CreateTransportClientSocket(
addresses_, net_log().net_log(), net_log().source()));
connect_start_time_ = base::TimeTicks::Now();
- return socket()->Connect(&callback_);
+ int rv = transport_socket_->Connect(&callback_);
+ if (rv == ERR_IO_PENDING &&
+ AddressListStartsWithIPv6AndHasAnIPv4Addr(addresses_)) {
+ fallback_timer_.Start(
+ base::TimeDelta::FromMilliseconds(kIPv6FallbackTimerInMs),
+ this, &TransportConnectJob::DoIPv6FallbackTransportConnect);
+ }
+ return rv;
}
int TransportConnectJob::DoTransportConnectComplete(int result) {
if (result == OK) {
+ bool is_ipv4 = addresses_.head()->ai_family != AF_INET6;
DCHECK(connect_start_time_ != base::TimeTicks());
DCHECK(start_time_ != base::TimeTicks());
base::TimeTicks now = base::TimeTicks::Now();
@@ -167,14 +249,107 @@
base::TimeDelta::FromMilliseconds(1),
base::TimeDelta::FromMinutes(10),
100);
+
+ if (is_ipv4) {
+ UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv4_No_Race",
+ connect_duration,
+ base::TimeDelta::FromMilliseconds(1),
+ base::TimeDelta::FromMinutes(10),
+ 100);
+ } else {
+ if (AddressListOnlyContainsIPv6Addresses(addresses_)) {
+ UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv6_Solo",
+ connect_duration,
+ base::TimeDelta::FromMilliseconds(1),
+ base::TimeDelta::FromMinutes(10),
+ 100);
+ } else {
+ UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv6_Raceable",
+ connect_duration,
+ base::TimeDelta::FromMilliseconds(1),
+ base::TimeDelta::FromMinutes(10),
+ 100);
+ }
+ }
+ set_socket(transport_socket_.release());
+ fallback_timer_.Stop();
} else {
- // Delete the socket on error.
- set_socket(NULL);
+ // Be a bit paranoid and kill off the fallback members to prevent reuse.
+ fallback_transport_socket_.reset();
+ fallback_addresses_.reset();
}
return result;
}
+void TransportConnectJob::DoIPv6FallbackTransportConnect() {
+ // The timer should only fire while we're waiting for the main connect to
+ // succeed.
+ if (next_state_ != STATE_TRANSPORT_CONNECT_COMPLETE) {
+ NOTREACHED();
+ return;
+ }
+
+ DCHECK(!fallback_transport_socket_.get());
+ DCHECK(!fallback_addresses_.get());
+
+ fallback_addresses_.reset(new AddressList(addresses_));
+ MakeAddrListStartWithIPv4(fallback_addresses_.get());
+ fallback_transport_socket_.reset(
+ client_socket_factory_->CreateTransportClientSocket(
+ *fallback_addresses_, net_log().net_log(), net_log().source()));
+ fallback_connect_start_time_ = base::TimeTicks::Now();
+ int rv = fallback_transport_socket_->Connect(&fallback_callback_);
+ if (rv != ERR_IO_PENDING)
+ DoIPv6FallbackTransportConnectComplete(rv);
+}
+
+void TransportConnectJob::DoIPv6FallbackTransportConnectComplete(int result) {
+ // This should only happen when we're waiting for the main connect to succeed.
+ if (next_state_ != STATE_TRANSPORT_CONNECT_COMPLETE) {
+ NOTREACHED();
+ return;
+ }
+
+ DCHECK_NE(ERR_IO_PENDING, result);
+ DCHECK(fallback_transport_socket_.get());
+ DCHECK(fallback_addresses_.get());
+
+ if (result == OK) {
+ DCHECK(fallback_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 - fallback_connect_start_time_;
+ UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency",
+ connect_duration,
+ base::TimeDelta::FromMilliseconds(1),
+ base::TimeDelta::FromMinutes(10),
+ 100);
+
+ UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv4_Wins_Race",
+ connect_duration,
+ base::TimeDelta::FromMilliseconds(1),
+ base::TimeDelta::FromMinutes(10),
+ 100);
+ set_socket(fallback_transport_socket_.release());
+ next_state_ = STATE_NONE;
+ transport_socket_.reset();
+ } else {
+ // Be a bit paranoid and kill off the fallback members to prevent reuse.
+ fallback_transport_socket_.reset();
+ fallback_addresses_.reset();
+ }
+ NotifyDelegateOfCompletion(result); // Deletes |this|
+}
+
int TransportConnectJob::ConnectInternal() {
next_state_ = STATE_RESOLVE_HOST;
start_time_ = base::TimeTicks::Now();
« no previous file with comments | « net/socket/transport_client_socket_pool.h ('k') | net/socket/transport_client_socket_pool_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698