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

Side by Side Diff: base/sync_socket_win.cc

Issue 23875019: Add SyncSocket::ReceiveWithTimeout() and SyncSocket unit tests. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixes. Created 7 years, 2 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
« base/sync_socket_unittest.cc ('K') | « base/sync_socket_unittest.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/sync_socket.h" 5 #include "base/sync_socket.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/win/scoped_handle.h" 8 #include "base/win/scoped_handle.h"
9 9
10 namespace base { 10 namespace base {
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 size_t CancelableFileOperation(Function operation, HANDLE file, 113 size_t CancelableFileOperation(Function operation, HANDLE file,
114 BufferType* buffer, size_t length, 114 BufferType* buffer, size_t length,
115 base::WaitableEvent* io_event, 115 base::WaitableEvent* io_event,
116 base::WaitableEvent* cancel_event, 116 base::WaitableEvent* cancel_event,
117 CancelableSyncSocket* socket, 117 CancelableSyncSocket* socket,
118 DWORD timeout_in_ms) { 118 DWORD timeout_in_ms) {
119 // The buffer must be byte size or the length check won't make much sense. 119 // The buffer must be byte size or the length check won't make much sense.
120 COMPILE_ASSERT(sizeof(buffer[0]) == sizeof(char), incorrect_buffer_type); 120 COMPILE_ASSERT(sizeof(buffer[0]) == sizeof(char), incorrect_buffer_type);
121 DCHECK_LE(length, kMaxMessageLength); 121 DCHECK_LE(length, kMaxMessageLength);
122 122
123 // Track the start time so we can reduce the timeout as data is read.
124 TimeTicks start_time;
125 if (timeout_in_ms != INFINITE)
126 start_time = base::TimeTicks::Now();
127
123 OVERLAPPED ol = {0}; 128 OVERLAPPED ol = {0};
124 ol.hEvent = io_event->handle(); 129 ol.hEvent = io_event->handle();
125 size_t count = 0; 130 size_t count = 0;
126 while (count < length) { 131 while (count < length && timeout_in_ms > 0) {
127 DWORD chunk = GetNextChunkSize(count, length); 132 DWORD chunk = GetNextChunkSize(count, length);
128 // This is either the ReadFile or WriteFile call depending on whether 133 // This is either the ReadFile or WriteFile call depending on whether
129 // we're receiving or sending data. 134 // we're receiving or sending data.
130 DWORD len = 0; 135 DWORD len = 0;
131 BOOL ok = operation(file, static_cast<BufferType*>(buffer) + count, chunk, 136 BOOL ok = operation(file, static_cast<BufferType*>(buffer) + count, chunk,
132 &len, &ol); 137 &len, &ol);
133 if (!ok) { 138 if (!ok) {
134 if (::GetLastError() == ERROR_IO_PENDING) { 139 if (::GetLastError() == ERROR_IO_PENDING) {
135 HANDLE events[] = { io_event->handle(), cancel_event->handle() }; 140 HANDLE events[] = { io_event->handle(), cancel_event->handle() };
136 int wait_result = WaitForMultipleObjects( 141 int wait_result = WaitForMultipleObjects(
137 arraysize(events), events, FALSE, timeout_in_ms); 142 arraysize(events), events, FALSE, timeout_in_ms);
138 if (wait_result == (WAIT_OBJECT_0 + 0)) { 143 if (wait_result == (WAIT_OBJECT_0 + 0)) {
139 GetOverlappedResult(file, &ol, &len, TRUE); 144 GetOverlappedResult(file, &ol, &len, TRUE);
140 } else if (wait_result == (WAIT_OBJECT_0 + 1)) { 145 } else if (wait_result == (WAIT_OBJECT_0 + 1)) {
141 VLOG(1) << "Shutdown was signaled. Closing socket."; 146 DVLOG(1) << "Shutdown was signaled. Closing socket.";
142 CancelIo(file); 147 CancelIo(file);
143 socket->Close(); 148 socket->Close();
144 count = 0; 149 count = 0;
145 break; 150 break;
146 } else { 151 } else {
147 // Timeout happened. 152 // Timeout happened.
148 DCHECK_EQ(WAIT_TIMEOUT, wait_result); 153 DCHECK_EQ(WAIT_TIMEOUT, wait_result);
149 if (!CancelIo(file)){ 154 if (!CancelIo(file))
150 DLOG(WARNING) << "CancelIo() failed"; 155 DLOG(WARNING) << "CancelIo() failed";
151 }
152 break; 156 break;
153 } 157 }
154 } else { 158 } else {
155 break; 159 break;
156 } 160 }
157 } 161 }
158 162
159 count += len; 163 count += len;
160 164
161 // Quit the operation if we can't write/read anymore. 165 // Quit the operation if we can't write/read anymore.
162 if (len != chunk) 166 if (len != chunk)
163 break; 167 break;
168
169 // Since TimeTicks::Now() is expensive, only bother updating the timeout if
170 // we have more work to do.
171 if (timeout_in_ms != INFINITE && count < length)
172 timeout_in_ms -= (base::TimeTicks::Now() - start_time).InMilliseconds();
164 } 173 }
165 174
166 return (count > 0) ? count : 0; 175 return (count > 0) ? count : 0;
167 } 176 }
168 177
169 } // namespace 178 } // namespace
170 179
171 #if defined(COMPONENT_BUILD) 180 #if defined(COMPONENT_BUILD)
172 const SyncSocket::Handle SyncSocket::kInvalidHandle = INVALID_HANDLE_VALUE; 181 const SyncSocket::Handle SyncSocket::kInvalidHandle = INVALID_HANDLE_VALUE;
173 #endif 182 #endif
(...skipping 26 matching lines...) Expand all
200 DWORD chunk = GetNextChunkSize(count, length); 209 DWORD chunk = GetNextChunkSize(count, length);
201 if (WriteFile(handle_, static_cast<const char*>(buffer) + count, 210 if (WriteFile(handle_, static_cast<const char*>(buffer) + count,
202 chunk, &len, NULL) == FALSE) { 211 chunk, &len, NULL) == FALSE) {
203 return (0 < count) ? count : 0; 212 return (0 < count) ? count : 0;
204 } 213 }
205 count += len; 214 count += len;
206 } 215 }
207 return count; 216 return count;
208 } 217 }
209 218
219 size_t SyncSocket::ReceiveWithTimeout(void* buffer,
220 size_t length,
221 TimeDelta timeout) {
222 NOTIMPLEMENTED();
223 return 0;
224 }
225
210 size_t SyncSocket::Receive(void* buffer, size_t length) { 226 size_t SyncSocket::Receive(void* buffer, size_t length) {
211 DCHECK_LE(length, kMaxMessageLength); 227 DCHECK_LE(length, kMaxMessageLength);
212 size_t count = 0; 228 size_t count = 0;
213 while (count < length) { 229 while (count < length) {
214 DWORD len; 230 DWORD len;
215 DWORD chunk = GetNextChunkSize(count, length); 231 DWORD chunk = GetNextChunkSize(count, length);
216 if (ReadFile(handle_, static_cast<char*>(buffer) + count, 232 if (ReadFile(handle_, static_cast<char*>(buffer) + count,
217 chunk, &len, NULL) == FALSE) { 233 chunk, &len, NULL) == FALSE) {
218 return (0 < count) ? count : 0; 234 return (0 < count) ? count : 0;
219 } 235 }
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
251 } 267 }
252 268
253 size_t CancelableSyncSocket::Send(const void* buffer, size_t length) { 269 size_t CancelableSyncSocket::Send(const void* buffer, size_t length) {
254 static const DWORD kWaitTimeOutInMs = 500; 270 static const DWORD kWaitTimeOutInMs = 500;
255 return CancelableFileOperation( 271 return CancelableFileOperation(
256 &WriteFile, handle_, reinterpret_cast<const char*>(buffer), 272 &WriteFile, handle_, reinterpret_cast<const char*>(buffer),
257 length, &file_operation_, &shutdown_event_, this, kWaitTimeOutInMs); 273 length, &file_operation_, &shutdown_event_, this, kWaitTimeOutInMs);
258 } 274 }
259 275
260 size_t CancelableSyncSocket::Receive(void* buffer, size_t length) { 276 size_t CancelableSyncSocket::Receive(void* buffer, size_t length) {
261 return CancelableFileOperation(&ReadFile, handle_, 277 return CancelableFileOperation(
262 reinterpret_cast<char*>(buffer), length, &file_operation_, 278 &ReadFile, handle_, reinterpret_cast<char*>(buffer), length,
263 &shutdown_event_, this, INFINITE); 279 &file_operation_, &shutdown_event_, this, INFINITE);
280 }
281
282 size_t CancelableSyncSocket::ReceiveWithTimeout(void* buffer,
283 size_t length,
284 base::TimeDelta timeout) {
285 return CancelableFileOperation(
286 &ReadFile, handle_, reinterpret_cast<char*>(buffer), length,
287 &file_operation_, &shutdown_event_, this, timeout.InMilliseconds());
264 } 288 }
265 289
266 // static 290 // static
267 bool CancelableSyncSocket::CreatePair(CancelableSyncSocket* socket_a, 291 bool CancelableSyncSocket::CreatePair(CancelableSyncSocket* socket_a,
268 CancelableSyncSocket* socket_b) { 292 CancelableSyncSocket* socket_b) {
269 return CreatePairImpl(&socket_a->handle_, &socket_b->handle_, true); 293 return CreatePairImpl(&socket_a->handle_, &socket_b->handle_, true);
270 } 294 }
271 295
272 296
273 } // namespace base 297 } // namespace base
OLDNEW
« base/sync_socket_unittest.cc ('K') | « base/sync_socket_unittest.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698