Chromium Code Reviews| 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 "net/socket/tcp_client_socket_win.h" | 5 #include "net/socket/tcp_client_socket_win.h" |
| 6 | 6 |
| 7 #include <mstcpip.h> | 7 #include <mstcpip.h> |
| 8 | 8 |
| 9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
| 10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 259 static const int kMaxSlowStartThrottle = 32 * kInitialSlowStartThrottle; | 259 static const int kMaxSlowStartThrottle = 32 * kInitialSlowStartThrottle; |
| 260 int slow_start_throttle_; | 260 int slow_start_throttle_; |
| 261 | 261 |
| 262 DISALLOW_COPY_AND_ASSIGN(Core); | 262 DISALLOW_COPY_AND_ASSIGN(Core); |
| 263 }; | 263 }; |
| 264 | 264 |
| 265 TCPClientSocketWin::Core::Core( | 265 TCPClientSocketWin::Core::Core( |
| 266 TCPClientSocketWin* socket) | 266 TCPClientSocketWin* socket) |
| 267 : read_buffer_length_(0), | 267 : read_buffer_length_(0), |
| 268 write_buffer_length_(0), | 268 write_buffer_length_(0), |
| 269 disable_overlapped_reads_(g_disable_overlapped_reads), | 269 disable_overlapped_reads_(true), |
|
wtc
2013/03/06 17:33:43
Please ignore this change. I need this temporary c
| |
| 270 non_blocking_reads_initialized_(false), | 270 non_blocking_reads_initialized_(false), |
| 271 socket_(socket), | 271 socket_(socket), |
| 272 ALLOW_THIS_IN_INITIALIZER_LIST(reader_(this)), | 272 ALLOW_THIS_IN_INITIALIZER_LIST(reader_(this)), |
| 273 ALLOW_THIS_IN_INITIALIZER_LIST(writer_(this)), | 273 ALLOW_THIS_IN_INITIALIZER_LIST(writer_(this)), |
| 274 slow_start_throttle_(kInitialSlowStartThrottle) { | 274 slow_start_throttle_(kInitialSlowStartThrottle) { |
| 275 memset(&read_overlapped_, 0, sizeof(read_overlapped_)); | 275 memset(&read_overlapped_, 0, sizeof(read_overlapped_)); |
| 276 memset(&write_overlapped_, 0, sizeof(write_overlapped_)); | 276 memset(&write_overlapped_, 0, sizeof(write_overlapped_)); |
| 277 | 277 |
| 278 read_overlapped_.hEvent = WSACreateEvent(); | 278 read_overlapped_.hEvent = WSACreateEvent(); |
| 279 write_overlapped_.hEvent = WSACreateEvent(); | 279 write_overlapped_.hEvent = WSACreateEvent(); |
| (...skipping 553 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 833 } | 833 } |
| 834 | 834 |
| 835 int TCPClientSocketWin::DoRead(IOBuffer* buf, int buf_len, | 835 int TCPClientSocketWin::DoRead(IOBuffer* buf, int buf_len, |
| 836 const CompletionCallback& callback) { | 836 const CompletionCallback& callback) { |
| 837 if (core_->disable_overlapped_reads_) { | 837 if (core_->disable_overlapped_reads_) { |
| 838 if (!core_->non_blocking_reads_initialized_) { | 838 if (!core_->non_blocking_reads_initialized_) { |
| 839 WSAEventSelect(socket_, core_->read_overlapped_.hEvent, | 839 WSAEventSelect(socket_, core_->read_overlapped_.hEvent, |
| 840 FD_READ | FD_CLOSE); | 840 FD_READ | FD_CLOSE); |
| 841 core_->non_blocking_reads_initialized_ = true; | 841 core_->non_blocking_reads_initialized_ = true; |
| 842 } | 842 } |
| 843 // Sometimes core_->read_overlapped_.hEvent is signaled at this | |
| 844 // point. It is usually the 3rd-5th times we call recv() on the | |
| 845 // socket, never the first time. | |
| 843 int rv = recv(socket_, buf->data(), buf_len, 0); | 846 int rv = recv(socket_, buf->data(), buf_len, 0); |
| 844 if (rv == SOCKET_ERROR) { | 847 if (rv == SOCKET_ERROR) { |
| 845 int os_error = WSAGetLastError(); | 848 int os_error = WSAGetLastError(); |
| 846 if (os_error != WSAEWOULDBLOCK) { | 849 if (os_error != WSAEWOULDBLOCK) { |
| 847 int net_error = MapSystemError(os_error); | 850 int net_error = MapSystemError(os_error); |
| 848 net_log_.AddEvent(NetLog::TYPE_SOCKET_READ_ERROR, | 851 net_log_.AddEvent(NetLog::TYPE_SOCKET_READ_ERROR, |
| 849 CreateNetLogSocketErrorCallback(net_error, os_error)); | 852 CreateNetLogSocketErrorCallback(net_error, os_error)); |
| 850 return net_error; | 853 return net_error; |
| 851 } | 854 } |
| 852 } else { | 855 } else { |
| 853 base::StatsCounter read_bytes("tcp.read_bytes"); | 856 base::StatsCounter read_bytes("tcp.read_bytes"); |
| 854 if (rv > 0) { | 857 if (rv > 0) { |
| 855 use_history_.set_was_used_to_convey_data(); | 858 use_history_.set_was_used_to_convey_data(); |
| 856 read_bytes.Add(rv); | 859 read_bytes.Add(rv); |
| 857 num_bytes_read_ += rv; | 860 num_bytes_read_ += rv; |
| 858 } | 861 } |
| 859 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, rv, | 862 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, rv, |
| 860 buf->data()); | 863 buf->data()); |
| 864 BOOL ok = WSAResetEvent(core_->read_overlapped_.hEvent); | |
|
rvargas (doing something else)
2013/03/06 23:08:49
I think this can cause unwanted hangs (unlikely, b
Pat Meenan
2013/03/07 15:11:04
What are you trying to solve by manually resetting
| |
| 865 CHECK(ok); | |
| 861 return rv; | 866 return rv; |
| 862 } | 867 } |
| 863 } else { | 868 } else { |
| 864 buf_len = core_->ThrottleReadSize(buf_len); | 869 buf_len = core_->ThrottleReadSize(buf_len); |
| 865 | 870 |
| 866 WSABUF read_buffer; | 871 WSABUF read_buffer; |
| 867 read_buffer.len = buf_len; | 872 read_buffer.len = buf_len; |
| 868 read_buffer.buf = buf->data(); | 873 read_buffer.buf = buf->data(); |
| 869 | 874 |
| 870 // TODO(wtc): Remove the assertion after enough testing. | 875 // TODO(wtc): Remove the assertion after enough testing. |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1015 core_->write_iobuffer_ = NULL; | 1020 core_->write_iobuffer_ = NULL; |
| 1016 DoWriteCallback(rv); | 1021 DoWriteCallback(rv); |
| 1017 } | 1022 } |
| 1018 | 1023 |
| 1019 void TCPClientSocketWin::DidSignalRead() { | 1024 void TCPClientSocketWin::DidSignalRead() { |
| 1020 DCHECK(waiting_read_); | 1025 DCHECK(waiting_read_); |
| 1021 int os_error = 0; | 1026 int os_error = 0; |
| 1022 WSANETWORKEVENTS network_events; | 1027 WSANETWORKEVENTS network_events; |
| 1023 int rv = WSAEnumNetworkEvents(socket_, core_->read_overlapped_.hEvent, | 1028 int rv = WSAEnumNetworkEvents(socket_, core_->read_overlapped_.hEvent, |
| 1024 &network_events); | 1029 &network_events); |
| 1030 AssertEventNotSignaled(core_->read_overlapped_.hEvent); | |
|
wtc
2013/03/06 17:33:43
This asserts that WSAEnumNetworkEvents resets the
rvargas (doing something else)
2013/03/06 23:08:49
Sounds like a race to me.
Pat Meenan
2013/03/07 15:11:04
Agreed, it's not atomic so it's theoretically poss
| |
| 1025 if (rv == SOCKET_ERROR) { | 1031 if (rv == SOCKET_ERROR) { |
| 1032 NOTREACHED(); | |
|
rvargas (doing something else)
2013/03/06 23:08:49
I'm assuming this is for development purposes... I
| |
| 1026 os_error = WSAGetLastError(); | 1033 os_error = WSAGetLastError(); |
| 1027 rv = MapSystemError(os_error); | 1034 rv = MapSystemError(os_error); |
| 1028 } else if (network_events.lNetworkEvents & FD_READ) { | 1035 } else if (network_events.lNetworkEvents) { |
| 1029 rv = DoRead(core_->read_iobuffer_, core_->read_buffer_length_, | 1036 rv = DoRead(core_->read_iobuffer_, core_->read_buffer_length_, |
| 1030 read_callback_); | 1037 read_callback_); |
|
wtc
2013/03/06 17:33:43
I got the inspiration of this change from the old-
Pat Meenan
2013/03/07 15:11:04
Is the last error from the recv() here as granular
wtc
2013/03/14 01:24:45
Yes, in fact it is better.
When the peer resets t
| |
| 1031 if (rv == ERR_IO_PENDING) | 1038 if (rv == ERR_IO_PENDING) |
| 1032 return; | 1039 return; |
| 1033 } else if (network_events.lNetworkEvents & FD_CLOSE) { | |
| 1034 if (network_events.iErrorCode[FD_CLOSE_BIT]) { | |
| 1035 rv = MapSystemError(network_events.iErrorCode[FD_CLOSE_BIT]); | |
| 1036 net_log_.AddEvent(NetLog::TYPE_SOCKET_READ_ERROR, | |
| 1037 CreateNetLogSocketErrorCallback(rv, os_error)); | |
|
wtc
2013/03/06 17:33:43
If you prefer a smaller change, I can call DoRead(
| |
| 1038 } else { | |
| 1039 rv = 0; | |
| 1040 } | |
| 1041 } else { | 1040 } else { |
| 1042 // This should not happen but I have seen cases where we will get | 1041 // This should not happen but I have seen cases where we will get |
| 1043 // signaled but the network events flags are all clear (0). | 1042 // signaled but the network events flags are all clear (0). |
|
wtc
2013/03/06 17:33:43
The WSAResetEvent call I added on line 864 elimina
rvargas (doing something else)
2013/03/06 23:08:49
I'm thinking that we either accept a spurious wake
Pat Meenan
2013/03/07 15:11:04
How often do the Spurious wake-ups happen from IsC
wtc
2013/03/14 01:24:45
I confirmed that the spurious wake-ups are NOT cau
| |
| 1043 NOTREACHED(); | |
|
rvargas (doing something else)
2013/03/06 23:08:49
same thing here. If this triggers for a developer
| |
| 1044 core_->WatchForRead(); | 1044 core_->WatchForRead(); |
| 1045 return; | 1045 return; |
| 1046 } | 1046 } |
| 1047 waiting_read_ = false; | 1047 waiting_read_ = false; |
| 1048 core_->read_iobuffer_ = NULL; | 1048 core_->read_iobuffer_ = NULL; |
| 1049 core_->read_buffer_length_ = 0; | 1049 core_->read_buffer_length_ = 0; |
| 1050 DoReadCallback(rv); | 1050 DoReadCallback(rv); |
| 1051 } | 1051 } |
| 1052 | 1052 |
| 1053 } // namespace net | 1053 } // namespace net |
| OLD | NEW |