Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2360)

Unified Diff: chrome/browser/sync/notifier/base/win32/async_network_alive_win32.cc

Issue 194065: Initial commit of sync engine code to browser/sync.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Fixes to gtest include path, reverted syncapi. Created 11 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/sync/notifier/base/win32/async_network_alive_win32.cc
===================================================================
--- chrome/browser/sync/notifier/base/win32/async_network_alive_win32.cc (revision 0)
+++ chrome/browser/sync/notifier/base/win32/async_network_alive_win32.cc (revision 0)
@@ -0,0 +1,233 @@
+// 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 <winsock2.h>
+
+#include "chrome/browser/sync/notifier/base/async_network_alive.h"
+#include "chrome/browser/sync/notifier/base/utils.h"
+#include "talk/base/criticalsection.h"
+#include "talk/base/logging.h"
+#include "talk/base/scoped_ptr.h"
+#include "talk/base/common.h"
+#include "third_party/smartany/scoped_any.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_) // unblock any waiting for network changes
+ SetEvent(get(event_handle_));
+ // finishes the iteration.
+ VERIFY(WSALookupServiceEnd(ws_handle_) == 0);
+ ws_handle_ = NULL;
+ LOG_F(LS_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_F(LS_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_F(LS_WARNING) << "failed:" << result;
+ *error = true;
+ break;
+ }
+ }
+ } while (true);
+ LOG_F(LS_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_);
+ reset(event_handle_, ::CreateEvent(NULL, FALSE, FALSE, NULL));
+ if (!event_handle_) {
+ LOG_F(LS_WARNING) << "failed to CreateEvent";
+ return false;
+ }
+ WSAOVERLAPPED overlapped = {0};
+ overlapped.hEvent = get(event_handle_);
+ WSACOMPLETION completion;
+ ::SetZero(completion);
+ completion.Type = NSP_NOTIFY_EVENT;
+ completion.Parameters.Event.lpOverlapped = &overlapped;
+
+ LOG_F(LS_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_F(LS_WARNING) << "failed: " << result;
+ reset(event_handle_);
+ return false;
+ }
+ }
+ LOG_F(LS_INFO) << "waiting";
+ WaitForSingleObject(get(event_handle_), INFINITE);
+ reset(event_handle_);
+ LOG_F(LS_INFO) << "changed";
+ return true;
+ }
+
+ private:
+ int Initialize() {
+ WSADATA wsa_data;
+ LOG_F(LS_INFO) << "calling WSAStartup";
+ int result = ::WSAStartup(MAKEWORD(2, 2), &wsa_data);
+ if (result != ERROR_SUCCESS) {
+ LOG_F(LS_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_F(LS_INFO) << "WSACleanup 2";
+ ::WSACleanup();
+ ASSERT(ws_handle_ == NULL);
+ ws_handle_ = NULL;
+ return result;
+ }
+ return 0;
+ }
+ talk_base::CriticalSection crit_sect_;
+ HANDLE ws_handle_;
+ scoped_event 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;
+ }
+ }
+ alive_ = network_info_->IsAlive(&error_);
+ }
+
+ virtual void OnWorkStop() {
+ if (network_info_) {
+ network_info_->Close();
+ }
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(AsyncNetworkAliveWin32);
+};
+
+AsyncNetworkAlive* AsyncNetworkAlive::Create() {
+ return new AsyncNetworkAliveWin32();
+}
+
+} // namespace notifier
Property changes on: chrome\browser\sync\notifier\base\win32\async_network_alive_win32.cc
___________________________________________________________________
Added: svn:eol-style
+ LF

Powered by Google App Engine
This is Rietveld 408576698