1/* 2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include "config.h" 27#include "NetworkStateNotifier.h" 28 29#include <wtf/MainThread.h> 30#include <wtf/Vector.h> 31 32#include <winsock2.h> 33#include <iphlpapi.h> 34 35namespace WebCore { 36 37void NetworkStateNotifier::updateState() 38{ 39 // Assume that we're online until proven otherwise. 40 m_isOnLine = true; 41 42 Vector<char> buffer; 43 DWORD size = 0; 44 45 if (::GetAdaptersAddresses(AF_UNSPEC, 0, 0, 0, &size) != ERROR_BUFFER_OVERFLOW) 46 return; 47 48 buffer.resize(size); 49 PIP_ADAPTER_ADDRESSES addresses = reinterpret_cast<PIP_ADAPTER_ADDRESSES>(buffer.data()); 50 51 if (::GetAdaptersAddresses(AF_UNSPEC, 0, 0, addresses, &size) != ERROR_SUCCESS) { 52 // We couldn't determine whether we're online or not, so assume that we are. 53 return; 54 } 55 56 for (; addresses; addresses = addresses->Next) { 57 if (addresses->IfType == MIB_IF_TYPE_LOOPBACK) 58 continue; 59 60 if (addresses->OperStatus != IfOperStatusUp) 61 continue; 62 63 // We found an interface that was up. 64 return; 65 } 66 67 // We didn't find any valid interfaces, so we must be offline. 68 m_isOnLine = false; 69} 70 71void NetworkStateNotifier::addressChanged() 72{ 73 bool oldOnLine = m_isOnLine; 74 75 updateState(); 76 77 if (m_isOnLine == oldOnLine) 78 return; 79 80 notifyNetworkStateChange(); 81} 82 83void NetworkStateNotifier::callAddressChanged(void* context) 84{ 85 static_cast<NetworkStateNotifier*>(context)->addressChanged(); 86} 87 88void CALLBACK NetworkStateNotifier::addrChangeCallback(void* context, BOOLEAN timedOut) 89{ 90 // NotifyAddrChange only notifies us of a single address change. Now that we've been notified, 91 // we need to call it again so we'll get notified the *next* time. 92 static_cast<NetworkStateNotifier*>(context)->registerForAddressChange(); 93 94 callOnMainThread(callAddressChanged, context); 95} 96 97void NetworkStateNotifier::registerForAddressChange() 98{ 99 HANDLE handle; 100 ::NotifyAddrChange(&handle, &m_overlapped); 101} 102 103NetworkStateNotifier::NetworkStateNotifier() 104 : m_isOnLine(false) 105{ 106 updateState(); 107 108 memset(&m_overlapped, 0, sizeof(m_overlapped)); 109 110// FIXME: Check m_overlapped on WinCE. 111#if !OS(WINCE) 112 m_overlapped.hEvent = ::CreateEvent(0, false, false, 0); 113 114 ::RegisterWaitForSingleObject(&m_waitHandle, m_overlapped.hEvent, addrChangeCallback, this, INFINITE, 0); 115 116 registerForAddressChange(); 117#endif 118} 119 120} // namespace WebCore 121