OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/base/network_change_notifier_linux.h" | 5 #include "net/base/network_change_notifier_linux.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <sys/socket.h> | 8 #include <sys/socket.h> |
9 | 9 |
10 #include "base/bind.h" | |
11 #include "base/callback_old.h" | |
12 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
13 #include "base/eintr_wrapper.h" | 11 #include "base/eintr_wrapper.h" |
14 #include "base/file_util.h" | |
15 #include "base/files/file_path_watcher.h" | |
16 #include "base/task.h" | 12 #include "base/task.h" |
17 #include "base/threading/thread.h" | 13 #include "base/threading/thread.h" |
18 #include "net/base/net_errors.h" | 14 #include "net/base/net_errors.h" |
19 #include "net/base/network_change_notifier_netlink_linux.h" | 15 #include "net/base/network_change_notifier_netlink_linux.h" |
20 | 16 |
21 using ::base::files::FilePathWatcher; | |
22 | |
23 namespace net { | 17 namespace net { |
24 | 18 |
25 namespace { | 19 namespace { |
26 | 20 |
27 const int kInvalidSocket = -1; | 21 const int kInvalidSocket = -1; |
28 | 22 |
29 class DNSWatchDelegate : public FilePathWatcher::Delegate { | |
30 public: | |
31 explicit DNSWatchDelegate(Callback0::Type* callback) | |
32 : callback_(callback) {} | |
33 virtual ~DNSWatchDelegate() {} | |
34 // FilePathWatcher::Delegate interface | |
35 virtual void OnFilePathChanged(const FilePath& path) OVERRIDE; | |
36 virtual void OnFilePathError(const FilePath& path) OVERRIDE; | |
37 private: | |
38 scoped_ptr<Callback0::Type> callback_; | |
39 DISALLOW_COPY_AND_ASSIGN(DNSWatchDelegate); | |
40 }; | |
41 | |
42 void DNSWatchDelegate::OnFilePathChanged(const FilePath& path) { | |
43 // Calls NetworkChangeNotifier::NotifyObserversOfDNSChange(). | |
44 if (callback_.get()) | |
45 callback_->Run(); | |
46 } | |
47 | |
48 void DNSWatchDelegate::OnFilePathError(const FilePath& path) { | |
49 LOG(ERROR) << "DNSWatchDelegate::OnFilePathError for " << path.value(); | |
50 } | |
51 | |
52 } // namespace | 23 } // namespace |
53 | 24 |
54 class NetworkChangeNotifierLinux::Thread | 25 class NetworkChangeNotifierLinux::Thread |
55 : public base::Thread, public MessageLoopForIO::Watcher { | 26 : public base::Thread, public MessageLoopForIO::Watcher { |
56 public: | 27 public: |
57 Thread(); | 28 Thread(); |
58 virtual ~Thread(); | 29 virtual ~Thread(); |
59 | 30 |
60 // MessageLoopForIO::Watcher: | 31 // MessageLoopForIO::Watcher: |
61 virtual void OnFileCanReadWithoutBlocking(int fd); | 32 virtual void OnFileCanReadWithoutBlocking(int fd); |
62 virtual void OnFileCanWriteWithoutBlocking(int /* fd */); | 33 virtual void OnFileCanWriteWithoutBlocking(int /* fd */); |
63 | 34 |
64 protected: | 35 protected: |
65 // base::Thread | 36 // base::Thread |
66 virtual void Init(); | 37 virtual void Init(); |
67 virtual void CleanUp(); | 38 virtual void CleanUp(); |
68 | 39 |
69 private: | 40 private: |
70 void NotifyObserversOfIPAddressChange() { | 41 void NotifyObserversOfIPAddressChange() { |
71 NetworkChangeNotifier::NotifyObserversOfIPAddressChange(); | 42 NetworkChangeNotifier::NotifyObserversOfIPAddressChange(); |
72 } | 43 } |
73 | 44 |
74 void NotifyObserversOfDNSChange() { | |
75 NetworkChangeNotifier::NotifyObserversOfDNSChange(); | |
76 } | |
77 | |
78 // Starts listening for netlink messages. Also handles the messages if there | 45 // Starts listening for netlink messages. Also handles the messages if there |
79 // are any available on the netlink socket. | 46 // are any available on the netlink socket. |
80 void ListenForNotifications(); | 47 void ListenForNotifications(); |
81 | 48 |
82 // Attempts to read from the netlink socket into |buf| of length |len|. | 49 // Attempts to read from the netlink socket into |buf| of length |len|. |
83 // Returns the bytes read on synchronous success and ERR_IO_PENDING if the | 50 // Returns the bytes read on synchronous success and ERR_IO_PENDING if the |
84 // recv() would block. Otherwise, it returns a net error code. | 51 // recv() would block. Otherwise, it returns a net error code. |
85 int ReadNotificationMessage(char* buf, size_t len); | 52 int ReadNotificationMessage(char* buf, size_t len); |
86 | 53 |
87 // The netlink socket descriptor. | 54 // The netlink socket descriptor. |
88 int netlink_fd_; | 55 int netlink_fd_; |
89 MessageLoopForIO::FileDescriptorWatcher netlink_watcher_; | 56 MessageLoopForIO::FileDescriptorWatcher netlink_watcher_; |
90 | 57 |
91 // Technically only needed for ChromeOS, but it's ugly to #ifdef out. | 58 // Technically only needed for ChromeOS, but it's ugly to #ifdef out. |
92 ScopedRunnableMethodFactory<Thread> method_factory_; | 59 ScopedRunnableMethodFactory<Thread> method_factory_; |
93 | 60 |
94 // Used to watch for changes to /etc/resolv.conf and /etc/hosts. | |
95 scoped_ptr<base::files::FilePathWatcher> resolv_file_watcher_; | |
96 scoped_ptr<base::files::FilePathWatcher> hosts_file_watcher_; | |
97 scoped_refptr<DNSWatchDelegate> file_watcher_delegate_; | |
98 | |
99 DISALLOW_COPY_AND_ASSIGN(Thread); | 61 DISALLOW_COPY_AND_ASSIGN(Thread); |
100 }; | 62 }; |
101 | 63 |
102 NetworkChangeNotifierLinux::Thread::Thread() | 64 NetworkChangeNotifierLinux::Thread::Thread() |
103 : base::Thread("NetworkChangeNotifier"), | 65 : base::Thread("NetworkChangeNotifier"), |
104 netlink_fd_(kInvalidSocket), | 66 netlink_fd_(kInvalidSocket), |
105 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { | 67 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {} |
106 } | |
107 | 68 |
108 NetworkChangeNotifierLinux::Thread::~Thread() {} | 69 NetworkChangeNotifierLinux::Thread::~Thread() {} |
109 | 70 |
110 void NetworkChangeNotifierLinux::Thread::Init() { | 71 void NetworkChangeNotifierLinux::Thread::Init() { |
111 resolv_file_watcher_.reset(new FilePathWatcher); | |
112 hosts_file_watcher_.reset(new FilePathWatcher); | |
113 file_watcher_delegate_ = new DNSWatchDelegate(NewCallback(this, | |
114 &NetworkChangeNotifierLinux::Thread::NotifyObserversOfDNSChange)); | |
115 if (!resolv_file_watcher_->Watch( | |
116 FilePath(FILE_PATH_LITERAL("/etc/resolv.conf")), | |
117 file_watcher_delegate_.get())) { | |
118 LOG(ERROR) << "Failed to setup watch for /etc/resolv.conf"; | |
119 } | |
120 if (!hosts_file_watcher_->Watch(FilePath(FILE_PATH_LITERAL("/etc/hosts")), | |
121 file_watcher_delegate_.get())) { | |
122 LOG(ERROR) << "Failed to setup watch for /etc/hosts"; | |
123 } | |
124 netlink_fd_ = InitializeNetlinkSocket(); | 72 netlink_fd_ = InitializeNetlinkSocket(); |
125 if (netlink_fd_ < 0) { | 73 if (netlink_fd_ < 0) { |
126 netlink_fd_ = kInvalidSocket; | 74 netlink_fd_ = kInvalidSocket; |
127 return; | 75 return; |
128 } | 76 } |
129 ListenForNotifications(); | 77 ListenForNotifications(); |
130 } | 78 } |
131 | 79 |
132 void NetworkChangeNotifierLinux::Thread::CleanUp() { | 80 void NetworkChangeNotifierLinux::Thread::CleanUp() { |
133 if (netlink_fd_ != kInvalidSocket) { | 81 if (netlink_fd_ != kInvalidSocket) { |
134 if (HANDLE_EINTR(close(netlink_fd_)) != 0) | 82 if (HANDLE_EINTR(close(netlink_fd_)) != 0) |
135 PLOG(ERROR) << "Failed to close socket"; | 83 PLOG(ERROR) << "Failed to close socket"; |
136 netlink_fd_ = kInvalidSocket; | 84 netlink_fd_ = kInvalidSocket; |
137 netlink_watcher_.StopWatchingFileDescriptor(); | 85 netlink_watcher_.StopWatchingFileDescriptor(); |
138 } | 86 } |
139 // Kill watchers early to make sure they won't try to call | |
140 // into us via the delegate during destruction. | |
141 resolv_file_watcher_.reset(); | |
142 hosts_file_watcher_.reset(); | |
143 } | 87 } |
144 | 88 |
145 void NetworkChangeNotifierLinux::Thread::OnFileCanReadWithoutBlocking(int fd) { | 89 void NetworkChangeNotifierLinux::Thread::OnFileCanReadWithoutBlocking(int fd) { |
146 DCHECK_EQ(fd, netlink_fd_); | 90 DCHECK_EQ(fd, netlink_fd_); |
147 ListenForNotifications(); | 91 ListenForNotifications(); |
148 } | 92 } |
149 | 93 |
150 void NetworkChangeNotifierLinux::Thread::OnFileCanWriteWithoutBlocking( | 94 void NetworkChangeNotifierLinux::Thread::OnFileCanWriteWithoutBlocking( |
151 int /* fd */) { | 95 int /* fd */) { |
152 NOTREACHED(); | 96 NOTREACHED(); |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 // check that the notifier thread shut down properly. | 160 // check that the notifier thread shut down properly. |
217 notifier_thread_->Stop(); | 161 notifier_thread_->Stop(); |
218 } | 162 } |
219 | 163 |
220 bool NetworkChangeNotifierLinux::IsCurrentlyOffline() const { | 164 bool NetworkChangeNotifierLinux::IsCurrentlyOffline() const { |
221 // TODO(eroman): http://crbug.com/53473 | 165 // TODO(eroman): http://crbug.com/53473 |
222 return false; | 166 return false; |
223 } | 167 } |
224 | 168 |
225 } // namespace net | 169 } // namespace net |
OLD | NEW |