Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(124)

Side by Side Diff: net/socket/tcp_client_socket_win.cc

Issue 22188002: Cleanup the Win overlapped reads vs. non-blocking reads by removing the overlapped read code path (Closed) Base URL: https://src.chromium.org/chrome/trunk/src/
Patch Set: Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/socket/tcp_client_socket_win.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « net/socket/tcp_client_socket_win.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698