diff options
author | David Pursell <dpursell@google.com> | 2016-02-01 09:42:09 -0800 |
---|---|---|
committer | David Pursell <dpursell@google.com> | 2016-02-03 10:01:38 -0800 |
commit | b34e4a06eeaaeaa42e0de6fdb44fb4202839b996 (patch) | |
tree | fb6863fedd661d98f6fbe0a344133623d660f6af /fastboot/socket.cpp | |
parent | f971b6a24b2d785187cf98cb002b9aee9ab6b2a7 (diff) |
libcutils/fastboot: improve multi-buffer write.
Fixes libcutils multi-buffer write interface to be more friendly and
hooks into it from the fastboot Socket class.
Bug: http://b/26558551
Change-Id: Ibb3a8428fc379755602de52722c1260f9e345bc0
Diffstat (limited to 'fastboot/socket.cpp')
-rw-r--r-- | fastboot/socket.cpp | 70 |
1 files changed, 56 insertions, 14 deletions
diff --git a/fastboot/socket.cpp b/fastboot/socket.cpp index 0a3ddfa2f..d49f47ff2 100644 --- a/fastboot/socket.cpp +++ b/fastboot/socket.cpp @@ -89,7 +89,8 @@ class UdpSocket : public Socket { UdpSocket(Type type, cutils_socket_t sock); - ssize_t Send(const void* data, size_t length) override; + bool Send(const void* data, size_t length) override; + bool Send(std::vector<cutils_socket_buffer_t> buffers) override; ssize_t Receive(void* data, size_t length, int timeout_ms) override; private: @@ -109,9 +110,20 @@ UdpSocket::UdpSocket(Type type, cutils_socket_t sock) : Socket(sock) { } } -ssize_t UdpSocket::Send(const void* data, size_t length) { +bool UdpSocket::Send(const void* data, size_t length) { return TEMP_FAILURE_RETRY(sendto(sock_, reinterpret_cast<const char*>(data), length, 0, - reinterpret_cast<sockaddr*>(addr_.get()), addr_size_)); + reinterpret_cast<sockaddr*>(addr_.get()), addr_size_)) == + static_cast<ssize_t>(length); +} + +bool UdpSocket::Send(std::vector<cutils_socket_buffer_t> buffers) { + size_t total_length = 0; + for (const auto& buffer : buffers) { + total_length += buffer.length; + } + + return TEMP_FAILURE_RETRY(socket_send_buffers_function_( + sock_, buffers.data(), buffers.size())) == static_cast<ssize_t>(total_length); } ssize_t UdpSocket::Receive(void* data, size_t length, int timeout_ms) { @@ -135,7 +147,8 @@ class TcpSocket : public Socket { public: TcpSocket(cutils_socket_t sock) : Socket(sock) {} - ssize_t Send(const void* data, size_t length) override; + bool Send(const void* data, size_t length) override; + bool Send(std::vector<cutils_socket_buffer_t> buffers) override; ssize_t Receive(void* data, size_t length, int timeout_ms) override; std::unique_ptr<Socket> Accept() override; @@ -144,23 +157,52 @@ class TcpSocket : public Socket { DISALLOW_COPY_AND_ASSIGN(TcpSocket); }; -ssize_t TcpSocket::Send(const void* data, size_t length) { - size_t total = 0; +bool TcpSocket::Send(const void* data, size_t length) { + while (length > 0) { + ssize_t sent = + TEMP_FAILURE_RETRY(send(sock_, reinterpret_cast<const char*>(data), length, 0)); - while (total < length) { - ssize_t bytes = TEMP_FAILURE_RETRY( - send(sock_, reinterpret_cast<const char*>(data) + total, length - total, 0)); + if (sent == -1) { + return false; + } + length -= sent; + } - if (bytes == -1) { - if (total == 0) { - return -1; + return true; +} + +bool TcpSocket::Send(std::vector<cutils_socket_buffer_t> buffers) { + while (!buffers.empty()) { + ssize_t sent = TEMP_FAILURE_RETRY( + socket_send_buffers_function_(sock_, buffers.data(), buffers.size())); + + if (sent == -1) { + return false; + } + + // Adjust the buffers to skip past the bytes we've just sent. + auto iter = buffers.begin(); + while (sent > 0) { + if (iter->length > static_cast<size_t>(sent)) { + // Incomplete buffer write; adjust the buffer to point to the next byte to send. + iter->length -= sent; + iter->data = reinterpret_cast<const char*>(iter->data) + sent; + break; } + + // Complete buffer write; move on to the next buffer. + sent -= iter->length; + ++iter; + } + + // Shortcut the common case: we've written everything remaining. + if (iter == buffers.end()) { break; } - total += bytes; + buffers.erase(buffers.begin(), iter); } - return total; + return true; } ssize_t TcpSocket::Receive(void* data, size_t length, int timeout_ms) { |