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

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

Issue 9721002: [net/dns] Removes locking from DnsConfigServiceWin and adds local computer name. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Responded to review. Added normalization and comments. Created 8 years, 9 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
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_win.h" 5 #include "net/dns/dns_config_service_win.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <string> 8 #include <string>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/callback.h" 11 #include "base/callback.h"
12 #include "base/compiler_specific.h" 12 #include "base/compiler_specific.h"
13 #include "base/file_path.h" 13 #include "base/file_path.h"
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/memory/scoped_ptr.h" 15 #include "base/memory/scoped_ptr.h"
16 #include "base/string_split.h" 16 #include "base/string_split.h"
17 #include "base/string_util.h" 17 #include "base/string_util.h"
18 #include "base/synchronization/lock.h" 18 #include "base/synchronization/lock.h"
19 #include "base/threading/non_thread_safe.h"
19 #include "base/threading/thread_restrictions.h" 20 #include "base/threading/thread_restrictions.h"
20 #include "base/utf_string_conversions.h" 21 #include "base/utf_string_conversions.h"
21 #include "base/win/object_watcher.h" 22 #include "base/win/object_watcher.h"
22 #include "base/win/registry.h" 23 #include "base/win/registry.h"
23 #include "base/win/windows_version.h" 24 #include "base/win/windows_version.h"
24 #include "googleurl/src/url_canon.h" 25 #include "googleurl/src/url_canon.h"
25 #include "net/base/net_util.h" 26 #include "net/base/net_util.h"
27 #include "net/base/network_change_notifier.h"
26 #include "net/dns/dns_protocol.h" 28 #include "net/dns/dns_protocol.h"
27 #include "net/dns/file_path_watcher_wrapper.h" 29 #include "net/dns/file_path_watcher_wrapper.h"
28 #include "net/dns/serial_worker.h" 30 #include "net/dns/serial_worker.h"
29 31
30 #pragma comment(lib, "iphlpapi.lib") 32 #pragma comment(lib, "iphlpapi.lib")
31 33
32 namespace net { 34 namespace net {
33 35
34 namespace internal { 36 namespace internal {
35 37
36 namespace { 38 namespace {
37 39
38 // Watches a single registry key for changes. Thread-safe. 40 // Registry key paths.
39 class RegistryWatcher : public base::win::ObjectWatcher::Delegate { 41 const wchar_t* const kTcpipPath =
42 L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters";
43 const wchar_t* const kTcpip6Path =
44 L"SYSTEM\\CurrentControlSet\\Services\\Tcpip6\\Parameters";
45 const wchar_t* const kDnscachePath =
46 L"SYSTEM\\CurrentControlSet\\Services\\Dnscache\\Parameters";
47 const wchar_t* const kPolicyPath =
48 L"SOFTWARE\\Policies\\Microsoft\\Windows NT\\DNSClient";
49
50 // Convenience for reading values using RegKey.
51 class RegistryReader : public base::NonThreadSafe {
40 public: 52 public:
41 typedef base::Callback<void(bool succeeded)> CallbackType; 53 explicit RegistryReader(const wchar_t* key) {
42 RegistryWatcher() {} 54 // Ignoring the result. |key_.Valid()| will catch failures.
43 55 key_.Open(HKEY_LOCAL_MACHINE, key, KEY_QUERY_VALUE);
44 bool Watch(const wchar_t* key, const CallbackType& callback) {
45 base::AutoLock lock(lock_);
46 DCHECK(!callback.is_null());
47 CancelLocked();
48 if (key_.Open(HKEY_LOCAL_MACHINE, key,
49 KEY_NOTIFY | KEY_QUERY_VALUE) != ERROR_SUCCESS)
50 return false;
51 if (key_.StartWatching() != ERROR_SUCCESS)
52 return false;
53 if (!watcher_.StartWatching(key_.watch_event(), this))
54 return false;
55 callback_ = callback;
56 return true;
57 }
58
59 void Cancel() {
60 base::AutoLock lock(lock_);
61 CancelLocked();
62 }
63
64 virtual void OnObjectSignaled(HANDLE object) OVERRIDE {
65 base::AutoLock lock(lock_);
66 bool succeeded = (key_.StartWatching() == ERROR_SUCCESS) &&
67 watcher_.StartWatching(key_.watch_event(), this);
68 if (!callback_.is_null())
69 callback_.Run(succeeded);
70 } 56 }
71 57
72 bool ReadString(const wchar_t* name, 58 bool ReadString(const wchar_t* name,
73 DnsSystemSettings::RegString* out) const { 59 DnsSystemSettings::RegString* out) const {
74 base::AutoLock lock(lock_); 60 DCHECK(CalledOnValidThread());
75 out->set = false; 61 out->set = false;
76 if (!key_.Valid()) { 62 if (!key_.Valid()) {
77 // Assume that if the |key_| is invalid then the key is missing. 63 // Assume that if the |key_| is invalid then the key is missing.
78 return true; 64 return true;
79 } 65 }
80 LONG result = key_.ReadValue(name, &out->value); 66 LONG result = key_.ReadValue(name, &out->value);
81 if (result == ERROR_SUCCESS) { 67 if (result == ERROR_SUCCESS) {
82 out->set = true; 68 out->set = true;
83 return true; 69 return true;
84 } 70 }
85 return (result == ERROR_FILE_NOT_FOUND); 71 return (result == ERROR_FILE_NOT_FOUND);
86 } 72 }
87 73
88 bool ReadDword(const wchar_t* name, 74 bool ReadDword(const wchar_t* name,
89 DnsSystemSettings::RegDword* out) const { 75 DnsSystemSettings::RegDword* out) const {
90 base::AutoLock lock(lock_); 76 DCHECK(CalledOnValidThread());
91 out->set = false; 77 out->set = false;
92 if (!key_.Valid()) { 78 if (!key_.Valid()) {
93 // Assume that if the |key_| is invalid then the key is missing. 79 // Assume that if the |key_| is invalid then the key is missing.
94 return true; 80 return true;
95 } 81 }
96 LONG result = key_.ReadValueDW(name, &out->value); 82 LONG result = key_.ReadValueDW(name, &out->value);
97 if (result == ERROR_SUCCESS) { 83 if (result == ERROR_SUCCESS) {
98 out->set = true; 84 out->set = true;
99 return true; 85 return true;
100 } 86 }
101 return (result == ERROR_FILE_NOT_FOUND); 87 return (result == ERROR_FILE_NOT_FOUND);
102 } 88 }
103 89
104 private: 90 private:
105 void CancelLocked() { 91 base::win::RegKey key_;
106 lock_.AssertAcquired(); 92
93 DISALLOW_COPY_AND_ASSIGN(RegistryReader);
94 };
95
96
97 // Watches a single registry key for changes.
98 class RegistryWatcher : public base::win::ObjectWatcher::Delegate,
99 public base::NonThreadSafe {
100 public:
101 typedef base::Callback<void(bool succeeded)> CallbackType;
102 RegistryWatcher() {}
103
104 bool Watch(const wchar_t* key, const CallbackType& callback) {
105 DCHECK(CalledOnValidThread());
106 DCHECK(!callback.is_null());
107 Cancel();
108 if (key_.Open(HKEY_LOCAL_MACHINE, key, KEY_NOTIFY) != ERROR_SUCCESS)
109 return false;
110 if (key_.StartWatching() != ERROR_SUCCESS)
111 return false;
112 if (!watcher_.StartWatching(key_.watch_event(), this))
113 return false;
114 callback_ = callback;
115 return true;
116 }
117
118 bool IsWatching() const {
119 DCHECK(CalledOnValidThread());
120 return !callback_.is_null();
121 }
122
123 void Cancel() {
124 DCHECK(CalledOnValidThread());
107 callback_.Reset(); 125 callback_.Reset();
108 if (key_.Valid()) { 126 if (key_.Valid()) {
109 watcher_.StopWatching(); 127 watcher_.StopWatching();
110 key_.StopWatching(); 128 key_.StopWatching();
129 key_.Close();
111 } 130 }
112 } 131 }
113 132
114 mutable base::Lock lock_; 133 virtual void OnObjectSignaled(HANDLE object) OVERRIDE {
134 DCHECK(CalledOnValidThread());
135 bool succeeded = (key_.StartWatching() == ERROR_SUCCESS) &&
136 watcher_.StartWatching(key_.watch_event(), this);
137 CallbackType callback = callback_;
138 if (!succeeded)
139 Cancel();
140 if (!callback.is_null())
141 callback.Run(succeeded);
142 }
143
144 private:
115 CallbackType callback_; 145 CallbackType callback_;
116 base::win::RegKey key_; 146 base::win::RegKey key_;
117 base::win::ObjectWatcher watcher_; 147 base::win::ObjectWatcher watcher_;
118 148
119 DISALLOW_COPY_AND_ASSIGN(RegistryWatcher); 149 DISALLOW_COPY_AND_ASSIGN(RegistryWatcher);
120 }; 150 };
121 151
152 // Returns NULL if failed.
153 scoped_ptr_malloc<IP_ADAPTER_ADDRESSES> ReadIpHelper(ULONG flags) {
154 base::ThreadRestrictions::AssertIOAllowed();
155
156 scoped_ptr_malloc<IP_ADAPTER_ADDRESSES> out;
157 ULONG len = 15000; // As recommended by MSDN for GetAdaptersAddresses.
158 UINT rv = ERROR_BUFFER_OVERFLOW;
159 // Try up to three times.
160 for (unsigned tries = 0;
161 (tries < 3) && (rv == ERROR_BUFFER_OVERFLOW);
162 tries++) {
163 out.reset(
164 reinterpret_cast<PIP_ADAPTER_ADDRESSES>(malloc(len)));
mmenke 2012/03/22 19:36:08 nit: Think this will all fit on one line. Next l
165 rv = GetAdaptersAddresses(AF_UNSPEC, flags, NULL,
166 out.get(), &len);
167 }
168 if (rv != NO_ERROR)
169 out.reset();
170 return out.Pass();
171 }
172
122 // Converts a string16 domain name to ASCII, possibly using punycode. 173 // Converts a string16 domain name to ASCII, possibly using punycode.
123 // Returns true if the conversion succeeds and output is not empty. In case of 174 // Returns true if the conversion succeeds and output is not empty. In case of
124 // failure, |domain| might become dirty. 175 // failure, |domain| might become dirty.
125 bool ParseDomainASCII(const string16& widestr, std::string* domain) { 176 bool ParseDomainASCII(const string16& widestr, std::string* domain) {
126 DCHECK(domain); 177 DCHECK(domain);
127 if (widestr.empty()) 178 if (widestr.empty())
128 return false; 179 return false;
129 180
130 // Check if already ASCII. 181 // Check if already ASCII.
131 if (IsStringASCII(widestr)) { 182 if (IsStringASCII(widestr)) {
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
316 : service_(service), 367 : service_(service),
317 success_(false) {} 368 success_(false) {}
318 369
319 bool Watch() { 370 bool Watch() {
320 DCHECK(loop()->BelongsToCurrentThread()); 371 DCHECK(loop()->BelongsToCurrentThread());
321 372
322 RegistryWatcher::CallbackType callback = 373 RegistryWatcher::CallbackType callback =
323 base::Bind(&ConfigReader::OnChange, base::Unretained(this)); 374 base::Bind(&ConfigReader::OnChange, base::Unretained(this));
324 375
325 // The Tcpip key must be present. 376 // The Tcpip key must be present.
326 if (!tcpip_watcher_.Watch( 377 if (!tcpip_watcher_.Watch(kTcpipPath, callback))
327 L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
328 callback))
329 return false; 378 return false;
330 379
331 // Watch for IPv6 nameservers. 380 // Watch for IPv6 nameservers.
332 tcpip6_watcher_.Watch( 381 tcpip6_watcher_.Watch(kTcpip6Path, callback);
333 L"SYSTEM\\CurrentControlSet\\Services\\Tcpip6\\Parameters",
334 callback);
335 382
336 // DNS suffix search list and devolution can be configured via group 383 // DNS suffix search list and devolution can be configured via group
337 // policy which sets this registry key. If the key is missing, the policy 384 // policy which sets this registry key. If the key is missing, the policy
338 // does not apply, and the DNS client uses Tcpip and Dnscache settings. 385 // does not apply, and the DNS client uses Tcpip and Dnscache settings.
339 // If a policy is installed, DnsConfigService will need to be restarted. 386 // If a policy is installed, DnsConfigService will need to be restarted.
340 // BUG=99509 387 // BUG=99509
341 388
342 dnscache_watcher_.Watch( 389 dnscache_watcher_.Watch(kDnscachePath, callback);
343 L"SYSTEM\\CurrentControlSet\\Services\\Dnscache\\Parameters", 390 policy_watcher_.Watch(kPolicyPath, callback);
344 callback);
345
346 policy_watcher_.Watch(
347 L"SOFTWARE\\Policies\\Microsoft\\Windows NT\\DNSClient",
348 callback);
349 391
350 WorkNow(); 392 WorkNow();
351 return true; 393 return true;
352 } 394 }
353 395
354 void Cancel() { 396 void Cancel() {
355 DCHECK(loop()->BelongsToCurrentThread()); 397 DCHECK(loop()->BelongsToCurrentThread());
356 SerialWorker::Cancel(); 398 SerialWorker::Cancel();
357 policy_watcher_.Cancel(); 399 policy_watcher_.Cancel();
358 dnscache_watcher_.Cancel(); 400 dnscache_watcher_.Cancel();
(...skipping 11 matching lines...) Expand all
370 if (!IsCancelled()) 412 if (!IsCancelled())
371 service_->InvalidateConfig(); 413 service_->InvalidateConfig();
372 // We don't trust a config that we cannot watch in the future. 414 // We don't trust a config that we cannot watch in the future.
373 // TODO(szym): re-start watcher if that makes sense. http://crbug.com/116139 415 // TODO(szym): re-start watcher if that makes sense. http://crbug.com/116139
374 if (succeeded) 416 if (succeeded)
375 WorkNow(); 417 WorkNow();
376 else 418 else
377 LOG(ERROR) << "Failed to watch DNS config"; 419 LOG(ERROR) << "Failed to watch DNS config";
378 } 420 }
379 421
380 bool ReadIpHelper(DnsSystemSettings* settings) { 422 bool ReadDevolutionSetting(const RegistryReader& reader,
381 base::ThreadRestrictions::AssertIOAllowed();
382
383 ULONG flags = GAA_FLAG_SKIP_ANYCAST |
384 GAA_FLAG_SKIP_UNICAST |
385 GAA_FLAG_SKIP_MULTICAST |
386 GAA_FLAG_SKIP_FRIENDLY_NAME;
387 ULONG len = 15000; // As recommended by MSDN for GetAdaptersAddresses.
388 UINT rv = ERROR_BUFFER_OVERFLOW;
389 // Try up to three times.
390 for (unsigned tries = 0;
391 (tries < 3) && (rv == ERROR_BUFFER_OVERFLOW);
392 tries++) {
393 settings->addresses.reset(
394 reinterpret_cast<PIP_ADAPTER_ADDRESSES>(malloc(len)));
395 rv = GetAdaptersAddresses(AF_UNSPEC, flags, NULL,
396 settings->addresses.get(), &len);
397 }
398 return (rv == NO_ERROR);
399 }
400
401 bool ReadDevolutionSetting(const RegistryWatcher& watcher,
402 DnsSystemSettings::DevolutionSetting& setting) { 423 DnsSystemSettings::DevolutionSetting& setting) {
403 return watcher.ReadDword(L"UseDomainNameDevolution", &setting.enabled) && 424 return reader.ReadDword(L"UseDomainNameDevolution", &setting.enabled) &&
404 watcher.ReadDword(L"DomainNameDevolutionLevel", &setting.level); 425 reader.ReadDword(L"DomainNameDevolutionLevel", &setting.level);
405 } 426 }
406 427
407 virtual void DoWork() OVERRIDE { 428 virtual void DoWork() OVERRIDE {
408 // Should be called on WorkerPool. 429 // Should be called on WorkerPool.
409 success_ = false; 430 success_ = false;
410 431
411 DnsSystemSettings settings; 432 DnsSystemSettings settings;
412 memset(&settings, 0, sizeof(settings)); 433 memset(&settings, 0, sizeof(settings));
413 if (!ReadIpHelper(&settings)) 434 settings.addresses = ReadIpHelper(GAA_FLAG_SKIP_ANYCAST |
435 GAA_FLAG_SKIP_UNICAST |
436 GAA_FLAG_SKIP_MULTICAST |
437 GAA_FLAG_SKIP_FRIENDLY_NAME);
438 if (!settings.addresses.get())
414 return; // no point reading the rest 439 return; // no point reading the rest
415 440
416 if (!policy_watcher_.ReadString(L"SearchList", 441 RegistryReader tcpip_reader(kTcpipPath);
417 &settings.policy_search_list)) 442 RegistryReader tcpip6_reader(kTcpip6Path);
443 RegistryReader dnscache_reader(kDnscachePath);
444 RegistryReader policy_reader(kPolicyPath);
445
446 if (!policy_reader.ReadString(L"SearchList",
447 &settings.policy_search_list))
418 return; 448 return;
419 449
420 if (!tcpip_watcher_.ReadString(L"SearchList", &settings.tcpip_search_list)) 450 if (!tcpip_reader.ReadString(L"SearchList", &settings.tcpip_search_list))
421 return; 451 return;
422 452
423 if (!tcpip_watcher_.ReadString(L"Domain", &settings.tcpip_domain)) 453 if (!tcpip_reader.ReadString(L"Domain", &settings.tcpip_domain))
424 return; 454 return;
425 455
426 if (!ReadDevolutionSetting(policy_watcher_, settings.policy_devolution)) 456 if (!ReadDevolutionSetting(policy_reader, settings.policy_devolution))
427 return; 457 return;
428 458
429 if (!ReadDevolutionSetting(dnscache_watcher_, 459 if (!ReadDevolutionSetting(dnscache_reader,
430 settings.dnscache_devolution)) 460 settings.dnscache_devolution))
431 return; 461 return;
432 462
433 if (!ReadDevolutionSetting(tcpip_watcher_, settings.tcpip_devolution)) 463 if (!ReadDevolutionSetting(tcpip_reader, settings.tcpip_devolution))
434 return; 464 return;
435 465
436 if (!policy_watcher_.ReadDword(L"AppendToMultiLabelName", 466 if (!policy_reader.ReadDword(L"AppendToMultiLabelName",
437 &settings.append_to_multi_label_name)) 467 &settings.append_to_multi_label_name))
438 return; 468 return;
439 469
440 success_ = ConvertSettingsToDnsConfig(settings, &dns_config_); 470 success_ = ConvertSettingsToDnsConfig(settings, &dns_config_);
441 } 471 }
442 472
443 virtual void OnWorkFinished() OVERRIDE { 473 virtual void OnWorkFinished() OVERRIDE {
444 DCHECK(loop()->BelongsToCurrentThread()); 474 DCHECK(loop()->BelongsToCurrentThread());
445 DCHECK(!IsCancelled()); 475 DCHECK(!IsCancelled());
446 if (success_) { 476 if (success_) {
447 service_->OnConfigRead(dns_config_); 477 service_->OnConfigRead(dns_config_);
448 } else { 478 } else {
449 LOG(WARNING) << "Failed to read config."; 479 LOG(WARNING) << "Failed to read config.";
450 } 480 }
451 } 481 }
452 482
453 DnsConfigServiceWin* service_; 483 DnsConfigServiceWin* service_;
454 // Written in DoRead(), read in OnReadFinished(). No locking required. 484 // Written in DoRead(), read in OnReadFinished(). No locking required.
455 DnsConfig dns_config_; 485 DnsConfig dns_config_;
456 bool success_; 486 bool success_;
457 487
458 RegistryWatcher tcpip_watcher_; 488 RegistryWatcher tcpip_watcher_;
459 RegistryWatcher tcpip6_watcher_; 489 RegistryWatcher tcpip6_watcher_;
460 RegistryWatcher dnscache_watcher_; 490 RegistryWatcher dnscache_watcher_;
461 RegistryWatcher policy_watcher_; 491 RegistryWatcher policy_watcher_;
462 }; 492 };
463 493
494 FilePath GetHostsPath() {
495 TCHAR buffer[MAX_PATH];
496 UINT rc = GetSystemDirectory(buffer, MAX_PATH);
497 DCHECK(0 < rc && rc < MAX_PATH);
498 return FilePath(buffer).Append(FILE_PATH_LITERAL("drivers\\etc\\hosts"));
499 }
500
501 // An extension for DnsHostsReader which also watches the HOSTS file,
502 // reads local name from GetComputerNameEx, local IP from GetAdaptersAddresses,
503 // and observes changes to local IP address.
504 class DnsConfigServiceWin::HostsReader
505 : public DnsHostsReader,
506 public NetworkChangeNotifier::IPAddressObserver {
507 public:
508 explicit HostsReader(DnsConfigServiceWin* service)
509 : DnsHostsReader(GetHostsPath()), service_(service) {
510 }
511
512 bool Watch() {
513 DCHECK(loop()->BelongsToCurrentThread());
514 DCHECK(!IsCancelled());
515
516 // In case the reader is restarted, remove it from the observer list.
517 NetworkChangeNotifier::RemoveIPAddressObserver(this);
518
519 if (!hosts_watcher_.Watch(path(),
520 base::Bind(&HostsReader::OnHostsChanged,
521 base::Unretained(this)))) {
522 return false;
523 }
524 NetworkChangeNotifier::AddIPAddressObserver(this);
525 WorkNow();
526 return true;
527 }
528
529 // Cancels the underlying SerialWorker. Cannot be undone.
530 void Cancel() {
531 DnsHostsReader::Cancel();
532 hosts_watcher_.Cancel();
533 NetworkChangeNotifier::RemoveIPAddressObserver(this);
534 }
535
536 private:
537 virtual void OnIPAddressChanged() OVERRIDE {
538 DCHECK(loop()->BelongsToCurrentThread());
539 service_->InvalidateHosts();
540 if (!hosts_watcher_.IsWatching())
541 return;
542 WorkNow();
543 }
544
545 void OnHostsChanged(bool succeeded) {
546 DCHECK(loop()->BelongsToCurrentThread());
547 service_->InvalidateHosts();
548 if (succeeded)
549 WorkNow();
550 else
551 LOG(ERROR) << "Failed to watch DNS hosts";
552 }
553
554 virtual void DoWork() OVERRIDE {
555 DnsHostsReader::DoWork();
556
557 if (!success_)
558 return;
559
560 // Default address of local computer name and "localhost" can be overridden
561 // by the HOSTS file, but if it's not there, then we need to fill it in.
562
563 success_ = false;
564
565 WCHAR buffer[MAX_PATH];
566 DWORD size = MAX_PATH;
567 std::string localname;
568 if (!GetComputerNameExW(ComputerNameDnsHostname, buffer, &size) ||
569 !ParseDomainASCII(buffer, &localname)) {
570 LOG(ERROR) << "Failed to read local computer name";
571 return;
572 }
573 StringToLowerASCII(&localname);
574
575 scoped_ptr_malloc<IP_ADAPTER_ADDRESSES> addresses =
576 ReadIpHelper(GAA_FLAG_SKIP_ANYCAST |
577 GAA_FLAG_SKIP_DNS_SERVER |
578 GAA_FLAG_SKIP_MULTICAST |
579 GAA_FLAG_SKIP_FRIENDLY_NAME);
580 if (!addresses.get())
581 return;
582
583 // The order of adapters is the network binding order, so stick to the
584 // first good adapter for each family.
585 bool have_ipv4 =
586 dns_hosts_.count(DnsHostsKey(localname, ADDRESS_FAMILY_IPV4)) > 0;
587 bool have_ipv6 =
588 dns_hosts_.count(DnsHostsKey(localname, ADDRESS_FAMILY_IPV6)) > 0;
589 for (const IP_ADAPTER_ADDRESSES* adapter = addresses.get();
590 adapter != NULL && !(have_ipv4 && have_ipv6);
mmenke 2012/03/22 19:36:08 nit: Think (!have_ipv4 || !have_ipv6) is a little
591 adapter = adapter->Next) {
592 if (adapter->OperStatus != IfOperStatusUp)
593 continue;
594 if (adapter->IfType == IF_TYPE_SOFTWARE_LOOPBACK)
595 continue;
596
597 for (const IP_ADAPTER_UNICAST_ADDRESS* address =
598 adapter->FirstUnicastAddress;
599 address != NULL;
600 address = address->Next) {
601 IPEndPoint ipe;
602 if (!ipe.FromSockAddr(address->Address.lpSockaddr,
603 address->Address.iSockaddrLength)) {
604 return;
605 }
606 if (!have_ipv4 && (ipe.GetFamily() == AF_INET)) {
607 have_ipv4 = true;
608 dns_hosts_[DnsHostsKey(localname, ADDRESS_FAMILY_IPV4)] =
609 ipe.address();
610 } else if (!have_ipv6 && (ipe.GetFamily() == AF_INET6)) {
611 have_ipv6 = true;
612 dns_hosts_[DnsHostsKey(localname, ADDRESS_FAMILY_IPV6)] =
613 ipe.address();
614 }
mmenke 2012/03/22 19:36:08 You could simplify this as well. I don't think th
615 }
616 }
617
618 const unsigned char kIPv4Localhost[] = { 127, 0, 0, 1 };
619 const unsigned char kIPv6Localhost[] = { 0, 0, 0, 0, 0, 0, 0, 0,
620 0, 0, 0, 0, 0, 0, 0, 1 };
621 IPAddressNumber loopback_ipv4(kIPv4Localhost,
622 kIPv4Localhost + arraysize(kIPv4Localhost));
623 IPAddressNumber loopback_ipv6(kIPv6Localhost,
624 kIPv6Localhost + arraysize(kIPv6Localhost));
625 dns_hosts_.insert(
mmenke 2012/03/22 19:36:08 You should add a comment that this will not overwr
626 std::make_pair(DnsHostsKey("localhost", ADDRESS_FAMILY_IPV4),
627 loopback_ipv4));
628 dns_hosts_.insert(
629 std::make_pair(DnsHostsKey("localhost", ADDRESS_FAMILY_IPV6),
630 loopback_ipv6));
631 success_ = true;
632 }
633
634 virtual void OnWorkFinished() OVERRIDE {
635 DCHECK(loop()->BelongsToCurrentThread());
636 if (!success_ || !hosts_watcher_.IsWatching())
637 return;
638 service_->OnHostsRead(dns_hosts_);
639 }
640
641 DnsConfigServiceWin* service_;
642 FilePathWatcherWrapper hosts_watcher_;
643
644 DISALLOW_COPY_AND_ASSIGN(HostsReader);
645 };
646
647
464 DnsConfigServiceWin::DnsConfigServiceWin() 648 DnsConfigServiceWin::DnsConfigServiceWin()
465 : config_reader_(new ConfigReader(this)), 649 : config_reader_(new ConfigReader(this)),
466 hosts_watcher_(new FilePathWatcherWrapper()) {} 650 hosts_reader_(new HostsReader(this)) {}
467 651
468 DnsConfigServiceWin::~DnsConfigServiceWin() { 652 DnsConfigServiceWin::~DnsConfigServiceWin() {
469 DCHECK(CalledOnValidThread()); 653 DCHECK(CalledOnValidThread());
470 config_reader_->Cancel(); 654 config_reader_->Cancel();
471 if (hosts_reader_) 655 hosts_reader_->Cancel();
472 hosts_reader_->Cancel();
473 } 656 }
474 657
475 void DnsConfigServiceWin::Watch(const CallbackType& callback) { 658 void DnsConfigServiceWin::Watch(const CallbackType& callback) {
476 DCHECK(CalledOnValidThread()); 659 DCHECK(CalledOnValidThread());
477 DCHECK(!callback.is_null()); 660 DCHECK(!callback.is_null());
478 set_callback(callback); 661 set_callback(callback);
479 662
480 // This is done only once per lifetime so open the keys and file watcher 663 // This is done only once per lifetime so open the keys and file watcher
481 // handles on this thread. 664 // handles on this thread.
482 // TODO(szym): Should/can this be avoided? http://crbug.com/114223 665 // TODO(szym): Should/can this be avoided? http://crbug.com/114223
483 base::ThreadRestrictions::ScopedAllowIO allow_io; 666 base::ThreadRestrictions::ScopedAllowIO allow_io;
484 667
485 if (!config_reader_->Watch()) { 668 if (!config_reader_->Watch()) {
486 LOG(ERROR) << "Failed to start watching DNS config"; 669 LOG(ERROR) << "Failed to start watching DNS config";
487 InvalidateConfig(); 670 InvalidateConfig();
488 } 671 }
489 672
490 TCHAR buffer[MAX_PATH]; 673 if (!hosts_reader_->Watch()) {
491 UINT rc = GetSystemDirectory(buffer, MAX_PATH); 674 LOG(ERROR) << "Failed to start watching HOSTS";
492 DCHECK(0 < rc && rc < MAX_PATH); 675 InvalidateHosts();
493 FilePath hosts_path = FilePath(buffer).
494 Append(FILE_PATH_LITERAL("drivers\\etc\\hosts"));
495 hosts_reader_ = new DnsHostsReader(
496 hosts_path,
497 base::Bind(&DnsConfigServiceWin::OnHostsRead, base::Unretained(this)));
498 if (hosts_watcher_->Watch(hosts_path,
499 base::Bind(&DnsConfigServiceWin::OnHostsChanged,
500 base::Unretained(this)))) {
501 OnHostsChanged(true);
502 } else {
503 OnHostsChanged(false);
504 } 676 }
505 } 677 }
506 678
507 void DnsConfigServiceWin::OnHostsChanged(bool succeeded) {
508 InvalidateHosts();
509 if (succeeded)
510 hosts_reader_->WorkNow();
511 else
512 LOG(ERROR) << "Failed to watch DNS hosts";
513 }
514
515 } // namespace internal 679 } // namespace internal
516 680
517 // static 681 // static
518 scoped_ptr<DnsConfigService> DnsConfigService::CreateSystemService() { 682 scoped_ptr<DnsConfigService> DnsConfigService::CreateSystemService() {
519 return scoped_ptr<DnsConfigService>(new internal::DnsConfigServiceWin()); 683 return scoped_ptr<DnsConfigService>(new internal::DnsConfigServiceWin());
520 } 684 }
521 685
522 } // namespace net 686 } // namespace net
523 687
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698