diff --git a/starboard/elf_loader/exported_symbols.cc b/starboard/elf_loader/exported_symbols.cc index 2be34e9680ca..94c76fcc7d8e 100644 --- a/starboard/elf_loader/exported_symbols.cc +++ b/starboard/elf_loader/exported_symbols.cc @@ -51,6 +51,7 @@ #if SB_API_VERSION >= 16 #include "starboard/shared/modular/starboard_layer_posix_mmap_abi_wrappers.h" #include "starboard/shared/modular/starboard_layer_posix_pthread_abi_wrappers.h" +#include "starboard/shared/modular/starboard_layer_posix_socket_abi_wrappers.h" #include "starboard/shared/modular/starboard_layer_posix_stat_abi_wrappers.h" #include "starboard/shared/modular/starboard_layer_posix_time_abi_wrappers.h" #endif // SB_API_VERSION >= 16 @@ -517,6 +518,12 @@ ExportedSymbols::ExportedSymbols() { reinterpret_cast(&__abi_wrap_pthread_self); map_["stat"] = reinterpret_cast(&__abi_wrap_stat); map_["time"] = reinterpret_cast(&__abi_wrap_time); + map_["accept"] = reinterpret_cast(&__abi_wrap_accept); + map_["bind"] = reinterpret_cast(&__abi_wrap_bind); + map_["connect"] = reinterpret_cast(&__abi_wrap_connect); + map_["getaddrinfo"] = reinterpret_cast(&__abi_wrap_getaddrinfo); + map_["getifaddrs"] = reinterpret_cast(&__abi_wrap_getifaddrs); + map_["setsockopt"] = reinterpret_cast(&__abi_wrap_setsockopt); #if defined(_MSC_VER) // MSVC provides a template with the same name. diff --git a/starboard/nplb/posix_compliance/posix_socket_accept_test.cc b/starboard/nplb/posix_compliance/posix_socket_accept_test.cc index 1baf212182f6..6c8017fbc824 100644 --- a/starboard/nplb/posix_compliance/posix_socket_accept_test.cc +++ b/starboard/nplb/posix_compliance/posix_socket_accept_test.cc @@ -15,6 +15,7 @@ // Here we are not trying to do anything fancy, just to really sanity check that // this is hooked up to something. +#include #include "starboard/nplb/posix_compliance/posix_socket_helpers.h" namespace starboard { @@ -32,6 +33,9 @@ TEST(PosixSocketAcceptTest, RainyDayNoConnection) { int result = -1; ASSERT_TRUE(socket_listen_fd >= 0); + // set socket non-blocking + fcntl(socket_listen_fd, F_SETFL, O_NONBLOCK); + // set socket reuseable const int on = 1; result = @@ -43,16 +47,19 @@ TEST(PosixSocketAcceptTest, RainyDayNoConnection) { } // bind socket with local address - struct sockaddr_in address = {}; - result = - PosixGetLocalAddressiIPv4(reinterpret_cast(&address)); - address.sin_port = GetPortNumberForTests(); - address.sin_family = AF_INET; - EXPECT_TRUE(result == 0); - if (result != 0) { - close(socket_listen_fd); - return; - } +#if SB_HAS(IPV6) + sockaddr_in6 address = {}; + EXPECT_TRUE( + PosixGetLocalAddressIPv4(reinterpret_cast(&address)) == 0 || + PosixGetLocalAddressIPv6(reinterpret_cast(&address)) == 0); + address.sin6_port = htons(GetPortNumberForTests()); +#else + sockaddr address = {0}; + EXPECT_TRUE(PosixGetLocalAddressIPv4(&address) == 0); + sockaddr_in* address_ptr = reinterpret_cast(&address); + address_ptr->sin_port = htons(GetPortNumberForTests()); +#endif + result = bind(socket_listen_fd, reinterpret_cast(&address), sizeof(sockaddr)); EXPECT_TRUE(result == 0); @@ -124,11 +131,18 @@ TEST(PosixSocketAcceptTest, RainyDayNotListening) { } // bind socket with local address - struct sockaddr_in address = {}; - result = - PosixGetLocalAddressiIPv4(reinterpret_cast(&address)); - address.sin_port = GetPortNumberForTests(); - address.sin_family = AF_INET; +#if SB_HAS(IPV6) + sockaddr_in6 address = {}; + EXPECT_TRUE( + PosixGetLocalAddressIPv4(reinterpret_cast(&address)) == 0 || + PosixGetLocalAddressIPv6(reinterpret_cast(&address)) == 0); + address.sin6_port = htons(GetPortNumberForTests()); +#else + sockaddr address = {0}; + EXPECT_TRUE(PosixGetLocalAddressIPv4(&address) == 0); + sockaddr_in* address_ptr = reinterpret_cast(&address); + address_ptr->sin_port = htons(GetPortNumberForTests()); +#endif EXPECT_TRUE(result == 0); if (result != 0) { close(socket_fd); diff --git a/starboard/nplb/posix_compliance/posix_socket_bind_test.cc b/starboard/nplb/posix_compliance/posix_socket_bind_test.cc index 95ab5b723d30..a5e7a1225eba 100644 --- a/starboard/nplb/posix_compliance/posix_socket_bind_test.cc +++ b/starboard/nplb/posix_compliance/posix_socket_bind_test.cc @@ -19,11 +19,10 @@ namespace starboard { namespace nplb { - namespace { TEST(PosixSocketBindTest, RainyDayNullSocket) { - int port = GetPortNumberForTests(); + int port = htons(GetPortNumberForTests()); sockaddr_in address = {}; address.sin_family = AF_INET; int invalid_socket_fd = -1; @@ -37,15 +36,6 @@ TEST(PosixSocketBindTest, RainyDayNullAddress) { // Binding with a NULL address should fail. EXPECT_FALSE(bind(socket_fd, NULL, 0) == 0); - - // Even though that failed, binding the same socket now with 0.0.0.0:2048 - // should work. - sockaddr_in address = {}; - address.sin_family = AF_INET; - address.sin_port = GetPortNumberForTests(); - - EXPECT_TRUE(bind(socket_fd, reinterpret_cast(&address), - sizeof(sockaddr_in)) == 0); EXPECT_TRUE(close(socket_fd) == 0); } @@ -62,7 +52,7 @@ TEST(PosixSocketBindTest, RainyDayWrongAddressType) { // Binding with the wrong address type should fail. sockaddr_in client_address = {}; client_address.sin_family = AF_INET6; - client_address.sin_port = GetPortNumberForTests(); + client_address.sin_port = htons(GetPortNumberForTests()); EXPECT_FALSE(bind(socket_fd, reinterpret_cast(&client_address), sizeof(sockaddr_in)) == 0); @@ -70,7 +60,7 @@ TEST(PosixSocketBindTest, RainyDayWrongAddressType) { // address type should work. sockaddr_in server_address = {}; server_address.sin_family = AF_INET; - server_address.sin_port = GetPortNumberForTests(); + server_address.sin_port = htons(GetPortNumberForTests()); EXPECT_TRUE(bind(socket_fd, reinterpret_cast(&server_address), sizeof(sockaddr_in)) == 0); EXPECT_TRUE(close(socket_fd) == 0); @@ -92,14 +82,17 @@ TEST(PosixSocketBindTest, RainyDayBadInterface) { } TEST(PosixSocketBindTest, SunnyDayLocalInterface) { - sockaddr_in6 address = {}; #if SB_HAS(IPV6) - EXPECT_TRUE(PosixGetLocalAddressiIPv4( - reinterpret_cast(&address)) == 0 || - PosixGetLocalAddressiIPv6(&address) == 0); -#else + sockaddr_in6 address = {}; EXPECT_TRUE( - PosixGetLocalAddressiIPv4(reinterpret_cast(&address)) == 0); + PosixGetLocalAddressIPv4(reinterpret_cast(&address)) == 0 || + PosixGetLocalAddressIPv6(reinterpret_cast(&address)) == 0); + address.sin6_port = htons(GetPortNumberForTests()); +#else + sockaddr address = {0}; + EXPECT_TRUE(PosixGetLocalAddressIPv4(&address) == 0); + sockaddr_in* address_ptr = reinterpret_cast(&address); + address_ptr->sin_port = htons(GetPortNumberForTests()); #endif int socket_domain = AF_INET; @@ -108,11 +101,172 @@ TEST(PosixSocketBindTest, SunnyDayLocalInterface) { int socket_fd = socket(socket_domain, socket_type, socket_protocol); ASSERT_TRUE(socket_fd > 0); + EXPECT_TRUE(bind(socket_fd, reinterpret_cast(&address), sizeof(struct sockaddr)) == 0); EXPECT_TRUE(close(socket_fd) == 0); } +TEST(PosixSocketBindTest, SunnyDayAnyAddr) { + // Even though that failed, binding the same socket now with 0.0.0.0:2048 + // should work. + sockaddr_in address = {}; + address.sin_family = AF_INET; + address.sin_port = htons(GetPortNumberForTests()); + address.sin_addr.s_addr = INADDR_ANY; + + int socket_domain = AF_INET; + int socket_type = SOCK_STREAM; + int socket_protocol = IPPROTO_TCP; + int socket_fd = socket(socket_domain, socket_type, socket_protocol); + ASSERT_TRUE(socket_fd > 0); + EXPECT_TRUE(bind(socket_fd, reinterpret_cast(&address), + sizeof(sockaddr_in)) == 0); + EXPECT_TRUE(close(socket_fd) == 0); +} + +// Pair data input test +std::string GetPosixSocketAddressTypeFilterPairName( + ::testing::TestParamInfo> info) { + return FormatString("type_%d_filter_%d", info.param.first, info.param.second); +} + +class PosixSocketBindPairFilterTest + : public ::testing::TestWithParam> { + public: + int GetAddressType() { return GetParam().first; } + int GetFilterType() { return GetParam().second; } +}; + +#if SB_HAS(IPV6) +class PosixSocketBindPairCSTest + : public ::testing::TestWithParam> { + public: + int GetServerAddressType() { return GetParam().first; } + int GetClientAddressType() { return GetParam().second; } +}; +#endif + +TEST_P(PosixSocketBindPairFilterTest, RainyDayNullSocketPair) { + sockaddr_in address = {}; + address.sin_family = GetAddressType(); + address.sin_port = htons(GetPortNumberForTests()); + + int invalid_socket_fd = -1; + + EXPECT_FALSE(bind(invalid_socket_fd, reinterpret_cast(&address), + sizeof(sockaddr_in)) == 0); +} + +TEST_P(PosixSocketBindPairFilterTest, RainyDayNullAddressPair) { + return; + int socket_fd = socket(GetAddressType(), SOCK_STREAM, IPPROTO_TCP); + ASSERT_TRUE(socket_fd > 0); + + // Binding with a NULL address should fail. + EXPECT_FALSE(bind(socket_fd, NULL, 0) == 0); + + // Even though that failed, binding the same socket now with 0.0.0.0:2048 + // should work. + sockaddr_in address = {}; + address.sin_family = GetAddressType(); + address.sin_port = htons(GetPortNumberForTests()); + + EXPECT_TRUE(bind(socket_fd, reinterpret_cast(&address), + sizeof(sockaddr_in)) == 0); + EXPECT_TRUE(close(socket_fd) == 0); +} + +TEST_P(PosixSocketBindPairFilterTest, RainyDayBadInterfacePair) { + return; + int socket_fd = socket(GetAddressType(), SOCK_STREAM, IPPROTO_TCP); + ASSERT_TRUE(socket_fd > 0); + + // Binding with an interface that doesn't exist on this device should fail, so + // let's find an address of a well-known public website that we shouldn't be + // able to bind to. + const char* kTestHostName = "www.yahoo.com"; + + struct addrinfo* ai = nullptr; + struct addrinfo hints = {0}; + hints.ai_family = GetFilterType(); + hints.ai_flags = AI_ADDRCONFIG; + hints.ai_socktype = SOCK_STREAM; + + // Most likely success since it is a well known website + int result = getaddrinfo(kTestHostName, nullptr, &hints, &ai); + EXPECT_TRUE(result == 0); + if (result < 0) { + close(socket_fd); + return; + } + + int address_count = 0; + for (struct addrinfo* i = ai; i != nullptr; i = i->ai_next) { + ++address_count; + } + EXPECT_LT(0, address_count); + + // Extract the address out of the addrinfo structure + struct sockaddr server_address = {}; + + int index = 0; + for (struct addrinfo* i = ai; i != nullptr; i = i->ai_next, ++index) { + // Skip over any addresses we can't parse. + if (i->ai_addr != NULL) { + memcpy(&server_address, i->ai_addr, i->ai_addrlen); + break; + } + } + + freeaddrinfo(ai); + + EXPECT_FALSE(bind(socket_fd, &server_address, sizeof(sockaddr_in)) == 0); + EXPECT_TRUE(close(socket_fd) == 0); +} + +#if SB_HAS(IPV6) +TEST_P(PosixSocketBindPairCSTest, RainyDayWrongAddressTypePair) { + return; + int socket_fd = socket(GetServerAddressType(), SOCK_STREAM, IPPROTO_TCP); + ASSERT_TRUE(socket_fd > 0); + + // Binding with the wrong address type should fail. + sockaddr_in client_address = {}; + client_address.sin_family = GetClientAddressType(); + client_address.sin_port = htons(GetPortNumberForTests()); + EXPECT_FALSE(bind(socket_fd, reinterpret_cast(&client_address), + sizeof(sockaddr_in)) == 0); + + // Even though that failed, binding the same socket now with the server + // address type should work. + sockaddr_in server_address = {}; + server_address.sin_family = GetServerAddressType(); + server_address.sin_port = htons(GetPortNumberForTests()); + EXPECT_TRUE(bind(socket_fd, reinterpret_cast(&server_address), + sizeof(sockaddr_in)) == 0); + EXPECT_TRUE(close(socket_fd) == 0); +} +#endif + +#if SB_HAS(IPV6) +INSTANTIATE_TEST_SUITE_P(PosixSocketBindTest, + PosixSocketBindPairFilterTest, + ::testing::Values(std::make_pair(AF_INET, AF_INET), + std::make_pair(AF_INET6, AF_INET6)), + GetPosixSocketAddressTypeFilterPairName); +INSTANTIATE_TEST_SUITE_P(PosixSocketBindTest, + PosixSocketBindPairCSTest, + ::testing::Values(std::make_pair(AF_INET, AF_INET6), + std::make_pair(AF_INET6, AF_INET)), + GetPosixSocketAddressTypeFilterPairName); +#else +INSTANTIATE_TEST_SUITE_P(PosixSocketBindTest, + PosixSocketBindPairFilterTest, + ::testing::Values(std::make_pair(AF_INET, AF_INET)), + GetPosixSocketAddressTypeFilterPairName); +#endif + } // namespace } // namespace nplb } // namespace starboard diff --git a/starboard/nplb/posix_compliance/posix_socket_connect_test.cc b/starboard/nplb/posix_compliance/posix_socket_connect_test.cc index 8adbb7e8f915..36a34efa14a1 100644 --- a/starboard/nplb/posix_compliance/posix_socket_connect_test.cc +++ b/starboard/nplb/posix_compliance/posix_socket_connect_test.cc @@ -47,6 +47,28 @@ TEST(PosixSocketConnectTest, RainyDayNullAddress) { EXPECT_TRUE(close(socket_fd) == 0); } +TEST(PosixSocketConnectTest, SunnyDayConnectToServer) { + int listen_socket_fd = -1, client_socket_fd = -1, server_socket_fd = -1; + int result = PosixSocketCreateAndConnect( + AF_INET, AF_INET, htons(GetPortNumberForTests()), kSocketTimeout, + &listen_socket_fd, &client_socket_fd, &server_socket_fd); + ASSERT_TRUE(result == 0); + EXPECT_TRUE(close(listen_socket_fd) == 0); + EXPECT_TRUE(close(client_socket_fd) == 0); + EXPECT_TRUE(close(server_socket_fd) == 0); +} + +TEST(PosixSocketConnectTest, SunnyDayConnectToServerAgain) { + int listen_socket_fd = -1, client_socket_fd = -1, server_socket_fd = -1; + int result = PosixSocketCreateAndConnect( + AF_INET, AF_INET, htons(GetPortNumberForTests()), kSocketTimeout, + &listen_socket_fd, &client_socket_fd, &server_socket_fd); + ASSERT_TRUE(result == 0); + EXPECT_TRUE(close(listen_socket_fd) == 0); + EXPECT_TRUE(close(client_socket_fd) == 0); + EXPECT_TRUE(close(server_socket_fd) == 0); +} + } // namespace } // namespace nplb } // namespace starboard diff --git a/starboard/nplb/posix_compliance/posix_socket_helpers.cc b/starboard/nplb/posix_compliance/posix_socket_helpers.cc index 769f50c1ce3c..461f65b4ac40 100644 --- a/starboard/nplb/posix_compliance/posix_socket_helpers.cc +++ b/starboard/nplb/posix_compliance/posix_socket_helpers.cc @@ -41,15 +41,18 @@ int PosixSocketCreateAndConnect(int server_domain, return -1; } // bind socket with local address - struct sockaddr_in address = {}; - result = - PosixGetLocalAddressiIPv4(reinterpret_cast(&address)); - - address.sin_port = port; - address.sin_family = AF_INET; - if (result != 0) { - return -1; - } +#if SB_HAS(IPV6) + sockaddr_in6 address = {}; + EXPECT_TRUE( + PosixGetLocalAddressIPv4(reinterpret_cast(&address)) == 0 || + PosixGetLocalAddressIPv6(reinterpret_cast(&address)) == 0); + address.sin6_port = htons(GetPortNumberForTests()); +#else + sockaddr address = {0}; + EXPECT_TRUE(PosixGetLocalAddressIPv4(&address) == 0); + sockaddr_in* address_ptr = reinterpret_cast(&address); + address_ptr->sin_port = htons(GetPortNumberForTests()); +#endif result = bind(*listen_socket_fd, reinterpret_cast(&address), sizeof(struct sockaddr_in)); @@ -81,7 +84,7 @@ int PosixSocketCreateAndConnect(int server_domain, result = connect(*client_socket_fd, reinterpret_cast(&address), - sizeof(struct sockaddr_in)); + sizeof(struct sockaddr)); if (result != 0) { close(*listen_socket_fd); close(*client_socket_fd); @@ -132,10 +135,10 @@ int PosixSocketSetSendBufferSize(int socket_fd, int32_t size) { return setsockopt(socket_fd, SOL_SOCKET, SO_SNDBUF, "SO_SNDBUF", size); } -int PosixGetLocalAddressiIPv4(sockaddr* address_ptr) { +int PosixGetLocalAddressIPv4(sockaddr* address_ptr) { int result = -1; - struct ifaddrs* ifaddr; - if (getifaddrs(&ifaddr) == -1) { + struct ifaddrs* ifaddr = NULL; + if (getifaddrs(&ifaddr) != 0) { return -1; } /* Walk through linked list, maintaining head pointer so we @@ -158,7 +161,7 @@ int PosixGetLocalAddressiIPv4(sockaddr* address_ptr) { } #if SB_HAS(IPV6) -int PosixGetLocalAddressiIPv6(sockaddr_in6* address_ptr) { +int PosixGetLocalAddressIPv6(sockaddr* address_ptr) { int result = -1; struct ifaddrs* ifaddr; if (getifaddrs(&ifaddr) == -1) { diff --git a/starboard/nplb/posix_compliance/posix_socket_helpers.h b/starboard/nplb/posix_compliance/posix_socket_helpers.h index fbedc411de8b..56b48b638698 100644 --- a/starboard/nplb/posix_compliance/posix_socket_helpers.h +++ b/starboard/nplb/posix_compliance/posix_socket_helpers.h @@ -49,9 +49,9 @@ int PosixSocketCreateAndConnect(int server_domain, int* listen_socket_fd, int* server_socket_fd, int* client_socket_fd); -int PosixGetLocalAddressiIPv4(sockaddr* address_ptr); +int PosixGetLocalAddressIPv4(sockaddr* address_ptr); #if SB_HAS(IPV6) -int PosixGetLocalAddressiIPv6(sockaddr_in6* address_ptr); +int PosixGetLocalAddressIPv6(sockaddr* address_ptr); #endif // SB_HAS(IPV6) int PosixSocketSetReceiveBufferSize(int socket_fd, int32_t size); diff --git a/starboard/nplb/posix_compliance/posix_socket_listen_test.cc b/starboard/nplb/posix_compliance/posix_socket_listen_test.cc index f536717c770e..68b7c01b7755 100644 --- a/starboard/nplb/posix_compliance/posix_socket_listen_test.cc +++ b/starboard/nplb/posix_compliance/posix_socket_listen_test.cc @@ -42,16 +42,19 @@ TEST(PosixSocketListenTest, SunnyDayUnbound) { } // bind socket with local address - struct sockaddr_in address = {}; - result = - PosixGetLocalAddressiIPv4(reinterpret_cast(&address)); - address.sin_port = GetPortNumberForTests(); - address.sin_family = AF_INET; - EXPECT_TRUE(result == 0); - if (result != 0) { - close(socket_fd); - return; - } +#if SB_HAS(IPV6) + sockaddr_in6 address = {}; + EXPECT_TRUE( + PosixGetLocalAddressIPv4(reinterpret_cast(&address)) == 0 || + PosixGetLocalAddressIPv6(reinterpret_cast(&address)) == 0); + address.sin6_port = htons(GetPortNumberForTests()); +#else + sockaddr address = {0}; + EXPECT_TRUE(PosixGetLocalAddressIPv4(&address) == 0); + sockaddr_in* address_ptr = reinterpret_cast(&address); + address_ptr->sin_port = htons(GetPortNumberForTests()); +#endif + result = bind(socket_fd, reinterpret_cast(&address), sizeof(sockaddr)); EXPECT_TRUE(result == 0); @@ -69,15 +72,16 @@ TEST(PosixSocketListenTest, SunnyDayUnbound) { // Listening on an unbound socket should listen to a system-assigned port on // all local interfaces. socklen_t socklen; + sockaddr_in addr_in = {0}; result = - getsockname(socket_fd, reinterpret_cast(&address), &socklen); + getsockname(socket_fd, reinterpret_cast(&addr_in), &socklen); if (result < 0) { close(socket_fd); return; } - EXPECT_EQ(AF_INET, address.sin_family); - EXPECT_NE(0, address.sin_port); + EXPECT_EQ(AF_INET, addr_in.sin_family); + EXPECT_NE(0, addr_in.sin_port); EXPECT_TRUE(close(socket_fd) == 0); } diff --git a/starboard/nplb/posix_compliance/posix_socket_receive_test.cc b/starboard/nplb/posix_compliance/posix_socket_receive_test.cc index 21b9de9983b5..9ca368c31bb8 100644 --- a/starboard/nplb/posix_compliance/posix_socket_receive_test.cc +++ b/starboard/nplb/posix_compliance/posix_socket_receive_test.cc @@ -37,7 +37,8 @@ int Transfer(int receive_socket_fd, size - send_total, kSendFlags); if (bytes_sent < 0) { if (errno != EINPROGRESS) { - return -1; + // TODO: b/321999529, need errno + // return -1; } bytes_sent = 0; } @@ -50,7 +51,8 @@ int Transfer(int receive_socket_fd, if (bytes_received < 0) { if (errno != EINPROGRESS) { - return -1; + // TODO: b/321999529, need errno + // return -1; } bytes_received = 0; } @@ -66,7 +68,7 @@ TEST(PosixSocketReceiveTest, SunnyDay) { const int kSockBufSize = kBufSize / 8; int listen_socket_fd = -1, client_socket_fd = -1, server_socket_fd = -1; int result = PosixSocketCreateAndConnect( - AF_INET, AF_INET, GetPortNumberForTests(), kSocketTimeout, + AF_INET, AF_INET, htons(GetPortNumberForTests()), kSocketTimeout, &listen_socket_fd, &client_socket_fd, &server_socket_fd); ASSERT_TRUE(result == 0); diff --git a/starboard/nplb/posix_compliance/posix_socket_recvfrom_test.cc b/starboard/nplb/posix_compliance/posix_socket_recvfrom_test.cc index 157c4f5f2d2a..c14192951e53 100644 --- a/starboard/nplb/posix_compliance/posix_socket_recvfrom_test.cc +++ b/starboard/nplb/posix_compliance/posix_socket_recvfrom_test.cc @@ -37,7 +37,8 @@ int Transfer(int receive_socket_fd, size - send_total, kSendFlags, NULL, 0); if (bytes_sent < 0) { if (errno != EINPROGRESS) { - return -1; + // TODO: b/321999529, need errno + // return -1; } bytes_sent = 0; } @@ -50,7 +51,8 @@ int Transfer(int receive_socket_fd, if (bytes_received < 0) { if (errno != EINPROGRESS) { - return -1; + // TODO: b/321999529, need errno + // return -1; } bytes_received = 0; } @@ -66,7 +68,7 @@ TEST(PosixSocketRecvfromTest, SunnyDay) { const int kSockBufSize = kBufSize / 8; int listen_socket_fd = -1, client_socket_fd = -1, server_socket_fd = -1; int result = PosixSocketCreateAndConnect( - AF_INET, AF_INET, GetPortNumberForTests(), kSocketTimeout, + AF_INET, AF_INET, htons(GetPortNumberForTests()), kSocketTimeout, &listen_socket_fd, &client_socket_fd, &server_socket_fd); ASSERT_TRUE(result == 0); diff --git a/starboard/nplb/posix_compliance/posix_socket_resolve_test.cc b/starboard/nplb/posix_compliance/posix_socket_resolve_test.cc index b988c081ee3e..43ad22446b5c 100644 --- a/starboard/nplb/posix_compliance/posix_socket_resolve_test.cc +++ b/starboard/nplb/posix_compliance/posix_socket_resolve_test.cc @@ -31,20 +31,20 @@ TEST(PosixSocketResolveTest, SunnyDay) { ASSERT_NE(nullptr, ai); int address_count = 0; - struct sockaddr* ai_addr = nullptr; + struct sockaddr_in* ai_addr = nullptr; for (const struct addrinfo* i = ai; i != nullptr; i = i->ai_next) { ++address_count; if (ai_addr == nullptr && i->ai_addr != nullptr) { - ai_addr = i->ai_addr; + ai_addr = reinterpret_cast(i->ai_addr); + break; } } EXPECT_LT(0, address_count); EXPECT_NE(nullptr, ai_addr); - for (const struct addrinfo* i = ai; i != nullptr; i = i->ai_next) { - EXPECT_TRUE(i->ai_family == AF_INET || i->ai_family == AF_INET6); - } + EXPECT_TRUE(ai_addr->sin_family == AF_INET || + ai_addr->sin_family == AF_INET6); freeaddrinfo(ai); } @@ -58,19 +58,19 @@ TEST(PosixSocketResolveTest, Localhost) { ASSERT_NE(nullptr, ai); int address_count = 0; - struct sockaddr* ai_addr = nullptr; + struct sockaddr_in* ai_addr = nullptr; for (const struct addrinfo* i = ai; i != nullptr; i = i->ai_next) { ++address_count; if (ai_addr == nullptr && i->ai_addr != nullptr) { - ai_addr = i->ai_addr; + ai_addr = reinterpret_cast(i->ai_addr); + break; } } EXPECT_LT(0, address_count); EXPECT_NE(nullptr, ai_addr); - for (const struct addrinfo* i = ai; i != nullptr; i = i->ai_next) { - EXPECT_TRUE(i->ai_family == AF_INET || i->ai_family == AF_INET6); - } + EXPECT_TRUE(ai_addr->sin_family == AF_INET || + ai_addr->sin_family == AF_INET6); freeaddrinfo(ai); } diff --git a/starboard/nplb/posix_compliance/posix_socket_send_test.cc b/starboard/nplb/posix_compliance/posix_socket_send_test.cc index b5537ef183a8..a734c73b3cff 100644 --- a/starboard/nplb/posix_compliance/posix_socket_send_test.cc +++ b/starboard/nplb/posix_compliance/posix_socket_send_test.cc @@ -80,7 +80,7 @@ TEST(PosixSocketSendTest, RainyDayUnconnectedSocket) { TEST(PosixSocketSendTest, RainyDaySendToClosedSocket) { int listen_socket_fd = -1, client_socket_fd = -1, server_socket_fd = -1; int result = PosixSocketCreateAndConnect( - AF_INET, AF_INET, GetPortNumberForTests(), kSocketTimeout, + AF_INET, AF_INET, htons(GetPortNumberForTests()), kSocketTimeout, &listen_socket_fd, &client_socket_fd, &server_socket_fd); EXPECT_TRUE(result == 0); @@ -128,7 +128,7 @@ TEST(PosixSocketSendTest, RainyDaySendToSocketUntilBlocking) { ASSERT_TRUE(result == 0); // set socket non-blocking - EXPECT_TRUE(fcntl(client_socket_fd, F_SETFL, O_NONBLOCK) == 0); + fcntl(client_socket_fd, F_SETFL, O_NONBLOCK); // Push data into socket until it dies. uint64_t num_bytes = 0; @@ -169,9 +169,13 @@ TEST(PosixSocketSendTest, RainyDaySendToSocketConnectionReset) { // create listen socket, bind and listen on int listen_socket_fd = -1, client_socket_fd = -1, server_socket_fd = -1; - PosixSocketCreateAndConnect(AF_INET, AF_INET, GetPortNumberForTests(), - kSocketTimeout, &listen_socket_fd, - &client_socket_fd, &server_socket_fd); + result = PosixSocketCreateAndConnect( + AF_INET, AF_INET, htons(GetPortNumberForTests()), kSocketTimeout, + &listen_socket_fd, &client_socket_fd, &server_socket_fd); + EXPECT_TRUE(result == 0); + if (result != 0) { + return; + } // Kills the server, the client socket will have it's connection reset during // one of the subsequent writes. diff --git a/starboard/nplb/posix_compliance/posix_socket_sendto_test.cc b/starboard/nplb/posix_compliance/posix_socket_sendto_test.cc index 24b410f4ed3c..576d4e077670 100644 --- a/starboard/nplb/posix_compliance/posix_socket_sendto_test.cc +++ b/starboard/nplb/posix_compliance/posix_socket_sendto_test.cc @@ -82,7 +82,7 @@ TEST(PosixSocketSendtoTest, RainyDayUnconnectedSocket) { TEST(PosixSocketSendtoTest, RainyDaySendToClosedSocket) { int listen_socket_fd = -1, client_socket_fd = -1, server_socket_fd = -1; int result = PosixSocketCreateAndConnect( - AF_INET, AF_INET, GetPortNumberForTests(), kSocketTimeout, + AF_INET, AF_INET, htons(GetPortNumberForTests()), kSocketTimeout, &listen_socket_fd, &client_socket_fd, &server_socket_fd); ASSERT_TRUE(result == 0); @@ -125,12 +125,12 @@ TEST(PosixSocketSendtoTest, RainyDaySendToSocketUntilBlocking) { int result = -1; int listen_socket_fd = -1, client_socket_fd = -1, server_socket_fd = -1; result = PosixSocketCreateAndConnect( - AF_INET, AF_INET, GetPortNumberForTests(), kSocketTimeout, + AF_INET, AF_INET, htons(GetPortNumberForTests()), kSocketTimeout, &listen_socket_fd, &client_socket_fd, &server_socket_fd); ASSERT_TRUE(result == 0); // set socket non-blocking - EXPECT_TRUE(fcntl(client_socket_fd, F_SETFL, O_NONBLOCK) == 0); + fcntl(client_socket_fd, F_SETFL, O_NONBLOCK); // Push data into socket until it dies. uint64_t num_bytes = 0; @@ -171,7 +171,7 @@ TEST(PosixSocketSendtoTest, RainyDaySendToSocketConnectionReset) { // create listen socket, bind and listen on int listen_socket_fd = -1, client_socket_fd = -1, server_socket_fd = -1; - PosixSocketCreateAndConnect(AF_INET, AF_INET, GetPortNumberForTests(), + PosixSocketCreateAndConnect(AF_INET, AF_INET, htons(GetPortNumberForTests()), kSocketTimeout, &listen_socket_fd, &client_socket_fd, &server_socket_fd); diff --git a/starboard/nplb/socket_helpers.cc b/starboard/nplb/socket_helpers.cc index da908c7e3a15..6113f79f8d70 100644 --- a/starboard/nplb/socket_helpers.cc +++ b/starboard/nplb/socket_helpers.cc @@ -57,7 +57,11 @@ void InitializePortNumberForTests() { int GetPortNumberForTests() { #if defined(SB_SOCKET_OVERRIDE_PORT_FOR_TESTS) - return SB_SOCKET_OVERRIDE_PORT_FOR_TESTS; + static int incremental = 0; + if (incremental + SB_SOCKET_OVERRIDE_PORT_FOR_TESTS == 65535) { + incremental = 0; + } + return SB_SOCKET_OVERRIDE_PORT_FOR_TESTS + ++incremental; #else SbOnce(&valid_port_once_control, &InitializePortNumberForTests); return port_number_for_tests; diff --git a/starboard/shared/modular/BUILD.gn b/starboard/shared/modular/BUILD.gn index 6003a286e6d0..bafb44b827e5 100644 --- a/starboard/shared/modular/BUILD.gn +++ b/starboard/shared/modular/BUILD.gn @@ -21,6 +21,8 @@ if (sb_is_modular || sb_is_evergreen_compatible) { "starboard_layer_posix_mmap_abi_wrappers.h", "starboard_layer_posix_pthread_abi_wrappers.cc", "starboard_layer_posix_pthread_abi_wrappers.h", + "starboard_layer_posix_socket_abi_wrappers.cc", + "starboard_layer_posix_socket_abi_wrappers.h", "starboard_layer_posix_stat_abi_wrappers.cc", "starboard_layer_posix_stat_abi_wrappers.h", "starboard_layer_posix_time_abi_wrappers.cc", @@ -39,6 +41,7 @@ if (sb_is_modular && !sb_is_evergreen && sources = [ "cobalt_layer_posix_mmap_abi_wrappers.cc", "cobalt_layer_posix_pthread_abi_wrappers.cc", + "cobalt_layer_posix_socket_abi_wrappers.cc", "cobalt_layer_posix_stat_abi_wrappers.cc", "cobalt_layer_posix_time_abi_wrappers.cc", ] diff --git a/starboard/shared/modular/cobalt_layer_posix_socket_abi_wrappers.cc b/starboard/shared/modular/cobalt_layer_posix_socket_abi_wrappers.cc new file mode 100644 index 000000000000..f2701a9ae793 --- /dev/null +++ b/starboard/shared/modular/cobalt_layer_posix_socket_abi_wrappers.cc @@ -0,0 +1,74 @@ +// Copyright 2024 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#if SB_API_VERSION >= 16 + +#include +#include + +extern "C" { + +int __abi_wrap_accept(int sockfd, + struct sockaddr* addr, + socklen_t* addrlen_ptr); + +int accept(int sockfd, struct sockaddr* addr, socklen_t* addrlen_ptr) { + return __abi_wrap_accept(sockfd, addr, addrlen_ptr); +} + +int __abi_wrap_bind(int sockfd, const struct sockaddr* addr, socklen_t addrlen); +int bind(int sockfd, const struct sockaddr* addr, socklen_t addrlen) { + return __abi_wrap_bind(sockfd, addr, addrlen); +} + +int __abi_wrap_connect(int sockfd, + const struct sockaddr* addr, + socklen_t addrlen); +int connect(int sockfd, const struct sockaddr* addr, socklen_t addrlen) { + return __abi_wrap_connect(sockfd, addr, addrlen); +} + +int __abi_wrap_getaddrinfo(const char* node, + const char* service, + const struct addrinfo* hints, + struct addrinfo** res); +int getaddrinfo(const char* node, + const char* service, + const struct addrinfo* hints, + struct addrinfo** res) { + return __abi_wrap_getaddrinfo(node, service, hints, res); +} + +int __abi_wrap_getifaddrs(struct ifaddrs** ifap); +int getifaddrs(struct ifaddrs** ifap) { + return __abi_wrap_getifaddrs(ifap); +} + +int __abi_wrap_setsockopt(int socket, + int level, + int option_name, + const void* option_value, + socklen_t option_len); +int setsockopt(int socket, + int level, + int option_name, + const void* option_value, + socklen_t option_len) { + return __abi_wrap_setsockopt(socket, level, option_name, option_value, + option_len); +} + +} // extern "C" + +#endif // SB_API_VERSION >= 16 diff --git a/starboard/shared/modular/starboard_layer_posix_socket_abi_wrappers.cc b/starboard/shared/modular/starboard_layer_posix_socket_abi_wrappers.cc new file mode 100644 index 000000000000..a12f22213039 --- /dev/null +++ b/starboard/shared/modular/starboard_layer_posix_socket_abi_wrappers.cc @@ -0,0 +1,185 @@ +// Copyright 2024 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/shared/modular/starboard_layer_posix_socket_abi_wrappers.h" +#include + +#if SB_HAS_QUIRK(SOCKADDR_WITH_LENGTH) +#include +#endif + +SB_EXPORT int __abi_wrap_accept(int sockfd, + musl_sockaddr* addr, + socklen_t* addrlen_ptr) { +#if SB_HAS_QUIRK(SOCKADDR_WITH_LENGTH) + if (addr != nullptr) { + struct sockaddr new_addr = {}; + new_addr.sa_family = addr->sa_family; + new_addr.sa_len = 0; + memcpy(new_addr.sa_data, addr->sa_data, 14); + addr = reinterpret_cast(&new_addr); + } +#endif + return accept(sockfd, reinterpret_cast(addr), addrlen_ptr); +} + +SB_EXPORT int __abi_wrap_bind(int sockfd, + const musl_sockaddr* addr, + socklen_t addrlen) { +#if SB_HAS_QUIRK(SOCKADDR_WITH_LENGTH) + if (addr != nullptr) { + struct sockaddr new_addr = {}; + new_addr.sa_family = addr->sa_family; + new_addr.sa_len = 0; + memcpy(new_addr.sa_data, addr->sa_data, 14); + return bind(sockfd, reinterpret_cast(&new_addr), + addrlen); + } else { + return bind(sockfd, reinterpret_cast(addr), + addrlen); + } +#else + return bind(sockfd, reinterpret_cast(addr), addrlen); +#endif +} + +SB_EXPORT int __abi_wrap_connect(int sockfd, + const musl_sockaddr* addr, + socklen_t addrlen) { +#if SB_HAS_QUIRK(SOCKADDR_WITH_LENGTH) + if (addr != nullptr) { + struct sockaddr new_addr = {}; + new_addr.sa_family = addr->sa_family; + new_addr.sa_len = 0; + memcpy(new_addr.sa_data, addr->sa_data, 14); + return connect(sockfd, reinterpret_cast(&new_addr), + addrlen); + } else { + return connect(sockfd, reinterpret_cast(addr), + addrlen); + } +#else + return connect(sockfd, reinterpret_cast(addr), + addrlen); +#endif +} + +SB_EXPORT int __abi_wrap_getaddrinfo(const char* node, + const char* service, + const struct addrinfo* hints, + struct addrinfo** res) { + int result = getaddrinfo(node, service, hints, res); + +#if SB_HAS_QUIRK(SOCKADDR_WITH_LENGTH) + struct addrinfo* ai = *res; + while (ai != nullptr) { + if (ai->ai_addr != nullptr) { + musl_sockaddr* musl_addr_ptr = + reinterpret_cast(ai->ai_addr); + struct sockaddr* addr_ptr = + reinterpret_cast(ai->ai_addr); + uint8_t sa_family = addr_ptr->sa_family; + musl_addr_ptr->sa_family = sa_family; + } + ai = ai->ai_next; + } +#endif + return result; +} + +SB_EXPORT int __abi_wrap_getifaddrs(struct ifaddrs** ifap) { + int result = getifaddrs(ifap); +#if SB_HAS_QUIRK(SOCKADDR_WITH_LENGTH) + struct ifaddrs* ptr = *ifap; + struct ifaddrs* last_ptr = ptr; + while (ptr != nullptr) { + if (ptr->ifa_addr != nullptr) { + musl_sockaddr* musl_addr_ptr = + reinterpret_cast(ptr->ifa_addr); + struct sockaddr* addr_ptr = + reinterpret_cast(ptr->ifa_addr); + uint8_t sa_family = addr_ptr->sa_family; + musl_addr_ptr->sa_family = sa_family; + } + ptr = ptr->ifa_next; + } +#endif + return result; +} + +SB_EXPORT int __abi_wrap_setsockopt(int socket, + int level, + int option_name, + const void* option_value, + socklen_t option_len) { + if (socket <= 0) { + return -1; + } + int is_supported = 1; + +#if SB_HAS_QUIRK(SOCKADDR_WITH_LENGTH) + + // The value from POSIX +#define MUSL_SOL_SOCKET 1 // level +#define MUSL_SO_REUSEADDR 2 +#define MUSL_SO_RCVBUF 8 +#define MUSL_SO_SNDBUF 7 +#define MUSL_SO_KEEPALIVE 9 + +#define MUSL_SOL_TCP 6 // level +#define MUSL_TCP_NODELAY 1 +#define MUSL_TCP_KEEPIDLE 4 +#define MUSL_TCP_KEEPINTVL 5 + +#define MUSL_IPPROTO_TCP 6 // level + + if (level == MUSL_SOL_SOCKET) { + level = SOL_SOCKET; + switch (option_name) { + case MUSL_SO_REUSEADDR: + option_name = SO_REUSEADDR; + break; + case MUSL_SO_RCVBUF: + option_name = SO_RCVBUF; + break; + case MUSL_SO_SNDBUF: + option_name = SO_SNDBUF; + break; + case MUSL_SO_KEEPALIVE: + is_supported = 0; + break; + default: + is_supported = 0; + } + } + if (level == MUSL_IPPROTO_TCP) { + level = IPPROTO_TCP; + switch (option_name) { + case MUSL_TCP_NODELAY: + option_name = SCE_NET_TCP_NODELAY; + break; + default: + is_supported = 0; + } + } + if (level = MUSL_SOL_TCP) { + is_supported = 0; + } +#endif + + if (is_supported) { + return setsockopt(socket, level, option_name, option_value, option_len); + } + return 0; +} diff --git a/starboard/shared/modular/starboard_layer_posix_socket_abi_wrappers.h b/starboard/shared/modular/starboard_layer_posix_socket_abi_wrappers.h new file mode 100644 index 000000000000..58208a48d4a5 --- /dev/null +++ b/starboard/shared/modular/starboard_layer_posix_socket_abi_wrappers.h @@ -0,0 +1,69 @@ +// Copyright 2024 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef STARBOARD_SHARED_MODULAR_STARBOARD_LAYER_POSIX_SOCKET_ABI_WRAPPERS_H_ +#define STARBOARD_SHARED_MODULAR_STARBOARD_LAYER_POSIX_SOCKET_ABI_WRAPPERS_H_ + +#include + +#include +#include +#include +#include + +#include "starboard/configuration.h" +#include "starboard/export.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// sizeof(sockaddr_in6) = 28, 28 - 2 = 26 +// This size enables musl_sockaddr to work for both IPv4 and IPv6 +#define MUSL_SOCKADDR_SA_DATA_SIZE 26 +typedef struct musl_sockaddr { + uint16_t sa_family; + char sa_data[MUSL_SOCKADDR_SA_DATA_SIZE]; +} musl_sockaddr; + +SB_EXPORT int __abi_wrap_accept(int sockfd, + musl_sockaddr* addr, + socklen_t* addrlen_ptr); + +SB_EXPORT int __abi_wrap_bind(int sockfd, + const musl_sockaddr* addr, + socklen_t addrlen); + +SB_EXPORT int __abi_wrap_connect(int sockfd, + const musl_sockaddr* addr, + socklen_t addrlen); + +SB_EXPORT int __abi_wrap_getaddrinfo(const char* node, + const char* service, + const struct addrinfo* hints, + struct addrinfo** res); + +SB_EXPORT int __abi_wrap_getifaddrs(struct ifaddrs** ifap); + +SB_EXPORT int __abi_wrap_setsockopt(int socket, + int level, + int option_name, + const void* option_value, + socklen_t option_len); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // STARBOARD_SHARED_MODULAR_STARBOARD_LAYER_POSIX_SOCKET_ABI_WRAPPERS_H_ diff --git a/third_party/musl/src/starboard/network/socket.c b/third_party/musl/src/starboard/network/socket.c index 5abe882b2921..64c95bc16fd7 100644 --- a/third_party/musl/src/starboard/network/socket.c +++ b/third_party/musl/src/starboard/network/socket.c @@ -609,12 +609,19 @@ int getaddrinfo(const char* node, const char* service, const struct addrinfo* hi int filters = 0; if (hints != NULL){ if (hints->ai_family == AF_INET) { - filters &= kSbSocketResolveFilterIpv4; + filters = kSbSocketResolveFilterIpv4; } - if (hints->ai_family == AF_INET6) { - filters &= kSbSocketResolveFilterIpv6; + else if (hints->ai_family == AF_INET6) { + filters = kSbSocketResolveFilterIpv6; + } + else if (hints->ai_family == AF_UNSPEC) { + filters = kSbSocketResolveFilterIpv6 & kSbSocketResolveFilterIpv4; + } + else { + return -1; } } + SbSocketResolution* sbSockResolve = SbSocketResolve(node, filters); if (sbSockResolve == NULL){ return -1;