OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/socket/tcp_client_socket_win.h" | 5 #include "net/socket/tcp_client_socket_win.h" |
6 | 6 |
7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
8 #include "base/compiler_specific.h" | 8 #include "base/compiler_specific.h" |
9 #include "base/memory_debug.h" | 9 #include "base/memory_debug.h" |
10 #include "base/stats_counters.h" | 10 #include "base/stats_counters.h" |
11 #include "base/string_util.h" | 11 #include "base/string_util.h" |
12 #include "base/sys_info.h" | 12 #include "base/sys_info.h" |
13 #include "net/base/address_list_net_log_param.h" | 13 #include "net/base/address_list_net_log_param.h" |
14 #include "net/base/connection_type_histograms.h" | 14 #include "net/base/connection_type_histograms.h" |
15 #include "net/base/io_buffer.h" | 15 #include "net/base/io_buffer.h" |
16 #include "net/base/net_errors.h" | 16 #include "net/base/net_errors.h" |
17 #include "net/base/net_log.h" | 17 #include "net/base/net_log.h" |
18 #include "net/base/net_util.h" | 18 #include "net/base/net_util.h" |
19 #include "net/base/sys_addrinfo.h" | 19 #include "net/base/sys_addrinfo.h" |
20 #include "net/base/winsock_init.h" | 20 #include "net/base/winsock_init.h" |
21 | 21 |
22 namespace net { | 22 namespace net { |
23 | 23 |
24 namespace { | 24 namespace { |
25 | 25 |
| 26 // Assert that the (manual-reset) event object is not signaled. |
| 27 void AssertEventNotSignaled(WSAEVENT hEvent) { |
| 28 DWORD wait_rv = WaitForSingleObject(hEvent, 0); |
| 29 if (wait_rv != WAIT_TIMEOUT) { |
| 30 DWORD err = ERROR_SUCCESS; |
| 31 if (wait_rv == WAIT_FAILED) |
| 32 err = GetLastError(); |
| 33 CHECK(false); // Crash. |
| 34 // This LOG statement is unreachable since we have already crashed, but it |
| 35 // should prevent the compiler from optimizing away the |wait_rv| and |
| 36 // |err| variables so they appear nicely on the stack in crash dumps. |
| 37 LOG(INFO) << "wait_rv=" << wait_rv << ", err=" << err; |
| 38 } |
| 39 } |
| 40 |
26 // If the (manual-reset) event object is signaled, resets it and returns true. | 41 // If the (manual-reset) event object is signaled, resets it and returns true. |
27 // Otherwise, does nothing and returns false. Called after a Winsock function | 42 // Otherwise, does nothing and returns false. Called after a Winsock function |
28 // succeeds synchronously | 43 // succeeds synchronously |
29 // | 44 // |
30 // Our testing shows that except in rare cases (when running inside QEMU), | 45 // Our testing shows that except in rare cases (when running inside QEMU), |
31 // the event object is already signaled at this point, so we call this method | 46 // the event object is already signaled at this point, so we call this method |
32 // to avoid a context switch in common cases. This is just a performance | 47 // to avoid a context switch in common cases. This is just a performance |
33 // optimization. The code still works if this function simply returns false. | 48 // optimization. The code still works if this function simply returns false. |
34 bool ResetEventIfSignaled(WSAEVENT hEvent) { | 49 bool ResetEventIfSignaled(WSAEVENT hEvent) { |
35 // TODO(wtc): Remove the CHECKs after enough testing. | 50 // TODO(wtc): Remove the CHECKs after enough testing. |
(...skipping 465 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
501 DCHECK_NE(socket_, INVALID_SOCKET); | 516 DCHECK_NE(socket_, INVALID_SOCKET); |
502 DCHECK(!waiting_read_); | 517 DCHECK(!waiting_read_); |
503 DCHECK(!read_callback_); | 518 DCHECK(!read_callback_); |
504 DCHECK(!core_->read_iobuffer_); | 519 DCHECK(!core_->read_iobuffer_); |
505 | 520 |
506 buf_len = core_->ThrottleReadSize(buf_len); | 521 buf_len = core_->ThrottleReadSize(buf_len); |
507 | 522 |
508 core_->read_buffer_.len = buf_len; | 523 core_->read_buffer_.len = buf_len; |
509 core_->read_buffer_.buf = buf->data(); | 524 core_->read_buffer_.buf = buf->data(); |
510 | 525 |
511 // TODO(wtc): Remove the CHECK after enough testing. | 526 // TODO(wtc): Remove the assertion after enough testing. |
512 CHECK_EQ(static_cast<DWORD>(WAIT_TIMEOUT), | 527 AssertEventNotSignaled(core_->read_overlapped_.hEvent); |
513 WaitForSingleObject(core_->read_overlapped_.hEvent, 0)); | |
514 DWORD num, flags = 0; | 528 DWORD num, flags = 0; |
515 int rv = WSARecv(socket_, &core_->read_buffer_, 1, &num, &flags, | 529 int rv = WSARecv(socket_, &core_->read_buffer_, 1, &num, &flags, |
516 &core_->read_overlapped_, NULL); | 530 &core_->read_overlapped_, NULL); |
517 if (rv == 0) { | 531 if (rv == 0) { |
518 if (ResetEventIfSignaled(core_->read_overlapped_.hEvent)) { | 532 if (ResetEventIfSignaled(core_->read_overlapped_.hEvent)) { |
519 // Because of how WSARecv fills memory when used asynchronously, Purify | 533 // Because of how WSARecv fills memory when used asynchronously, Purify |
520 // isn't able to detect that it's been initialized, so it scans for 0xcd | 534 // isn't able to detect that it's been initialized, so it scans for 0xcd |
521 // in the buffer and reports UMRs (uninitialized memory reads) for those | 535 // in the buffer and reports UMRs (uninitialized memory reads) for those |
522 // individual bytes. We override that in PURIFY builds to avoid the | 536 // individual bytes. We override that in PURIFY builds to avoid the |
523 // false error reports. | 537 // false error reports. |
(...skipping 27 matching lines...) Expand all Loading... |
551 DCHECK_GT(buf_len, 0); | 565 DCHECK_GT(buf_len, 0); |
552 DCHECK(!core_->write_iobuffer_); | 566 DCHECK(!core_->write_iobuffer_); |
553 | 567 |
554 static StatsCounter reads("tcp.writes"); | 568 static StatsCounter reads("tcp.writes"); |
555 reads.Increment(); | 569 reads.Increment(); |
556 | 570 |
557 core_->write_buffer_.len = buf_len; | 571 core_->write_buffer_.len = buf_len; |
558 core_->write_buffer_.buf = buf->data(); | 572 core_->write_buffer_.buf = buf->data(); |
559 core_->write_buffer_length_ = buf_len; | 573 core_->write_buffer_length_ = buf_len; |
560 | 574 |
561 // TODO(wtc): Remove the CHECK after enough testing. | 575 // TODO(wtc): Remove the assertion after enough testing. |
562 CHECK_EQ(static_cast<DWORD>(WAIT_TIMEOUT), | 576 AssertEventNotSignaled(core_->write_overlapped_.hEvent); |
563 WaitForSingleObject(core_->write_overlapped_.hEvent, 0)); | |
564 DWORD num; | 577 DWORD num; |
565 int rv = WSASend(socket_, &core_->write_buffer_, 1, &num, 0, | 578 int rv = WSASend(socket_, &core_->write_buffer_, 1, &num, 0, |
566 &core_->write_overlapped_, NULL); | 579 &core_->write_overlapped_, NULL); |
567 if (rv == 0) { | 580 if (rv == 0) { |
568 if (ResetEventIfSignaled(core_->write_overlapped_.hEvent)) { | 581 if (ResetEventIfSignaled(core_->write_overlapped_.hEvent)) { |
569 rv = static_cast<int>(num); | 582 rv = static_cast<int>(num); |
570 if (rv > buf_len || rv < 0) { | 583 if (rv > buf_len || rv < 0) { |
571 // It seems that some winsock interceptors report that more was written | 584 // It seems that some winsock interceptors report that more was written |
572 // than was available. Treat this as an error. http://crbug.com/27870 | 585 // than was available. Treat this as an error. http://crbug.com/27870 |
573 LOG(ERROR) << "Detected broken LSP: Asked to write " << buf_len | 586 LOG(ERROR) << "Detected broken LSP: Asked to write " << buf_len |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
768 } else { | 781 } else { |
769 net_log_.AddEvent(NetLog::TYPE_SOCKET_BYTES_SENT, | 782 net_log_.AddEvent(NetLog::TYPE_SOCKET_BYTES_SENT, |
770 new NetLogIntegerParameter("num_bytes", rv)); | 783 new NetLogIntegerParameter("num_bytes", rv)); |
771 } | 784 } |
772 } | 785 } |
773 core_->write_iobuffer_ = NULL; | 786 core_->write_iobuffer_ = NULL; |
774 DoWriteCallback(rv); | 787 DoWriteCallback(rv); |
775 } | 788 } |
776 | 789 |
777 } // namespace net | 790 } // namespace net |
OLD | NEW |