libcutils: add multi-buffer socket send.

Unix and Windows both have functions to write multiple buffers to a
socket with a single call but they have very different signatures. This
CL creates some cross-platform functions to be able to perform these
operations in a uniform way, which will be required for upcoming
fastboot functionality.

This CL also fixes some inconsistent spacing in the touched files.

Bug: http://b/26558551
Change-Id: I8f14d52d3a1de1f3b464267666d6cd3b54263238
diff --git a/libcutils/sockets_unix.c b/libcutils/sockets_unix.c
index 5eddc4b..3e7cea0 100644
--- a/libcutils/sockets_unix.c
+++ b/libcutils/sockets_unix.c
@@ -47,12 +47,25 @@
 }
 
 int socket_close(int sock) {
-  return close(sock);
+    return close(sock);
 }
 
 int socket_set_receive_timeout(cutils_socket_t sock, int timeout_ms) {
-  struct timeval tv;
-  tv.tv_sec = timeout_ms / 1000;
-  tv.tv_usec = (timeout_ms % 1000) * 1000;
-  return setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
+    struct timeval tv;
+    tv.tv_sec = timeout_ms / 1000;
+    tv.tv_usec = (timeout_ms % 1000) * 1000;
+    return setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
+}
+
+cutils_socket_buffer_t make_cutils_socket_buffer(void* data, size_t length) {
+    cutils_socket_buffer_t buffer;
+    buffer.iov_base = data;
+    buffer.iov_len = length;
+    return buffer;
+}
+
+ssize_t socket_send_buffers(cutils_socket_t sock,
+                            cutils_socket_buffer_t* buffers,
+                            size_t num_buffers) {
+    return writev(sock, buffers, num_buffers);
 }
diff --git a/libcutils/sockets_windows.c b/libcutils/sockets_windows.c
index 1bf2933..8153688 100644
--- a/libcutils/sockets_windows.c
+++ b/libcutils/sockets_windows.c
@@ -58,3 +58,22 @@
     return setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout_ms,
                       sizeof(timeout_ms));
 }
+
+cutils_socket_buffer_t make_cutils_socket_buffer(void* data, size_t length) {
+    cutils_socket_buffer_t buffer;
+    buffer.buf = data;
+    buffer.len = length;
+    return buffer;
+}
+
+ssize_t socket_send_buffers(cutils_socket_t sock,
+                            cutils_socket_buffer_t* buffers,
+                            size_t num_buffers) {
+    DWORD bytes_sent = 0;
+
+    if (WSASend(sock, buffers, num_buffers, &bytes_sent, 0, NULL, NULL) !=
+            SOCKET_ERROR) {
+        return bytes_sent;
+    }
+    return -1;
+}
diff --git a/libcutils/tests/sockets_test.cpp b/libcutils/tests/sockets_test.cpp
index 6c74b9a..40fa9b1 100644
--- a/libcutils/tests/sockets_test.cpp
+++ b/libcutils/tests/sockets_test.cpp
@@ -34,17 +34,17 @@
     ASSERT_NE(INVALID_SOCKET, server);
     ASSERT_NE(INVALID_SOCKET, client);
 
-    char buffer[3];
+    char buffer[128];
     sockaddr_storage addr;
     socklen_t addr_size = sizeof(addr);
 
     // Send client -> server first to get the UDP client's address.
     ASSERT_EQ(3, send(client, "foo", 3, 0));
     if (type == SOCK_DGRAM) {
-        EXPECT_EQ(3, recvfrom(server, buffer, 3, 0,
+        EXPECT_EQ(3, recvfrom(server, buffer, sizeof(buffer), 0,
                               reinterpret_cast<sockaddr*>(&addr), &addr_size));
     } else {
-        EXPECT_EQ(3, recv(server, buffer, 3, 0));
+        EXPECT_EQ(3, recv(server, buffer, sizeof(buffer), 0));
     }
     EXPECT_EQ(0, memcmp(buffer, "foo", 3));
 
@@ -55,9 +55,20 @@
     } else {
         ASSERT_EQ(3, send(server, "bar", 3, 0));
     }
-    EXPECT_EQ(3, recv(client, buffer, 3, 0));
+    EXPECT_EQ(3, recv(client, buffer, sizeof(buffer), 0));
     EXPECT_EQ(0, memcmp(buffer, "bar", 3));
 
+    // Send multiple buffers using socket_send_buffers().
+    std::string data[] = {"foo", "bar", "12345"};
+    cutils_socket_buffer_t socket_buffers[3];
+    for (int i = 0; i < 3; ++i) {
+        socket_buffers[i] = make_cutils_socket_buffer(&data[i][0],
+                                                      data[i].length());
+    }
+    EXPECT_EQ(11, socket_send_buffers(client, socket_buffers, 3));
+    EXPECT_EQ(11, recv(server, buffer, sizeof(buffer), 0));
+    EXPECT_EQ(0, memcmp(buffer, "foobar12345", 11));
+
     EXPECT_EQ(0, socket_close(server));
     EXPECT_EQ(0, socket_close(client));
 }
@@ -171,3 +182,8 @@
     EXPECT_EQ(0, socket_close(client));
     EXPECT_EQ(0, socket_close(handler));
 }
+
+// Tests socket_send_buffers() failure.
+TEST(SocketsTest, TestSocketSendBuffersFailure) {
+    EXPECT_EQ(-1, socket_send_buffers(INVALID_SOCKET, nullptr, 0));
+}