Loading include/cutils/sockets.h +5 −0 Original line number Diff line number Diff line Loading @@ -131,6 +131,11 @@ int socket_close(cutils_socket_t sock); */ int socket_set_receive_timeout(cutils_socket_t sock, int timeout_ms); /* * Returns the local port the socket is bound to or -1 on error. */ int socket_get_local_port(cutils_socket_t sock); /* * 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/Android.mk +9 −8 Original line number Diff line number Diff line Loading @@ -17,21 +17,22 @@ LOCAL_PATH := $(my-dir) include $(CLEAR_VARS) libcutils_common_sources := \ hashmap.c \ atomic.c.arm \ native_handle.c \ config_utils.c \ fs_config.c \ hashmap.c \ iosched_policy.c \ load_file.c \ strlcpy.c \ native_handle.c \ open_memstream.c \ process_name.c \ record_stream.c \ sched_policy.c \ sockets.cpp \ strdup16to8.c \ strdup8to16.c \ record_stream.c \ process_name.c \ strlcpy.c \ threads.c \ sched_policy.c \ iosched_policy.c \ fs_config.c # some files must not be compiled when building against Mingw # they correspond to features not used by our host development tools Loading libcutils/sockets.cpp 0 → 100644 +47 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 The Android Open Source Project * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ // This file contains socket implementation that can be shared between // platforms as long as the correct headers are included. #include <cutils/sockets.h> #if !defined(_WIN32) #include <netinet/in.h> #endif int socket_get_local_port(cutils_socket_t sock) { sockaddr_storage addr; socklen_t addr_size = sizeof(addr); if (getsockname(sock, reinterpret_cast<sockaddr*>(&addr), &addr_size) == 0) { // sockaddr_in and sockaddr_in6 always overlap the port field. return ntohs(reinterpret_cast<sockaddr_in*>(&addr)->sin_port); } return -1; } libcutils/tests/sockets_test.cpp +45 −30 Original line number Diff line number Diff line Loading @@ -15,9 +15,8 @@ */ // Tests socket functionality using loopback connections. Requires IPv4 and // IPv6 capabilities, and that kTestPort is available for loopback // communication. These tests also assume that no UDP packets are lost, // which should be the case for loopback communication, but is not guaranteed. // IPv6 capabilities. These tests assume that no UDP packets are lost, which // should be the case for loopback communication, but is not guaranteed. #include <cutils/sockets.h> Loading @@ -25,11 +24,6 @@ #include <gtest/gtest.h> enum { // This port must be available for loopback communication. kTestPort = 54321 }; // Makes sure the passed sockets are valid, sends data between them, and closes // them. Any failures are logged with gtest. // Loading Loading @@ -87,22 +81,43 @@ void TestReceiveTimeout(cutils_socket_t sock) { EXPECT_LE(1.0, difftime(time(nullptr), start_time)); } // Tests socket_get_local_port(). TEST(SocketsTest, TestGetLocalPort) { cutils_socket_t server; // Check a bunch of ports so that we can ignore any conflicts in case // of ports already being taken, but if a server is able to start up we // should always be able to read its port. for (int port : {10000, 12345, 15999, 20202, 25000}) { for (int type : {SOCK_DGRAM, SOCK_STREAM}) { server = socket_inaddr_any_server(port, SOCK_DGRAM); if (server != INVALID_SOCKET) { EXPECT_EQ(port, socket_get_local_port(server)); } socket_close(server); } } // Check expected failure for an invalid socket. EXPECT_EQ(-1, socket_get_local_port(INVALID_SOCKET)); } // Tests socket_inaddr_any_server() and socket_network_client() for IPv4 UDP. TEST(SocketsTest, TestIpv4UdpLoopback) { cutils_socket_t server = socket_inaddr_any_server(kTestPort, SOCK_DGRAM); cutils_socket_t client = socket_network_client("127.0.0.1", kTestPort, SOCK_DGRAM); cutils_socket_t server = socket_inaddr_any_server(0, SOCK_DGRAM); cutils_socket_t client = socket_network_client( "127.0.0.1", socket_get_local_port(server), SOCK_DGRAM); TestConnectedSockets(server, client, SOCK_DGRAM); } // Tests socket_inaddr_any_server() and socket_network_client() for IPv4 TCP. TEST(SocketsTest, TestIpv4TcpLoopback) { cutils_socket_t server = socket_inaddr_any_server(kTestPort, SOCK_STREAM); cutils_socket_t server = socket_inaddr_any_server(0, SOCK_STREAM); ASSERT_NE(INVALID_SOCKET, server); cutils_socket_t client = socket_network_client("127.0.0.1", kTestPort, SOCK_STREAM); cutils_socket_t client = socket_network_client( "127.0.0.1", socket_get_local_port(server), SOCK_STREAM); cutils_socket_t handler = accept(server, nullptr, nullptr); EXPECT_EQ(0, socket_close(server)); Loading @@ -111,20 +126,20 @@ TEST(SocketsTest, TestIpv4TcpLoopback) { // Tests socket_inaddr_any_server() and socket_network_client() for IPv6 UDP. TEST(SocketsTest, TestIpv6UdpLoopback) { cutils_socket_t server = socket_inaddr_any_server(kTestPort, SOCK_DGRAM); cutils_socket_t client = socket_network_client("::1", kTestPort, SOCK_DGRAM); cutils_socket_t server = socket_inaddr_any_server(0, SOCK_DGRAM); cutils_socket_t client = socket_network_client( "::1", socket_get_local_port(server), SOCK_DGRAM); TestConnectedSockets(server, client, SOCK_DGRAM); } // Tests socket_inaddr_any_server() and socket_network_client() for IPv6 TCP. TEST(SocketsTest, TestIpv6TcpLoopback) { cutils_socket_t server = socket_inaddr_any_server(kTestPort, SOCK_STREAM); cutils_socket_t server = socket_inaddr_any_server(0, SOCK_STREAM); ASSERT_NE(INVALID_SOCKET, server); cutils_socket_t client = socket_network_client("::1", kTestPort, SOCK_STREAM); cutils_socket_t client = socket_network_client( "::1", socket_get_local_port(server), SOCK_STREAM); cutils_socket_t handler = accept(server, nullptr, nullptr); EXPECT_EQ(0, socket_close(server)); Loading @@ -133,7 +148,7 @@ TEST(SocketsTest, TestIpv6TcpLoopback) { // Tests setting a receive timeout for UDP sockets. TEST(SocketsTest, TestUdpReceiveTimeout) { cutils_socket_t sock = socket_inaddr_any_server(kTestPort, SOCK_DGRAM); cutils_socket_t sock = socket_inaddr_any_server(0, SOCK_DGRAM); ASSERT_NE(INVALID_SOCKET, sock); TestReceiveTimeout(sock); Loading @@ -143,11 +158,11 @@ TEST(SocketsTest, TestUdpReceiveTimeout) { // Tests setting a receive timeout for TCP sockets. TEST(SocketsTest, TestTcpReceiveTimeout) { cutils_socket_t server = socket_inaddr_any_server(kTestPort, SOCK_STREAM); cutils_socket_t server = socket_inaddr_any_server(0, SOCK_STREAM); ASSERT_NE(INVALID_SOCKET, server); cutils_socket_t client = socket_network_client("localhost", kTestPort, SOCK_STREAM); cutils_socket_t client = socket_network_client( "localhost", socket_get_local_port(server), SOCK_STREAM); cutils_socket_t handler = accept(server, nullptr, nullptr); EXPECT_EQ(0, socket_close(server)); Loading Loading
include/cutils/sockets.h +5 −0 Original line number Diff line number Diff line Loading @@ -131,6 +131,11 @@ int socket_close(cutils_socket_t sock); */ int socket_set_receive_timeout(cutils_socket_t sock, int timeout_ms); /* * Returns the local port the socket is bound to or -1 on error. */ int socket_get_local_port(cutils_socket_t sock); /* * 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/Android.mk +9 −8 Original line number Diff line number Diff line Loading @@ -17,21 +17,22 @@ LOCAL_PATH := $(my-dir) include $(CLEAR_VARS) libcutils_common_sources := \ hashmap.c \ atomic.c.arm \ native_handle.c \ config_utils.c \ fs_config.c \ hashmap.c \ iosched_policy.c \ load_file.c \ strlcpy.c \ native_handle.c \ open_memstream.c \ process_name.c \ record_stream.c \ sched_policy.c \ sockets.cpp \ strdup16to8.c \ strdup8to16.c \ record_stream.c \ process_name.c \ strlcpy.c \ threads.c \ sched_policy.c \ iosched_policy.c \ fs_config.c # some files must not be compiled when building against Mingw # they correspond to features not used by our host development tools Loading
libcutils/sockets.cpp 0 → 100644 +47 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 The Android Open Source Project * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ // This file contains socket implementation that can be shared between // platforms as long as the correct headers are included. #include <cutils/sockets.h> #if !defined(_WIN32) #include <netinet/in.h> #endif int socket_get_local_port(cutils_socket_t sock) { sockaddr_storage addr; socklen_t addr_size = sizeof(addr); if (getsockname(sock, reinterpret_cast<sockaddr*>(&addr), &addr_size) == 0) { // sockaddr_in and sockaddr_in6 always overlap the port field. return ntohs(reinterpret_cast<sockaddr_in*>(&addr)->sin_port); } return -1; }
libcutils/tests/sockets_test.cpp +45 −30 Original line number Diff line number Diff line Loading @@ -15,9 +15,8 @@ */ // Tests socket functionality using loopback connections. Requires IPv4 and // IPv6 capabilities, and that kTestPort is available for loopback // communication. These tests also assume that no UDP packets are lost, // which should be the case for loopback communication, but is not guaranteed. // IPv6 capabilities. These tests assume that no UDP packets are lost, which // should be the case for loopback communication, but is not guaranteed. #include <cutils/sockets.h> Loading @@ -25,11 +24,6 @@ #include <gtest/gtest.h> enum { // This port must be available for loopback communication. kTestPort = 54321 }; // Makes sure the passed sockets are valid, sends data between them, and closes // them. Any failures are logged with gtest. // Loading Loading @@ -87,22 +81,43 @@ void TestReceiveTimeout(cutils_socket_t sock) { EXPECT_LE(1.0, difftime(time(nullptr), start_time)); } // Tests socket_get_local_port(). TEST(SocketsTest, TestGetLocalPort) { cutils_socket_t server; // Check a bunch of ports so that we can ignore any conflicts in case // of ports already being taken, but if a server is able to start up we // should always be able to read its port. for (int port : {10000, 12345, 15999, 20202, 25000}) { for (int type : {SOCK_DGRAM, SOCK_STREAM}) { server = socket_inaddr_any_server(port, SOCK_DGRAM); if (server != INVALID_SOCKET) { EXPECT_EQ(port, socket_get_local_port(server)); } socket_close(server); } } // Check expected failure for an invalid socket. EXPECT_EQ(-1, socket_get_local_port(INVALID_SOCKET)); } // Tests socket_inaddr_any_server() and socket_network_client() for IPv4 UDP. TEST(SocketsTest, TestIpv4UdpLoopback) { cutils_socket_t server = socket_inaddr_any_server(kTestPort, SOCK_DGRAM); cutils_socket_t client = socket_network_client("127.0.0.1", kTestPort, SOCK_DGRAM); cutils_socket_t server = socket_inaddr_any_server(0, SOCK_DGRAM); cutils_socket_t client = socket_network_client( "127.0.0.1", socket_get_local_port(server), SOCK_DGRAM); TestConnectedSockets(server, client, SOCK_DGRAM); } // Tests socket_inaddr_any_server() and socket_network_client() for IPv4 TCP. TEST(SocketsTest, TestIpv4TcpLoopback) { cutils_socket_t server = socket_inaddr_any_server(kTestPort, SOCK_STREAM); cutils_socket_t server = socket_inaddr_any_server(0, SOCK_STREAM); ASSERT_NE(INVALID_SOCKET, server); cutils_socket_t client = socket_network_client("127.0.0.1", kTestPort, SOCK_STREAM); cutils_socket_t client = socket_network_client( "127.0.0.1", socket_get_local_port(server), SOCK_STREAM); cutils_socket_t handler = accept(server, nullptr, nullptr); EXPECT_EQ(0, socket_close(server)); Loading @@ -111,20 +126,20 @@ TEST(SocketsTest, TestIpv4TcpLoopback) { // Tests socket_inaddr_any_server() and socket_network_client() for IPv6 UDP. TEST(SocketsTest, TestIpv6UdpLoopback) { cutils_socket_t server = socket_inaddr_any_server(kTestPort, SOCK_DGRAM); cutils_socket_t client = socket_network_client("::1", kTestPort, SOCK_DGRAM); cutils_socket_t server = socket_inaddr_any_server(0, SOCK_DGRAM); cutils_socket_t client = socket_network_client( "::1", socket_get_local_port(server), SOCK_DGRAM); TestConnectedSockets(server, client, SOCK_DGRAM); } // Tests socket_inaddr_any_server() and socket_network_client() for IPv6 TCP. TEST(SocketsTest, TestIpv6TcpLoopback) { cutils_socket_t server = socket_inaddr_any_server(kTestPort, SOCK_STREAM); cutils_socket_t server = socket_inaddr_any_server(0, SOCK_STREAM); ASSERT_NE(INVALID_SOCKET, server); cutils_socket_t client = socket_network_client("::1", kTestPort, SOCK_STREAM); cutils_socket_t client = socket_network_client( "::1", socket_get_local_port(server), SOCK_STREAM); cutils_socket_t handler = accept(server, nullptr, nullptr); EXPECT_EQ(0, socket_close(server)); Loading @@ -133,7 +148,7 @@ TEST(SocketsTest, TestIpv6TcpLoopback) { // Tests setting a receive timeout for UDP sockets. TEST(SocketsTest, TestUdpReceiveTimeout) { cutils_socket_t sock = socket_inaddr_any_server(kTestPort, SOCK_DGRAM); cutils_socket_t sock = socket_inaddr_any_server(0, SOCK_DGRAM); ASSERT_NE(INVALID_SOCKET, sock); TestReceiveTimeout(sock); Loading @@ -143,11 +158,11 @@ TEST(SocketsTest, TestUdpReceiveTimeout) { // Tests setting a receive timeout for TCP sockets. TEST(SocketsTest, TestTcpReceiveTimeout) { cutils_socket_t server = socket_inaddr_any_server(kTestPort, SOCK_STREAM); cutils_socket_t server = socket_inaddr_any_server(0, SOCK_STREAM); ASSERT_NE(INVALID_SOCKET, server); cutils_socket_t client = socket_network_client("localhost", kTestPort, SOCK_STREAM); cutils_socket_t client = socket_network_client( "localhost", socket_get_local_port(server), SOCK_STREAM); cutils_socket_t handler = accept(server, nullptr, nullptr); EXPECT_EQ(0, socket_close(server)); Loading