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

Unified Diff: net/socket/tcp_socket_win.cc

Issue 2690943004: Add ReadIfReady() for tcp_socket_win (Closed)
Patch Set: self Created 3 years, 10 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/socket/tcp_socket_win.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/socket/tcp_socket_win.cc
diff --git a/net/socket/tcp_socket_win.cc b/net/socket/tcp_socket_win.cc
index 2ec130ee1cbd68b2d50a38223091997d4015a914..27591b610a751e67fd6f1214a87505f71db8b910 100644
--- a/net/socket/tcp_socket_win.cc
+++ b/net/socket/tcp_socket_win.cc
@@ -489,20 +489,52 @@ int TCPSocketWin::Read(IOBuffer* buf,
int buf_len,
const CompletionCallback& callback) {
DCHECK(CalledOnValidThread());
- DCHECK_NE(socket_, INVALID_SOCKET);
- DCHECK(!waiting_read_);
- CHECK(read_callback_.is_null());
DCHECK(!core_->read_iobuffer_.get());
xunjieli 2017/03/06 14:43:31 Note: This is not moved to ReadIfReady() because w
-
- return DoRead(buf, buf_len, callback);
+ // base::Unretained() is safe because RetryRead() won't be called when |this|
+ // is gone.
+ int rv =
+ ReadIfReady(buf, buf_len,
+ base::Bind(&TCPSocketWin::RetryRead, base::Unretained(this)));
+ if (rv != ERR_IO_PENDING)
+ return rv;
+ read_callback_ = callback;
+ core_->read_iobuffer_ = buf;
+ core_->read_buffer_length_ = buf_len;
+ return ERR_IO_PENDING;
}
int TCPSocketWin::ReadIfReady(IOBuffer* buf,
int buf_len,
const CompletionCallback& callback) {
DCHECK(CalledOnValidThread());
- // TODO(xunjieli): Implement this.
- return ERR_READ_IF_READY_NOT_IMPLEMENTED;
+ DCHECK_NE(socket_, INVALID_SOCKET);
+ DCHECK(!waiting_read_);
+ DCHECK(read_if_ready_callback_.is_null());
+
+ if (!core_->non_blocking_reads_initialized_) {
+ WSAEventSelect(socket_, core_->read_overlapped_.hEvent, FD_READ | FD_CLOSE);
+ core_->non_blocking_reads_initialized_ = true;
+ }
+ int rv = recv(socket_, buf->data(), buf_len, 0);
+ int os_error = WSAGetLastError();
+ if (rv == SOCKET_ERROR) {
+ if (os_error != WSAEWOULDBLOCK) {
+ int net_error = MapSystemError(os_error);
+ net_log_.AddEvent(NetLogEventType::SOCKET_READ_ERROR,
+ CreateNetLogSocketErrorCallback(net_error, os_error));
+ return net_error;
+ }
+ } else {
+ net_log_.AddByteTransferEvent(NetLogEventType::SOCKET_BYTES_RECEIVED, rv,
+ buf->data());
+ NetworkActivityMonitor::GetInstance()->IncrementBytesReceived(rv);
+ return rv;
+ }
+
+ waiting_read_ = true;
+ read_if_ready_callback_ = callback;
+ core_->WatchForRead();
+ return ERR_IO_PENDING;
}
int TCPSocketWin::Write(IOBuffer* buf,
@@ -685,6 +717,7 @@ void TCPSocketWin::Close() {
waiting_write_ = false;
read_callback_.Reset();
+ read_if_ready_callback_.Reset();
write_callback_.Reset();
peer_address_.reset();
connect_os_error_ = 0;
@@ -879,35 +912,21 @@ void TCPSocketWin::LogConnectEnd(int net_error) {
sizeof(source_address)));
}
-int TCPSocketWin::DoRead(IOBuffer* buf, int buf_len,
- const CompletionCallback& callback) {
- if (!core_->non_blocking_reads_initialized_) {
- WSAEventSelect(socket_, core_->read_overlapped_.hEvent,
- FD_READ | FD_CLOSE);
- core_->non_blocking_reads_initialized_ = true;
- }
- int rv = recv(socket_, buf->data(), buf_len, 0);
- int os_error = WSAGetLastError();
- if (rv == SOCKET_ERROR) {
- if (os_error != WSAEWOULDBLOCK) {
- int net_error = MapSystemError(os_error);
- net_log_.AddEvent(NetLogEventType::SOCKET_READ_ERROR,
- CreateNetLogSocketErrorCallback(net_error, os_error));
- return net_error;
- }
- } else {
- net_log_.AddByteTransferEvent(NetLogEventType::SOCKET_BYTES_RECEIVED, rv,
- buf->data());
- NetworkActivityMonitor::GetInstance()->IncrementBytesReceived(rv);
- return rv;
- }
+void TCPSocketWin::RetryRead(int rv) {
+ DCHECK(core_->read_iobuffer_);
- waiting_read_ = true;
- read_callback_ = callback;
- core_->read_iobuffer_ = buf;
- core_->read_buffer_length_ = buf_len;
- core_->WatchForRead();
- return ERR_IO_PENDING;
+ if (rv == OK) {
+ // base::Unretained() is safe because RetryRead() won't be called when
+ // |this| is gone.
+ rv = ReadIfReady(
+ core_->read_iobuffer_.get(), core_->read_buffer_length_,
+ base::Bind(&TCPSocketWin::RetryRead, base::Unretained(this)));
+ if (rv == ERR_IO_PENDING)
+ return;
+ }
+ core_->read_iobuffer_ = nullptr;
+ core_->read_buffer_length_ = 0;
+ base::ResetAndReturn(&read_callback_).Run(rv);
}
void TCPSocketWin::DidCompleteConnect() {
@@ -989,7 +1008,7 @@ void TCPSocketWin::DidCompleteWrite() {
void TCPSocketWin::DidSignalRead() {
DCHECK(waiting_read_);
- DCHECK(!read_callback_.is_null());
+ DCHECK(!read_if_ready_callback_.is_null());
int os_error = 0;
WSANETWORKEVENTS network_events;
@@ -1010,20 +1029,19 @@ void TCPSocketWin::DidSignalRead() {
// network_events.iErrorCode[FD_CLOSE_BIT] is 0, it is a graceful
// connection closure. It is tempting to directly set rv to 0 in
// this case, but the MSDN pages for WSAEventSelect and
- // WSAAsyncSelect recommend we still call DoRead():
+ // WSAAsyncSelect recommend we still call RetryRead():
// FD_CLOSE should only be posted after all data is read from a
// socket, but an application should check for remaining data upon
// receipt of FD_CLOSE to avoid any possibility of losing data.
//
// If network_events.iErrorCode[FD_READ_BIT] or
// network_events.iErrorCode[FD_CLOSE_BIT] is nonzero, still call
- // DoRead() because recv() reports a more accurate error code
+ // RetryRead() because recv() reports a more accurate error code
// (WSAECONNRESET vs. WSAECONNABORTED) when the connection was
// reset.
- rv = DoRead(core_->read_iobuffer_.get(), core_->read_buffer_length_,
- read_callback_);
- if (rv == ERR_IO_PENDING)
- return;
+ waiting_read_ = false;
+ base::ResetAndReturn(&read_if_ready_callback_).Run(OK);
+ 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!
} else {
// This may happen because Read() may succeed synchronously and
// consume all the received data without resetting the event object.
@@ -1031,12 +1049,9 @@ void TCPSocketWin::DidSignalRead() {
return;
}
- waiting_read_ = false;
- core_->read_iobuffer_ = NULL;
- core_->read_buffer_length_ = 0;
-
DCHECK_NE(rv, ERR_IO_PENDING);
- base::ResetAndReturn(&read_callback_).Run(rv);
+ waiting_read_ = false;
+ base::ResetAndReturn(&read_if_ready_callback_).Run(rv);
}
bool TCPSocketWin::GetEstimatedRoundTripTime(base::TimeDelta* out_rtt) const {
« no previous file with comments | « net/socket/tcp_socket_win.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698