dns_config_service.h 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  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
  3. // found in the LICENSE file.
  4. #ifndef NET_DNS_DNS_CONFIG_SERVICE_H_
  5. #define NET_DNS_DNS_CONFIG_SERVICE_H_
  6. #include <map>
  7. #include <memory>
  8. #include "base/files/file_path.h"
  9. #include "base/memory/raw_ptr.h"
  10. #include "base/memory/weak_ptr.h"
  11. #include "base/sequence_checker.h"
  12. #include "base/time/time.h"
  13. #include "base/timer/timer.h"
  14. #include "net/base/net_export.h"
  15. #include "net/dns/dns_config.h"
  16. #include "net/dns/dns_hosts.h"
  17. #include "net/dns/serial_worker.h"
  18. #include "third_party/abseil-cpp/absl/types/optional.h"
  19. #include "url/gurl.h"
  20. namespace net {
  21. // Service for reading system DNS settings, on demand or when signalled by
  22. // internal watchers and NetworkChangeNotifier. This object is not thread-safe
  23. // and methods may perform blocking I/O so methods must be called on a sequence
  24. // that allows blocking (i.e. base::MayBlock).
  25. class NET_EXPORT_PRIVATE DnsConfigService {
  26. public:
  27. // Callback interface for the client, called on the same thread as
  28. // ReadConfig() and WatchConfig().
  29. typedef base::RepeatingCallback<void(const DnsConfig& config)> CallbackType;
  30. // DHCP and user-induced changes are on the order of seconds, so 150ms should
  31. // not add perceivable delay. On the other hand, config readers should finish
  32. // within 150ms with the rare exception of I/O block or extra large HOSTS.
  33. static const base::TimeDelta kInvalidationTimeout;
  34. // Creates the platform-specific DnsConfigService. May return |nullptr| if
  35. // reading system DNS settings is not supported on the current platform.
  36. static std::unique_ptr<DnsConfigService> CreateSystemService();
  37. DnsConfigService(const DnsConfigService&) = delete;
  38. DnsConfigService& operator=(const DnsConfigService&) = delete;
  39. virtual ~DnsConfigService();
  40. // Attempts to read the configuration. Will run |callback| when succeeded.
  41. // Can be called at most once.
  42. void ReadConfig(const CallbackType& callback);
  43. // Registers systems watchers. Will attempt to read config after watch starts,
  44. // but only if watchers started successfully. Will run |callback| iff config
  45. // changes from last call or has to be withdrawn. Can be called at most once.
  46. // Might require MessageLoopForIO.
  47. void WatchConfig(const CallbackType& callback);
  48. // Triggers invalidation and re-read of the current configuration (followed by
  49. // invocation of the callback). For use only on platforms expecting
  50. // network-stack-external notifications of DNS config changes.
  51. virtual void RefreshConfig();
  52. void set_watch_failed_for_testing(bool watch_failed) {
  53. watch_failed_ = watch_failed;
  54. }
  55. // Simulates a watcher trigger by calling OnConfigChanged().
  56. void TriggerOnConfigChangedForTesting(bool succeeded) {
  57. // Directly call ...Delayed() version to skip past delay logic.
  58. OnConfigChangedDelayed(succeeded);
  59. }
  60. protected:
  61. // Watcher to observe for changes to DNS config or HOSTS (via overriding
  62. // `Watch()` with platform specifics) and trigger necessary refreshes on
  63. // changes.
  64. class NET_EXPORT_PRIVATE Watcher {
  65. public:
  66. // `service` is expected to own the created Watcher and thus stay valid for
  67. // the lifetime of the created Watcher.
  68. explicit Watcher(DnsConfigService& service);
  69. virtual ~Watcher();
  70. Watcher(const Watcher&) = delete;
  71. Watcher& operator=(const Watcher&) = delete;
  72. virtual bool Watch() = 0;
  73. protected:
  74. // Hooks for detected changes. `succeeded` false to indicate that there was
  75. // an error watching for the change.
  76. void OnConfigChanged(bool succeeded);
  77. void OnHostsChanged(bool succeeded);
  78. void CheckOnCorrectSequence();
  79. private:
  80. void OnConfigChangedDelayed(bool success);
  81. // Back pointer. `this` is expected to be owned by `service_`, making this
  82. // raw pointer safe.
  83. const raw_ptr<DnsConfigService> service_;
  84. SEQUENCE_CHECKER(sequence_checker_);
  85. };
  86. // Reader of HOSTS files. In this base implementation, uses standard logic
  87. // appropriate to most platforms to read the HOSTS file located at
  88. // `hosts_file_path`.
  89. class NET_EXPORT_PRIVATE HostsReader : public SerialWorker {
  90. public:
  91. // `service` is expected to own the created reader and thus stay valid for
  92. // the lifetime of the created reader.
  93. HostsReader(base::FilePath::StringPieceType hosts_file_path,
  94. DnsConfigService& service);
  95. ~HostsReader() override;
  96. HostsReader(const HostsReader&) = delete;
  97. HostsReader& operator=(const HostsReader&) = delete;
  98. protected:
  99. class NET_EXPORT_PRIVATE WorkItem : public SerialWorker::WorkItem {
  100. public:
  101. explicit WorkItem(std::unique_ptr<DnsHostsParser> dns_hosts_parser);
  102. ~WorkItem() override;
  103. // Override if needed to implement platform-specific behavior, e.g. for a
  104. // platform-specific HOSTS format.
  105. virtual absl::optional<DnsHosts> ReadHosts();
  106. // Adds any necessary additional entries to the given `DnsHosts`. Returns
  107. // false on failure.
  108. //
  109. // Override if needed to implement platform-specific behavior.
  110. virtual bool AddAdditionalHostsTo(DnsHosts& in_out_dns_hosts);
  111. // SerialWorker::WorkItem:
  112. void DoWork() final;
  113. private:
  114. friend HostsReader;
  115. absl::optional<DnsHosts> hosts_;
  116. std::unique_ptr<DnsHostsParser> dns_hosts_parser_;
  117. };
  118. // SerialWorker:
  119. std::unique_ptr<SerialWorker::WorkItem> CreateWorkItem() override;
  120. bool OnWorkFinished(
  121. std::unique_ptr<SerialWorker::WorkItem> work_item) final;
  122. private:
  123. // Raw pointer to owning DnsConfigService. This must never be accessed
  124. // inside DoWork(), since service may be destroyed while SerialWorker is
  125. // running on worker thread.
  126. const raw_ptr<DnsConfigService> service_;
  127. const base::FilePath hosts_file_path_;
  128. };
  129. // On detecting config change, will post and wait `config_change_delay` before
  130. // triggering refreshes. Will trigger refreshes synchronously on nullopt.
  131. // Useful for platforms where multiple changes may be made and detected before
  132. // the config is stabilized and ready to be read.
  133. explicit DnsConfigService(base::FilePath::StringPieceType hosts_file_path,
  134. absl::optional<base::TimeDelta>
  135. config_change_delay = base::Milliseconds(50));
  136. // Immediately attempts to read the current configuration.
  137. virtual void ReadConfigNow() = 0;
  138. virtual void ReadHostsNow();
  139. // Registers system watchers. Returns true iff succeeds.
  140. virtual bool StartWatching() = 0;
  141. // Called when the current config (except hosts) has changed.
  142. void InvalidateConfig();
  143. // Called when the current hosts have changed.
  144. void InvalidateHosts();
  145. // Called with new config. |config|.hosts is ignored.
  146. void OnConfigRead(DnsConfig config);
  147. // Called with new hosts. Rest of the config is assumed unchanged.
  148. void OnHostsRead(DnsHosts hosts);
  149. SEQUENCE_CHECKER(sequence_checker_);
  150. private:
  151. // The timer counts from the last Invalidate* until complete config is read.
  152. void StartTimer();
  153. void OnTimeout();
  154. // Called when the config becomes complete. Stops the timer.
  155. void OnCompleteConfig();
  156. // Hooks for Watcher change notifications. `succeeded` false to indicate that
  157. // there was an error watching for the change.
  158. void OnConfigChanged(bool succeeded);
  159. void OnHostsChanged(bool succeeded);
  160. void OnConfigChangedDelayed(bool succeeded);
  161. CallbackType callback_;
  162. DnsConfig dns_config_;
  163. // True if any of the necessary watchers failed. In that case, the service
  164. // will communicate changes via OnTimeout, but will only send empty DnsConfig.
  165. bool watch_failed_ = false;
  166. // True after On*Read, before Invalidate*. Tells if the config is complete.
  167. bool have_config_ = false;
  168. bool have_hosts_ = false;
  169. // True if receiver needs to be updated when the config becomes complete.
  170. bool need_update_ = false;
  171. // True if the last config sent was empty (instead of |dns_config_|).
  172. // Set when |timer_| expires.
  173. bool last_sent_empty_ = true;
  174. const absl::optional<base::TimeDelta> config_change_delay_;
  175. const base::FilePath hosts_file_path_;
  176. // Created only if needed in ReadHostsNow() to avoid creating unnecessarily if
  177. // overridden for a platform-specific implementation.
  178. std::unique_ptr<HostsReader> hosts_reader_;
  179. // Started in Invalidate*, cleared in On*Read.
  180. base::OneShotTimer timer_;
  181. base::WeakPtrFactory<DnsConfigService> weak_factory_{this};
  182. };
  183. } // namespace net
  184. #endif // NET_DNS_DNS_CONFIG_SERVICE_H_