Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(591)

Side by Side Diff: net/dns/dns_config_service_posix.cc

Issue 10873018: [net] Move DnsConfigService to NetworkChangeNotifier. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: more fixes for mac Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/dns/dns_config_service_posix.h" 5 #include "net/dns/dns_config_service_posix.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/basictypes.h" 9 #include "base/basictypes.h"
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/files/file_path_watcher.h"
11 #include "base/file_path.h" 12 #include "base/file_path.h"
12 #include "base/file_util.h" 13 #include "base/file_util.h"
13 #include "base/memory/scoped_ptr.h" 14 #include "base/memory/scoped_ptr.h"
14 #include "base/metrics/histogram.h" 15 #include "base/metrics/histogram.h"
15 #include "base/time.h" 16 #include "base/time.h"
16 #include "net/base/ip_endpoint.h" 17 #include "net/base/ip_endpoint.h"
17 #include "net/base/net_util.h" 18 #include "net/base/net_util.h"
18 #include "net/dns/dns_hosts.h" 19 #include "net/dns/dns_hosts.h"
19 #include "net/dns/dns_protocol.h" 20 #include "net/dns/dns_protocol.h"
21 #include "net/dns/notify_watcher_mac.h"
20 #include "net/dns/serial_worker.h" 22 #include "net/dns/serial_worker.h"
21 23
22 namespace net { 24 namespace net {
23 25
24 #if !defined(OS_ANDROID) 26 #if !defined(OS_ANDROID)
25 namespace internal { 27 namespace internal {
26 28
27 namespace { 29 namespace {
28 30
31 const FilePath::CharType* kFilePathHosts = FILE_PATH_LITERAL("/etc/hosts");
32
33 #if defined(OS_MACOSX)
34 // From 10.7.3 configd-395.10/dnsinfo/dnsinfo.h
35 static const char* kDnsNotifyKey =
36 "com.apple.system.SystemConfiguration.dns_configuration";
37
38 class ConfigWatcher {
39 public:
40 bool Watch(const base::Callback<void(bool succeeded)>& callback) {
41 return watcher_.Watch(kDnsNotifyKey, callback);
42 }
43
44 private:
45 NotifyWatcherMac watcher_;
46 };
47 #else
48
29 #ifndef _PATH_RESCONF // Normally defined in <resolv.h> 49 #ifndef _PATH_RESCONF // Normally defined in <resolv.h>
30 #define _PATH_RESCONF "/etc/resolv.conf" 50 #define _PATH_RESCONF "/etc/resolv.conf"
31 #endif 51 #endif
32 52
33 const FilePath::CharType* kFilePathHosts = FILE_PATH_LITERAL("/etc/hosts"); 53 static const FilePath::CharType* kFilePathConfig =
54 FILE_PATH_LITERAL(_PATH_RESCONF);
55
56 class ConfigWatcher {
57 public:
58 typedef base::Callback<void(bool succeeded)> CallbackType;
59
60 bool Watch(const CallbackType& callback) {
61 callback_ = callback;
62 return watcher_.Watch(FilePath(kFilePathConfig),
63 base::Bind(&ConfigWatcher::OnCallback,
64 base::Unretained(this)));
65 }
66
67 private:
68 void OnCallback(const FilePath& path, bool error) {
69 callback_.Run(!error);
70 }
71
72 base::files::FilePathWatcher watcher_;
73 CallbackType callback_;
74 };
75 #endif
34 76
35 ConfigParsePosixResult ReadDnsConfig(DnsConfig* config) { 77 ConfigParsePosixResult ReadDnsConfig(DnsConfig* config) {
36 ConfigParsePosixResult result; 78 ConfigParsePosixResult result;
37 #if defined(OS_OPENBSD) 79 #if defined(OS_OPENBSD)
38 // Note: res_ninit in glibc always returns 0 and sets RES_INIT. 80 // Note: res_ninit in glibc always returns 0 and sets RES_INIT.
39 // res_init behaves the same way. 81 // res_init behaves the same way.
40 memset(&_res, 0, sizeof(_res)); 82 memset(&_res, 0, sizeof(_res));
41 if (res_init() == 0) { 83 if (res_init() == 0) {
42 result = ConvertResStateToDnsConfig(_res, config); 84 result = ConvertResStateToDnsConfig(_res, config);
43 } else { 85 } else {
(...skipping 12 matching lines...) Expand all
56 res_ndestroy(&res); 98 res_ndestroy(&res);
57 #else 99 #else
58 res_nclose(&res); 100 res_nclose(&res);
59 #endif 101 #endif
60 #endif 102 #endif
61 // Override timeout value to match default setting on Windows. 103 // Override timeout value to match default setting on Windows.
62 config->timeout = base::TimeDelta::FromSeconds(kDnsTimeoutSeconds); 104 config->timeout = base::TimeDelta::FromSeconds(kDnsTimeoutSeconds);
63 return result; 105 return result;
64 } 106 }
65 107
108 } // namespace
109
110 class DnsConfigServicePosix::Watcher {
111 public:
112 explicit Watcher(DnsConfigServicePosix* service) : service_(service) {}
113 ~Watcher() {}
114
115 bool Watch() {
116 bool success = true;
117 if (!config_watcher_.Watch(
118 base::Bind(&DnsConfigServicePosix::OnConfigChanged,
119 base::Unretained(service_)))) {
120 LOG(ERROR) << "DNS config watch failed to start.";
121 success = false;
122 }
123 if (!hosts_watcher_.Watch(FilePath(kFilePathHosts),
124 base::Bind(&Watcher::OnHostsChanged,
125 base::Unretained(this)))) {
126 LOG(ERROR) << "DNS hosts watch failed to start.";
127 success = false;
128 }
129 return success;
130 }
131
132 private:
133 void OnHostsChanged(const FilePath& path, bool error) {
134 service_->OnHostsChanged(!error);
135 }
136
137 DnsConfigServicePosix* service_;
138 ConfigWatcher config_watcher_;
139 base::files::FilePathWatcher hosts_watcher_;
140
141 DISALLOW_COPY_AND_ASSIGN(Watcher);
142 };
143
66 // A SerialWorker that uses libresolv to initialize res_state and converts 144 // A SerialWorker that uses libresolv to initialize res_state and converts
67 // it to DnsConfig. 145 // it to DnsConfig.
68 class ConfigReader : public SerialWorker { 146 class DnsConfigServicePosix::ConfigReader : public SerialWorker {
69 public: 147 public:
70 typedef base::Callback<void(const DnsConfig& config)> CallbackType; 148 explicit ConfigReader(DnsConfigServicePosix* service)
71 explicit ConfigReader(const CallbackType& callback) 149 : service_(service), success_(false) {}
72 : callback_(callback), success_(false) {}
73 150
74 virtual void DoWork() OVERRIDE { 151 virtual void DoWork() OVERRIDE {
75 base::TimeTicks start_time = base::TimeTicks::Now(); 152 base::TimeTicks start_time = base::TimeTicks::Now();
76 ConfigParsePosixResult result = ReadDnsConfig(&dns_config_); 153 ConfigParsePosixResult result = ReadDnsConfig(&dns_config_);
77 success_ = (result == CONFIG_PARSE_POSIX_OK); 154 success_ = (result == CONFIG_PARSE_POSIX_OK);
78 UMA_HISTOGRAM_ENUMERATION("AsyncDNS.ConfigParsePosix", 155 UMA_HISTOGRAM_ENUMERATION("AsyncDNS.ConfigParsePosix",
79 result, CONFIG_PARSE_POSIX_MAX); 156 result, CONFIG_PARSE_POSIX_MAX);
80 UMA_HISTOGRAM_BOOLEAN("AsyncDNS.ConfigParseResult", success_); 157 UMA_HISTOGRAM_BOOLEAN("AsyncDNS.ConfigParseResult", success_);
81 UMA_HISTOGRAM_TIMES("AsyncDNS.ConfigParseDuration", 158 UMA_HISTOGRAM_TIMES("AsyncDNS.ConfigParseDuration",
82 base::TimeTicks::Now() - start_time); 159 base::TimeTicks::Now() - start_time);
83 } 160 }
84 161
85 virtual void OnWorkFinished() OVERRIDE { 162 virtual void OnWorkFinished() OVERRIDE {
86 DCHECK(!IsCancelled()); 163 DCHECK(!IsCancelled());
87 if (success_) { 164 if (success_) {
88 callback_.Run(dns_config_); 165 service_->OnConfigRead(dns_config_);
89 } else { 166 } else {
90 LOG(WARNING) << "Failed to read DnsConfig."; 167 LOG(WARNING) << "Failed to read DnsConfig.";
91 } 168 }
92 } 169 }
93 170
94 private: 171 private:
95 virtual ~ConfigReader() {} 172 virtual ~ConfigReader() {}
96 173
97 const CallbackType callback_; 174 DnsConfigServicePosix* service_;
98 // Written in DoWork, read in OnWorkFinished, no locking necessary. 175 // Written in DoWork, read in OnWorkFinished, no locking necessary.
99 DnsConfig dns_config_; 176 DnsConfig dns_config_;
100 bool success_; 177 bool success_;
101 178
102 DISALLOW_COPY_AND_ASSIGN(ConfigReader); 179 DISALLOW_COPY_AND_ASSIGN(ConfigReader);
103 }; 180 };
104 181
105 // A SerialWorker that reads the HOSTS file and runs Callback. 182 // A SerialWorker that reads the HOSTS file and runs Callback.
106 class HostsReader : public SerialWorker { 183 class DnsConfigServicePosix::HostsReader : public SerialWorker {
107 public: 184 public:
108 typedef base::Callback<void(const DnsHosts& hosts)> CallbackType; 185 explicit HostsReader(DnsConfigServicePosix* service)
109 explicit HostsReader(const CallbackType& callback) 186 : service_(service), path_(kFilePathHosts), success_(false) {}
110 : path_(kFilePathHosts), callback_(callback), success_(false) {}
111 187
112 private: 188 private:
113 virtual ~HostsReader() {} 189 virtual ~HostsReader() {}
114 190
115 virtual void DoWork() OVERRIDE { 191 virtual void DoWork() OVERRIDE {
116 base::TimeTicks start_time = base::TimeTicks::Now(); 192 base::TimeTicks start_time = base::TimeTicks::Now();
117 success_ = ParseHostsFile(path_, &hosts_); 193 success_ = ParseHostsFile(path_, &hosts_);
118 UMA_HISTOGRAM_BOOLEAN("AsyncDNS.HostParseResult", success_); 194 UMA_HISTOGRAM_BOOLEAN("AsyncDNS.HostParseResult", success_);
119 UMA_HISTOGRAM_TIMES("AsyncDNS.HostsParseDuration", 195 UMA_HISTOGRAM_TIMES("AsyncDNS.HostsParseDuration",
120 base::TimeTicks::Now() - start_time); 196 base::TimeTicks::Now() - start_time);
121 } 197 }
122 198
123 virtual void OnWorkFinished() OVERRIDE { 199 virtual void OnWorkFinished() OVERRIDE {
124 if (success_) { 200 if (success_) {
125 callback_.Run(hosts_); 201 service_->OnHostsRead(hosts_);
126 } else { 202 } else {
127 LOG(WARNING) << "Failed to read DnsHosts."; 203 LOG(WARNING) << "Failed to read DnsHosts.";
128 } 204 }
129 } 205 }
130 206
207 DnsConfigServicePosix* service_;
131 const FilePath path_; 208 const FilePath path_;
132 const CallbackType callback_; 209 const CallbackType callback_;
133 // Written in DoWork, read in OnWorkFinished, no locking necessary. 210 // Written in DoWork, read in OnWorkFinished, no locking necessary.
134 DnsHosts hosts_; 211 DnsHosts hosts_;
135 bool success_; 212 bool success_;
136 213
137 DISALLOW_COPY_AND_ASSIGN(HostsReader); 214 DISALLOW_COPY_AND_ASSIGN(HostsReader);
138 }; 215 };
139 216
140 } // namespace 217 DnsConfigServicePosix::DnsConfigServicePosix()
141 218 : watcher_(new Watcher(this)),
142 DnsConfigServicePosix::DnsConfigServicePosix() { 219 config_reader_(new ConfigReader(this)),
143 config_reader_ = new ConfigReader( 220 hosts_reader_(new HostsReader(this)) {}
144 base::Bind(&DnsConfigServicePosix::OnConfigRead,
145 base::Unretained(this)));
146 hosts_reader_ = new HostsReader(
147 base::Bind(&DnsConfigServicePosix::OnHostsRead,
148 base::Unretained(this)));
149 }
150 221
151 DnsConfigServicePosix::~DnsConfigServicePosix() { 222 DnsConfigServicePosix::~DnsConfigServicePosix() {
152 config_reader_->Cancel(); 223 config_reader_->Cancel();
153 hosts_reader_->Cancel(); 224 hosts_reader_->Cancel();
154 } 225 }
155 226
156 void DnsConfigServicePosix::OnDNSChanged(unsigned detail) { 227 void DnsConfigServicePosix::ReadNow() {
157 if (detail & NetworkChangeNotifier::CHANGE_DNS_WATCH_FAILED) { 228 config_reader_->WorkNow();
158 InvalidateConfig(); 229 hosts_reader_->WorkNow();
159 InvalidateHosts(); 230 }
160 // We don't trust a config that we cannot watch in the future. 231
232 bool DnsConfigServicePosix::StartWatching() {
233 // TODO(szym): re-start watcher if that makes sense. http://crbug.com/116139
234 return watcher_->Watch();
235 }
236
237 void DnsConfigServicePosix::OnConfigChanged(bool succeeded) {
238 InvalidateConfig();
239 if (succeeded) {
240 config_reader_->WorkNow();
241 } else {
242 LOG(ERROR) << "DNS config watch failed.";
243 // Don't trust the result if the watcher failed.
244 // Note: The SerialWorker will need to be re-constructed to accept new jobs.
161 config_reader_->Cancel(); 245 config_reader_->Cancel();
162 hosts_reader_->Cancel();
163 return;
164 }
165 if (detail & NetworkChangeNotifier::CHANGE_DNS_WATCH_STARTED)
166 detail = ~0; // Assume everything changed.
167 if (detail & NetworkChangeNotifier::CHANGE_DNS_SETTINGS) {
168 InvalidateConfig();
169 config_reader_->WorkNow();
170 }
171 if (detail & NetworkChangeNotifier::CHANGE_DNS_HOSTS) {
172 InvalidateHosts();
173 hosts_reader_->WorkNow();
174 } 246 }
175 } 247 }
176 248
249 void DnsConfigServicePosix::OnHostsChanged(bool succeeded) {
250 InvalidateHosts();
251 if (succeeded) {
252 hosts_reader_->WorkNow();
253 } else {
254 LOG(ERROR) << "DNS hosts watch failed.";
255 // Don't trust the result if the watcher failed.
256 // Note: The SerialWorker will need to be re-constructed to accept new jobs.
257 hosts_reader_->Cancel();
258 }
259 }
260
177 ConfigParsePosixResult ConvertResStateToDnsConfig(const struct __res_state& res, 261 ConfigParsePosixResult ConvertResStateToDnsConfig(const struct __res_state& res,
178 DnsConfig* dns_config) { 262 DnsConfig* dns_config) {
179 CHECK(dns_config != NULL); 263 CHECK(dns_config != NULL);
180 if (!(res.options & RES_INIT)) 264 if (!(res.options & RES_INIT))
181 return CONFIG_PARSE_POSIX_RES_INIT_UNSET; 265 return CONFIG_PARSE_POSIX_RES_INIT_UNSET;
182 266
183 dns_config->nameservers.clear(); 267 dns_config->nameservers.clear();
184 268
185 #if defined(OS_MACOSX) || defined(OS_FREEBSD) 269 #if defined(OS_MACOSX) || defined(OS_FREEBSD)
186 union res_sockaddr_union addresses[MAXNS]; 270 union res_sockaddr_union addresses[MAXNS];
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 scoped_ptr<DnsConfigService> DnsConfigService::CreateSystemService() { 360 scoped_ptr<DnsConfigService> DnsConfigService::CreateSystemService() {
277 return scoped_ptr<DnsConfigService>(new internal::DnsConfigServicePosix()); 361 return scoped_ptr<DnsConfigService>(new internal::DnsConfigServicePosix());
278 } 362 }
279 363
280 #else // defined(OS_ANDROID) 364 #else // defined(OS_ANDROID)
281 // Android NDK provides only a stub <resolv.h> header. 365 // Android NDK provides only a stub <resolv.h> header.
282 class StubDnsConfigService : public DnsConfigService { 366 class StubDnsConfigService : public DnsConfigService {
283 public: 367 public:
284 StubDnsConfigService() {} 368 StubDnsConfigService() {}
285 virtual ~StubDnsConfigService() {} 369 virtual ~StubDnsConfigService() {}
286 virtual void OnDNSChanged(unsigned detail) OVERRIDE {} 370 private:
371 virtual void ReadNow() OVERRIDE {}
372 virtual bool StartWatching() OVERRIDE { return false; }
287 }; 373 };
288 // static 374 // static
289 scoped_ptr<DnsConfigService> DnsConfigService::CreateSystemService() { 375 scoped_ptr<DnsConfigService> DnsConfigService::CreateSystemService() {
290 return scoped_ptr<DnsConfigService>(new StubDnsConfigService()); 376 return scoped_ptr<DnsConfigService>(new StubDnsConfigService());
291 } 377 }
292 #endif 378 #endif
293 379
294 } // namespace net 380 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698