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); |
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( |
836 net_log_.AddEvent(NetLog::TYPE_SOCKET_READ_ERROR, | 807 NetLog::TYPE_SOCKET_READ_ERROR, |
837 CreateNetLogSocketErrorCallback(net_error, os_error)); | 808 CreateNetLogSocketErrorCallback(net_error, os_error)); |
838 return net_error; | 809 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 } | 810 } |
850 } else { | 811 } else { |
851 buf_len = core_->ThrottleReadSize(buf_len); | 812 base::StatsCounter read_bytes("tcp.read_bytes"); |
852 | 813 if (rv > 0) { |
853 WSABUF read_buffer; | 814 use_history_.set_was_used_to_convey_data(); |
854 read_buffer.len = buf_len; | 815 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 } | 816 } |
| 817 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, rv, |
| 818 buf->data()); |
| 819 return rv; |
883 } | 820 } |
884 | 821 |
885 waiting_read_ = true; | 822 waiting_read_ = true; |
886 read_callback_ = callback; | 823 read_callback_ = callback; |
887 core_->read_iobuffer_ = buf; | 824 core_->read_iobuffer_ = buf; |
888 core_->read_buffer_length_ = buf_len; | 825 core_->read_buffer_length_ = buf_len; |
889 core_->WatchForRead(); | 826 core_->WatchForRead(); |
890 return ERR_IO_PENDING; | 827 return ERR_IO_PENDING; |
891 } | 828 } |
892 | 829 |
893 void TCPClientSocketWin::DoReadCallback(int rv) { | 830 void TCPClientSocketWin::DoReadCallback(int rv) { |
894 DCHECK_NE(rv, ERR_IO_PENDING); | 831 DCHECK_NE(rv, ERR_IO_PENDING); |
895 DCHECK(!read_callback_.is_null()); | 832 DCHECK(!read_callback_.is_null()); |
896 | 833 |
897 // Since Run may result in Read being called, clear read_callback_ up front. | 834 // Since Run may result in Read being called, clear read_callback_ up front. |
898 CompletionCallback c = read_callback_; | 835 CompletionCallback c = read_callback_; |
899 read_callback_.Reset(); | 836 read_callback_.Reset(); |
900 c.Run(rv); | 837 c.Run(rv); |
901 } | 838 } |
902 | 839 |
903 void TCPClientSocketWin::DoWriteCallback(int rv) { | 840 void TCPClientSocketWin::DoWriteCallback(int rv) { |
904 DCHECK_NE(rv, ERR_IO_PENDING); | 841 DCHECK_NE(rv, ERR_IO_PENDING); |
905 DCHECK(!write_callback_.is_null()); | 842 DCHECK(!write_callback_.is_null()); |
906 | 843 |
907 // since Run may result in Write being called, clear write_callback_ up front. | 844 // Since Run may result in Write being called, 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 |