Merge "libcutils: add socket_get_local_port()."
This commit is contained in:
commit
d90adbc45b
4 changed files with 106 additions and 38 deletions
|
|
@ -131,6 +131,11 @@ int socket_close(cutils_socket_t sock);
|
||||||
*/
|
*/
|
||||||
int socket_set_receive_timeout(cutils_socket_t sock, int timeout_ms);
|
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
|
* 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
|
* connected local socket (e.g. AF_LOCAL) and returns whether the peer
|
||||||
|
|
|
||||||
|
|
@ -17,21 +17,22 @@ LOCAL_PATH := $(my-dir)
|
||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
libcutils_common_sources := \
|
libcutils_common_sources := \
|
||||||
hashmap.c \
|
|
||||||
atomic.c.arm \
|
atomic.c.arm \
|
||||||
native_handle.c \
|
|
||||||
config_utils.c \
|
config_utils.c \
|
||||||
|
fs_config.c \
|
||||||
|
hashmap.c \
|
||||||
|
iosched_policy.c \
|
||||||
load_file.c \
|
load_file.c \
|
||||||
strlcpy.c \
|
native_handle.c \
|
||||||
open_memstream.c \
|
open_memstream.c \
|
||||||
|
process_name.c \
|
||||||
|
record_stream.c \
|
||||||
|
sched_policy.c \
|
||||||
|
sockets.cpp \
|
||||||
strdup16to8.c \
|
strdup16to8.c \
|
||||||
strdup8to16.c \
|
strdup8to16.c \
|
||||||
record_stream.c \
|
strlcpy.c \
|
||||||
process_name.c \
|
|
||||||
threads.c \
|
threads.c \
|
||||||
sched_policy.c \
|
|
||||||
iosched_policy.c \
|
|
||||||
fs_config.c
|
|
||||||
|
|
||||||
# some files must not be compiled when building against Mingw
|
# some files must not be compiled when building against Mingw
|
||||||
# they correspond to features not used by our host development tools
|
# they correspond to features not used by our host development tools
|
||||||
|
|
|
||||||
47
libcutils/sockets.cpp
Normal file
47
libcutils/sockets.cpp
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
@ -15,9 +15,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Tests socket functionality using loopback connections. Requires IPv4 and
|
// Tests socket functionality using loopback connections. Requires IPv4 and
|
||||||
// IPv6 capabilities, and that kTestPort is available for loopback
|
// IPv6 capabilities. These tests assume that no UDP packets are lost, which
|
||||||
// communication. These tests also assume that no UDP packets are lost,
|
// should be the case for loopback communication, but is not guaranteed.
|
||||||
// which should be the case for loopback communication, but is not guaranteed.
|
|
||||||
|
|
||||||
#include <cutils/sockets.h>
|
#include <cutils/sockets.h>
|
||||||
|
|
||||||
|
|
@ -25,11 +24,6 @@
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
#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
|
// Makes sure the passed sockets are valid, sends data between them, and closes
|
||||||
// them. Any failures are logged with gtest.
|
// them. Any failures are logged with gtest.
|
||||||
//
|
//
|
||||||
|
|
@ -47,19 +41,19 @@ static void TestConnectedSockets(cutils_socket_t server, cutils_socket_t client,
|
||||||
// Send client -> server first to get the UDP client's address.
|
// Send client -> server first to get the UDP client's address.
|
||||||
ASSERT_EQ(3, send(client, "foo", 3, 0));
|
ASSERT_EQ(3, send(client, "foo", 3, 0));
|
||||||
if (type == SOCK_DGRAM) {
|
if (type == SOCK_DGRAM) {
|
||||||
EXPECT_EQ(3, recvfrom(server, buffer, 3, 0,
|
EXPECT_EQ(3, recvfrom(server, buffer, 3, 0,
|
||||||
reinterpret_cast<sockaddr*>(&addr), &addr_size));
|
reinterpret_cast<sockaddr*>(&addr), &addr_size));
|
||||||
} else {
|
} else {
|
||||||
EXPECT_EQ(3, recv(server, buffer, 3, 0));
|
EXPECT_EQ(3, recv(server, buffer, 3, 0));
|
||||||
}
|
}
|
||||||
EXPECT_EQ(0, memcmp(buffer, "foo", 3));
|
EXPECT_EQ(0, memcmp(buffer, "foo", 3));
|
||||||
|
|
||||||
// Now send server -> client.
|
// Now send server -> client.
|
||||||
if (type == SOCK_DGRAM) {
|
if (type == SOCK_DGRAM) {
|
||||||
ASSERT_EQ(3, sendto(server, "bar", 3, 0,
|
ASSERT_EQ(3, sendto(server, "bar", 3, 0,
|
||||||
reinterpret_cast<sockaddr*>(&addr), addr_size));
|
reinterpret_cast<sockaddr*>(&addr), addr_size));
|
||||||
} else {
|
} else {
|
||||||
ASSERT_EQ(3, send(server, "bar", 3, 0));
|
ASSERT_EQ(3, send(server, "bar", 3, 0));
|
||||||
}
|
}
|
||||||
EXPECT_EQ(3, recv(client, buffer, 3, 0));
|
EXPECT_EQ(3, recv(client, buffer, 3, 0));
|
||||||
EXPECT_EQ(0, memcmp(buffer, "bar", 3));
|
EXPECT_EQ(0, memcmp(buffer, "bar", 3));
|
||||||
|
|
@ -87,22 +81,43 @@ void TestReceiveTimeout(cutils_socket_t sock) {
|
||||||
EXPECT_LE(1.0, difftime(time(nullptr), start_time));
|
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.
|
// Tests socket_inaddr_any_server() and socket_network_client() for IPv4 UDP.
|
||||||
TEST(SocketsTest, TestIpv4UdpLoopback) {
|
TEST(SocketsTest, TestIpv4UdpLoopback) {
|
||||||
cutils_socket_t server = socket_inaddr_any_server(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", kTestPort,
|
cutils_socket_t client = socket_network_client(
|
||||||
SOCK_DGRAM);
|
"127.0.0.1", socket_get_local_port(server), SOCK_DGRAM);
|
||||||
|
|
||||||
TestConnectedSockets(server, client, SOCK_DGRAM);
|
TestConnectedSockets(server, client, SOCK_DGRAM);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests socket_inaddr_any_server() and socket_network_client() for IPv4 TCP.
|
// Tests socket_inaddr_any_server() and socket_network_client() for IPv4 TCP.
|
||||||
TEST(SocketsTest, TestIpv4TcpLoopback) {
|
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);
|
ASSERT_NE(INVALID_SOCKET, server);
|
||||||
|
|
||||||
cutils_socket_t client = socket_network_client("127.0.0.1", kTestPort,
|
cutils_socket_t client = socket_network_client(
|
||||||
SOCK_STREAM);
|
"127.0.0.1", socket_get_local_port(server), SOCK_STREAM);
|
||||||
cutils_socket_t handler = accept(server, nullptr, nullptr);
|
cutils_socket_t handler = accept(server, nullptr, nullptr);
|
||||||
EXPECT_EQ(0, socket_close(server));
|
EXPECT_EQ(0, socket_close(server));
|
||||||
|
|
||||||
|
|
@ -111,20 +126,20 @@ TEST(SocketsTest, TestIpv4TcpLoopback) {
|
||||||
|
|
||||||
// Tests socket_inaddr_any_server() and socket_network_client() for IPv6 UDP.
|
// Tests socket_inaddr_any_server() and socket_network_client() for IPv6 UDP.
|
||||||
TEST(SocketsTest, TestIpv6UdpLoopback) {
|
TEST(SocketsTest, TestIpv6UdpLoopback) {
|
||||||
cutils_socket_t server = socket_inaddr_any_server(kTestPort, SOCK_DGRAM);
|
cutils_socket_t server = socket_inaddr_any_server(0, SOCK_DGRAM);
|
||||||
cutils_socket_t client = socket_network_client("::1", kTestPort,
|
cutils_socket_t client = socket_network_client(
|
||||||
SOCK_DGRAM);
|
"::1", socket_get_local_port(server), SOCK_DGRAM);
|
||||||
|
|
||||||
TestConnectedSockets(server, client, SOCK_DGRAM);
|
TestConnectedSockets(server, client, SOCK_DGRAM);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests socket_inaddr_any_server() and socket_network_client() for IPv6 TCP.
|
// Tests socket_inaddr_any_server() and socket_network_client() for IPv6 TCP.
|
||||||
TEST(SocketsTest, TestIpv6TcpLoopback) {
|
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);
|
ASSERT_NE(INVALID_SOCKET, server);
|
||||||
|
|
||||||
cutils_socket_t client = socket_network_client("::1", kTestPort,
|
cutils_socket_t client = socket_network_client(
|
||||||
SOCK_STREAM);
|
"::1", socket_get_local_port(server), SOCK_STREAM);
|
||||||
cutils_socket_t handler = accept(server, nullptr, nullptr);
|
cutils_socket_t handler = accept(server, nullptr, nullptr);
|
||||||
EXPECT_EQ(0, socket_close(server));
|
EXPECT_EQ(0, socket_close(server));
|
||||||
|
|
||||||
|
|
@ -133,7 +148,7 @@ TEST(SocketsTest, TestIpv6TcpLoopback) {
|
||||||
|
|
||||||
// Tests setting a receive timeout for UDP sockets.
|
// Tests setting a receive timeout for UDP sockets.
|
||||||
TEST(SocketsTest, TestUdpReceiveTimeout) {
|
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);
|
ASSERT_NE(INVALID_SOCKET, sock);
|
||||||
|
|
||||||
TestReceiveTimeout(sock);
|
TestReceiveTimeout(sock);
|
||||||
|
|
@ -143,11 +158,11 @@ TEST(SocketsTest, TestUdpReceiveTimeout) {
|
||||||
|
|
||||||
// Tests setting a receive timeout for TCP sockets.
|
// Tests setting a receive timeout for TCP sockets.
|
||||||
TEST(SocketsTest, TestTcpReceiveTimeout) {
|
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);
|
ASSERT_NE(INVALID_SOCKET, server);
|
||||||
|
|
||||||
cutils_socket_t client = socket_network_client("localhost", kTestPort,
|
cutils_socket_t client = socket_network_client(
|
||||||
SOCK_STREAM);
|
"localhost", socket_get_local_port(server), SOCK_STREAM);
|
||||||
cutils_socket_t handler = accept(server, nullptr, nullptr);
|
cutils_socket_t handler = accept(server, nullptr, nullptr);
|
||||||
EXPECT_EQ(0, socket_close(server));
|
EXPECT_EQ(0, socket_close(server));
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue