fix(libSceNet): preserve successful stream recvfrom results
This commit is contained in:
parent
6e653bef51
commit
74defef675
|
|
@ -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<const sockaddr_in&>(native);
|
||||
|
|
|
|||
|
|
@ -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<std::uint8_t, 28> destination{};
|
||||
destination[0] = static_cast<std::uint8_t>(addressSize);
|
||||
destination[1] = static_cast<std::uint8_t>(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<std::uint8_t, 28> 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<std::uint8_t, 28> 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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue