Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d95ecfc4 authored by David Pursell's avatar David Pursell Committed by Gerrit Code Review
Browse files

Merge "libcutils: add multi-buffer socket send."

parents d90adbc4 8385fb29
Loading
Loading
Loading
Loading
+25 −0
Original line number Diff line number Diff line
@@ -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
@@ -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
+18 −5
Original line number Diff line number Diff line
@@ -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);
}
+19 −0
Original line number Diff line number Diff line
@@ -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;
}
+20 −4
Original line number Diff line number Diff line
@@ -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));

@@ -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));
}
@@ -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));
}