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

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

Issue 193103: Build sync engine as part of the browser build (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/sync/notifier/base/async_network_alive.h"
6
7 #include <winsock2.h>
8
9 #include "base/scoped_handle_win.h"
10 #include "chrome/browser/sync/notifier/base/utils.h"
11 #include "talk/base/common.h"
12 #include "talk/base/criticalsection.h"
13 #include "talk/base/logging.h"
14 #include "talk/base/scoped_ptr.h"
15
16 namespace notifier {
17
18 class PlatformNetworkInfo {
19 public:
20 PlatformNetworkInfo() : ws_handle_(NULL), event_handle_(NULL) {
21 }
22
23 ~PlatformNetworkInfo() {
24 Close();
25 }
26
27 void Close() {
28 talk_base::CritScope crit_scope(&crit_sect_);
29 if (ws_handle_) {
30 if (event_handle_.IsValid()) // Unblock any waiting for network changes.
31 SetEvent(event_handle_.Get());
32 // finishes the iteration.
33 VERIFY(WSALookupServiceEnd(ws_handle_) == 0);
34 ws_handle_ = NULL;
35 LOG(INFO) << "WSACleanup 1";
36 ::WSACleanup();
37 }
38 }
39
40 bool IsAlive(bool* error) {
41 ASSERT(error);
42 *error = false;
43
44 // If IsAlive was previously called, we need a new handle.
45 // Why? If we use the same handle, we only get diffs on what changed
46 // which isn't what we want.
47 Close();
48 int result = Initialize();
49 if (result != 0) {
50 LOG(ERROR) << "failed:" << result;
51 // Default to alive on error.
52 *error = true;
53 return true;
54 }
55
56 bool alive = false;
57
58 // Retrieve network info and move to next one. In this function, we only
59 // need to know whether or not there is network connection.
60 // allocate 256 bytes for name, it should be enough for most cases.
61 // If the name is longer, it is OK as we will check the code returned and
62 // set correct network status.
63 char result_buffer[sizeof(WSAQUERYSET) + 256] = {0};
64 bool flush_previous_result = false;
65 do {
66 DWORD control_flags = LUP_RETURN_NAME;
67 if (flush_previous_result) {
68 control_flags |= LUP_FLUSHPREVIOUS;
69 }
70 DWORD length = sizeof(result_buffer);
71 reinterpret_cast<WSAQUERYSET*>(&result_buffer[0])->dwSize =
72 sizeof(WSAQUERYSET);
73 // ws_handle_ may be NULL (if exiting), but the call will simply fail
74 int result = ::WSALookupServiceNext(
75 ws_handle_,
76 control_flags,
77 &length,
78 reinterpret_cast<WSAQUERYSET*>(&result_buffer[0]));
79
80 if (result == 0) {
81 // get at least one connection, return "connected".
82 alive = true;
83 } else {
84 ASSERT(result == SOCKET_ERROR);
85 result = ::WSAGetLastError();
86 if (result == WSA_E_NO_MORE || result == WSAENOMORE) {
87 break;
88 }
89
90 // Error code WSAEFAULT means there is a network connection but the
91 // result_buffer size is too small to contain the results. The
92 // variable "length" returned from WSALookupServiceNext is the minimum
93 // number of bytes required. We do not need to retrieve detail info.
94 // Return "alive" in this case.
95 if (result == WSAEFAULT) {
96 alive = true;
97 flush_previous_result = true;
98 } else {
99 LOG(WARNING) << "failed:" << result;
100 *error = true;
101 break;
102 }
103 }
104 } while (true);
105 LOG(INFO) << "alive: " << alive;
106 return alive;
107 }
108
109 bool WaitForChange() {
110 // IsAlive must be called first.
111 int junk1 = 0, junk2 = 0;
112 DWORD bytes_returned = 0;
113 int result = SOCKET_ERROR;
114 {
115 talk_base::CritScope crit_scope(&crit_sect_);
116 if (!ws_handle_)
117 return false;
118 ASSERT(!event_handle_.IsValid());
119 event_handle_.Set(CreateEvent(NULL, FALSE, FALSE, NULL));
120 if (!event_handle_.IsValid()) {
121 LOG(WARNING) << "failed to CreateEvent";
122 return false;
123 }
124 WSAOVERLAPPED overlapped = {0};
125 overlapped.hEvent = event_handle_.Get();
126 WSACOMPLETION completion;
127 ::SetZero(completion);
128 completion.Type = NSP_NOTIFY_EVENT;
129 completion.Parameters.Event.lpOverlapped = &overlapped;
130
131 LOG(INFO) << "calling WSANSPIoctl";
132 // Do a non-blocking request for change notification. event_handle_
133 // will get signaled when there is a change, so we wait on it later.
134 // It can also be signaled by Close() in order allow clean termination.
135 result = ::WSANSPIoctl(ws_handle_,
136 SIO_NSP_NOTIFY_CHANGE,
137 &junk1,
138 0,
139 &junk2,
140 0,
141 &bytes_returned,
142 &completion);
143 }
144 if (NO_ERROR != result) {
145 result = ::WSAGetLastError();
146 if (WSA_IO_PENDING != result) {
147 LOG(WARNING) << "failed: " << result;
148 event_handle_.Close();
149 return false;
150 }
151 }
152 LOG(INFO) << "waiting";
153 WaitForSingleObject(event_handle_.Get(), INFINITE);
154 event_handle_.Close();
155 LOG(INFO) << "changed";
156 return true;
157 }
158
159 private:
160 int Initialize() {
161 WSADATA wsa_data;
162 LOG(INFO) << "calling WSAStartup";
163 int result = ::WSAStartup(MAKEWORD(2, 2), &wsa_data);
164 if (result != ERROR_SUCCESS) {
165 LOG(ERROR) << "failed:" << result;
166 return result;
167 }
168
169 WSAQUERYSET query_set = {0};
170 query_set.dwSize = sizeof(WSAQUERYSET);
171 query_set.dwNameSpace = NS_NLA;
172 // Initiate a client query to iterate through the
173 // currently connected networks.
174 if (0 != ::WSALookupServiceBegin(&query_set, LUP_RETURN_ALL,
175 &ws_handle_)) {
176 result = ::WSAGetLastError();
177 LOG(INFO) << "WSACleanup 2";
178 ::WSACleanup();
179 ASSERT(ws_handle_ == NULL);
180 ws_handle_ = NULL;
181 return result;
182 }
183 return 0;
184 }
185 talk_base::CriticalSection crit_sect_;
186 HANDLE ws_handle_;
187 ScopedHandle event_handle_;
188 DISALLOW_COPY_AND_ASSIGN(PlatformNetworkInfo);
189 };
190
191 class AsyncNetworkAliveWin32 : public AsyncNetworkAlive {
192 public:
193 AsyncNetworkAliveWin32() {
194 }
195
196 virtual ~AsyncNetworkAliveWin32() {
197 if (network_info_) {
198 delete network_info_;
199 network_info_ = NULL;
200 }
201 }
202
203 protected:
204 // SignalThread Interface
205 virtual void DoWork() {
206 if (!network_info_) {
207 network_info_ = new PlatformNetworkInfo();
208 } else {
209 // Since network_info is set, it means that
210 // we are suppose to wait for network state changes.
211 if (!network_info_->WaitForChange()) {
212 // The wait was aborted so we must be shutting down.
213 alive_ = false;
214 error_ = true;
215 return;
216 }
217 }
218 alive_ = network_info_->IsAlive(&error_);
219 }
220
221 virtual void OnWorkStop() {
222 if (network_info_) {
223 network_info_->Close();
224 }
225 }
226
227 private:
228 DISALLOW_COPY_AND_ASSIGN(AsyncNetworkAliveWin32);
229 };
230
231 AsyncNetworkAlive* AsyncNetworkAlive::Create() {
232 return new AsyncNetworkAliveWin32();
233 }
234
235 } // namespace notifier
OLDNEW
« no previous file with comments | « chrome/browser/sync/glue/sync_backend_host.cc ('k') | chrome/browser/sync/notifier/base/win32/time_win32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698