Loading include/cutils/sockets.h +25 −0 Original line number Diff line number Diff line Loading @@ -30,12 +30,15 @@ typedef int socklen_t; typedef SOCKET cutils_socket_t; typedef WSABUF cutils_socket_buffer_t; #else #include <sys/socket.h> #include <sys/uio.h> typedef int cutils_socket_t; typedef struct iovec cutils_socket_buffer_t; #define INVALID_SOCKET (-1) #endif Loading Loading @@ -136,6 +139,28 @@ int socket_set_receive_timeout(cutils_socket_t sock, int timeout_ms); */ int socket_get_local_port(cutils_socket_t sock); /* * Sends to a socket from multiple buffers; wraps writev() on Unix or WSASend() * on Windows. This can give significant speedup compared to calling send() * multiple times. * * Because Unix and Windows use different structs to hold buffers, we also * need a generic function to set up the buffers. * * Example usage: * cutils_socket_buffer_t buffers[2] = { * make_cutils_socket_buffer(data0, len0), * make_cutils_socket_buffer(data1, len1) * }; * socket_send_buffers(sock, buffers, 2); * * Returns the number of bytes written or -1 on error. */ cutils_socket_buffer_t make_cutils_socket_buffer(void* data, size_t length); ssize_t socket_send_buffers(cutils_socket_t sock, cutils_socket_buffer_t* buffers, size_t num_buffers); /* * socket_peer_is_trusted - Takes a socket which is presumed to be a * connected local socket (e.g. AF_LOCAL) and returns whether the peer Loading libcutils/sockets_unix.c +18 −5 Original line number Diff line number Diff line Loading @@ -56,3 +56,16 @@ int socket_set_receive_timeout(cutils_socket_t sock, int timeout_ms) { 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); } libcutils/sockets_windows.c +19 −0 Original line number Diff line number Diff line Loading @@ -58,3 +58,22 @@ int socket_set_receive_timeout(cutils_socket_t sock, int timeout_ms) { 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; } libcutils/tests/sockets_test.cpp +20 −4 Original line number Diff line number Diff line Loading @@ -34,17 +34,17 @@ static void TestConnectedSockets(cutils_socket_t server, cutils_socket_t client, 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)); Loading @@ -55,9 +55,20 @@ static void TestConnectedSockets(cutils_socket_t server, cutils_socket_t client, } 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)); } Loading Loading @@ -171,3 +182,8 @@ TEST(SocketsTest, TestTcpReceiveTimeout) { 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)); } Loading
include/cutils/sockets.h +25 −0 Original line number Diff line number Diff line Loading @@ -30,12 +30,15 @@ typedef int socklen_t; typedef SOCKET cutils_socket_t; typedef WSABUF cutils_socket_buffer_t; #else #include <sys/socket.h> #include <sys/uio.h> typedef int cutils_socket_t; typedef struct iovec cutils_socket_buffer_t; #define INVALID_SOCKET (-1) #endif Loading Loading @@ -136,6 +139,28 @@ int socket_set_receive_timeout(cutils_socket_t sock, int timeout_ms); */ int socket_get_local_port(cutils_socket_t sock); /* * Sends to a socket from multiple buffers; wraps writev() on Unix or WSASend() * on Windows. This can give significant speedup compared to calling send() * multiple times. * * Because Unix and Windows use different structs to hold buffers, we also * need a generic function to set up the buffers. * * Example usage: * cutils_socket_buffer_t buffers[2] = { * make_cutils_socket_buffer(data0, len0), * make_cutils_socket_buffer(data1, len1) * }; * socket_send_buffers(sock, buffers, 2); * * Returns the number of bytes written or -1 on error. */ cutils_socket_buffer_t make_cutils_socket_buffer(void* data, size_t length); ssize_t socket_send_buffers(cutils_socket_t sock, cutils_socket_buffer_t* buffers, size_t num_buffers); /* * socket_peer_is_trusted - Takes a socket which is presumed to be a * connected local socket (e.g. AF_LOCAL) and returns whether the peer Loading
libcutils/sockets_unix.c +18 −5 Original line number Diff line number Diff line Loading @@ -56,3 +56,16 @@ int socket_set_receive_timeout(cutils_socket_t sock, int timeout_ms) { 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); }
libcutils/sockets_windows.c +19 −0 Original line number Diff line number Diff line Loading @@ -58,3 +58,22 @@ int socket_set_receive_timeout(cutils_socket_t sock, int timeout_ms) { 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; }
libcutils/tests/sockets_test.cpp +20 −4 Original line number Diff line number Diff line Loading @@ -34,17 +34,17 @@ static void TestConnectedSockets(cutils_socket_t server, cutils_socket_t client, 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)); Loading @@ -55,9 +55,20 @@ static void TestConnectedSockets(cutils_socket_t server, cutils_socket_t client, } 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)); } Loading Loading @@ -171,3 +182,8 @@ TEST(SocketsTest, TestTcpReceiveTimeout) { 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)); }