1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/net/dns_probe_runner.h"
8 #include "content/public/browser/browser_thread.h"
9 #include "net/base/address_list.h"
10 #include "net/base/ip_endpoint.h"
11 #include "net/base/net_errors.h"
12 #include "net/base/net_log.h"
13 #include "net/base/net_util.h"
14 #include "net/base/network_change_notifier.h"
15 #include "net/dns/dns_client.h"
16 #include "net/dns/dns_protocol.h"
17 #include "net/dns/dns_response.h"
18 #include "net/dns/dns_transaction.h"
20 using base::TimeDelta
;
21 using content::BrowserThread
;
22 using net::AddressList
;
23 using net::BoundNetLog
;
25 using net::DnsResponse
;
26 using net::DnsTransaction
;
27 using net::DnsTransactionFactory
;
28 using net::IPAddressNumber
;
29 using net::IPEndPoint
;
31 using net::NetworkChangeNotifier
;
32 using net::ParseIPLiteralToNumber
;
34 namespace chrome_browser_net
{
36 const char* DnsProbeRunner::kKnownGoodHostname
= "google.com";
40 DnsProbeRunner::Result
EvaluateResponse(
42 const DnsResponse
* response
) {
47 // ERR_NAME_NOT_RESOLVED maps to NXDOMAIN, which means the server is working
48 // but returned a wrong answer.
49 case net::ERR_NAME_NOT_RESOLVED
:
50 return DnsProbeRunner::INCORRECT
;
52 // These results mean we heard *something* from the DNS server, but it was
53 // unsuccessful (SERVFAIL) or malformed.
54 case net::ERR_DNS_MALFORMED_RESPONSE
:
55 case net::ERR_DNS_SERVER_REQUIRES_TCP
: // Shouldn't happen; DnsTransaction
56 // will retry with TCP.
57 case net::ERR_DNS_SERVER_FAILED
:
58 case net::ERR_DNS_SORT_ERROR
: // Can only happen if the server responds.
59 return DnsProbeRunner::FAILING
;
61 // Any other error means we never reached the DNS server in the first place.
62 case net::ERR_DNS_TIMED_OUT
:
64 // Something else happened, probably at a network level.
65 return DnsProbeRunner::UNREACHABLE
;
68 AddressList addr_list
;
70 DnsResponse::Result result
= response
->ParseToAddressList(&addr_list
, &ttl
);
72 if (result
!= DnsResponse::DNS_PARSE_OK
)
73 return DnsProbeRunner::FAILING
;
74 else if (addr_list
.empty())
75 return DnsProbeRunner::INCORRECT
;
77 return DnsProbeRunner::CORRECT
;
82 DnsProbeRunner::DnsProbeRunner() : result_(UNKNOWN
), weak_factory_(this) {}
84 DnsProbeRunner::~DnsProbeRunner() {}
86 void DnsProbeRunner::SetClient(scoped_ptr
<net::DnsClient
> client
) {
87 client_
= client
.Pass();
90 void DnsProbeRunner::RunProbe(const base::Closure
& callback
) {
91 DCHECK(!callback
.is_null());
92 DCHECK(client_
.get());
93 DCHECK(callback_
.is_null());
94 DCHECK(!transaction_
.get());
97 DnsTransactionFactory
* factory
= client_
->GetTransactionFactory();
99 // If the DnsTransactionFactory is NULL, then the DnsConfig is invalid, so
100 // the runner can't run a transaction. Return UNKNOWN asynchronously.
102 BrowserThread::PostTask(
105 base::Bind(&DnsProbeRunner::CallCallback
,
106 weak_factory_
.GetWeakPtr()));
110 transaction_
= factory
->CreateTransaction(
112 net::dns_protocol::kTypeA
,
113 base::Bind(&DnsProbeRunner::OnTransactionComplete
,
114 weak_factory_
.GetWeakPtr()),
117 transaction_
->Start();
120 bool DnsProbeRunner::IsRunning() const {
121 return !callback_
.is_null();
124 void DnsProbeRunner::OnTransactionComplete(
125 DnsTransaction
* transaction
,
127 const DnsResponse
* response
) {
128 DCHECK(!callback_
.is_null());
129 DCHECK(transaction_
.get());
130 DCHECK_EQ(transaction_
.get(), transaction
);
132 result_
= EvaluateResponse(net_error
, response
);
133 transaction_
.reset();
135 BrowserThread::PostTask(
138 base::Bind(&DnsProbeRunner::CallCallback
,
139 weak_factory_
.GetWeakPtr()));
142 void DnsProbeRunner::CallCallback() {
143 DCHECK(!callback_
.is_null());
144 DCHECK(!transaction_
.get());
146 // Clear callback in case it starts a new probe immediately.
147 const base::Closure callback
= callback_
;
152 } // namespace chrome_browser_net