diff options
author | mmenke@chromium.org <mmenke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-19 21:08:33 +0000 |
---|---|---|
committer | mmenke@chromium.org <mmenke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-19 21:08:33 +0000 |
commit | ae8e80fcb776688c4d61787998f273c57e4e23ef (patch) | |
tree | 9e7bd1cd8b7b3cbe24c841619ccac8c4ef4de2aa /net/base | |
parent | 4ddb900984e74201a1923927f6a5bd4cbda3524e (diff) | |
download | chromium_src-ae8e80fcb776688c4d61787998f273c57e4e23ef.zip chromium_src-ae8e80fcb776688c4d61787998f273c57e4e23ef.tar.gz chromium_src-ae8e80fcb776688c4d61787998f273c57e4e23ef.tar.bz2 |
Add ipv6 probe events to NetLog, and add a button
to net-internals to re-run the probe.
R=eroman@chromium.org
BUG=132132
Review URL: https://chromiumcodereview.appspot.com/10766004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@147528 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/base')
-rw-r--r-- | net/base/host_resolver_impl.cc | 33 | ||||
-rw-r--r-- | net/base/net_log_event_type_list.h | 16 | ||||
-rw-r--r-- | net/base/net_log_source_type_list.h | 1 | ||||
-rw-r--r-- | net/base/net_util.cc | 120 | ||||
-rw-r--r-- | net/base/net_util.h | 33 |
5 files changed, 144 insertions, 59 deletions
diff --git a/net/base/host_resolver_impl.cc b/net/base/host_resolver_impl.cc index b8858ab..9ec0a37 100644 --- a/net/base/host_resolver_impl.cc +++ b/net/base/host_resolver_impl.cc @@ -961,9 +961,10 @@ class HostResolverImpl::ProcTask class HostResolverImpl::IPv6ProbeJob : public base::RefCountedThreadSafe<HostResolverImpl::IPv6ProbeJob> { public: - explicit IPv6ProbeJob(HostResolverImpl* resolver) + IPv6ProbeJob(HostResolverImpl* resolver, NetLog* net_log) : resolver_(resolver), - origin_loop_(base::MessageLoopProxy::current()) { + origin_loop_(base::MessageLoopProxy::current()), + net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_IPV6_PROBE_JOB)) { DCHECK(resolver); } @@ -971,6 +972,7 @@ class HostResolverImpl::IPv6ProbeJob DCHECK(origin_loop_->BelongsToCurrentThread()); if (was_canceled()) return; + net_log_.BeginEvent(NetLog::TYPE_IPV6_PROBE_RUNNING); const bool kIsSlow = true; base::WorkerPool::PostTask( FROM_HERE, base::Bind(&IPv6ProbeJob::DoProbe, this), kIsSlow); @@ -981,6 +983,7 @@ class HostResolverImpl::IPv6ProbeJob DCHECK(origin_loop_->BelongsToCurrentThread()); if (was_canceled()) return; + net_log_.AddEvent(NetLog::TYPE_CANCELLED); resolver_ = NULL; // Read/write ONLY on origin thread. } @@ -990,6 +993,8 @@ class HostResolverImpl::IPv6ProbeJob ~IPv6ProbeJob() { } + // Returns true if cancelled or if probe results have already been received + // on the origin thread. bool was_canceled() const { DCHECK(origin_loop_->BelongsToCurrentThread()); return !resolver_; @@ -998,20 +1003,28 @@ class HostResolverImpl::IPv6ProbeJob // Run on worker thread. void DoProbe() { // Do actual testing on this thread, as it takes 40-100ms. - AddressFamily family = IPv6Supported() ? ADDRESS_FAMILY_UNSPECIFIED - : ADDRESS_FAMILY_IPV4; - origin_loop_->PostTask( FROM_HERE, - base::Bind(&IPv6ProbeJob::OnProbeComplete, this, family)); + base::Bind(&IPv6ProbeJob::OnProbeComplete, this, TestIPv6Support())); } // Callback for when DoProbe() completes. - void OnProbeComplete(AddressFamily address_family) { + void OnProbeComplete(const IPv6SupportResult& support_result) { DCHECK(origin_loop_->BelongsToCurrentThread()); + net_log_.EndEvent( + NetLog::TYPE_IPV6_PROBE_RUNNING, + base::Bind(&IPv6SupportResult::ToNetLogValue, + base::Unretained(&support_result))); if (was_canceled()) return; - resolver_->IPv6ProbeSetDefaultAddressFamily(address_family); + + // Clear |resolver_| so that no cancel event is logged. + HostResolverImpl* resolver = resolver_; + resolver_ = NULL; + + resolver->IPv6ProbeSetDefaultAddressFamily( + support_result.ipv6_supported ? ADDRESS_FAMILY_UNSPECIFIED + : ADDRESS_FAMILY_IPV4); } // Used/set only on origin thread. @@ -1020,6 +1033,8 @@ class HostResolverImpl::IPv6ProbeJob // Used to post ourselves onto the origin thread. scoped_refptr<base::MessageLoopProxy> origin_loop_; + BoundNetLog net_log_; + DISALLOW_COPY_AND_ASSIGN(IPv6ProbeJob); }; @@ -1954,7 +1969,7 @@ void HostResolverImpl::OnIPAddressChanged() { cache_->clear(); if (ipv6_probe_monitoring_) { DiscardIPv6ProbeJob(); - ipv6_probe_job_ = new IPv6ProbeJob(this); + ipv6_probe_job_ = new IPv6ProbeJob(this, net_log_); ipv6_probe_job_->Start(); } #if defined(OS_POSIX) && !defined(OS_MACOSX) diff --git a/net/base/net_log_event_type_list.h b/net/base/net_log_event_type_list.h index 7ce2fa6..864ed7b 100644 --- a/net/base/net_log_event_type_list.h +++ b/net/base/net_log_event_type_list.h @@ -1669,3 +1669,19 @@ EVENT_TYPE(FILE_STREAM_CLOSE) // "net_error": <net::Error code>, // } EVENT_TYPE(FILE_STREAM_ERROR) + +// ------------------------------------------------------------------------ +// IPv6 Probe events. +// ------------------------------------------------------------------------ + +// This event lasts from the point an IPv6ProbeJob is created until completion. +// +// The END contains the following parameters: +// { +// "ipv6_supported": <Boolean indicating whether or not the probe determined +// IPv6 may be supported>, +// "ipv6_support_status": <String indicating the reason for that result>, +// "os_error": <Platform dependent error code, associated with the result, +// if any> +// } +EVENT_TYPE(IPV6_PROBE_RUNNING) diff --git a/net/base/net_log_source_type_list.h b/net/base/net_log_source_type_list.h index 810906b..68d0284 100644 --- a/net/base/net_log_source_type_list.h +++ b/net/base/net_log_source_type_list.h @@ -25,4 +25,5 @@ SOURCE_TYPE(CERT_VERIFIER_JOB) SOURCE_TYPE(HTTP_PIPELINED_CONNECTION) SOURCE_TYPE(DOWNLOAD) SOURCE_TYPE(FILESTREAM) +SOURCE_TYPE(IPV6_PROBE_JOB) diff --git a/net/base/net_util.cc b/net/base/net_util.cc index 1aa954c..56e779a 100644 --- a/net/base/net_util.cc +++ b/net/base/net_util.cc @@ -52,6 +52,7 @@ #include "base/time.h" #include "base/utf_offset_string_conversions.h" #include "base/utf_string_conversions.h" +#include "base/values.h" #include "googleurl/src/gurl.h" #include "googleurl/src/url_canon.h" #include "googleurl/src/url_canon_ip.h" @@ -1974,53 +1975,39 @@ ScopedPortException::~ScopedPortException() { namespace { -enum IPv6SupportStatus { - IPV6_CANNOT_CREATE_SOCKETS, - IPV6_CAN_CREATE_SOCKETS, - IPV6_GETIFADDRS_FAILED, - IPV6_GLOBAL_ADDRESS_MISSING, - IPV6_GLOBAL_ADDRESS_PRESENT, - IPV6_INTERFACE_ARRAY_TOO_SHORT, - IPV6_SUPPORT_MAX // Bounding values for enumeration. +const char* kFinalStatusNames[] = { + "Cannot create sockets", + "Can create sockets", + "Can't get addresses", + "Global ipv6 address missing", + "Global ipv6 address present", + "Interface array too short", + "Probing not supported", // IPV6_SUPPORT_MAX }; - -void IPv6SupportResults(IPv6SupportStatus result) { - static bool run_once = false; - if (!run_once) { - run_once = true; - UMA_HISTOGRAM_ENUMERATION("Net.IPv6Status", result, IPV6_SUPPORT_MAX); - } else { - UMA_HISTOGRAM_ENUMERATION("Net.IPv6Status_retest", result, - IPV6_SUPPORT_MAX); - } -} - -} // namespace +COMPILE_ASSERT(arraysize(kFinalStatusNames) == IPV6_SUPPORT_MAX + 1, + IPv6SupportStatus_name_count_mismatch); // TODO(jar): The following is a simple estimate of IPv6 support. We may need // to do a test resolution, and a test connection, to REALLY verify support. -// static -bool IPv6Supported() { +IPv6SupportResult TestIPv6SupportInternal() { #if defined(OS_ANDROID) // TODO: We should fully implement IPv6 probe once 'getifaddrs' API available; // Another approach is implementing the similar feature by // java.net.NetworkInterface through JNI. NOTIMPLEMENTED(); - return true; + return IPv6SupportResult(true, IPV6_SUPPORT_MAX, 0); #elif defined(OS_POSIX) int test_socket = socket(AF_INET6, SOCK_STREAM, 0); - if (test_socket == -1) { - IPv6SupportResults(IPV6_CANNOT_CREATE_SOCKETS); - return false; - } + if (test_socket == -1) + return IPv6SupportResult(false, IPV6_CANNOT_CREATE_SOCKETS, errno); close(test_socket); // Check to see if any interface has a IPv6 address. struct ifaddrs* interface_addr = NULL; int rv = getifaddrs(&interface_addr); if (rv != 0) { - IPv6SupportResults(IPV6_GETIFADDRS_FAILED); - return true; // Don't yet block IPv6. + // Don't yet block IPv6. + return IPv6SupportResult(true, IPV6_GETIFADDRS_FAILED, errno); } bool found_ipv6 = false; @@ -2046,19 +2033,17 @@ bool IPv6Supported() { break; } freeifaddrs(interface_addr); - if (!found_ipv6) { - IPv6SupportResults(IPV6_GLOBAL_ADDRESS_MISSING); - return false; - } + if (!found_ipv6) + return IPv6SupportResult(false, IPV6_GLOBAL_ADDRESS_MISSING, 0); - IPv6SupportResults(IPV6_GLOBAL_ADDRESS_PRESENT); - return true; + return IPv6SupportResult(true, IPV6_GLOBAL_ADDRESS_PRESENT, 0); #elif defined(OS_WIN) EnsureWinsockInit(); SOCKET test_socket = socket(AF_INET6, SOCK_STREAM, 0); if (test_socket == INVALID_SOCKET) { - IPv6SupportResults(IPV6_CANNOT_CREATE_SOCKETS); - return false; + return IPv6SupportResult(false, + IPV6_CANNOT_CREATE_SOCKETS, + WSAGetLastError()); } closesocket(test_socket); @@ -2081,13 +2066,11 @@ bool IPv6Supported() { NULL, adapters.get(), &adapters_size); num_tries++; } while (error == ERROR_BUFFER_OVERFLOW && num_tries <= 3); - if (error == ERROR_NO_DATA) { - IPv6SupportResults(IPV6_GLOBAL_ADDRESS_MISSING); - return false; - } + if (error == ERROR_NO_DATA) + return IPv6SupportResult(false, IPV6_GLOBAL_ADDRESS_MISSING, error); if (error != ERROR_SUCCESS) { - IPv6SupportResults(IPV6_GETIFADDRS_FAILED); - return true; // Don't yet block IPv6. + // Don't yet block IPv6. + return IPv6SupportResult(true, IPV6_GETIFADDRS_FAILED, error); } PIP_ADAPTER_ADDRESSES adapter; @@ -2108,19 +2091,58 @@ bool IPv6Supported() { struct in6_addr* sin6_addr = &addr_in6->sin6_addr; if (IN6_IS_ADDR_LOOPBACK(sin6_addr) || IN6_IS_ADDR_LINKLOCAL(sin6_addr)) continue; - IPv6SupportResults(IPV6_GLOBAL_ADDRESS_PRESENT); - return true; + return IPv6SupportResult(true, IPV6_GLOBAL_ADDRESS_PRESENT, 0); } } - IPv6SupportResults(IPV6_GLOBAL_ADDRESS_MISSING); - return false; + return IPv6SupportResult(false, IPV6_GLOBAL_ADDRESS_MISSING, 0); #else NOTIMPLEMENTED(); - return true; + return IPv6SupportResult(true, IPV6_SUPPORT_MAX, 0); #endif // defined(various platforms) } +} // namespace + +IPv6SupportResult::IPv6SupportResult(bool ipv6_supported, + IPv6SupportStatus ipv6_support_status, + int os_error) + : ipv6_supported(ipv6_supported), + ipv6_support_status(ipv6_support_status), + os_error(os_error) { +} + +base::Value* IPv6SupportResult::ToNetLogValue( + NetLog::LogLevel /* log_level */) const { + base::DictionaryValue* dict = new DictionaryValue(); + dict->SetBoolean("ipv6_supported", ipv6_supported); + dict->SetString("ipv6_support_status", + kFinalStatusNames[ipv6_support_status]); + if (os_error) + dict->SetInteger("os_error", os_error); + return dict; +} + +IPv6SupportResult TestIPv6Support() { + IPv6SupportResult result = TestIPv6SupportInternal(); + + // Record UMA. + if (result.ipv6_support_status != IPV6_SUPPORT_MAX) { + static bool run_once = false; + if (!run_once) { + run_once = true; + UMA_HISTOGRAM_ENUMERATION("Net.IPv6Status", + result.ipv6_support_status, + IPV6_SUPPORT_MAX); + } else { + UMA_HISTOGRAM_ENUMERATION("Net.IPv6Status_retest", + result.ipv6_support_status, + IPV6_SUPPORT_MAX); + } + } + return result; +} + bool HaveOnlyLoopbackAddresses() { #if defined(OS_ANDROID) return android::HaveOnlyLoopbackAddresses(); diff --git a/net/base/net_util.h b/net/base/net_util.h index 0b4ca64..69c9a97 100644 --- a/net/base/net_util.h +++ b/net/base/net_util.h @@ -24,6 +24,7 @@ #include "base/string16.h" #include "net/base/escape.h" #include "net/base/net_export.h" +#include "net/base/net_log.h" class FilePath; class GURL; @@ -362,10 +363,40 @@ class NET_EXPORT ScopedPortException { DISALLOW_COPY_AND_ASSIGN(ScopedPortException); }; +// These are used for UMA histograms. Any new values must be added to the end. +enum IPv6SupportStatus { + IPV6_CANNOT_CREATE_SOCKETS, + IPV6_CAN_CREATE_SOCKETS, // Obsolete + IPV6_GETIFADDRS_FAILED, + IPV6_GLOBAL_ADDRESS_MISSING, + IPV6_GLOBAL_ADDRESS_PRESENT, + IPV6_INTERFACE_ARRAY_TOO_SHORT, + IPV6_SUPPORT_MAX // Bounding value for enumeration. Also used for case + // where detection is not supported. +}; + +// Encapsulates the results of an IPv6 probe. +struct NET_EXPORT IPv6SupportResult { + IPv6SupportResult(bool ipv6_supported, + IPv6SupportStatus ipv6_support_status, + int os_error); + + // Serializes the results to a Value. Caller takes ownership of the returned + // Value. + base::Value* ToNetLogValue(NetLog::LogLevel log_level) const; + + bool ipv6_supported; + // Set to IPV6_SUPPORT_MAX if detection isn't supported. + IPv6SupportStatus ipv6_support_status; + + // Error code from the OS, or zero if there was no error. + int os_error; +}; + // Perform a simplistic test to see if IPv6 is supported by trying to create an // IPv6 socket. // TODO(jar): Make test more in-depth as needed. -NET_EXPORT bool IPv6Supported(); +NET_EXPORT IPv6SupportResult TestIPv6Support(); // Returns true if it can determine that only loopback addresses are configured. // i.e. if only 127.0.0.1 and ::1 are routable. |