Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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_socket.h" | 5 #include "net/socket/tcp_socket.h" |
| 6 #include "net/socket/tcp_socket_win.h" | 6 #include "net/socket/tcp_socket_win.h" |
| 7 | 7 |
| 8 #include <errno.h> | 8 #include <errno.h> |
| 9 #include <mstcpip.h> | 9 #include <mstcpip.h> |
| 10 | 10 |
| (...skipping 471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 482 if (os_error != WSAEWOULDBLOCK) | 482 if (os_error != WSAEWOULDBLOCK) |
| 483 return false; | 483 return false; |
| 484 | 484 |
| 485 return true; | 485 return true; |
| 486 } | 486 } |
| 487 | 487 |
| 488 int TCPSocketWin::Read(IOBuffer* buf, | 488 int TCPSocketWin::Read(IOBuffer* buf, |
| 489 int buf_len, | 489 int buf_len, |
| 490 const CompletionCallback& callback) { | 490 const CompletionCallback& callback) { |
| 491 DCHECK(CalledOnValidThread()); | 491 DCHECK(CalledOnValidThread()); |
| 492 DCHECK_NE(socket_, INVALID_SOCKET); | |
| 493 DCHECK(!waiting_read_); | |
| 494 CHECK(read_callback_.is_null()); | |
| 495 DCHECK(!core_->read_iobuffer_.get()); | 492 DCHECK(!core_->read_iobuffer_.get()); |
|
xunjieli
2017/03/06 14:43:31
Note: This is not moved to ReadIfReady() because w
| |
| 496 | 493 // base::Unretained() is safe because RetryRead() won't be called when |this| |
| 497 return DoRead(buf, buf_len, callback); | 494 // is gone. |
| 495 int rv = | |
| 496 ReadIfReady(buf, buf_len, | |
| 497 base::Bind(&TCPSocketWin::RetryRead, base::Unretained(this))); | |
| 498 if (rv != ERR_IO_PENDING) | |
| 499 return rv; | |
| 500 read_callback_ = callback; | |
| 501 core_->read_iobuffer_ = buf; | |
| 502 core_->read_buffer_length_ = buf_len; | |
| 503 return ERR_IO_PENDING; | |
| 498 } | 504 } |
| 499 | 505 |
| 500 int TCPSocketWin::ReadIfReady(IOBuffer* buf, | 506 int TCPSocketWin::ReadIfReady(IOBuffer* buf, |
| 501 int buf_len, | 507 int buf_len, |
| 502 const CompletionCallback& callback) { | 508 const CompletionCallback& callback) { |
| 503 DCHECK(CalledOnValidThread()); | 509 DCHECK(CalledOnValidThread()); |
| 504 // TODO(xunjieli): Implement this. | 510 DCHECK_NE(socket_, INVALID_SOCKET); |
| 505 return ERR_READ_IF_READY_NOT_IMPLEMENTED; | 511 DCHECK(!waiting_read_); |
| 512 DCHECK(read_if_ready_callback_.is_null()); | |
| 513 | |
| 514 if (!core_->non_blocking_reads_initialized_) { | |
| 515 WSAEventSelect(socket_, core_->read_overlapped_.hEvent, FD_READ | FD_CLOSE); | |
| 516 core_->non_blocking_reads_initialized_ = true; | |
| 517 } | |
| 518 int rv = recv(socket_, buf->data(), buf_len, 0); | |
| 519 int os_error = WSAGetLastError(); | |
| 520 if (rv == SOCKET_ERROR) { | |
| 521 if (os_error != WSAEWOULDBLOCK) { | |
| 522 int net_error = MapSystemError(os_error); | |
| 523 net_log_.AddEvent(NetLogEventType::SOCKET_READ_ERROR, | |
| 524 CreateNetLogSocketErrorCallback(net_error, os_error)); | |
| 525 return net_error; | |
| 526 } | |
| 527 } else { | |
| 528 net_log_.AddByteTransferEvent(NetLogEventType::SOCKET_BYTES_RECEIVED, rv, | |
| 529 buf->data()); | |
| 530 NetworkActivityMonitor::GetInstance()->IncrementBytesReceived(rv); | |
| 531 return rv; | |
| 532 } | |
| 533 | |
| 534 waiting_read_ = true; | |
| 535 read_if_ready_callback_ = callback; | |
| 536 core_->WatchForRead(); | |
| 537 return ERR_IO_PENDING; | |
| 506 } | 538 } |
| 507 | 539 |
| 508 int TCPSocketWin::Write(IOBuffer* buf, | 540 int TCPSocketWin::Write(IOBuffer* buf, |
| 509 int buf_len, | 541 int buf_len, |
| 510 const CompletionCallback& callback) { | 542 const CompletionCallback& callback) { |
| 511 DCHECK(CalledOnValidThread()); | 543 DCHECK(CalledOnValidThread()); |
| 512 DCHECK_NE(socket_, INVALID_SOCKET); | 544 DCHECK_NE(socket_, INVALID_SOCKET); |
| 513 DCHECK(!waiting_write_); | 545 DCHECK(!waiting_write_); |
| 514 CHECK(write_callback_.is_null()); | 546 CHECK(write_callback_.is_null()); |
| 515 DCHECK_GT(buf_len, 0); | 547 DCHECK_GT(buf_len, 0); |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 678 } | 710 } |
| 679 core_->Detach(); | 711 core_->Detach(); |
| 680 core_ = NULL; | 712 core_ = NULL; |
| 681 } | 713 } |
| 682 | 714 |
| 683 waiting_connect_ = false; | 715 waiting_connect_ = false; |
| 684 waiting_read_ = false; | 716 waiting_read_ = false; |
| 685 waiting_write_ = false; | 717 waiting_write_ = false; |
| 686 | 718 |
| 687 read_callback_.Reset(); | 719 read_callback_.Reset(); |
| 720 read_if_ready_callback_.Reset(); | |
| 688 write_callback_.Reset(); | 721 write_callback_.Reset(); |
| 689 peer_address_.reset(); | 722 peer_address_.reset(); |
| 690 connect_os_error_ = 0; | 723 connect_os_error_ = 0; |
| 691 } | 724 } |
| 692 | 725 |
| 693 void TCPSocketWin::DetachFromThread() { | 726 void TCPSocketWin::DetachFromThread() { |
| 694 base::NonThreadSafe::DetachFromThread(); | 727 base::NonThreadSafe::DetachFromThread(); |
| 695 } | 728 } |
| 696 | 729 |
| 697 void TCPSocketWin::StartLoggingMultipleConnectAttempts( | 730 void TCPSocketWin::StartLoggingMultipleConnectAttempts( |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 872 return; | 905 return; |
| 873 } | 906 } |
| 874 | 907 |
| 875 net_log_.EndEvent( | 908 net_log_.EndEvent( |
| 876 NetLogEventType::TCP_CONNECT, | 909 NetLogEventType::TCP_CONNECT, |
| 877 CreateNetLogSourceAddressCallback( | 910 CreateNetLogSourceAddressCallback( |
| 878 reinterpret_cast<const struct sockaddr*>(&source_address), | 911 reinterpret_cast<const struct sockaddr*>(&source_address), |
| 879 sizeof(source_address))); | 912 sizeof(source_address))); |
| 880 } | 913 } |
| 881 | 914 |
| 882 int TCPSocketWin::DoRead(IOBuffer* buf, int buf_len, | 915 void TCPSocketWin::RetryRead(int rv) { |
| 883 const CompletionCallback& callback) { | 916 DCHECK(core_->read_iobuffer_); |
| 884 if (!core_->non_blocking_reads_initialized_) { | 917 |
| 885 WSAEventSelect(socket_, core_->read_overlapped_.hEvent, | 918 if (rv == OK) { |
| 886 FD_READ | FD_CLOSE); | 919 // base::Unretained() is safe because RetryRead() won't be called when |
| 887 core_->non_blocking_reads_initialized_ = true; | 920 // |this| is gone. |
| 921 rv = ReadIfReady( | |
| 922 core_->read_iobuffer_.get(), core_->read_buffer_length_, | |
| 923 base::Bind(&TCPSocketWin::RetryRead, base::Unretained(this))); | |
| 924 if (rv == ERR_IO_PENDING) | |
| 925 return; | |
| 888 } | 926 } |
| 889 int rv = recv(socket_, buf->data(), buf_len, 0); | 927 core_->read_iobuffer_ = nullptr; |
| 890 int os_error = WSAGetLastError(); | 928 core_->read_buffer_length_ = 0; |
| 891 if (rv == SOCKET_ERROR) { | 929 base::ResetAndReturn(&read_callback_).Run(rv); |
| 892 if (os_error != WSAEWOULDBLOCK) { | |
| 893 int net_error = MapSystemError(os_error); | |
| 894 net_log_.AddEvent(NetLogEventType::SOCKET_READ_ERROR, | |
| 895 CreateNetLogSocketErrorCallback(net_error, os_error)); | |
| 896 return net_error; | |
| 897 } | |
| 898 } else { | |
| 899 net_log_.AddByteTransferEvent(NetLogEventType::SOCKET_BYTES_RECEIVED, rv, | |
| 900 buf->data()); | |
| 901 NetworkActivityMonitor::GetInstance()->IncrementBytesReceived(rv); | |
| 902 return rv; | |
| 903 } | |
| 904 | |
| 905 waiting_read_ = true; | |
| 906 read_callback_ = callback; | |
| 907 core_->read_iobuffer_ = buf; | |
| 908 core_->read_buffer_length_ = buf_len; | |
| 909 core_->WatchForRead(); | |
| 910 return ERR_IO_PENDING; | |
| 911 } | 930 } |
| 912 | 931 |
| 913 void TCPSocketWin::DidCompleteConnect() { | 932 void TCPSocketWin::DidCompleteConnect() { |
| 914 DCHECK(waiting_connect_); | 933 DCHECK(waiting_connect_); |
| 915 DCHECK(!read_callback_.is_null()); | 934 DCHECK(!read_callback_.is_null()); |
| 916 int result; | 935 int result; |
| 917 | 936 |
| 918 WSANETWORKEVENTS events; | 937 WSANETWORKEVENTS events; |
| 919 int rv; | 938 int rv; |
| 920 int os_error = 0; | 939 int os_error = 0; |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 982 } | 1001 } |
| 983 | 1002 |
| 984 core_->write_iobuffer_ = NULL; | 1003 core_->write_iobuffer_ = NULL; |
| 985 | 1004 |
| 986 DCHECK_NE(rv, ERR_IO_PENDING); | 1005 DCHECK_NE(rv, ERR_IO_PENDING); |
| 987 base::ResetAndReturn(&write_callback_).Run(rv); | 1006 base::ResetAndReturn(&write_callback_).Run(rv); |
| 988 } | 1007 } |
| 989 | 1008 |
| 990 void TCPSocketWin::DidSignalRead() { | 1009 void TCPSocketWin::DidSignalRead() { |
| 991 DCHECK(waiting_read_); | 1010 DCHECK(waiting_read_); |
| 992 DCHECK(!read_callback_.is_null()); | 1011 DCHECK(!read_if_ready_callback_.is_null()); |
| 993 | 1012 |
| 994 int os_error = 0; | 1013 int os_error = 0; |
| 995 WSANETWORKEVENTS network_events; | 1014 WSANETWORKEVENTS network_events; |
| 996 int rv = WSAEnumNetworkEvents(socket_, core_->read_overlapped_.hEvent, | 1015 int rv = WSAEnumNetworkEvents(socket_, core_->read_overlapped_.hEvent, |
| 997 &network_events); | 1016 &network_events); |
| 998 os_error = WSAGetLastError(); | 1017 os_error = WSAGetLastError(); |
| 999 | 1018 |
| 1000 if (rv == SOCKET_ERROR) { | 1019 if (rv == SOCKET_ERROR) { |
| 1001 rv = MapSystemError(os_error); | 1020 rv = MapSystemError(os_error); |
| 1002 } else if (network_events.lNetworkEvents) { | 1021 } else if (network_events.lNetworkEvents) { |
| 1003 // TODO(pkasting): Remove ScopedTracker below once crbug.com/462778 is | 1022 // TODO(pkasting): Remove ScopedTracker below once crbug.com/462778 is |
| 1004 // fixed. | 1023 // fixed. |
| 1005 tracked_objects::ScopedTracker tracking_profile2( | 1024 tracked_objects::ScopedTracker tracking_profile2( |
| 1006 FROM_HERE_WITH_EXPLICIT_FUNCTION( | 1025 FROM_HERE_WITH_EXPLICIT_FUNCTION( |
| 1007 "462778 TCPSocketWin::DidSignalRead -> DoRead")); | 1026 "462778 TCPSocketWin::DidSignalRead -> DoRead")); |
| 1008 DCHECK_EQ(network_events.lNetworkEvents & ~(FD_READ | FD_CLOSE), 0); | 1027 DCHECK_EQ(network_events.lNetworkEvents & ~(FD_READ | FD_CLOSE), 0); |
| 1009 // If network_events.lNetworkEvents is FD_CLOSE and | 1028 // If network_events.lNetworkEvents is FD_CLOSE and |
| 1010 // network_events.iErrorCode[FD_CLOSE_BIT] is 0, it is a graceful | 1029 // network_events.iErrorCode[FD_CLOSE_BIT] is 0, it is a graceful |
| 1011 // connection closure. It is tempting to directly set rv to 0 in | 1030 // connection closure. It is tempting to directly set rv to 0 in |
| 1012 // this case, but the MSDN pages for WSAEventSelect and | 1031 // this case, but the MSDN pages for WSAEventSelect and |
| 1013 // WSAAsyncSelect recommend we still call DoRead(): | 1032 // WSAAsyncSelect recommend we still call RetryRead(): |
| 1014 // FD_CLOSE should only be posted after all data is read from a | 1033 // FD_CLOSE should only be posted after all data is read from a |
| 1015 // socket, but an application should check for remaining data upon | 1034 // socket, but an application should check for remaining data upon |
| 1016 // receipt of FD_CLOSE to avoid any possibility of losing data. | 1035 // receipt of FD_CLOSE to avoid any possibility of losing data. |
| 1017 // | 1036 // |
| 1018 // If network_events.iErrorCode[FD_READ_BIT] or | 1037 // If network_events.iErrorCode[FD_READ_BIT] or |
| 1019 // network_events.iErrorCode[FD_CLOSE_BIT] is nonzero, still call | 1038 // network_events.iErrorCode[FD_CLOSE_BIT] is nonzero, still call |
| 1020 // DoRead() because recv() reports a more accurate error code | 1039 // RetryRead() because recv() reports a more accurate error code |
| 1021 // (WSAECONNRESET vs. WSAECONNABORTED) when the connection was | 1040 // (WSAECONNRESET vs. WSAECONNABORTED) when the connection was |
| 1022 // reset. | 1041 // reset. |
| 1023 rv = DoRead(core_->read_iobuffer_.get(), core_->read_buffer_length_, | 1042 waiting_read_ = false; |
| 1024 read_callback_); | 1043 base::ResetAndReturn(&read_if_ready_callback_).Run(OK); |
| 1025 if (rv == ERR_IO_PENDING) | 1044 return; |
|
davidben
2017/03/06 22:09:08
I think you can replace these three lines with rv
xunjieli
2017/03/06 22:14:03
Done. Neat!
| |
| 1026 return; | |
| 1027 } else { | 1045 } else { |
| 1028 // This may happen because Read() may succeed synchronously and | 1046 // This may happen because Read() may succeed synchronously and |
| 1029 // consume all the received data without resetting the event object. | 1047 // consume all the received data without resetting the event object. |
| 1030 core_->WatchForRead(); | 1048 core_->WatchForRead(); |
| 1031 return; | 1049 return; |
| 1032 } | 1050 } |
| 1033 | 1051 |
| 1052 DCHECK_NE(rv, ERR_IO_PENDING); | |
| 1034 waiting_read_ = false; | 1053 waiting_read_ = false; |
| 1035 core_->read_iobuffer_ = NULL; | 1054 base::ResetAndReturn(&read_if_ready_callback_).Run(rv); |
| 1036 core_->read_buffer_length_ = 0; | |
| 1037 | |
| 1038 DCHECK_NE(rv, ERR_IO_PENDING); | |
| 1039 base::ResetAndReturn(&read_callback_).Run(rv); | |
| 1040 } | 1055 } |
| 1041 | 1056 |
| 1042 bool TCPSocketWin::GetEstimatedRoundTripTime(base::TimeDelta* out_rtt) const { | 1057 bool TCPSocketWin::GetEstimatedRoundTripTime(base::TimeDelta* out_rtt) const { |
| 1043 DCHECK(out_rtt); | 1058 DCHECK(out_rtt); |
| 1044 // TODO(bmcquade): Consider implementing using | 1059 // TODO(bmcquade): Consider implementing using |
| 1045 // GetPerTcpConnectionEStats/GetPerTcp6ConnectionEStats. | 1060 // GetPerTcpConnectionEStats/GetPerTcp6ConnectionEStats. |
| 1046 return false; | 1061 return false; |
| 1047 } | 1062 } |
| 1048 | 1063 |
| 1049 } // namespace net | 1064 } // namespace net |
| OLD | NEW |