| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 "net/base/tcp_client_socket.h" | 5 #include "net/base/tcp_client_socket.h" |
| 6 | 6 |
| 7 #include "base/memory_debug.h" | 7 #include "base/memory_debug.h" |
| 8 #include "base/string_util.h" | 8 #include "base/string_util.h" |
| 9 #include "base/trace_event.h" | 9 #include "base/trace_event.h" |
| 10 #include "net/base/net_errors.h" | 10 #include "net/base/net_errors.h" |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 81 return rv; | 81 return rv; |
| 82 | 82 |
| 83 // WSACreateEvent creates a manual-reset event object. | 83 // WSACreateEvent creates a manual-reset event object. |
| 84 overlapped_.hEvent = WSACreateEvent(); | 84 overlapped_.hEvent = WSACreateEvent(); |
| 85 // WSAEventSelect sets the socket to non-blocking mode as a side effect. | 85 // WSAEventSelect sets the socket to non-blocking mode as a side effect. |
| 86 // Our connect() and recv() calls require that the socket be non-blocking. | 86 // Our connect() and recv() calls require that the socket be non-blocking. |
| 87 WSAEventSelect(socket_, overlapped_.hEvent, FD_CONNECT); | 87 WSAEventSelect(socket_, overlapped_.hEvent, FD_CONNECT); |
| 88 | 88 |
| 89 if (!connect(socket_, ai->ai_addr, static_cast<int>(ai->ai_addrlen))) { | 89 if (!connect(socket_, ai->ai_addr, static_cast<int>(ai->ai_addrlen))) { |
| 90 // Connected without waiting! | 90 // Connected without waiting! |
| 91 CHECK(WaitForSingleObject(overlapped_.hEvent, 0) == WAIT_OBJECT_0); | 91 WaitForAndResetEvent(); |
| 92 BOOL ok = WSAResetEvent(overlapped_.hEvent); | |
| 93 CHECK(ok); | |
| 94 TRACE_EVENT_END("socket.connect", this, ""); | 92 TRACE_EVENT_END("socket.connect", this, ""); |
| 95 return OK; | 93 return OK; |
| 96 } | 94 } |
| 97 | 95 |
| 98 DWORD err = WSAGetLastError(); | 96 DWORD err = WSAGetLastError(); |
| 99 if (err != WSAEWOULDBLOCK) { | 97 if (err != WSAEWOULDBLOCK) { |
| 100 LOG(ERROR) << "connect failed: " << err; | 98 LOG(ERROR) << "connect failed: " << err; |
| 101 return MapWinsockError(err); | 99 return MapWinsockError(err); |
| 102 } | 100 } |
| 103 | 101 |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 163 int buf_len, | 161 int buf_len, |
| 164 CompletionCallback* callback) { | 162 CompletionCallback* callback) { |
| 165 DCHECK(socket_ != INVALID_SOCKET); | 163 DCHECK(socket_ != INVALID_SOCKET); |
| 166 DCHECK(wait_state_ == NOT_WAITING); | 164 DCHECK(wait_state_ == NOT_WAITING); |
| 167 DCHECK(!callback_); | 165 DCHECK(!callback_); |
| 168 | 166 |
| 169 buffer_.len = buf_len; | 167 buffer_.len = buf_len; |
| 170 buffer_.buf = buf; | 168 buffer_.buf = buf; |
| 171 | 169 |
| 172 TRACE_EVENT_BEGIN("socket.read", this, ""); | 170 TRACE_EVENT_BEGIN("socket.read", this, ""); |
| 173 // TODO(wtc): Remove the CHECKs after enough testing. | 171 // TODO(wtc): Remove the CHECK after enough testing. |
| 174 CHECK(WaitForSingleObject(overlapped_.hEvent, 0) == WAIT_TIMEOUT); | 172 CHECK(WaitForSingleObject(overlapped_.hEvent, 0) == WAIT_TIMEOUT); |
| 175 DWORD num, flags = 0; | 173 DWORD num, flags = 0; |
| 176 int rv = WSARecv(socket_, &buffer_, 1, &num, &flags, &overlapped_, NULL); | 174 int rv = WSARecv(socket_, &buffer_, 1, &num, &flags, &overlapped_, NULL); |
| 177 if (rv == 0) { | 175 if (rv == 0) { |
| 178 CHECK(WaitForSingleObject(overlapped_.hEvent, 0) == WAIT_OBJECT_0); | 176 WaitForAndResetEvent(); |
| 179 BOOL ok = WSAResetEvent(overlapped_.hEvent); | |
| 180 CHECK(ok); | |
| 181 TRACE_EVENT_END("socket.read", this, StringPrintf("%d bytes", num)); | 177 TRACE_EVENT_END("socket.read", this, StringPrintf("%d bytes", num)); |
| 182 | 178 |
| 183 // Because of how WSARecv fills memory when used asynchronously, Purify | 179 // Because of how WSARecv fills memory when used asynchronously, Purify |
| 184 // isn't able to detect that it's been initialized, so it scans for 0xcd | 180 // isn't able to detect that it's been initialized, so it scans for 0xcd |
| 185 // in the buffer and reports UMRs (uninitialized memory reads) for those | 181 // in the buffer and reports UMRs (uninitialized memory reads) for those |
| 186 // individual bytes. We override that in PURIFY builds to avoid the false | 182 // individual bytes. We override that in PURIFY builds to avoid the false |
| 187 // error reports. | 183 // error reports. |
| 188 // See bug 5297. | 184 // See bug 5297. |
| 189 base::MemoryDebug::MarkAsInitialized(buffer_.buf, num); | 185 base::MemoryDebug::MarkAsInitialized(buffer_.buf, num); |
| 190 return static_cast<int>(num); | 186 return static_cast<int>(num); |
| 191 } | 187 } |
| 192 int err = WSAGetLastError(); | 188 int err = WSAGetLastError(); |
| 193 if (err == WSA_IO_PENDING) { | 189 if (err == WSA_IO_PENDING) { |
| 194 watcher_.StartWatching(overlapped_.hEvent, this); | 190 watcher_.StartWatching(overlapped_.hEvent, this); |
| 195 wait_state_ = WAITING_READ; | 191 wait_state_ = WAITING_READ; |
| 196 callback_ = callback; | 192 callback_ = callback; |
| 197 return ERR_IO_PENDING; | 193 return ERR_IO_PENDING; |
| 198 } | 194 } |
| 199 return MapWinsockError(err); | 195 return MapWinsockError(err); |
| 200 } | 196 } |
| 201 | 197 |
| 202 // TODO(wtc): This temporary function is intended to determine the return | |
| 203 // value and error code of the WaitForSingleObject call in | |
| 204 // TCPClientSocket::Write if it doesn't return the expected WAIT_OBJECT_0. | |
| 205 // See http://crbug.com/6500. | |
| 206 static void CrashBug6500(DWORD wait_rv, DWORD wait_error) { | |
| 207 // wait_error is meaningful only if wait_rv is WAIT_FAILED. | |
| 208 CHECK(false) << wait_rv << wait_error; | |
| 209 } | |
| 210 | |
| 211 int TCPClientSocket::Write(const char* buf, | 198 int TCPClientSocket::Write(const char* buf, |
| 212 int buf_len, | 199 int buf_len, |
| 213 CompletionCallback* callback) { | 200 CompletionCallback* callback) { |
| 214 DCHECK(socket_ != INVALID_SOCKET); | 201 DCHECK(socket_ != INVALID_SOCKET); |
| 215 DCHECK(wait_state_ == NOT_WAITING); | 202 DCHECK(wait_state_ == NOT_WAITING); |
| 216 DCHECK(!callback_); | 203 DCHECK(!callback_); |
| 217 | 204 |
| 218 buffer_.len = buf_len; | 205 buffer_.len = buf_len; |
| 219 buffer_.buf = const_cast<char*>(buf); | 206 buffer_.buf = const_cast<char*>(buf); |
| 220 | 207 |
| 221 TRACE_EVENT_BEGIN("socket.write", this, ""); | 208 TRACE_EVENT_BEGIN("socket.write", this, ""); |
| 222 // TODO(wtc): Remove the CHECKs after enough testing. | 209 // TODO(wtc): Remove the CHECK after enough testing. |
| 223 CHECK(WaitForSingleObject(overlapped_.hEvent, 0) == WAIT_TIMEOUT); | 210 CHECK(WaitForSingleObject(overlapped_.hEvent, 0) == WAIT_TIMEOUT); |
| 224 DWORD num; | 211 DWORD num; |
| 225 int rv = WSASend(socket_, &buffer_, 1, &num, 0, &overlapped_, NULL); | 212 int rv = WSASend(socket_, &buffer_, 1, &num, 0, &overlapped_, NULL); |
| 226 if (rv == 0) { | 213 if (rv == 0) { |
| 227 DWORD wait_rv = WaitForSingleObject(overlapped_.hEvent, 0); | 214 WaitForAndResetEvent(); |
| 228 if (wait_rv != WAIT_OBJECT_0) { | |
| 229 DWORD wait_error = GetLastError(); | |
| 230 CrashBug6500(wait_rv, wait_error); | |
| 231 } | |
| 232 BOOL ok = WSAResetEvent(overlapped_.hEvent); | |
| 233 CHECK(ok); | |
| 234 TRACE_EVENT_END("socket.write", this, StringPrintf("%d bytes", num)); | 215 TRACE_EVENT_END("socket.write", this, StringPrintf("%d bytes", num)); |
| 235 return static_cast<int>(num); | 216 return static_cast<int>(num); |
| 236 } | 217 } |
| 237 int err = WSAGetLastError(); | 218 int err = WSAGetLastError(); |
| 238 if (err == WSA_IO_PENDING) { | 219 if (err == WSA_IO_PENDING) { |
| 239 watcher_.StartWatching(overlapped_.hEvent, this); | 220 watcher_.StartWatching(overlapped_.hEvent, this); |
| 240 wait_state_ = WAITING_WRITE; | 221 wait_state_ = WAITING_WRITE; |
| 241 callback_ = callback; | 222 callback_ = callback; |
| 242 return ERR_IO_PENDING; | 223 return ERR_IO_PENDING; |
| 243 } | 224 } |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 372 case WAITING_READ: | 353 case WAITING_READ: |
| 373 case WAITING_WRITE: | 354 case WAITING_WRITE: |
| 374 DidCompleteIO(); | 355 DidCompleteIO(); |
| 375 break; | 356 break; |
| 376 default: | 357 default: |
| 377 NOTREACHED(); | 358 NOTREACHED(); |
| 378 break; | 359 break; |
| 379 } | 360 } |
| 380 } | 361 } |
| 381 | 362 |
| 363 void TCPClientSocket::WaitForAndResetEvent() { |
| 364 // TODO(wtc): Remove the CHECKs after enough testing. |
| 365 DWORD wait_rv = WaitForSingleObject(overlapped_.hEvent, INFINITE); |
| 366 CHECK(wait_rv == WAIT_OBJECT_0); |
| 367 BOOL ok = WSAResetEvent(overlapped_.hEvent); |
| 368 CHECK(ok); |
| 369 } |
| 370 |
| 382 } // namespace net | 371 } // namespace net |
| 383 | 372 |
| OLD | NEW |