OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |