| Index: chrome/browser/sync/notifier/base/win/async_network_alive_win32.cc
|
| ===================================================================
|
| --- chrome/browser/sync/notifier/base/win/async_network_alive_win32.cc (revision 46353)
|
| +++ chrome/browser/sync/notifier/base/win/async_network_alive_win32.cc (working copy)
|
| @@ -1,251 +0,0 @@
|
| -// Copyright (c) 2009 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "chrome/browser/sync/notifier/base/async_network_alive.h"
|
| -
|
| -#include <winsock2.h>
|
| -
|
| -#include "base/scoped_handle_win.h"
|
| -#include "chrome/browser/sync/notifier/base/utils.h"
|
| -#include "talk/base/common.h"
|
| -#include "talk/base/criticalsection.h"
|
| -#include "talk/base/logging.h"
|
| -#include "talk/base/physicalsocketserver.h"
|
| -#include "talk/base/scoped_ptr.h"
|
| -
|
| -namespace notifier {
|
| -
|
| -class PlatformNetworkInfo {
|
| - public:
|
| - PlatformNetworkInfo() : ws_handle_(NULL), event_handle_(NULL) {
|
| - }
|
| -
|
| - ~PlatformNetworkInfo() {
|
| - Close();
|
| - }
|
| -
|
| - void Close() {
|
| - talk_base::CritScope crit_scope(&crit_sect_);
|
| - if (ws_handle_) {
|
| - if (event_handle_.IsValid()) // Unblock any waiting for network changes.
|
| - SetEvent(event_handle_.Get());
|
| - // finishes the iteration.
|
| - VERIFY(WSALookupServiceEnd(ws_handle_) == 0);
|
| - ws_handle_ = NULL;
|
| - LOG(INFO) << "WSACleanup 1";
|
| - ::WSACleanup();
|
| - }
|
| - }
|
| -
|
| - bool IsAlive(bool* error) {
|
| - ASSERT(error);
|
| - *error = false;
|
| -
|
| - // If IsAlive was previously called, we need a new handle.
|
| - // Why? If we use the same handle, we only get diffs on what changed
|
| - // which isn't what we want.
|
| - Close();
|
| - int result = Initialize();
|
| - if (result != 0) {
|
| - LOG(ERROR) << "failed:" << result;
|
| - // Default to alive on error.
|
| - *error = true;
|
| - return true;
|
| - }
|
| -
|
| - bool alive = false;
|
| -
|
| - // Retrieve network info and move to next one. 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.
|
| - char result_buffer[sizeof(WSAQUERYSET) + 256] = {0};
|
| - bool flush_previous_result = false;
|
| - do {
|
| - DWORD control_flags = LUP_RETURN_NAME;
|
| - if (flush_previous_result) {
|
| - control_flags |= LUP_FLUSHPREVIOUS;
|
| - }
|
| - DWORD length = sizeof(result_buffer);
|
| - reinterpret_cast<WSAQUERYSET*>(&result_buffer[0])->dwSize =
|
| - sizeof(WSAQUERYSET);
|
| - // ws_handle_ may be NULL (if exiting), but the call will simply fail
|
| - int result = ::WSALookupServiceNext(
|
| - ws_handle_,
|
| - control_flags,
|
| - &length,
|
| - reinterpret_cast<WSAQUERYSET*>(&result_buffer[0]));
|
| -
|
| - if (result == 0) {
|
| - // get at least one connection, return "connected".
|
| - alive = true;
|
| - } else {
|
| - ASSERT(result == SOCKET_ERROR);
|
| - result = ::WSAGetLastError();
|
| - if (result == WSA_E_NO_MORE || result == WSAENOMORE) {
|
| - break;
|
| - }
|
| -
|
| - // 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.
|
| - // Return "alive" in this case.
|
| - if (result == WSAEFAULT) {
|
| - alive = true;
|
| - flush_previous_result = true;
|
| - } else {
|
| - LOG(WARNING) << "failed:" << result;
|
| - *error = true;
|
| - break;
|
| - }
|
| - }
|
| - } while (true);
|
| -
|
| - LOG(INFO) << "alive: " << alive;
|
| - return alive;
|
| - }
|
| -
|
| - bool WaitForChange() {
|
| - // IsAlive must be called first.
|
| - int junk1 = 0, junk2 = 0;
|
| - DWORD bytes_returned = 0;
|
| - int result = SOCKET_ERROR;
|
| - {
|
| - talk_base::CritScope crit_scope(&crit_sect_);
|
| - if (!ws_handle_)
|
| - return false;
|
| - ASSERT(!event_handle_.IsValid());
|
| - event_handle_.Set(CreateEvent(NULL, FALSE, FALSE, NULL));
|
| - if (!event_handle_.IsValid()) {
|
| - LOG(WARNING) << "failed to CreateEvent";
|
| - return false;
|
| - }
|
| - WSAOVERLAPPED overlapped = {0};
|
| - overlapped.hEvent = event_handle_.Get();
|
| - WSACOMPLETION completion;
|
| - ::SetZero(completion);
|
| - completion.Type = NSP_NOTIFY_EVENT;
|
| - completion.Parameters.Event.lpOverlapped = &overlapped;
|
| -
|
| - LOG(INFO) << "calling WSANSPIoctl";
|
| - // Do a non-blocking request for change notification. event_handle_
|
| - // will get signaled when there is a change, so we wait on it later.
|
| - // It can also be signaled by Close() in order allow clean termination.
|
| - result = ::WSANSPIoctl(ws_handle_,
|
| - SIO_NSP_NOTIFY_CHANGE,
|
| - &junk1,
|
| - 0,
|
| - &junk2,
|
| - 0,
|
| - &bytes_returned,
|
| - &completion);
|
| - }
|
| - if (NO_ERROR != result) {
|
| - result = ::WSAGetLastError();
|
| - if (WSA_IO_PENDING != result) {
|
| - LOG(WARNING) << "failed: " << result;
|
| - event_handle_.Close();
|
| - return false;
|
| - }
|
| - }
|
| - LOG(INFO) << "waiting";
|
| - WaitForSingleObject(event_handle_.Get(), INFINITE);
|
| - event_handle_.Close();
|
| - LOG(INFO) << "changed";
|
| - return true;
|
| - }
|
| -
|
| - private:
|
| - int Initialize() {
|
| - WSADATA wsa_data;
|
| - LOG(INFO) << "calling WSAStartup";
|
| - int result = ::WSAStartup(MAKEWORD(2, 2), &wsa_data);
|
| - if (result != ERROR_SUCCESS) {
|
| - LOG(ERROR) << "failed:" << result;
|
| - return result;
|
| - }
|
| -
|
| - WSAQUERYSET query_set = {0};
|
| - query_set.dwSize = sizeof(WSAQUERYSET);
|
| - query_set.dwNameSpace = NS_NLA;
|
| - // Initiate a client query to iterate through the
|
| - // currently connected networks.
|
| - if (0 != ::WSALookupServiceBegin(&query_set, LUP_RETURN_ALL,
|
| - &ws_handle_)) {
|
| - result = ::WSAGetLastError();
|
| - LOG(INFO) << "WSACleanup 2";
|
| - ::WSACleanup();
|
| - ASSERT(ws_handle_ == NULL);
|
| - ws_handle_ = NULL;
|
| - return result;
|
| - }
|
| - return 0;
|
| - }
|
| - talk_base::CriticalSection crit_sect_;
|
| - HANDLE ws_handle_;
|
| - ScopedHandle event_handle_;
|
| - DISALLOW_COPY_AND_ASSIGN(PlatformNetworkInfo);
|
| -};
|
| -
|
| -class AsyncNetworkAliveWin32 : public AsyncNetworkAlive {
|
| - public:
|
| - AsyncNetworkAliveWin32() {
|
| - }
|
| -
|
| - virtual ~AsyncNetworkAliveWin32() {
|
| - if (network_info_) {
|
| - delete network_info_;
|
| - network_info_ = NULL;
|
| - }
|
| - }
|
| -
|
| - protected:
|
| - // SignalThread Interface
|
| - virtual void DoWork() {
|
| - if (!network_info_) {
|
| - network_info_ = new PlatformNetworkInfo();
|
| - } else {
|
| - // Since network_info is set, it means that
|
| - // we are suppose to wait for network state changes.
|
| - if (!network_info_->WaitForChange()) {
|
| - // The wait was aborted so we must be shutting down.
|
| - alive_ = false;
|
| - error_ = true;
|
| - return;
|
| - }
|
| - }
|
| -
|
| - if (network_info_->IsAlive(&error_)) {
|
| - // If there is an active connection, check that www.google.com:80
|
| - // is reachable.
|
| - talk_base::PhysicalSocketServer physical;
|
| - scoped_ptr<talk_base::Socket> socket(physical.CreateSocket(SOCK_STREAM));
|
| - if (socket->Connect(talk_base::SocketAddress("talk.google.com", 5222))) {
|
| - alive_ = false;
|
| - } else {
|
| - alive_ = true;
|
| - }
|
| - } else {
|
| - // If there are no available connections, then we aren't alive.
|
| - alive_ = false;
|
| - }
|
| - }
|
| -
|
| - virtual void OnWorkStop() {
|
| - if (network_info_) {
|
| - network_info_->Close();
|
| - }
|
| - }
|
| -
|
| - private:
|
| - DISALLOW_COPY_AND_ASSIGN(AsyncNetworkAliveWin32);
|
| -};
|
| -
|
| -AsyncNetworkAlive* AsyncNetworkAlive::Create() {
|
| - return new AsyncNetworkAliveWin32();
|
| -}
|
| -
|
| -} // namespace notifier
|
|
|