OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 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. | |
4 | |
5 #include "chrome/browser/net/dns_probe_runner.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/memory/scoped_ptr.h" | |
9 #include "net/base/ip_endpoint.h" | |
10 #include "net/base/net_errors.h" | |
11 #include "net/base/net_log.h" | |
12 #include "net/base/net_util.h" | |
13 #include "net/base/network_change_notifier.h" | |
14 #include "net/dns/dns_client.h" | |
15 #include "net/dns/dns_config_service.h" | |
16 #include "net/dns/dns_protocol.h" | |
17 #include "net/dns/dns_response.h" | |
18 #include "net/dns/dns_transaction.h" | |
19 | |
20 using base::TimeDelta; | |
21 using net::AddressList; | |
22 using net::BoundNetLog; | |
23 using net::DnsClient; | |
24 using net::DnsConfig; | |
25 using net::DnsResponse; | |
26 using net::DnsTransaction; | |
27 using net::IPAddressNumber; | |
28 using net::IPEndPoint; | |
29 using net::NetLog; | |
30 using net::NetworkChangeNotifier; | |
31 using net::ParseIPLiteralToNumber; | |
32 | |
33 namespace { | |
34 | |
35 // The public DNS servers used by the DnsProbeService to verify internet | |
36 // connectivity. | |
37 const char kPublicDnsPrimary[] = "8.8.8.8"; | |
38 const char kPublicDnsSecondary[] = "8.8.4.4"; | |
39 | |
40 IPEndPoint MakeDnsEndPoint(const std::string& dns_ip_literal) { | |
41 IPAddressNumber dns_ip_number; | |
42 bool rv = ParseIPLiteralToNumber(dns_ip_literal, &dns_ip_number); | |
43 DCHECK(rv); | |
44 return IPEndPoint(dns_ip_number, net::dns_protocol::kDefaultPort); | |
45 } | |
46 | |
47 // Returns true if the given net_error indicates that we received a response | |
48 // from the DNS server containing an error, or false if the given net_error | |
49 // indicates that we never received a response. | |
50 bool DidReceiveDnsResponse(int net_error) { | |
51 switch (net_error) { | |
52 case net::ERR_NAME_NOT_RESOLVED: // NXDOMAIN maps to this. | |
53 case net::ERR_DNS_MALFORMED_RESPONSE: | |
54 case net::ERR_DNS_SERVER_REQUIRES_TCP: | |
55 case net::ERR_DNS_SERVER_FAILED: | |
56 case net::ERR_DNS_SORT_ERROR: // Can only happen if the server responds. | |
57 return true; | |
58 default: | |
59 return false; | |
60 } | |
61 } | |
62 | |
63 } // namespace | |
64 | |
65 DnsProbeRunner::ProbeInfo::ProbeInfo( | |
66 DnsProbeRunner::Type type, | |
67 const DnsProbeRunner::ProbeCallback& callback) | |
68 : type(type), | |
69 callback(callback) {} | |
70 | |
71 DnsProbeRunner::ProbeInfo::~ProbeInfo() {} | |
72 | |
73 DnsProbeRunner::DnsProbeRunner() | |
74 : weak_factory_(this), | |
75 bound_net_log_(BoundNetLog::Make(NULL, NetLog::SOURCE_DNS_PROBER)), | |
76 mock_mode_(DnsProbeRunner::NO_MOCK) { | |
77 NetworkChangeNotifier::AddDNSObserver(this); | |
78 InitializeSystemClient(); | |
79 InitializePublicClient(); | |
80 } | |
81 | |
82 DnsProbeRunner::~DnsProbeRunner() { | |
83 NetworkChangeNotifier::RemoveDNSObserver(this); | |
84 for (TransactionMap::iterator it = pending_transactions_.begin(); | |
85 it != pending_transactions_.end(); ++it) { | |
86 delete it->first; | |
87 } | |
88 } | |
89 | |
90 void DnsProbeRunner::OnDNSChanged() { | |
91 InitializeSystemClient(); | |
szym
2013/06/07 19:31:28
Note that this does not affect any pending transac
Deprecated (see juliatuttle)
2013/06/11 01:07:34
That's okay; error pages can be obsolete for other
| |
92 } | |
93 | |
94 void DnsProbeRunner::RunProbe(Type type, | |
95 const ProbeCallback& callback) { | |
96 if (mock_mode_ == MOCK_RESULTS) { | |
97 callback.Run(type, GetMockResult(type)); | |
98 return; | |
99 } | |
100 | |
101 DnsTransaction* transaction = | |
102 GetClient(type)->GetTransactionFactory()->CreateTransaction( | |
103 "google.com", | |
104 net::dns_protocol::kTypeA, | |
105 base::Bind(&DnsProbeRunner::OnTransactionComplete, | |
106 weak_factory_.GetWeakPtr(), | |
107 true /* async */), | |
108 bound_net_log_).release(); | |
109 | |
110 pending_transactions_.insert(std::pair<DnsTransaction*,ProbeInfo>( | |
111 transaction, | |
112 ProbeInfo(type, callback))); | |
szym
2013/06/07 19:31:28
Instead bind ProbeInfo as an argument to OnTransac
Deprecated (see juliatuttle)
2013/06/11 01:07:34
Obsolete.
| |
113 | |
114 int rv = transaction->Start(); | |
115 if (rv != net::ERR_IO_PENDING) { | |
116 OnTransactionComplete(false /* not async */, | |
117 transaction, | |
118 rv, | |
119 NULL); | |
120 } | |
121 } | |
122 | |
123 void DnsProbeRunner::SetClientsForTesting( | |
124 scoped_ptr<DnsClient> mock_system_client, | |
125 scoped_ptr<DnsClient> mock_public_client) { | |
126 DCHECK_EQ(NO_MOCK, mock_mode_); | |
127 DCHECK(mock_system_client.get()); | |
128 DCHECK(mock_public_client.get()); | |
129 | |
130 mock_mode_ = MOCK_CLIENTS; | |
131 mock_system_client_ = mock_system_client.Pass(); | |
132 mock_public_client_ = mock_public_client.Pass(); | |
133 } | |
134 | |
135 void DnsProbeRunner::SetResultsForTesting( | |
136 Result system_result, | |
137 Result public_result) { | |
138 mock_mode_ = MOCK_RESULTS; | |
139 mock_system_result_ = system_result; | |
140 mock_public_result_ = public_result; | |
141 mock_system_client_.reset(); | |
142 mock_public_client_.reset(); | |
143 } | |
144 | |
145 void DnsProbeRunner::InitializeSystemClient() { | |
146 DnsConfig config; | |
147 NetworkChangeNotifier::GetDnsConfig(&config); | |
148 config.search.clear(); | |
149 config.attempts = 1; | |
150 config.randomize_ports = false; | |
151 | |
152 scoped_ptr<DnsClient> client = DnsClient::CreateClient(NULL); | |
153 client->SetConfig(config); | |
154 | |
155 system_client_ = client.Pass(); | |
156 } | |
157 | |
158 void DnsProbeRunner::InitializePublicClient() { | |
159 DnsConfig config; | |
160 config.nameservers.push_back(MakeDnsEndPoint(kPublicDnsPrimary)); | |
161 config.nameservers.push_back(MakeDnsEndPoint(kPublicDnsSecondary)); | |
162 config.search.clear(); | |
163 config.attempts = 1; | |
164 config.randomize_ports = false; | |
165 | |
166 scoped_ptr<DnsClient> client = DnsClient::CreateClient(NULL); | |
167 client->SetConfig(config); | |
168 | |
169 public_client_ = client.Pass(); | |
170 } | |
171 | |
172 DnsProbeRunner::Result DnsProbeRunner::GetMockResult(Type type) { | |
173 DCHECK_EQ(MOCK_RESULTS, mock_mode_); | |
174 | |
175 switch (type) { | |
176 case SYSTEM: | |
177 return mock_system_result_; | |
178 case PUBLIC: | |
179 return mock_public_result_; | |
180 } | |
181 | |
182 NOTREACHED(); | |
183 return UNKNOWN; | |
184 } | |
185 | |
186 DnsClient* DnsProbeRunner::GetClient(Type type) { | |
187 DCHECK_NE(MOCK_RESULTS, mock_mode_); | |
188 | |
189 switch (mock_mode_) { | |
190 case NO_MOCK: | |
191 switch (type) { | |
192 case SYSTEM: | |
193 return system_client_.get(); | |
194 case PUBLIC: | |
195 return public_client_.get(); | |
196 } | |
197 case MOCK_CLIENTS: | |
198 switch (type) { | |
199 case SYSTEM: | |
200 return mock_system_client_.get(); | |
201 case PUBLIC: | |
202 return mock_public_client_.get(); | |
203 } | |
204 case MOCK_RESULTS: | |
205 NOTREACHED(); | |
206 return NULL; | |
207 } | |
208 | |
209 NOTREACHED(); | |
210 return NULL; | |
211 } | |
212 | |
213 void DnsProbeRunner::OnTransactionComplete( | |
214 bool async, | |
215 DnsTransaction* transaction, | |
216 int net_error, | |
217 const DnsResponse* response) { | |
218 TransactionMap::iterator it = pending_transactions_.find(transaction); | |
219 // I'd use DCHECK_NE, but it doesn't know how to print iterators. | |
220 DCHECK(it != pending_transactions_.end()); | |
221 | |
222 const ProbeInfo& info = it->second; | |
223 const Result result = EvaluateResponse(async, net_error, response); | |
224 info.callback.Run(info.type, result); | |
225 | |
226 pending_transactions_.erase(it); | |
227 } | |
228 | |
229 DnsProbeRunner::Result DnsProbeRunner::EvaluateResponse( | |
230 bool async, | |
231 int net_error, | |
232 const DnsResponse* response) { | |
233 if (!async) { | |
szym
2013/06/07 19:31:28
I'm not sure you need this. The net_error returned
Deprecated (see juliatuttle)
2013/06/11 01:07:34
I don't *need* it, but I want to be explicit about
| |
234 return UNREACHABLE; | |
235 } | |
236 | |
237 if (net_error != net::OK) { | |
238 if (DidReceiveDnsResponse(net_error)) { | |
239 return FAILING; | |
240 } else { | |
241 return UNREACHABLE; | |
242 } | |
243 } | |
244 | |
245 AddressList addr_list; | |
246 TimeDelta ttl; | |
247 DnsResponse::Result result = response->ParseToAddressList(&addr_list, &ttl); | |
248 | |
249 if (result != DnsResponse::DNS_PARSE_OK) { | |
250 return FAILING; | |
251 } | |
252 | |
253 if (addr_list.empty()) { | |
254 return INCORRECT; | |
255 } | |
256 | |
257 return CORRECT; | |
258 } | |
OLD | NEW |