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 10 matching lines...) Expand all Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |