diff --git a/core/libs/prx/libSceNet/Export.cpp b/core/libs/prx/libSceNet/Export.cpp index 8203f4edc..acbf2713d 100644 --- a/core/libs/prx/libSceNet/Export.cpp +++ b/core/libs/prx/libSceNet/Export.cpp @@ -190,6 +190,10 @@ bool guest_to_native_address(const void* address, std::uint32_t length, bool native_to_guest_address(const sockaddr_storage& native, void* address, std::uint32_t* length) { if (!address || !length) return false; + if (native.ss_family == AF_UNSPEC) { + *length = 0; + return true; + } std::uint8_t bytes[28]{}; if (native.ss_family == AF_INET) { const auto& v4 = reinterpret_cast(native); diff --git a/core/libs/tests/GuestSceNet.cpp b/core/libs/tests/GuestSceNet.cpp index ba87b2401..e54ece035 100644 --- a/core/libs/tests/GuestSceNet.cpp +++ b/core/libs/tests/GuestSceNet.cpp @@ -319,6 +319,63 @@ static void CheckUnspecifiedIpv6() { Require(sceNetSocketClose(receiver) == 0); } +static void CheckStreamSender(int family) { + const auto addressSize = family == 2 ? 16u : 28u; + const int listener = sceNetSocket(nullptr, family, 1, 6); + Require(listener >= 0); + std::array destination{}; + destination[0] = static_cast(addressSize); + destination[1] = static_cast(family); + if (family == 2) { destination[4] = 127; destination[7] = 1; } + else destination[23] = 1; + Require(sceNetBind_nid_postfix(listener, destination.data(), addressSize) == 0 && sceNetListen(listener, 1) == 0); + std::uint32_t size = destination.size(); + Require(sceNetGetsockname(listener, destination.data(), &size) == 0 && size == addressSize); + const int client = sceNetSocket(nullptr, family, 1, 6); + Require(client >= 0 && sceNetConnect(client, destination.data(), addressSize) == 0); + const int accepted = sceNetAccept(listener, nullptr, nullptr); + Require(accepted >= 0); + const char payload[] = "stream"; + for (const auto endpoints : {std::array{accepted, client}, std::array{client, accepted}}) { + const auto receiver = endpoints[0], sender = endpoints[1]; + for (const std::uint32_t capacity : {0u, 1u, 16u, 28u, UINT32_MAX}) { + Require(sceNetSend(sender, payload, sizeof(payload), 0) == sizeof(payload)); + std::array address; + address.fill(0xa5); + char received[sizeof(payload)]{}; + size = capacity; + *sceNetErrnoLoc() = 123; + Require(sceNetRecvfrom(receiver, received, 0, 2, address.data(), &size) == 0); + Require(size == 0 && received[0] == 0 && *sceNetErrnoLoc() == 123); + Require(std::all_of(address.begin(), address.end(), [](auto byte) { return byte == 0xa5; })); + for (const int flags : {2, 0}) { + size = capacity; + *sceNetErrnoLoc() = 123; + Require(sceNetRecvfrom(receiver, received, sizeof(received), flags, address.data(), &size) == sizeof(payload)); + Require(size == 0 && std::memcmp(received, payload, sizeof(payload)) == 0 && *sceNetErrnoLoc() == 123); + Require(std::all_of(address.begin(), address.end(), [](auto byte) { return byte == 0xa5; })); + } + } + Require(sceNetSend(sender, payload, sizeof(payload), 0) == sizeof(payload)); + std::array address; + address.fill(0xa5); + char received[sizeof(payload)]{}; + Require(Failed(sceNetRecvfrom(receiver, received, sizeof(received), 0, address.data(), nullptr), 22)); + size = 123; + Require(sceNetRecvfrom(receiver, received, sizeof(received), 0, nullptr, &size) == sizeof(payload)); + Require(size == 123 && std::memcmp(received, payload, sizeof(payload)) == 0); + Require(sceNetShutdown(sender, 1) == 0); + for (const int flags : {2, 0}) { + size = address.size(); + *sceNetErrnoLoc() = 123; + Require(sceNetRecvfrom(receiver, received, sizeof(received), flags, address.data(), &size) == 0); + Require(size == 0 && *sceNetErrnoLoc() == 123); + Require(std::all_of(address.begin(), address.end(), [](auto byte) { return byte == 0xa5; })); + } + } + for (const int descriptor : {client, accepted, listener}) Require(sceNetSocketClose(descriptor) == 0); +} + int main() { const auto epoch = std::chrono::steady_clock::time_point{}; Require(KernelSocketSelect::DeadlineAfter(epoch, 2, 250000) == epoch + std::chrono::milliseconds(2250)); @@ -340,6 +397,8 @@ int main() { CheckAddressText(28, "1234:5678:9abc:def0:1234:5678:9abc:def0"); CheckLinkLocalAllNodesIpv6(); CheckUnspecifiedIpv6(); + CheckStreamSender(2); + if (!ipv6Unavailable) CheckStreamSender(28); const int listener = sceNetSocket(nullptr, 2, 1, 6); Require(listener >= 0);