Index: chrome/browser/net/dns_probe_runner.cc |
diff --git a/chrome/browser/net/dns_probe_runner.cc b/chrome/browser/net/dns_probe_runner.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..dd6d977413faf53d1a474a42e673286e723d5864 |
--- /dev/null |
+++ b/chrome/browser/net/dns_probe_runner.cc |
@@ -0,0 +1,151 @@ |
+// Copyright (c) 2013 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 "chrome/browser/net/dns_probe_runner.h" |
+ |
+#include "base/bind.h" |
+#include "base/memory/scoped_ptr.h" |
mmenke
2013/06/11 16:15:35
This is included in header (As is bind, though I g
Deprecated (see juliatuttle)
2013/06/13 14:37:04
Done.
|
+#include "net/base/ip_endpoint.h" |
+#include "net/base/net_errors.h" |
+#include "net/base/net_log.h" |
+#include "net/base/net_util.h" |
+#include "net/base/network_change_notifier.h" |
+#include "net/dns/dns_client.h" |
+#include "net/dns/dns_config_service.h" |
+#include "net/dns/dns_protocol.h" |
+#include "net/dns/dns_response.h" |
+#include "net/dns/dns_transaction.h" |
+ |
+using base::TimeDelta; |
+using net::AddressList; |
+using net::BoundNetLog; |
+using net::DnsClient; |
+using net::DnsConfig; |
+using net::DnsResponse; |
+using net::DnsTransaction; |
+using net::IPAddressNumber; |
+using net::IPEndPoint; |
+using net::NetLog; |
+using net::NetworkChangeNotifier; |
+using net::ParseIPLiteralToNumber; |
+ |
+namespace { |
+ |
+// The public DNS servers used by the DnsProbeService to verify internet |
+// connectivity. |
+const char kPublicDnsPrimary[] = "8.8.8.8"; |
+const char kPublicDnsSecondary[] = "8.8.4.4"; |
+ |
+IPEndPoint MakeDnsEndPoint(const std::string& dns_ip_literal) { |
+ IPAddressNumber dns_ip_number; |
+ bool rv = ParseIPLiteralToNumber(dns_ip_literal, &dns_ip_number); |
+ DCHECK(rv); |
+ return IPEndPoint(dns_ip_number, net::dns_protocol::kDefaultPort); |
+} |
+ |
+// Returns true if the given net_error indicates that we received a response |
mmenke
2013/06/11 16:15:35
nit: |net_error| (References to arguments should
Deprecated (see juliatuttle)
2013/06/13 14:37:04
Done.
|
+// from the DNS server containing an error, or false if the given net_error |
+// indicates that we never received a response. |
+bool DidReceiveDnsResponse(int net_error) { |
+ switch (net_error) { |
+ case net::ERR_NAME_NOT_RESOLVED: // NXDOMAIN maps to this. |
+ case net::ERR_DNS_MALFORMED_RESPONSE: |
+ case net::ERR_DNS_SERVER_REQUIRES_TCP: |
mmenke
2013/06/11 16:15:35
Think it's worth noting that this shouldn't happen
Deprecated (see juliatuttle)
2013/06/13 14:37:04
Done.
|
+ case net::ERR_DNS_SERVER_FAILED: |
+ case net::ERR_DNS_SORT_ERROR: // Can only happen if the server responds. |
+ return true; |
mmenke
2013/06/11 16:15:35
completely optional nit: Just to make the behavio
Deprecated (see juliatuttle)
2013/06/13 14:37:04
Done.
|
+ default: |
+ return false; |
+ } |
+} |
+ |
+} // namespace |
+ |
+namespace chrome_browser_net { |
+ |
+DnsProbeRunner::DnsProbeRunner() |
+ : weak_factory_(this), |
+ bound_net_log_(BoundNetLog::Make(NULL, NetLog::SOURCE_DNS_PROBER)) { |
mmenke
2013/06/11 16:15:35
Per other comment, not needed.
Deprecated (see juliatuttle)
2013/06/13 14:37:04
Done.
|
+} |
+ |
+DnsProbeRunner::~DnsProbeRunner() {} |
+ |
+void DnsProbeRunner::RunProbe(const ProbeCallback& callback) { |
+ DCHECK(client_.get()); |
+ DCHECK(!is_running()); |
+ DCHECK(!callback.is_null()); |
+ |
+ callback_ = callback; |
+ transaction_ = client_->GetTransactionFactory()->CreateTransaction( |
+ "google.com", |
mmenke
2013/06/11 16:15:35
Suggest putting this up top, with the public DNS I
Deprecated (see juliatuttle)
2013/06/13 14:37:04
Done.
|
+ net::dns_protocol::kTypeA, |
+ base::Bind(&DnsProbeRunner::OnTransactionComplete, |
+ weak_factory_.GetWeakPtr(), |
+ true /* async */), |
+ bound_net_log_); |
mmenke
2013/06/11 16:15:35
BoundNetLog()
Deprecated (see juliatuttle)
2013/06/13 14:37:04
Done.
|
+ |
+ int rv = transaction_->Start(); |
+ if (rv != net::ERR_IO_PENDING) { |
+ OnTransactionComplete(false /* not async */, |
+ transaction_.get(), |
+ rv, |
+ NULL); |
+ } |
+} |
+ |
+void DnsProbeRunner::set_client(scoped_ptr<net::DnsClient> client) { |
+ client_ = client.Pass(); |
+} |
+ |
+bool DnsProbeRunner::is_running() const { |
+ return transaction_.get(); |
+} |
+ |
+void DnsProbeRunner::OnTransactionComplete( |
+ bool async, |
+ DnsTransaction* transaction, |
+ int net_error, |
+ const DnsResponse* response) { |
+ DCHECK(is_running()); |
+ DCHECK_EQ(transaction_.get(), transaction); |
+ |
+ const Result result = EvaluateResponse(async, net_error, response); |
+ transaction_.reset(); |
+ callback_.Run(result); |
+ callback_ = ProbeCallback(); |
mmenke
2013/06/11 16:15:35
To avoid the possibility of any re-entrancy issues
Deprecated (see juliatuttle)
2013/06/13 14:37:04
Done.
|
+} |
+ |
+// static |
+DnsProbeRunner::Result DnsProbeRunner::EvaluateResponse( |
+ bool async, |
+ int net_error, |
+ const DnsResponse* response) { |
+ if (!async) { |
mmenke
2013/06/11 16:15:35
Do we need this case / parameter? Seems like we'd
Deprecated (see juliatuttle)
2013/06/13 14:37:04
I like having it explicit, but I'll drop it if you
mmenke
2013/06/13 15:00:12
I believe it's technically possible to get a sync
szym
2013/06/13 15:10:18
Actually, DnsTransaction can never complete synchr
mmenke
2013/06/13 15:42:12
Thanks! Hmm...That was added to fix a crasher whe
szym
2013/06/13 15:44:44
I'd like to say that it was by design, but yes, it
|
+ return UNREACHABLE; |
+ } |
+ |
+ if (net_error != net::OK) { |
+ if (DidReceiveDnsResponse(net_error)) { |
+ return FAILING; |
+ } else { |
+ return UNREACHABLE; |
+ } |
+ } |
+ |
+ AddressList addr_list; |
+ TimeDelta ttl; |
+ DnsResponse::Result result = response->ParseToAddressList(&addr_list, &ttl); |
+ |
+ if (result != DnsResponse::DNS_PARSE_OK) { |
+ return FAILING; |
+ } |
+ |
+ if (addr_list.empty()) { |
+ return INCORRECT; |
+ } |
+ |
+ return CORRECT; |
+} |
+ |
+} // namespace chrome_browser_net |