fastboot: add Socket timeout detection.
UDP fastboot will require re-transmission in the case of datagrams
getting lost. This CL adds Socket functionality to easily distinguish
between a normal timeout and a socket failure.
I also found some Windows docs that indicate sockets may become
invalid after a call to recv() times out. This has never occurred in
my testing, but to be safe this switches the timeout implementation
to use select() instead of SO_RCVTIMEO.
Bug: http://b/26154914
Change-Id: Id7b598f8aea5df1a3676d24702b489042d5f9e3a
diff --git a/fastboot/socket.h b/fastboot/socket.h
index c0bd7c9..de543db 100644
--- a/fastboot/socket.h
+++ b/fastboot/socket.h
@@ -81,13 +81,17 @@
virtual bool Send(std::vector<cutils_socket_buffer_t> buffers) = 0;
// Waits up to |timeout_ms| to receive up to |length| bytes of data. |timout_ms| of 0 will
- // block forever. Returns the number of bytes received or -1 on error/timeout. On timeout
- // errno will be set to EAGAIN or EWOULDBLOCK.
+ // block forever. Returns the number of bytes received or -1 on error/timeout; see
+ // ReceiveTimedOut() to distinguish between the two.
virtual ssize_t Receive(void* data, size_t length, int timeout_ms) = 0;
// Calls Receive() until exactly |length| bytes have been received or an error occurs.
virtual ssize_t ReceiveAll(void* data, size_t length, int timeout_ms);
+ // Returns true if the last Receive() call timed out normally and can be retried; fatal errors
+ // or successful reads will return false.
+ bool ReceiveTimedOut() { return receive_timed_out_; }
+
// Closes the socket. Returns 0 on success, -1 on error.
virtual int Close();
@@ -102,10 +106,13 @@
// Protected constructor to force factory function use.
Socket(cutils_socket_t sock);
- // Update the socket receive timeout if necessary.
- bool SetReceiveTimeout(int timeout_ms);
+ // Blocks up to |timeout_ms| until a read is possible on |sock_|, and sets |receive_timed_out_|
+ // as appropriate to help distinguish between normal timeouts and fatal errors. Returns true if
+ // a subsequent recv() on |sock_| will complete without blocking or if |timeout_ms| <= 0.
+ bool WaitForRecv(int timeout_ms);
cutils_socket_t sock_ = INVALID_SOCKET;
+ bool receive_timed_out_ = false;
// Non-class functions we want to override during tests to verify functionality. Implementation
// should call this rather than using socket_send_buffers() directly.
@@ -113,8 +120,6 @@
socket_send_buffers_function_ = &socket_send_buffers;
private:
- int receive_timeout_ms_ = 0;
-
FRIEND_TEST(SocketTest, TestTcpSendBuffers);
FRIEND_TEST(SocketTest, TestUdpSendBuffers);