OLD | NEW |
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/file_path.h" | 11 #include "base/file_path.h" |
12 #include "base/file_util.h" | 12 #include "base/file_util.h" |
13 #include "base/memory/scoped_ptr.h" | 13 #include "base/memory/scoped_ptr.h" |
14 #include "net/base/ip_endpoint.h" | 14 #include "net/base/ip_endpoint.h" |
15 #include "net/base/net_util.h" | 15 #include "net/base/net_util.h" |
16 #include "net/dns/file_path_watcher_wrapper.h" | 16 #include "net/dns/file_path_watcher_wrapper.h" |
17 #include "net/dns/serial_worker.h" | 17 #include "net/dns/serial_worker.h" |
18 | 18 |
19 #if defined(OS_MACOSX) | 19 namespace net { |
20 #include "net/dns/notify_watcher_mac.h" | 20 |
21 #endif | 21 namespace { |
22 | 22 |
23 #ifndef _PATH_RESCONF // Normally defined in <resolv.h> | 23 #ifndef _PATH_RESCONF // Normally defined in <resolv.h> |
24 #define _PATH_RESCONF "/etc/resolv.conf" | 24 #define _PATH_RESCONF "/etc/resolv.conf" |
25 #endif | 25 #endif |
26 | 26 |
27 namespace net { | |
28 | |
29 namespace { | |
30 | |
31 const FilePath::CharType* kFilePathHosts = FILE_PATH_LITERAL("/etc/hosts"); | 27 const FilePath::CharType* kFilePathHosts = FILE_PATH_LITERAL("/etc/hosts"); |
32 | 28 |
33 // A SerialWorker that uses libresolv to initialize res_state and converts | 29 // A SerialWorker that uses libresolv to initialize res_state and converts |
34 // it to DnsConfig. | 30 // it to DnsConfig. |
35 class ConfigReader : public SerialWorker { | 31 class ConfigReader : public SerialWorker { |
36 public: | 32 public: |
37 typedef base::Callback<void(const DnsConfig& config)> CallbackType; | 33 typedef base::Callback<void(const DnsConfig& config)> CallbackType; |
38 explicit ConfigReader(const CallbackType& callback) | 34 explicit ConfigReader(const CallbackType& callback) |
39 : callback_(callback), | 35 : callback_(callback), |
40 success_(false) {} | 36 success_(false) {} |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
78 CallbackType callback_; | 74 CallbackType callback_; |
79 // Written in DoWork, read in OnWorkFinished, no locking necessary. | 75 // Written in DoWork, read in OnWorkFinished, no locking necessary. |
80 DnsConfig dns_config_; | 76 DnsConfig dns_config_; |
81 bool success_; | 77 bool success_; |
82 }; | 78 }; |
83 | 79 |
84 } // namespace | 80 } // namespace |
85 | 81 |
86 namespace internal { | 82 namespace internal { |
87 | 83 |
88 #if defined(OS_MACOSX) | 84 DnsConfigServicePosix::DnsConfigServicePosix() { |
89 // From 10.7.3 configd-395.10/dnsinfo/dnsinfo.h | |
90 static const char* kDnsNotifyKey = | |
91 "com.apple.system.SystemConfiguration.dns_configuration"; | |
92 | |
93 class DnsConfigServicePosix::ConfigWatcher : public NotifyWatcherMac { | |
94 public: | |
95 bool Watch(const base::Callback<void(bool succeeded)>& callback) { | |
96 return NotifyWatcherMac::Watch(kDnsNotifyKey, callback); | |
97 } | |
98 }; | |
99 #else | |
100 static const FilePath::CharType* kFilePathConfig = | |
101 FILE_PATH_LITERAL(_PATH_RESCONF); | |
102 | |
103 class DnsConfigServicePosix::ConfigWatcher : public FilePathWatcherWrapper { | |
104 public: | |
105 bool Watch(const base::Callback<void(bool succeeded)>& callback) { | |
106 return FilePathWatcherWrapper::Watch(FilePath(kFilePathConfig), callback); | |
107 } | |
108 }; | |
109 #endif | |
110 | |
111 DnsConfigServicePosix::DnsConfigServicePosix() | |
112 : config_watcher_(new ConfigWatcher()), | |
113 hosts_watcher_(new FilePathWatcherWrapper()) { | |
114 config_reader_ = new ConfigReader( | 85 config_reader_ = new ConfigReader( |
115 base::Bind(&DnsConfigServicePosix::OnConfigRead, | 86 base::Bind(&DnsConfigServicePosix::OnConfigRead, |
116 base::Unretained(this))); | 87 base::Unretained(this))); |
117 hosts_reader_ = new DnsHostsReader( | 88 hosts_reader_ = new DnsHostsReader( |
118 FilePath(kFilePathHosts), | 89 FilePath(kFilePathHosts), |
119 base::Bind(&DnsConfigServicePosix::OnHostsRead, | 90 base::Bind(&DnsConfigServicePosix::OnHostsRead, |
120 base::Unretained(this))); | 91 base::Unretained(this))); |
121 } | 92 } |
122 | 93 |
123 DnsConfigServicePosix::~DnsConfigServicePosix() { | 94 DnsConfigServicePosix::~DnsConfigServicePosix() { |
124 config_reader_->Cancel(); | 95 config_reader_->Cancel(); |
125 hosts_reader_->Cancel(); | 96 hosts_reader_->Cancel(); |
126 } | 97 } |
127 | 98 |
128 void DnsConfigServicePosix::Watch(const CallbackType& callback) { | 99 void DnsConfigServicePosix::OnDNSChanged(unsigned detail) { |
129 DCHECK(CalledOnValidThread()); | 100 if (detail & NetworkChangeNotifier::CHANGE_DNS_WATCH_FAILED) { |
130 DCHECK(!callback.is_null()); | 101 InvalidateConfig(); |
131 set_callback(callback); | 102 InvalidateHosts(); |
132 | 103 // We don't trust a config that we cannot watch in the future. |
133 // Even if watchers fail, we keep the other one as it provides useful signals. | 104 config_reader_->Cancel(); |
134 if (config_watcher_->Watch( | 105 hosts_reader_->Cancel(); |
135 base::Bind(&DnsConfigServicePosix::OnConfigChanged, | 106 return; |
136 base::Unretained(this)))) { | |
137 OnConfigChanged(true); | |
138 } else { | |
139 OnConfigChanged(false); | |
140 } | 107 } |
141 | 108 if (detail & NetworkChangeNotifier::CHANGE_DNS_WATCH_STARTED) |
142 if (hosts_watcher_->Watch( | 109 detail = ~0; // Assume everything changed. |
143 FilePath(kFilePathHosts), | 110 if (detail & NetworkChangeNotifier::CHANGE_DNS_SETTINGS) { |
144 base::Bind(&DnsConfigServicePosix::OnHostsChanged, | 111 InvalidateConfig(); |
145 base::Unretained(this)))) { | 112 config_reader_->WorkNow(); |
146 OnHostsChanged(true); | 113 } |
147 } else { | 114 if (detail & NetworkChangeNotifier::CHANGE_DNS_HOSTS) { |
148 OnHostsChanged(false); | 115 InvalidateHosts(); |
| 116 hosts_reader_->WorkNow(); |
149 } | 117 } |
150 } | 118 } |
151 | 119 |
152 void DnsConfigServicePosix::OnConfigChanged(bool watch_succeeded) { | |
153 InvalidateConfig(); | |
154 // We don't trust a config that we cannot watch in the future. | |
155 // TODO(szym): re-start watcher if that makes sense. http://crbug.com/116139 | |
156 if (watch_succeeded) | |
157 config_reader_->WorkNow(); | |
158 else | |
159 LOG(ERROR) << "Failed to watch DNS config"; | |
160 } | |
161 | |
162 void DnsConfigServicePosix::OnHostsChanged(bool watch_succeeded) { | |
163 InvalidateHosts(); | |
164 if (watch_succeeded) | |
165 hosts_reader_->WorkNow(); | |
166 else | |
167 LOG(ERROR) << "Failed to watch DNS hosts"; | |
168 } | |
169 | |
170 #if !defined(OS_ANDROID) | 120 #if !defined(OS_ANDROID) |
171 bool ConvertResStateToDnsConfig(const struct __res_state& res, | 121 bool ConvertResStateToDnsConfig(const struct __res_state& res, |
172 DnsConfig* dns_config) { | 122 DnsConfig* dns_config) { |
173 CHECK(dns_config != NULL); | 123 CHECK(dns_config != NULL); |
174 DCHECK(res.options & RES_INIT); | 124 DCHECK(res.options & RES_INIT); |
175 | 125 |
176 dns_config->nameservers.clear(); | 126 dns_config->nameservers.clear(); |
177 | 127 |
178 #if defined(OS_MACOSX) || defined(OS_FREEBSD) | 128 #if defined(OS_MACOSX) || defined(OS_FREEBSD) |
179 union res_sockaddr_union addresses[MAXNS]; | 129 union res_sockaddr_union addresses[MAXNS]; |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
245 #endif // !defined(OS_ANDROID) | 195 #endif // !defined(OS_ANDROID) |
246 | 196 |
247 } // namespace internal | 197 } // namespace internal |
248 | 198 |
249 // static | 199 // static |
250 scoped_ptr<DnsConfigService> DnsConfigService::CreateSystemService() { | 200 scoped_ptr<DnsConfigService> DnsConfigService::CreateSystemService() { |
251 return scoped_ptr<DnsConfigService>(new internal::DnsConfigServicePosix()); | 201 return scoped_ptr<DnsConfigService>(new internal::DnsConfigServicePosix()); |
252 } | 202 } |
253 | 203 |
254 } // namespace net | 204 } // namespace net |
OLD | NEW |