Index: tools/android/forwarder2/socket.cc |
diff --git a/tools/android/forwarder2/socket.cc b/tools/android/forwarder2/socket.cc |
index 9564e9863475db61f63b42d4052a0be0c658a9fb..d6a47371b4c14ea1105d26d92e93e23f1503abe7 100644 |
--- a/tools/android/forwarder2/socket.cc |
+++ b/tools/android/forwarder2/socket.cc |
@@ -100,8 +100,25 @@ bool Socket::InitSocketInternal() { |
return false; |
tools::DisableNagle(socket_); |
int reuse_addr = 1; |
- setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, |
- &reuse_addr, sizeof(reuse_addr)); |
+ setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, |
+ sizeof(reuse_addr)); |
+ if (!SetNonBlocking()) |
+ return false; |
+ return true; |
+} |
+ |
+bool Socket::SetNonBlocking() { |
+ const int flags = fcntl(socket_, F_GETFL); |
+ if (flags < 0) { |
+ PLOG(ERROR) << "fcntl"; |
+ return false; |
+ } |
+ if (flags & O_NONBLOCK) |
+ return true; |
+ if (fcntl(socket_, F_SETFL, flags | O_NONBLOCK) < 0) { |
+ PLOG(ERROR) << "fcntl"; |
+ return false; |
+ } |
return true; |
} |
@@ -174,7 +191,7 @@ bool Socket::BindAndListen() { |
} |
errno = 0; |
if (getsockname(socket_, addr_ptr, &addrlen) != 0) { |
- LOG(ERROR) << "getsockname error: " << safe_strerror(errno);; |
+ PLOG(ERROR) << "getsockname"; |
SetSocketError(); |
return false; |
} |
@@ -195,45 +212,38 @@ bool Socket::Accept(Socket* new_socket) { |
SetSocketError(); |
return false; |
} |
- |
tools::DisableNagle(new_socket_fd); |
new_socket->socket_ = new_socket_fd; |
+ if (!new_socket->SetNonBlocking()) |
+ return false; |
return true; |
} |
bool Socket::Connect() { |
- // Set non-block because we use select for connect. |
- const int kFlags = fcntl(socket_, F_GETFL); |
- DCHECK(!(kFlags & O_NONBLOCK)); |
- fcntl(socket_, F_SETFL, kFlags | O_NONBLOCK); |
+ DCHECK(fcntl(socket_, F_GETFL) & O_NONBLOCK); |
errno = 0; |
if (HANDLE_EINTR(connect(socket_, addr_ptr_, addr_len_)) < 0 && |
errno != EINPROGRESS) { |
SetSocketError(); |
- PRESERVE_ERRNO_HANDLE_EINTR(fcntl(socket_, F_SETFL, kFlags)); |
return false; |
} |
// Wait for connection to complete, or receive a notification. |
if (!WaitForEvent(WRITE, kConnectTimeOut)) { |
SetSocketError(); |
- PRESERVE_ERRNO_HANDLE_EINTR(fcntl(socket_, F_SETFL, kFlags)); |
return false; |
} |
int socket_errno; |
socklen_t opt_len = sizeof(socket_errno); |
if (getsockopt(socket_, SOL_SOCKET, SO_ERROR, &socket_errno, &opt_len) < 0) { |
- LOG(ERROR) << "getsockopt(): " << safe_strerror(errno); |
+ PLOG(ERROR) << "getsockopt()"; |
SetSocketError(); |
- PRESERVE_ERRNO_HANDLE_EINTR(fcntl(socket_, F_SETFL, kFlags)); |
return false; |
} |
if (socket_errno != 0) { |
LOG(ERROR) << "Could not connect to host: " << safe_strerror(socket_errno); |
SetSocketError(); |
- PRESERVE_ERRNO_HANDLE_EINTR(fcntl(socket_, F_SETFL, kFlags)); |
return false; |
} |
- fcntl(socket_, F_SETFL, kFlags); |
return true; |
} |
@@ -247,6 +257,7 @@ bool Socket::Resolve(const std::string& host) { |
int errcode = getaddrinfo(host.c_str(), NULL, &hints, &res); |
if (errcode != 0) { |
+ errno = 0; |
SetSocketError(); |
freeaddrinfo(res); |
return false; |
@@ -302,8 +313,8 @@ int Socket::ReadNumBytes(void* buffer, size_t num_bytes) { |
void Socket::SetSocketError() { |
socket_error_ = true; |
- // We never use non-blocking socket. |
- DCHECK(errno != EAGAIN && errno != EWOULDBLOCK); |
+ DCHECK_NE(EAGAIN, errno); |
+ DCHECK_NE(EWOULDBLOCK, errno); |
Close(); |
} |
@@ -313,15 +324,43 @@ int Socket::Read(void* buffer, size_t buffer_size) { |
return 0; |
} |
int ret = HANDLE_EINTR(read(socket_, buffer, buffer_size)); |
- if (ret < 0) |
+ if (ret < 0) { |
+ PLOG(ERROR) << "read"; |
SetSocketError(); |
+ } |
+ return ret; |
+} |
+ |
+int Socket::NonBlockingRead(void* buffer, size_t buffer_size) { |
+ DCHECK(fcntl(socket_, F_GETFL) & O_NONBLOCK); |
digit1
2013/11/13 10:28:42
I really like this DCHECK(), thanks :)
|
+ int ret = HANDLE_EINTR(read(socket_, buffer, buffer_size)); |
+ if (ret < 0) { |
+ PLOG(ERROR) << "read"; |
+ SetSocketError(); |
+ } |
return ret; |
} |
int Socket::Write(const void* buffer, size_t count) { |
+ if (!WaitForEvent(WRITE, kNoTimeout)) { |
+ SetSocketError(); |
+ return 0; |
+ } |
int ret = HANDLE_EINTR(send(socket_, buffer, count, MSG_NOSIGNAL)); |
- if (ret < 0) |
+ if (ret < 0) { |
+ PLOG(ERROR) << "send"; |
SetSocketError(); |
+ } |
+ return ret; |
+} |
+ |
+int Socket::NonBlockingWrite(const void* buffer, size_t count) { |
+ DCHECK(fcntl(socket_, F_GETFL) & O_NONBLOCK); |
+ int ret = HANDLE_EINTR(send(socket_, buffer, count, MSG_NOSIGNAL)); |
+ if (ret < 0) { |
+ PLOG(ERROR) << "send"; |
+ SetSocketError(); |
+ } |
return ret; |
} |
@@ -363,8 +402,9 @@ int Socket::WriteNumBytes(const void* buffer, size_t num_bytes) { |
} |
bool Socket::WaitForEvent(EventType type, int timeout_secs) { |
- if (events_.empty() || socket_ == -1) |
+ if (socket_ == -1) |
return true; |
+ DCHECK(fcntl(socket_, F_GETFL) & O_NONBLOCK); |
fd_set read_fds; |
fd_set write_fds; |
FD_ZERO(&read_fds); |
@@ -388,6 +428,7 @@ bool Socket::WaitForEvent(EventType type, int timeout_secs) { |
max_fd = events_[i].fd; |
if (HANDLE_EINTR( |
select(max_fd + 1, &read_fds, &write_fds, NULL, tv_ptr)) <= 0) { |
+ PLOG(ERROR) << "select"; |
return false; |
} |
bool event_was_fired = false; |