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 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 175 public: | 175 public: |
| 176 explicit Core(TCPClientSocketWin* socket); | 176 explicit Core(TCPClientSocketWin* socket); |
| 177 | 177 |
| 178 // Start watching for the end of a read or write operation. | 178 // Start watching for the end of a read or write operation. |
| 179 void WatchForRead(); | 179 void WatchForRead(); |
| 180 void WatchForWrite(); | 180 void WatchForWrite(); |
| 181 | 181 |
| 182 // The TCPClientSocketWin is going away. | 182 // The TCPClientSocketWin is going away. |
| 183 void Detach() { socket_ = NULL; } | 183 void Detach() { socket_ = NULL; } |
| 184 | 184 |
| 185 // Throttle the read size based on our current slow start state. | |
| 186 // Returns the throttled read size. | |
| 187 int ThrottleReadSize(int size) { | |
| 188 if (slow_start_throttle_ < kMaxSlowStartThrottle) { | |
| 189 size = std::min(size, slow_start_throttle_); | |
| 190 slow_start_throttle_ *= 2; | |
| 191 } | |
| 192 return size; | |
| 193 } | |
| 194 | |
| 195 // The separate OVERLAPPED variables for asynchronous operation. | 185 // The separate OVERLAPPED variables for asynchronous operation. |
| 196 // |read_overlapped_| is used for both Connect() and Read(). | 186 // |read_overlapped_| is used for both Connect() and Read(). |
| 197 // |write_overlapped_| is only used for Write(); | 187 // |write_overlapped_| is only used for Write(); |
| 198 OVERLAPPED read_overlapped_; | 188 OVERLAPPED read_overlapped_; |
| 199 OVERLAPPED write_overlapped_; | 189 OVERLAPPED write_overlapped_; |
| 200 | 190 |
| 201 // The buffers used in Read() and Write(). | 191 // The buffers used in Read() and Write(). |
| 202 scoped_refptr<IOBuffer> read_iobuffer_; | 192 scoped_refptr<IOBuffer> read_iobuffer_; |
| 203 scoped_refptr<IOBuffer> write_iobuffer_; | 193 scoped_refptr<IOBuffer> write_iobuffer_; |
| 204 int read_buffer_length_; | 194 int read_buffer_length_; |
| 205 int write_buffer_length_; | 195 int write_buffer_length_; |
| 206 | 196 |
| 207 // Remember the state of g_disable_overlapped_reads for the duration of the | |
| 208 // socket based on what it was when the socket was created. | |
| 209 bool disable_overlapped_reads_; | |
| 210 bool non_blocking_reads_initialized_; | 197 bool non_blocking_reads_initialized_; |
| 211 | 198 |
| 212 private: | 199 private: |
| 213 friend class base::RefCounted<Core>; | 200 friend class base::RefCounted<Core>; |
| 214 | 201 |
| 215 class ReadDelegate : public base::win::ObjectWatcher::Delegate { | 202 class ReadDelegate : public base::win::ObjectWatcher::Delegate { |
| 216 public: | 203 public: |
| 217 explicit ReadDelegate(Core* core) : core_(core) {} | 204 explicit ReadDelegate(Core* core) : core_(core) {} |
| 218 virtual ~ReadDelegate() {} | 205 virtual ~ReadDelegate() {} |
| 219 | 206 |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 244 // |reader_| handles the signals from |read_watcher_|. | 231 // |reader_| handles the signals from |read_watcher_|. |
| 245 ReadDelegate reader_; | 232 ReadDelegate reader_; |
| 246 // |writer_| handles the signals from |write_watcher_|. | 233 // |writer_| handles the signals from |write_watcher_|. |
| 247 WriteDelegate writer_; | 234 WriteDelegate writer_; |
| 248 | 235 |
| 249 // |read_watcher_| watches for events from Connect() and Read(). | 236 // |read_watcher_| watches for events from Connect() and Read(). |
| 250 base::win::ObjectWatcher read_watcher_; | 237 base::win::ObjectWatcher read_watcher_; |
| 251 // |write_watcher_| watches for events from Write(); | 238 // |write_watcher_| watches for events from Write(); |
| 252 base::win::ObjectWatcher write_watcher_; | 239 base::win::ObjectWatcher write_watcher_; |
| 253 | 240 |
| 254 // When doing reads from the socket, we try to mirror TCP's slow start. | |
| 255 // We do this because otherwise the async IO subsystem artifically delays | |
| 256 // returning data to the application. | |
| 257 static const int kInitialSlowStartThrottle = 1 * 1024; | |
| 258 static const int kMaxSlowStartThrottle = 32 * kInitialSlowStartThrottle; | |
| 259 int slow_start_throttle_; | |
| 260 | |
| 261 DISALLOW_COPY_AND_ASSIGN(Core); | 241 DISALLOW_COPY_AND_ASSIGN(Core); |
| 262 }; | 242 }; |
| 263 | 243 |
| 264 TCPClientSocketWin::Core::Core( | 244 TCPClientSocketWin::Core::Core( |
| 265 TCPClientSocketWin* socket) | 245 TCPClientSocketWin* socket) |
| 266 : read_buffer_length_(0), | 246 : read_buffer_length_(0), |
| 267 write_buffer_length_(0), | 247 write_buffer_length_(0), |
| 268 disable_overlapped_reads_(g_disable_overlapped_reads), | |
| 269 non_blocking_reads_initialized_(false), | 248 non_blocking_reads_initialized_(false), |
| 270 socket_(socket), | 249 socket_(socket), |
| 271 reader_(this), | 250 reader_(this), |
| 272 writer_(this), | 251 writer_(this) { |
| 273 slow_start_throttle_(kInitialSlowStartThrottle) { | |
| 274 memset(&read_overlapped_, 0, sizeof(read_overlapped_)); | 252 memset(&read_overlapped_, 0, sizeof(read_overlapped_)); |
| 275 memset(&write_overlapped_, 0, sizeof(write_overlapped_)); | 253 memset(&write_overlapped_, 0, sizeof(write_overlapped_)); |
| 276 | 254 |
| 277 read_overlapped_.hEvent = WSACreateEvent(); | 255 read_overlapped_.hEvent = WSACreateEvent(); |
| 278 write_overlapped_.hEvent = WSACreateEvent(); | 256 write_overlapped_.hEvent = WSACreateEvent(); |
| 279 } | 257 } |
| 280 | 258 |
| 281 TCPClientSocketWin::Core::~Core() { | 259 TCPClientSocketWin::Core::~Core() { |
| 282 // Make sure the message loop is not watching this object anymore. | 260 // Make sure the message loop is not watching this object anymore. |
| 283 read_watcher_.StopWatching(); | 261 read_watcher_.StopWatching(); |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 300 // We grab an extra reference because there is an IO operation in progress. | 278 // We grab an extra reference because there is an IO operation in progress. |
| 301 // Balanced in WriteDelegate::OnObjectSignaled(). | 279 // Balanced in WriteDelegate::OnObjectSignaled(). |
| 302 AddRef(); | 280 AddRef(); |
| 303 write_watcher_.StartWatching(write_overlapped_.hEvent, &writer_); | 281 write_watcher_.StartWatching(write_overlapped_.hEvent, &writer_); |
| 304 } | 282 } |
| 305 | 283 |
| 306 void TCPClientSocketWin::Core::ReadDelegate::OnObjectSignaled( | 284 void TCPClientSocketWin::Core::ReadDelegate::OnObjectSignaled( |
| 307 HANDLE object) { | 285 HANDLE object) { |
| 308 DCHECK_EQ(object, core_->read_overlapped_.hEvent); | 286 DCHECK_EQ(object, core_->read_overlapped_.hEvent); |
| 309 if (core_->socket_) { | 287 if (core_->socket_) { |
| 310 if (core_->socket_->waiting_connect()) { | 288 if (core_->socket_->waiting_connect()) |
| 311 core_->socket_->DidCompleteConnect(); | 289 core_->socket_->DidCompleteConnect(); |
| 312 } else if (core_->disable_overlapped_reads_) { | 290 else |
| 313 core_->socket_->DidSignalRead(); | 291 core_->socket_->DidSignalRead(); |
| 314 } else { | |
| 315 core_->socket_->DidCompleteRead(); | |
| 316 } | |
| 317 } | 292 } |
| 318 | 293 |
| 319 core_->Release(); | 294 core_->Release(); |
| 320 } | 295 } |
| 321 | 296 |
| 322 void TCPClientSocketWin::Core::WriteDelegate::OnObjectSignaled( | 297 void TCPClientSocketWin::Core::WriteDelegate::OnObjectSignaled( |
| 323 HANDLE object) { | 298 HANDLE object) { |
| 324 DCHECK_EQ(object, core_->write_overlapped_.hEvent); | 299 DCHECK_EQ(object, core_->write_overlapped_.hEvent); |
| 325 if (core_->socket_) | 300 if (core_->socket_) |
| 326 core_->socket_->DidCompleteWrite(); | 301 core_->socket_->DidCompleteWrite(); |
| (...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 781 } | 756 } |
| 782 | 757 |
| 783 bool TCPClientSocketWin::SetKeepAlive(bool enable, int delay) { | 758 bool TCPClientSocketWin::SetKeepAlive(bool enable, int delay) { |
| 784 return SetTCPKeepAlive(socket_, enable, delay); | 759 return SetTCPKeepAlive(socket_, enable, delay); |
| 785 } | 760 } |
| 786 | 761 |
| 787 bool TCPClientSocketWin::SetNoDelay(bool no_delay) { | 762 bool TCPClientSocketWin::SetNoDelay(bool no_delay) { |
| 788 return DisableNagle(socket_, no_delay); | 763 return DisableNagle(socket_, no_delay); |
| 789 } | 764 } |
| 790 | 765 |
| 791 void TCPClientSocketWin::DisableOverlappedReads() { | |
| 792 g_disable_overlapped_reads = true; | |
| 793 } | |
| 794 | |
| 795 void TCPClientSocketWin::LogConnectCompletion(int net_error) { | 766 void TCPClientSocketWin::LogConnectCompletion(int net_error) { |
| 796 if (net_error == OK) | 767 if (net_error == OK) |
| 797 UpdateConnectionTypeHistograms(CONNECTION_ANY); | 768 UpdateConnectionTypeHistograms(CONNECTION_ANY); |
| 798 | 769 |
| 799 if (net_error != OK) { | 770 if (net_error != OK) { |
| 800 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, net_error); | 771 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, net_error); |
| 801 return; | 772 return; |
| 802 } | 773 } |
| 803 | 774 |
| 804 struct sockaddr_storage source_address; | 775 struct sockaddr_storage source_address; |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 815 | 786 |
| 816 net_log_.EndEvent( | 787 net_log_.EndEvent( |
| 817 NetLog::TYPE_TCP_CONNECT, | 788 NetLog::TYPE_TCP_CONNECT, |
| 818 CreateNetLogSourceAddressCallback( | 789 CreateNetLogSourceAddressCallback( |
| 819 reinterpret_cast<const struct sockaddr*>(&source_address), | 790 reinterpret_cast<const struct sockaddr*>(&source_address), |
| 820 sizeof(source_address))); | 791 sizeof(source_address))); |
| 821 } | 792 } |
| 822 | 793 |
| 823 int TCPClientSocketWin::DoRead(IOBuffer* buf, int buf_len, | 794 int TCPClientSocketWin::DoRead(IOBuffer* buf, int buf_len, |
| 824 const CompletionCallback& callback) { | 795 const CompletionCallback& callback) { |
| 825 if (core_->disable_overlapped_reads_) { | 796 if (!core_->non_blocking_reads_initialized_) { |
| 826 if (!core_->non_blocking_reads_initialized_) { | 797 WSAEventSelect(socket_, core_->read_overlapped_.hEvent, |
| 827 WSAEventSelect(socket_, core_->read_overlapped_.hEvent, | 798 FD_READ | FD_CLOSE); |
|
Ryan Sleevi
2013/08/06 19:43:38
nit: alignment
Pat Meenan
2013/08/07 13:54:17
Fixed
| |
| 828 FD_READ | FD_CLOSE); | 799 core_->non_blocking_reads_initialized_ = true; |
| 829 core_->non_blocking_reads_initialized_ = true; | 800 } |
| 830 } | 801 int rv = recv(socket_, buf->data(), buf_len, 0); |
| 831 int rv = recv(socket_, buf->data(), buf_len, 0); | 802 if (rv == SOCKET_ERROR) { |
| 832 if (rv == SOCKET_ERROR) { | 803 int os_error = WSAGetLastError(); |
| 833 int os_error = WSAGetLastError(); | 804 if (os_error != WSAEWOULDBLOCK) { |
| 834 if (os_error != WSAEWOULDBLOCK) { | 805 int net_error = MapSystemError(os_error); |
| 835 int net_error = MapSystemError(os_error); | 806 net_log_.AddEvent(NetLog::TYPE_SOCKET_READ_ERROR, |
| 836 net_log_.AddEvent(NetLog::TYPE_SOCKET_READ_ERROR, | 807 CreateNetLogSocketErrorCallback(net_error, os_error)); |
|
Ryan Sleevi
2013/08/06 19:43:38
nit: Style is wrong here, per http://google-styleg
Pat Meenan
2013/08/07 13:54:17
Fixed
| |
| 837 CreateNetLogSocketErrorCallback(net_error, os_error)); | 808 return net_error; |
| 838 return net_error; | |
| 839 } | |
| 840 } else { | |
| 841 base::StatsCounter read_bytes("tcp.read_bytes"); | |
| 842 if (rv > 0) { | |
| 843 use_history_.set_was_used_to_convey_data(); | |
| 844 read_bytes.Add(rv); | |
| 845 } | |
| 846 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, rv, | |
| 847 buf->data()); | |
| 848 return rv; | |
| 849 } | 809 } |
| 850 } else { | 810 } else { |
| 851 buf_len = core_->ThrottleReadSize(buf_len); | 811 base::StatsCounter read_bytes("tcp.read_bytes"); |
| 852 | 812 if (rv > 0) { |
| 853 WSABUF read_buffer; | 813 use_history_.set_was_used_to_convey_data(); |
| 854 read_buffer.len = buf_len; | 814 read_bytes.Add(rv); |
| 855 read_buffer.buf = buf->data(); | |
| 856 | |
| 857 // TODO(wtc): Remove the assertion after enough testing. | |
| 858 AssertEventNotSignaled(core_->read_overlapped_.hEvent); | |
| 859 DWORD num; | |
| 860 DWORD flags = 0; | |
| 861 int rv = WSARecv(socket_, &read_buffer, 1, &num, &flags, | |
| 862 &core_->read_overlapped_, NULL); | |
| 863 if (rv == 0) { | |
| 864 if (ResetEventIfSignaled(core_->read_overlapped_.hEvent)) { | |
| 865 base::StatsCounter read_bytes("tcp.read_bytes"); | |
| 866 if (num > 0) { | |
| 867 use_history_.set_was_used_to_convey_data(); | |
| 868 read_bytes.Add(num); | |
| 869 } | |
| 870 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, num, | |
| 871 buf->data()); | |
| 872 return static_cast<int>(num); | |
| 873 } | |
| 874 } else { | |
| 875 int os_error = WSAGetLastError(); | |
| 876 if (os_error != WSA_IO_PENDING) { | |
| 877 int net_error = MapSystemError(os_error); | |
| 878 net_log_.AddEvent(NetLog::TYPE_SOCKET_READ_ERROR, | |
| 879 CreateNetLogSocketErrorCallback(net_error, os_error)); | |
| 880 return net_error; | |
| 881 } | |
| 882 } | 815 } |
| 816 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, rv, | |
| 817 buf->data()); | |
| 818 return rv; | |
| 883 } | 819 } |
| 884 | 820 |
| 885 waiting_read_ = true; | 821 waiting_read_ = true; |
| 886 read_callback_ = callback; | 822 read_callback_ = callback; |
| 887 core_->read_iobuffer_ = buf; | 823 core_->read_iobuffer_ = buf; |
| 888 core_->read_buffer_length_ = buf_len; | 824 core_->read_buffer_length_ = buf_len; |
| 889 core_->WatchForRead(); | 825 core_->WatchForRead(); |
| 890 return ERR_IO_PENDING; | 826 return ERR_IO_PENDING; |
| 891 } | 827 } |
| 892 | 828 |
| 893 void TCPClientSocketWin::DoReadCallback(int rv) { | 829 void TCPClientSocketWin::DoReadCallback(int rv) { |
| 894 DCHECK_NE(rv, ERR_IO_PENDING); | 830 DCHECK_NE(rv, ERR_IO_PENDING); |
| 895 DCHECK(!read_callback_.is_null()); | 831 DCHECK(!read_callback_.is_null()); |
| 896 | 832 |
| 897 // Since Run may result in Read being called, clear read_callback_ up front. | 833 // Since Run may result in Read being called, clear read_callback_ up front. |
| 898 CompletionCallback c = read_callback_; | 834 CompletionCallback c = read_callback_; |
| 899 read_callback_.Reset(); | 835 read_callback_.Reset(); |
| 900 c.Run(rv); | 836 c.Run(rv); |
| 901 } | 837 } |
| 902 | 838 |
| 903 void TCPClientSocketWin::DoWriteCallback(int rv) { | 839 void TCPClientSocketWin::DoWriteCallback(int rv) { |
| 904 DCHECK_NE(rv, ERR_IO_PENDING); | 840 DCHECK_NE(rv, ERR_IO_PENDING); |
| 905 DCHECK(!write_callback_.is_null()); | 841 DCHECK(!write_callback_.is_null()); |
| 906 | 842 |
| 907 // since Run may result in Write being called, clear write_callback_ up front. | 843 // Since Run may result in Write being called, |
|
rvargas (doing something else)
2013/08/06 21:43:31
nit: This should still fit in one line.
Pat Meenan
2013/08/07 13:54:17
Thanks. Looks like my guidelines in my editor are
| |
| 844 // clear write_callback_ up front. | |
| 908 CompletionCallback c = write_callback_; | 845 CompletionCallback c = write_callback_; |
| 909 write_callback_.Reset(); | 846 write_callback_.Reset(); |
| 910 c.Run(rv); | 847 c.Run(rv); |
| 911 } | 848 } |
| 912 | 849 |
| 913 void TCPClientSocketWin::DidCompleteConnect() { | 850 void TCPClientSocketWin::DidCompleteConnect() { |
| 914 DCHECK_EQ(next_connect_state_, CONNECT_STATE_CONNECT_COMPLETE); | 851 DCHECK_EQ(next_connect_state_, CONNECT_STATE_CONNECT_COMPLETE); |
| 915 int result; | 852 int result; |
| 916 | 853 |
| 917 WSANETWORKEVENTS events; | 854 WSANETWORKEVENTS events; |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 931 } | 868 } |
| 932 | 869 |
| 933 connect_os_error_ = os_error; | 870 connect_os_error_ = os_error; |
| 934 rv = DoConnectLoop(result); | 871 rv = DoConnectLoop(result); |
| 935 if (rv != ERR_IO_PENDING) { | 872 if (rv != ERR_IO_PENDING) { |
| 936 LogConnectCompletion(rv); | 873 LogConnectCompletion(rv); |
| 937 DoReadCallback(rv); | 874 DoReadCallback(rv); |
| 938 } | 875 } |
| 939 } | 876 } |
| 940 | 877 |
| 941 void TCPClientSocketWin::DidCompleteRead() { | |
| 942 DCHECK(waiting_read_); | |
| 943 DWORD num_bytes, flags; | |
| 944 BOOL ok = WSAGetOverlappedResult(socket_, &core_->read_overlapped_, | |
| 945 &num_bytes, FALSE, &flags); | |
| 946 waiting_read_ = false; | |
| 947 int rv; | |
| 948 if (ok) { | |
| 949 base::StatsCounter read_bytes("tcp.read_bytes"); | |
| 950 read_bytes.Add(num_bytes); | |
| 951 if (num_bytes > 0) | |
| 952 use_history_.set_was_used_to_convey_data(); | |
| 953 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, | |
| 954 num_bytes, core_->read_iobuffer_->data()); | |
| 955 rv = static_cast<int>(num_bytes); | |
| 956 } else { | |
| 957 int os_error = WSAGetLastError(); | |
| 958 rv = MapSystemError(os_error); | |
| 959 net_log_.AddEvent(NetLog::TYPE_SOCKET_READ_ERROR, | |
| 960 CreateNetLogSocketErrorCallback(rv, os_error)); | |
| 961 } | |
| 962 WSAResetEvent(core_->read_overlapped_.hEvent); | |
| 963 core_->read_iobuffer_ = NULL; | |
| 964 core_->read_buffer_length_ = 0; | |
| 965 DoReadCallback(rv); | |
| 966 } | |
| 967 | |
| 968 void TCPClientSocketWin::DidCompleteWrite() { | 878 void TCPClientSocketWin::DidCompleteWrite() { |
| 969 DCHECK(waiting_write_); | 879 DCHECK(waiting_write_); |
| 970 | 880 |
| 971 DWORD num_bytes, flags; | 881 DWORD num_bytes, flags; |
| 972 BOOL ok = WSAGetOverlappedResult(socket_, &core_->write_overlapped_, | 882 BOOL ok = WSAGetOverlappedResult(socket_, &core_->write_overlapped_, |
| 973 &num_bytes, FALSE, &flags); | 883 &num_bytes, FALSE, &flags); |
| 974 WSAResetEvent(core_->write_overlapped_.hEvent); | 884 WSAResetEvent(core_->write_overlapped_.hEvent); |
| 975 waiting_write_ = false; | 885 waiting_write_ = false; |
| 976 int rv; | 886 int rv; |
| 977 if (!ok) { | 887 if (!ok) { |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1036 core_->WatchForRead(); | 946 core_->WatchForRead(); |
| 1037 return; | 947 return; |
| 1038 } | 948 } |
| 1039 waiting_read_ = false; | 949 waiting_read_ = false; |
| 1040 core_->read_iobuffer_ = NULL; | 950 core_->read_iobuffer_ = NULL; |
| 1041 core_->read_buffer_length_ = 0; | 951 core_->read_buffer_length_ = 0; |
| 1042 DoReadCallback(rv); | 952 DoReadCallback(rv); |
| 1043 } | 953 } |
| 1044 | 954 |
| 1045 } // namespace net | 955 } // namespace net |
| OLD | NEW |