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/base/network_change_notifier_win.h" | 5 #include "net/base/network_change_notifier_win.h" |
6 | 6 |
7 #include <iphlpapi.h> | 7 #include <iphlpapi.h> |
8 #include <winsock2.h> | 8 #include <winsock2.h> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
58 dns_config_service_thread_(new DnsConfigServiceThread()), | 58 dns_config_service_thread_(new DnsConfigServiceThread()), |
59 last_computed_connection_type_(RecomputeCurrentConnectionType()), | 59 last_computed_connection_type_(RecomputeCurrentConnectionType()), |
60 last_announced_offline_(last_computed_connection_type_ == | 60 last_announced_offline_(last_computed_connection_type_ == |
61 CONNECTION_NONE), | 61 CONNECTION_NONE), |
62 weak_factory_(this) { | 62 weak_factory_(this) { |
63 memset(&addr_overlapped_, 0, sizeof addr_overlapped_); | 63 memset(&addr_overlapped_, 0, sizeof addr_overlapped_); |
64 addr_overlapped_.hEvent = WSACreateEvent(); | 64 addr_overlapped_.hEvent = WSACreateEvent(); |
65 } | 65 } |
66 | 66 |
67 NetworkChangeNotifierWin::~NetworkChangeNotifierWin() { | 67 NetworkChangeNotifierWin::~NetworkChangeNotifierWin() { |
68 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); | |
68 if (is_watching_) { | 69 if (is_watching_) { |
69 CancelIPChangeNotify(&addr_overlapped_); | 70 CancelIPChangeNotify(&addr_overlapped_); |
mmenke
2017/05/26 20:20:03
This class uses an overlapped structure, which I d
| |
70 addr_watcher_.StopWatching(); | 71 addr_watcher_.StopWatching(); |
71 } | 72 } |
72 WSACloseEvent(addr_overlapped_.hEvent); | 73 WSACloseEvent(addr_overlapped_.hEvent); |
73 } | 74 } |
74 | 75 |
75 // static | 76 // static |
76 NetworkChangeNotifier::NetworkChangeCalculatorParams | 77 NetworkChangeNotifier::NetworkChangeCalculatorParams |
77 NetworkChangeNotifierWin::NetworkChangeCalculatorParamsWin() { | 78 NetworkChangeNotifierWin::NetworkChangeCalculatorParamsWin() { |
78 NetworkChangeCalculatorParams params; | 79 NetworkChangeCalculatorParams params; |
79 // Delay values arrived at by simple experimentation and adjusted so as to | 80 // Delay values arrived at by simple experimentation and adjusted so as to |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
129 // * Approach (2) took an average of 3.25 milliseconds to enumerate the | 130 // * Approach (2) took an average of 3.25 milliseconds to enumerate the |
130 // adapters. | 131 // adapters. |
131 // * Approach (3) took an average of 0.8 ms to enumerate the providers. | 132 // * Approach (3) took an average of 0.8 ms to enumerate the providers. |
132 // | 133 // |
133 // In terms of correctness, all three approaches were comparable for the simple | 134 // In terms of correctness, all three approaches were comparable for the simple |
134 // experiments I ran... However none of them correctly returned "offline" when | 135 // experiments I ran... However none of them correctly returned "offline" when |
135 // executing 'ipconfig /release'. | 136 // executing 'ipconfig /release'. |
136 // | 137 // |
137 NetworkChangeNotifier::ConnectionType | 138 NetworkChangeNotifier::ConnectionType |
138 NetworkChangeNotifierWin::RecomputeCurrentConnectionType() const { | 139 NetworkChangeNotifierWin::RecomputeCurrentConnectionType() const { |
139 DCHECK(CalledOnValidThread()); | 140 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
140 | 141 |
141 EnsureWinsockInit(); | 142 EnsureWinsockInit(); |
142 | 143 |
143 // The following code was adapted from: | 144 // The following code was adapted from: |
144 // http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/net/notifier/ base/win/async_network_alive_win32.cc?view=markup&pathrev=47343 | 145 // http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/net/notifier/ base/win/async_network_alive_win32.cc?view=markup&pathrev=47343 |
145 // The main difference is we only call WSALookupServiceNext once, whereas | 146 // The main difference is we only call WSALookupServiceNext once, whereas |
146 // the earlier code would traverse the entire list and pass LUP_FLUSHPREVIOUS | 147 // the earlier code would traverse the entire list and pass LUP_FLUSHPREVIOUS |
147 // to skip past the large results. | 148 // to skip past the large results. |
148 | 149 |
149 HANDLE ws_handle; | 150 HANDLE ws_handle; |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
211 return last_computed_connection_type_; | 212 return last_computed_connection_type_; |
212 } | 213 } |
213 | 214 |
214 void NetworkChangeNotifierWin::SetCurrentConnectionType( | 215 void NetworkChangeNotifierWin::SetCurrentConnectionType( |
215 ConnectionType connection_type) { | 216 ConnectionType connection_type) { |
216 base::AutoLock auto_lock(last_computed_connection_type_lock_); | 217 base::AutoLock auto_lock(last_computed_connection_type_lock_); |
217 last_computed_connection_type_ = connection_type; | 218 last_computed_connection_type_ = connection_type; |
218 } | 219 } |
219 | 220 |
220 void NetworkChangeNotifierWin::OnObjectSignaled(HANDLE object) { | 221 void NetworkChangeNotifierWin::OnObjectSignaled(HANDLE object) { |
221 DCHECK(CalledOnValidThread()); | 222 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
222 DCHECK(is_watching_); | 223 DCHECK(is_watching_); |
223 is_watching_ = false; | 224 is_watching_ = false; |
224 | 225 |
225 // Start watching for the next address change. | 226 // Start watching for the next address change. |
226 WatchForAddressChange(); | 227 WatchForAddressChange(); |
227 | 228 |
228 NotifyObservers(); | 229 NotifyObservers(); |
229 } | 230 } |
230 | 231 |
231 void NetworkChangeNotifierWin::NotifyObservers() { | 232 void NetworkChangeNotifierWin::NotifyObservers() { |
232 DCHECK(CalledOnValidThread()); | 233 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
233 SetCurrentConnectionType(RecomputeCurrentConnectionType()); | 234 SetCurrentConnectionType(RecomputeCurrentConnectionType()); |
234 NotifyObserversOfIPAddressChange(); | 235 NotifyObserversOfIPAddressChange(); |
235 | 236 |
236 // Calling GetConnectionType() at this very moment is likely to give | 237 // Calling GetConnectionType() at this very moment is likely to give |
237 // the wrong result, so we delay that until a little bit later. | 238 // the wrong result, so we delay that until a little bit later. |
238 // | 239 // |
239 // The one second delay chosen here was determined experimentally | 240 // The one second delay chosen here was determined experimentally |
240 // by adamk on Windows 7. | 241 // by adamk on Windows 7. |
241 // If after one second we determine we are still offline, we will | 242 // If after one second we determine we are still offline, we will |
242 // delay again. | 243 // delay again. |
243 offline_polls_ = 0; | 244 offline_polls_ = 0; |
244 timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(1), this, | 245 timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(1), this, |
245 &NetworkChangeNotifierWin::NotifyParentOfConnectionTypeChange); | 246 &NetworkChangeNotifierWin::NotifyParentOfConnectionTypeChange); |
246 } | 247 } |
247 | 248 |
248 void NetworkChangeNotifierWin::WatchForAddressChange() { | 249 void NetworkChangeNotifierWin::WatchForAddressChange() { |
249 DCHECK(CalledOnValidThread()); | 250 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
250 DCHECK(!is_watching_); | 251 DCHECK(!is_watching_); |
251 | 252 |
252 // NotifyAddrChange occasionally fails with ERROR_OPEN_FAILED for unknown | 253 // NotifyAddrChange occasionally fails with ERROR_OPEN_FAILED for unknown |
253 // reasons. More rarely, it's also been observed failing with | 254 // reasons. More rarely, it's also been observed failing with |
254 // ERROR_NO_SYSTEM_RESOURCES. When either of these happens, we retry later. | 255 // ERROR_NO_SYSTEM_RESOURCES. When either of these happens, we retry later. |
255 if (!WatchForAddressChangeInternal()) { | 256 if (!WatchForAddressChangeInternal()) { |
256 ++sequential_failures_; | 257 ++sequential_failures_; |
257 | 258 |
258 // TODO(mmenke): If the UMA histograms indicate that this fixes | 259 // TODO(mmenke): If the UMA histograms indicate that this fixes |
259 // http://crbug.com/69198, remove this histogram and consider reducing the | 260 // http://crbug.com/69198, remove this histogram and consider reducing the |
(...skipping 20 matching lines...) Expand all Loading... | |
280 if (sequential_failures_ < 2000) { | 281 if (sequential_failures_ < 2000) { |
281 UMA_HISTOGRAM_COUNTS_10000("Net.NotifyAddrChangeFailures", | 282 UMA_HISTOGRAM_COUNTS_10000("Net.NotifyAddrChangeFailures", |
282 sequential_failures_); | 283 sequential_failures_); |
283 } | 284 } |
284 | 285 |
285 is_watching_ = true; | 286 is_watching_ = true; |
286 sequential_failures_ = 0; | 287 sequential_failures_ = 0; |
287 } | 288 } |
288 | 289 |
289 bool NetworkChangeNotifierWin::WatchForAddressChangeInternal() { | 290 bool NetworkChangeNotifierWin::WatchForAddressChangeInternal() { |
290 DCHECK(CalledOnValidThread()); | 291 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
291 | 292 |
292 if (!dns_config_service_thread_->IsRunning()) { | 293 if (!dns_config_service_thread_->IsRunning()) { |
293 dns_config_service_thread_->StartWithOptions( | 294 dns_config_service_thread_->StartWithOptions( |
294 base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); | 295 base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); |
295 } | 296 } |
296 | 297 |
297 ResetEventIfSignaled(addr_overlapped_.hEvent); | 298 ResetEventIfSignaled(addr_overlapped_.hEvent); |
298 HANDLE handle = NULL; | 299 HANDLE handle = NULL; |
299 DWORD ret = NotifyAddrChange(&handle, &addr_overlapped_); | 300 DWORD ret = NotifyAddrChange(&handle, &addr_overlapped_); |
300 if (ret != ERROR_IO_PENDING) | 301 if (ret != ERROR_IO_PENDING) |
(...skipping 22 matching lines...) Expand all Loading... | |
323 | 324 |
324 NotifyObserversOfConnectionTypeChange(); | 325 NotifyObserversOfConnectionTypeChange(); |
325 double max_bandwidth_mbps = 0.0; | 326 double max_bandwidth_mbps = 0.0; |
326 ConnectionType connection_type = CONNECTION_NONE; | 327 ConnectionType connection_type = CONNECTION_NONE; |
327 GetCurrentMaxBandwidthAndConnectionType(&max_bandwidth_mbps, | 328 GetCurrentMaxBandwidthAndConnectionType(&max_bandwidth_mbps, |
328 &connection_type); | 329 &connection_type); |
329 NotifyObserversOfMaxBandwidthChange(max_bandwidth_mbps, connection_type); | 330 NotifyObserversOfMaxBandwidthChange(max_bandwidth_mbps, connection_type); |
330 } | 331 } |
331 | 332 |
332 } // namespace net | 333 } // namespace net |
OLD | NEW |