summaryrefslogtreecommitdiffstats
path: root/net/base
diff options
context:
space:
mode:
authormmenke@chromium.org <mmenke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-19 21:08:33 +0000
committermmenke@chromium.org <mmenke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-19 21:08:33 +0000
commitae8e80fcb776688c4d61787998f273c57e4e23ef (patch)
tree9e7bd1cd8b7b3cbe24c841619ccac8c4ef4de2aa /net/base
parent4ddb900984e74201a1923927f6a5bd4cbda3524e (diff)
downloadchromium_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.cc33
-rw-r--r--net/base/net_log_event_type_list.h16
-rw-r--r--net/base/net_log_source_type_list.h1
-rw-r--r--net/base/net_util.cc120
-rw-r--r--net/base/net_util.h33
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.