src/net/base/network_change_notifier_win.cc
// This implementation does not return the actual connection type but merely
// determines if the user is "online" (in which case it returns
// CONNECTION_UNKNOWN) or "offline" (and then it returns CONNECTION_NONE).
// This is challenging since the only thing we can test with certainty is
// whether a *particular* host is reachable.
//
// While we can't conclusively determine when a user is "online", we can at
// least reliably recognize some of the situtations when they are clearly
// "offline". For example, if the user's laptop is not plugged into an ethernet
// network and is not connected to any wireless networks, it must be offline.
//
// There are a number of different ways to implement this on Windows, each with
// their pros and cons. Here is a comparison of various techniques considered:
//
// (1) Use InternetGetConnectedState (wininet.dll). This function is really easy
// to use (literally a one-liner), and runs quickly. The drawback is it adds a
// dependency on the wininet DLL.
//
// (2) Enumerate all of the network interfaces using GetAdaptersAddresses
// (iphlpapi.dll), and assume we are "online" if there is at least one interface
// that is connected, and that interface is not a loopback or tunnel.
//
// Safari on Windows has a fairly simple implementation that does this:
// http://trac.webkit.org/browser/trunk/WebCore/platform/network/win/NetworkStateNotifierWin.cpp.
//
// Mozilla similarly uses this approach:
// http://mxr.mozilla.org/mozilla1.9.2/source/netwerk/system/win32/nsNotifyAddrListener.cpp
//
// The biggest drawback to this approach is it is quite complicated.
// WebKit's implementation for example doesn't seem to test for ICS gateways
// (internet connection sharing), whereas Mozilla's implementation has extra
// code to guess that.
//
// (3) The method used in this file comes from google talk, and is similar to
// method (2). The main difference is it enumerates the winsock namespace
// providers rather than the actual adapters.
//
// I ran some benchmarks comparing the performance of each on my Windows 7
// workstation. Here is what I found:
//   * Approach (1) was pretty much zero-cost after the initial call.
//   * Approach (2) took an average of 3.25 milliseconds to enumerate the
//     adapters.
//   * Approach (3) took an average of 0.8 ms to enumerate the providers.
//
// In terms of correctness, all three approaches were comparable for the simple
// experiments I ran... However none of them correctly returned "offline" when
// executing 'ipconfig /release'.
//
// static
This implementation does not return the actual connection type but merely
determines if the user is "online" (in which case it returns
CONNECTION_UNKNOWN) or "offline" (and then it returns CONNECTION_NONE).
This is challenging since the only thing we can test with certainty is
whether a *particular* host is reachable.

While we can't conclusively determine when a user is "online", we can at
least reliably recognize some of the situtations when they are clearly
"offline". For example, if the user's laptop is not plugged into an ethernet
network and is not connected to any wireless networks, it must be offline.

There are a number of different ways to implement this on Windows, each with
their pros and cons. Here is a comparison of various techniques considered.



(2) Enumerate all of the network interfaces using GetAdaptersAddresses
(iphlpapi.dll), and assume we are "online" if there is at least one interface
that is connected, and that interface is not a loopback or tunnel.





The biggest drawback to this approach is it is quite complicated.
WebKit's implementation for example doesn't seem to test for ICS gateways
(internet connection sharing), whereas Mozilla's implementation has extra
code to guess that.

(3) The method used in this file comes from google talk, and is similar to
method (2). The main difference is it enumerates the winsock namespace
providers rather than the actual adapters.

I ran some benchmarks comparing the performance of each on my Windows 7
workstation. Here is what I found:
Approach (1) was pretty much zero-cost after the initial call.
Approach (2) took an average of 3.25 milliseconds to enumerate the
adapters.
Approach (3) took an average of 0.8 ms to enumerate the providers.

In terms of correctness, all three approaches were comparable for the simple
experiments I ran... However none of them correctly returned "offline" when
executing 'ipconfig /release'.

static
This implementation does not return the actual connection type but merely determines if the user is " online " ( in which case it returns CONNECTION_UNKNOWN ) or " offline " ( and then it returns CONNECTION_NONE ) . This is challenging since the only thing we can test with certainty is whether a * particular * host is reachable . While we can ' t conclusively determine when a user is " online " we can at least reliably recognize some of the situtations when they are clearly " offline " . For example if the user ' s laptop is not plugged into an ethernet network and is not connected to any wireless networks it must be offline . There are a number of different ways to implement this on Windows each with their pros and cons . Here is a comparison of various techniques considered . ( 2 ) Enumerate all of the network interfaces using GetAdaptersAddresses ( iphlpapi . dll ) and assume we are " online " if there is at least one interface that is connected and that interface is not a loopback or tunnel . The biggest drawback to this approach is it is quite complicated . WebKit ' s implementation for example doesn ' t seem to test for ICS gateways ( internet connection sharing ) whereas Mozilla ' s implementation has extra code to guess that . ( 3 ) The method used in this file comes from google talk and is similar to method ( 2 ) . The main difference is it enumerates the winsock namespace providers rather than the actual adapters . I ran some benchmarks comparing the performance of each on my Windows 7 workstation . Here is what I found : Approach ( 1 ) was pretty much zero - cost after the initial call . Approach ( 2 ) took an average of 3 . 25 milliseconds to enumerate the adapters . Approach ( 3 ) took an average of 0 . 8 ms to enumerate the providers . In terms of correctness all three approaches were comparable for the simple experiments I ran ... However none of them correctly returned " offline " when executing ' ipconfig / release ' . static
NetworkChangeNotifier::ConnectionType
NetworkChangeNotifierWin::RecomputeCurrentConnectionType() {
  EnsureWinsockInit();
  HANDLE ws_handle;
  WSAQUERYSET query_set = {0};
  query_set.dwSize = sizeof(WSAQUERYSET);
  query_set.dwNameSpace = NS_NLA;
  if (0 != WSALookupServiceBegin(&query_set, LUP_RETURN_ALL,
                                 &ws_handle)) {
    LOG(ERROR) << "WSALookupServiceBegin failed with: " << WSAGetLastError();
    return NetworkChangeNotifier::CONNECTION_UNKNOWN;
  }
  bool found_connection = false;
  char result_buffer[sizeof(WSAQUERYSET) + 256] = {0};
  DWORD length = sizeof(result_buffer);
  reinterpret_cast<WSAQUERYSET*>(&result_buffer[0])->dwSize =
      sizeof(WSAQUERYSET);
  int result = WSALookupServiceNext(
      ws_handle,
      LUP_RETURN_NAME,
      &length,
      reinterpret_cast<WSAQUERYSET*>(&result_buffer[0]));
  if (result == 0) {
    found_connection = true;
  } else {
    DCHECK_EQ(SOCKET_ERROR, result);
    result = WSAGetLastError();
    if (result == WSAEFAULT) {
      found_connection = true;
    } else if (result == WSA_E_NO_MORE || result == WSAENOMORE) {
    } else {
      LOG(WARNING) << "WSALookupServiceNext() failed with:" << result;
    }
  }
  result = WSALookupServiceEnd(ws_handle);
  LOG_IF(ERROR, result != 0)
      << "WSALookupServiceEnd() failed with: " << result;
  return found_connection ? ConnectionTypeFromInterfaces()
                          : NetworkChangeNotifier::CONNECTION_NONE;
}
NetworkChangeNotifier :: ConnectionType NetworkChangeNotifierWin :: RecomputeCurrentConnectionType ( ) { EnsureWinsockInit ( ) ; HANDLE ws_handle ; WSAQUERYSET query_set = { 0 } ; query_set . dwSize = sizeof ( WSAQUERYSET ) ; query_set . dwNameSpace = NS_NLA ; if ( 0 != WSALookupServiceBegin ( & query_set , LUP_RETURN_ALL , & ws_handle ) ) { LOG ( ERROR ) << " " << WSAGetLastError ( ) ; return NetworkChangeNotifier :: CONNECTION_UNKNOWN ; } bool found_connection = false ; char result_buffer [ sizeof ( WSAQUERYSET ) + 256 ] = { 0 } ; DWORD length = sizeof ( result_buffer ) ; reinterpret_cast < WSAQUERYSET * > ( & result_buffer [ 0 ] ) -> dwSize = sizeof ( WSAQUERYSET ) ; int result = WSALookupServiceNext ( ws_handle , LUP_RETURN_NAME , & length , reinterpret_cast < WSAQUERYSET * > ( & result_buffer [ 0 ] ) ) ; if ( result == 0 ) { found_connection = true ; } else { DCHECK_EQ ( SOCKET_ERROR , result ) ; result = WSAGetLastError ( ) ; if ( result == WSAEFAULT ) { found_connection = true ; } else if ( result == WSA_E_NO_MORE || result == WSAENOMORE ) { } else { LOG ( WARNING ) << " " << result ; } } result = WSALookupServiceEnd ( ws_handle ) ; LOG_IF ( ERROR , result != 0 ) << " " << result ; return found_connection ? ConnectionTypeFromInterfaces ( ) : NetworkChangeNotifier :: CONNECTION_NONE ; }
This implementation does not return the actual connection type but merely
determines if the user is "online" (in which case it returns
CONNECTION_UNKNOWN) or "offline" (and then it returns CONNECTION_NONE).
This implementation does not return the actual connection type but merely determines if the user is " online " ( in which case it returns CONNECTION_UNKNOWN ) or " offline " ( and then it returns CONNECTION_NONE ) .
// The following code was adapted from: // http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/net/notifier/base/win/async_network_alive_win32.cc?view=markup&pathrev=47343 // The main difference is we only call WSALookupServiceNext once, whereas // the earlier code would traverse the entire list and pass LUP_FLUSHPREVIOUS // to skip past the large results. // Initiate a client query to iterate through the // currently connected networks. // Retrieve the first available network. In this function, we only // need to know whether or not there is network connection. // Allocate 256 bytes for name, it should be enough for most cases. // If the name is longer, it is OK as we will check the code returned and // set correct network status. // Found a connection! // Error code WSAEFAULT means there is a network connection but the // result_buffer size is too small to contain the results. The // variable "length" returned from WSALookupServiceNext is the minimum // number of bytes required. We do not need to retrieve detail info, // it is enough knowing there was a connection. // There was nothing to iterate over! // TODO(droger): Return something more detailed than CONNECTION_UNKNOWN.