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

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

Issue 10916016: Switch the TCP reads on Windows to use non-blocking/non-async I/O. (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: Created 8 years, 3 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 | Annotate | Revision Log
« 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 10 matching lines...) Expand all
21 #include "net/base/network_change_notifier.h" 21 #include "net/base/network_change_notifier.h"
22 #include "net/base/winsock_init.h" 22 #include "net/base/winsock_init.h"
23 #include "net/base/winsock_util.h" 23 #include "net/base/winsock_util.h"
24 #include "net/socket/socket_net_log_params.h" 24 #include "net/socket/socket_net_log_params.h"
25 25
26 namespace net { 26 namespace net {
27 27
28 namespace { 28 namespace {
29 29
30 const int kTCPKeepAliveSeconds = 45; 30 const int kTCPKeepAliveSeconds = 45;
31 const bool kUseNonBlockingSockets = true;
slamm_google 2012/08/30 17:47:25 Refer to the related but that explains the reason
pmeenan 2012/08/30 17:54:31 Will be switching this to use an experiment once I
31 32
32 bool SetSocketReceiveBufferSize(SOCKET socket, int32 size) { 33 bool SetSocketReceiveBufferSize(SOCKET socket, int32 size) {
33 int rv = setsockopt(socket, SOL_SOCKET, SO_RCVBUF, 34 int rv = setsockopt(socket, SOL_SOCKET, SO_RCVBUF,
34 reinterpret_cast<const char*>(&size), sizeof(size)); 35 reinterpret_cast<const char*>(&size), sizeof(size));
35 DCHECK(!rv) << "Could not set socket receive buffer size: " << GetLastError(); 36 DCHECK(!rv) << "Could not set socket receive buffer size: " << GetLastError();
36 return rv == 0; 37 return rv == 0;
37 } 38 }
38 39
39 bool SetSocketSendBufferSize(SOCKET socket, int32 size) { 40 bool SetSocketSendBufferSize(SOCKET socket, int32 size) {
40 int rv = setsockopt(socket, SOL_SOCKET, SO_SNDBUF, 41 int rv = setsockopt(socket, SOL_SOCKET, SO_SNDBUF,
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 write_watcher_.StartWatching(write_overlapped_.hEvent, &writer_); 297 write_watcher_.StartWatching(write_overlapped_.hEvent, &writer_);
297 } 298 }
298 299
299 void TCPClientSocketWin::Core::ReadDelegate::OnObjectSignaled( 300 void TCPClientSocketWin::Core::ReadDelegate::OnObjectSignaled(
300 HANDLE object) { 301 HANDLE object) {
301 DCHECK_EQ(object, core_->read_overlapped_.hEvent); 302 DCHECK_EQ(object, core_->read_overlapped_.hEvent);
302 if (core_->socket_) { 303 if (core_->socket_) {
303 if (core_->socket_->waiting_connect()) { 304 if (core_->socket_->waiting_connect()) {
304 core_->socket_->DidCompleteConnect(); 305 core_->socket_->DidCompleteConnect();
305 } else { 306 } else {
306 core_->socket_->DidCompleteRead(); 307 if (kUseNonBlockingSockets) {
308 core_->socket_->HandleReadSignalled();
slamm_google 2012/08/30 17:47:25 Signalled -> Signaled The dictionary has it both
pmeenan 2012/08/30 17:54:31 Thanks. Looked kind of strange.
309 } else {
310 core_->socket_->DidCompleteRead();
311 }
307 } 312 }
308 } 313 }
309 314
310 core_->Release(); 315 core_->Release();
311 } 316 }
312 317
313 void TCPClientSocketWin::Core::WriteDelegate::OnObjectSignaled( 318 void TCPClientSocketWin::Core::WriteDelegate::OnObjectSignaled(
314 HANDLE object) { 319 HANDLE object) {
315 DCHECK_EQ(object, core_->write_overlapped_.hEvent); 320 DCHECK_EQ(object, core_->write_overlapped_.hEvent);
316 if (core_->socket_) 321 if (core_->socket_)
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 DCHECK_EQ(socket_, INVALID_SOCKET); 354 DCHECK_EQ(socket_, INVALID_SOCKET);
350 355
351 int error = SetupSocket(socket); 356 int error = SetupSocket(socket);
352 if (error) 357 if (error)
353 return MapSystemError(error); 358 return MapSystemError(error);
354 359
355 socket_ = socket; 360 socket_ = socket;
356 SetNonBlocking(socket_); 361 SetNonBlocking(socket_);
357 362
358 core_ = new Core(this); 363 core_ = new Core(this);
364 if (kUseNonBlockingSockets) {
365 WSAEventSelect(socket_, core_->read_overlapped_.hEvent,
366 FD_READ | FD_CLOSE);
367 }
359 368
360 current_address_index_ = 0; 369 current_address_index_ = 0;
361 use_history_.set_was_ever_connected(); 370 use_history_.set_was_ever_connected();
362 371
363 return OK; 372 return OK;
364 } 373 }
365 374
366 int TCPClientSocketWin::Bind(const IPEndPoint& address) { 375 int TCPClientSocketWin::Bind(const IPEndPoint& address) {
367 if (current_address_index_ >= 0 || bind_address_.get()) { 376 if (current_address_index_ >= 0 || bind_address_.get()) {
368 // Cannot bind the socket if we are already connected or connecting. 377 // Cannot bind the socket if we are already connected or connecting.
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
480 return ERR_INVALID_ARGUMENT; 489 return ERR_INVALID_ARGUMENT;
481 if (bind(socket_, storage.addr, storage.addr_len)) 490 if (bind(socket_, storage.addr, storage.addr_len))
482 return MapSystemError(errno); 491 return MapSystemError(errno);
483 } 492 }
484 } 493 }
485 494
486 DCHECK(!core_); 495 DCHECK(!core_);
487 core_ = new Core(this); 496 core_ = new Core(this);
488 // WSAEventSelect sets the socket to non-blocking mode as a side effect. 497 // WSAEventSelect sets the socket to non-blocking mode as a side effect.
489 // Our connect() and recv() calls require that the socket be non-blocking. 498 // Our connect() and recv() calls require that the socket be non-blocking.
490 WSAEventSelect(socket_, core_->read_overlapped_.hEvent, FD_CONNECT); 499 if (kUseNonBlockingSockets) {
500 WSAEventSelect(socket_, core_->read_overlapped_.hEvent,
501 FD_CONNECT | FD_READ | FD_CLOSE);
502 } else {
503 WSAEventSelect(socket_, core_->read_overlapped_.hEvent, FD_CONNECT);
504 }
491 505
492 SockaddrStorage storage; 506 SockaddrStorage storage;
493 if (!endpoint.ToSockAddr(storage.addr, &storage.addr_len)) 507 if (!endpoint.ToSockAddr(storage.addr, &storage.addr_len))
494 return ERR_INVALID_ARGUMENT; 508 return ERR_INVALID_ARGUMENT;
495 connect_start_time_ = base::TimeTicks::Now(); 509 connect_start_time_ = base::TimeTicks::Now();
496 if (!connect(socket_, storage.addr, storage.addr_len)) { 510 if (!connect(socket_, storage.addr, storage.addr_len)) {
497 // Connected without waiting! 511 // Connected without waiting!
498 // 512 //
499 // The MSDN page for connect says: 513 // The MSDN page for connect says:
500 // With a nonblocking socket, the connection attempt cannot be completed 514 // With a nonblocking socket, the connection attempt cannot be completed
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
706 720
707 int TCPClientSocketWin::Read(IOBuffer* buf, 721 int TCPClientSocketWin::Read(IOBuffer* buf,
708 int buf_len, 722 int buf_len,
709 const CompletionCallback& callback) { 723 const CompletionCallback& callback) {
710 DCHECK(CalledOnValidThread()); 724 DCHECK(CalledOnValidThread());
711 DCHECK_NE(socket_, INVALID_SOCKET); 725 DCHECK_NE(socket_, INVALID_SOCKET);
712 DCHECK(!waiting_read_); 726 DCHECK(!waiting_read_);
713 DCHECK(read_callback_.is_null()); 727 DCHECK(read_callback_.is_null());
714 DCHECK(!core_->read_iobuffer_); 728 DCHECK(!core_->read_iobuffer_);
715 729
716 buf_len = core_->ThrottleReadSize(buf_len); 730 if (kUseNonBlockingSockets) {
731 core_->read_buffer_.len = buf_len;
732 core_->read_buffer_.buf = buf->data();
717 733
718 core_->read_buffer_.len = buf_len; 734 int flags = 0;
719 core_->read_buffer_.buf = buf->data(); 735 int rv = recv(socket_, core_->read_buffer_.buf, core_->read_buffer_.len,
720 736 flags);
721 // TODO(wtc): Remove the assertion after enough testing. 737 if (rv == SOCKET_ERROR) {
722 AssertEventNotSignaled(core_->read_overlapped_.hEvent); 738 int os_error = WSAGetLastError();
723 DWORD num, flags = 0; 739 if (os_error != WSAEWOULDBLOCK) {
724 int rv = WSARecv(socket_, &core_->read_buffer_, 1, &num, &flags, 740 int net_error = MapSystemError(os_error);
725 &core_->read_overlapped_, NULL); 741 net_log_.AddEvent(NetLog::TYPE_SOCKET_READ_ERROR,
726 if (rv == 0) { 742 CreateNetLogSocketErrorCallback(net_error, os_error));
slamm_google 2012/08/30 17:47:25 Indent one more space.
727 if (ResetEventIfSignaled(core_->read_overlapped_.hEvent)) { 743 return net_error;
744 }
745 } else {
728 base::StatsCounter read_bytes("tcp.read_bytes"); 746 base::StatsCounter read_bytes("tcp.read_bytes");
729 read_bytes.Add(num); 747 if (rv > 0) {
730 num_bytes_read_ += num;
731 if (num > 0)
732 use_history_.set_was_used_to_convey_data(); 748 use_history_.set_was_used_to_convey_data();
733 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, num, 749 read_bytes.Add(rv);
750 num_bytes_read_ += rv;
751 }
752 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, rv,
734 core_->read_buffer_.buf); 753 core_->read_buffer_.buf);
735 return static_cast<int>(num); 754 return rv;
736 } 755 }
737 } else { 756 } else {
738 int os_error = WSAGetLastError(); 757 buf_len = core_->ThrottleReadSize(buf_len);
739 if (os_error != WSA_IO_PENDING) { 758
740 int net_error = MapSystemError(os_error); 759 core_->read_buffer_.len = buf_len;
741 net_log_.AddEvent(NetLog::TYPE_SOCKET_READ_ERROR, 760 core_->read_buffer_.buf = buf->data();
742 CreateNetLogSocketErrorCallback(net_error, os_error)); 761
743 return net_error; 762 // TODO(wtc): Remove the assertion after enough testing.
763 AssertEventNotSignaled(core_->read_overlapped_.hEvent);
764 DWORD num, flags = 0;
765 int rv = WSARecv(socket_, &core_->read_buffer_, 1, &num, &flags,
slamm_google 2012/08/30 17:47:25 Add a comment to explain the 1 byte recv?
pmeenan 2012/08/30 17:54:31 Good catch. That was left over from my other impl
pmeenan 2012/08/31 15:05:23 Actually, this is 1 recv buffer, not the length an
766 &core_->read_overlapped_, NULL);
767 if (rv == 0) {
768 if (ResetEventIfSignaled(core_->read_overlapped_.hEvent)) {
769 base::StatsCounter read_bytes("tcp.read_bytes");
770 read_bytes.Add(num);
771 num_bytes_read_ += num;
772 if (num > 0)
773 use_history_.set_was_used_to_convey_data();
774 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, num,
775 core_->read_buffer_.buf);
776 return static_cast<int>(num);
777 }
778 } else {
779 int os_error = WSAGetLastError();
780 if (os_error != WSA_IO_PENDING) {
781 int net_error = MapSystemError(os_error);
782 net_log_.AddEvent(NetLog::TYPE_SOCKET_READ_ERROR,
783 CreateNetLogSocketErrorCallback(net_error, os_error));
784 return net_error;
785 }
744 } 786 }
745 } 787 }
788 waiting_read_ = true;
746 core_->WatchForRead(); 789 core_->WatchForRead();
747 waiting_read_ = true;
748 read_callback_ = callback; 790 read_callback_ = callback;
749 core_->read_iobuffer_ = buf; 791 core_->read_iobuffer_ = buf;
750 return ERR_IO_PENDING; 792 return ERR_IO_PENDING;
751 } 793 }
752 794
753 int TCPClientSocketWin::Write(IOBuffer* buf, 795 int TCPClientSocketWin::Write(IOBuffer* buf,
754 int buf_len, 796 int buf_len,
755 const CompletionCallback& callback) { 797 const CompletionCallback& callback) {
756 DCHECK(CalledOnValidThread()); 798 DCHECK(CalledOnValidThread());
757 DCHECK_NE(socket_, INVALID_SOCKET); 799 DCHECK_NE(socket_, INVALID_SOCKET);
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
893 } 935 }
894 936
895 connect_os_error_ = os_error; 937 connect_os_error_ = os_error;
896 rv = DoConnectLoop(result); 938 rv = DoConnectLoop(result);
897 if (rv != ERR_IO_PENDING) { 939 if (rv != ERR_IO_PENDING) {
898 LogConnectCompletion(rv); 940 LogConnectCompletion(rv);
899 DoReadCallback(rv); 941 DoReadCallback(rv);
900 } 942 }
901 } 943 }
902 944
945 void TCPClientSocketWin::HandleReadSignalled() {
946 DCHECK(waiting_read_);
947 int rv;
948 int os_error = 0;
949 WSANETWORKEVENTS events;
950 rv = WSAEnumNetworkEvents(socket_, core_->read_overlapped_.hEvent,
951 &events);
952 if (rv != SOCKET_ERROR) {
953 if (events.lNetworkEvents & FD_READ) {
954 os_error = events.iErrorCode[FD_READ_BIT];
955 if (os_error == 0) {
956 int flags = 0;
957 rv = recv(socket_, core_->read_buffer_.buf, core_->read_buffer_.len,
958 flags);
slamm_google 2012/08/30 17:47:25 Fix indentation.
959 if (rv == SOCKET_ERROR) {
960 os_error = WSAGetLastError();
961 }
962 }
963 } else if (events.lNetworkEvents & FD_CLOSE) {
964 os_error = events.iErrorCode[FD_CLOSE_BIT];
965 } else if (events.lNetworkEvents == 0) {
966 core_->WatchForRead();
967 return;
968 }
969 } else {
970 os_error = WSAGetLastError();
971 }
972 if (os_error != 0 && rv <= 0) {
973 rv = MapSystemError(os_error);
974 net_log_.AddEvent(NetLog::TYPE_SOCKET_READ_ERROR,
975 CreateNetLogSocketErrorCallback(rv, os_error));
976 }
977 waiting_read_ = false;
978 core_->read_iobuffer_ = NULL;
979 DoReadCallback(rv);
980 }
981
903 void TCPClientSocketWin::DidCompleteRead() { 982 void TCPClientSocketWin::DidCompleteRead() {
904 DCHECK(waiting_read_); 983 DCHECK(waiting_read_);
905 DWORD num_bytes, flags; 984 DWORD num_bytes, flags;
906 BOOL ok = WSAGetOverlappedResult(socket_, &core_->read_overlapped_, 985 BOOL ok = WSAGetOverlappedResult(socket_, &core_->read_overlapped_,
907 &num_bytes, FALSE, &flags); 986 &num_bytes, FALSE, &flags);
908 WSAResetEvent(core_->read_overlapped_.hEvent); 987 WSAResetEvent(core_->read_overlapped_.hEvent);
909 waiting_read_ = false; 988 waiting_read_ = false;
910 core_->read_iobuffer_ = NULL; 989 core_->read_iobuffer_ = NULL;
911 int rv; 990 int rv;
912 if (ok) { 991 if (ok) {
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
957 use_history_.set_was_used_to_convey_data(); 1036 use_history_.set_was_used_to_convey_data();
958 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_SENT, num_bytes, 1037 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_SENT, num_bytes,
959 core_->write_buffer_.buf); 1038 core_->write_buffer_.buf);
960 } 1039 }
961 } 1040 }
962 core_->write_iobuffer_ = NULL; 1041 core_->write_iobuffer_ = NULL;
963 DoWriteCallback(rv); 1042 DoWriteCallback(rv);
964 } 1043 }
965 1044
966 } // namespace net 1045 } // 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