mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-23 04:16:57 +02:00
network: UDPP2P
This commit is contained in:
+23
-6
@@ -891,6 +891,7 @@ struct P2pEndpoint {
|
|||||||
uint16_t virtual_port = 0;
|
uint16_t virtual_port = 0;
|
||||||
int nonblocking = 0;
|
int nonblocking = 0;
|
||||||
int broadcast = 0;
|
int broadcast = 0;
|
||||||
|
int use_crypto = 0;
|
||||||
int send_buffer = 9216;
|
int send_buffer = 9216;
|
||||||
int receive_buffer = 40 * 1024;
|
int receive_buffer = 40 * 1024;
|
||||||
};
|
};
|
||||||
@@ -1095,6 +1096,7 @@ static int* P2pSocketOption(P2pEndpoint& endpoint, int option) {
|
|||||||
case 0x1001: return &endpoint.send_buffer;
|
case 0x1001: return &endpoint.send_buffer;
|
||||||
case 0x1002: return &endpoint.receive_buffer;
|
case 0x1002: return &endpoint.receive_buffer;
|
||||||
case 0x1200: return &endpoint.nonblocking;
|
case 0x1200: return &endpoint.nonblocking;
|
||||||
|
case 0x20000: return &endpoint.use_crypto;
|
||||||
default: return nullptr;
|
default: return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2459,9 +2461,9 @@ int64_t KYTY_SYSV_ABI Recvfrom(int s, void* buf, uint64_t len, int flags, void*
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
NativeSocket socket = INVALID_NATIVE_SOCKET;
|
NativeSocket socket = INVALID_NATIVE_SOCKET;
|
||||||
std::shared_ptr<SocketTransport> transport;
|
SocketSlot state;
|
||||||
if (!GetSocketBackend(s, &socket, nullptr, &transport)) {
|
if (!GetSocketBackend(s, &socket, &state)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2469,6 +2471,21 @@ int64_t KYTY_SYSV_ABI Recvfrom(int s, void* buf, uint64_t len, int flags, void*
|
|||||||
if (host_flags < 0) {
|
if (host_flags < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (state.p2p) {
|
||||||
|
if (!state.p2p->bound || (!state.p2p->nonblocking && (flags & 0x80) == 0)) {
|
||||||
|
return SetGuestSocketError(Posix::POSIX_EOPNOTSUPP);
|
||||||
|
}
|
||||||
|
char pending;
|
||||||
|
if (::recv(socket, &pending, sizeof(pending), MSG_PEEK) < 0) {
|
||||||
|
SetHostSocketError();
|
||||||
|
// Winsock reports a peeked datagram's truncation as EMSGSIZE.
|
||||||
|
if (*Posix::GetErrorAddr() != Posix::POSIX_EMSGSIZE) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Pending UDPP2P packets still require framing and optional decryption.
|
||||||
|
return SetGuestSocketError(Posix::POSIX_EOPNOTSUPP);
|
||||||
|
}
|
||||||
|
|
||||||
const auto host_len = static_cast<SocketIoLength>(
|
const auto host_len = static_cast<SocketIoLength>(
|
||||||
std::min<uint64_t>(len, std::numeric_limits<SocketIoLength>::max()));
|
std::min<uint64_t>(len, std::numeric_limits<SocketIoLength>::max()));
|
||||||
@@ -2476,12 +2493,12 @@ int64_t KYTY_SYSV_ABI Recvfrom(int s, void* buf, uint64_t len, int flags, void*
|
|||||||
SocketLength host_addrlen = sizeof(host_addr);
|
SocketLength host_addrlen = sizeof(host_addr);
|
||||||
int64_t result = 0;
|
int64_t result = 0;
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
if (transport->type == SOCK_STREAM) {
|
if (state.transport->type == SOCK_STREAM) {
|
||||||
if (addr != nullptr &&
|
if (addr != nullptr &&
|
||||||
::getpeername(socket, reinterpret_cast<sockaddr*>(&host_addr), &host_addrlen) != 0) {
|
::getpeername(socket, reinterpret_cast<sockaddr*>(&host_addr), &host_addrlen) != 0) {
|
||||||
return SetHostSocketError();
|
return SetHostSocketError();
|
||||||
}
|
}
|
||||||
result = ReceiveStream(*transport, static_cast<char*>(buf), host_len, host_flags,
|
result = ReceiveStream(*state.transport, static_cast<char*>(buf), host_len, host_flags,
|
||||||
(flags & 0x80) != 0);
|
(flags & 0x80) != 0);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
return result;
|
return result;
|
||||||
@@ -2489,7 +2506,7 @@ int64_t KYTY_SYSV_ABI Recvfrom(int s, void* buf, uint64_t len, int flags, void*
|
|||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
transport.reset();
|
state.transport.reset();
|
||||||
if (addr == nullptr) {
|
if (addr == nullptr) {
|
||||||
result = ::recv(socket, static_cast<char*>(buf), host_len, host_flags);
|
result = ::recv(socket, static_cast<char*>(buf), host_len, host_flags);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -2173,6 +2173,53 @@ void CheckSocketWakeup() {
|
|||||||
"write shutdown drains queued bytes, signals EOF, and preserves reverse traffic");
|
"write shutdown drains queued bytes, signals EOF, and preserves reverse traffic");
|
||||||
Check(Net::SocketClose(shutdown_reader) == 0 && Net::SocketClose(shutdown_writer) == 0,
|
Check(Net::SocketClose(shutdown_reader) == 0 && Net::SocketClose(shutdown_writer) == 0,
|
||||||
"close half-shutdown sockets");
|
"close half-shutdown sockets");
|
||||||
|
const int encrypted = Net::Socket(2, 6, 0);
|
||||||
|
int crypto = -1;
|
||||||
|
uint32_t crypto_size = sizeof(crypto);
|
||||||
|
Check(encrypted >= 0 &&
|
||||||
|
Net::Getsockopt(encrypted, 0xffff, 0x20000, &crypto, &crypto_size) == 0 &&
|
||||||
|
crypto == 0,
|
||||||
|
"UDPP2P encryption defaults to disabled");
|
||||||
|
for (const int setting : {7, 0}) {
|
||||||
|
Check(Net::Setsockopt(encrypted, 0xffff, 0x20000, &setting, sizeof(setting)) == 0 &&
|
||||||
|
Net::Getsockopt(encrypted, 0xffff, 0x20000, &crypto, &crypto_size) == 0 &&
|
||||||
|
crypto == (setting != 0),
|
||||||
|
"UDPP2P encryption configuration retains normalized enable and disable values");
|
||||||
|
Check(Net::Send(encrypted, "x", 1, 0) == -1 &&
|
||||||
|
*Libs::Posix::GetErrorAddr() == Libs::Posix::POSIX_EOPNOTSUPP,
|
||||||
|
"UDPP2P configuration never exposes unframed plaintext transport");
|
||||||
|
}
|
||||||
|
std::array<uint8_t, 16> p2p_address {16, 2, 0x0e, 0x4a, 127, 0, 0, 1, 0x1e, 0x61};
|
||||||
|
Check(Net::Bind(encrypted, p2p_address.data(), p2p_address.size()) == 0,
|
||||||
|
"bind UDPP2P physical and virtual ports");
|
||||||
|
char untouched = '!';
|
||||||
|
auto source = p2p_address;
|
||||||
|
uint32_t source_size = source.size();
|
||||||
|
Check(Net::Recvfrom(encrypted, &untouched, 1, 0x80, source.data(), &source_size) == -1 &&
|
||||||
|
*Libs::Posix::GetErrorAddr() == Libs::Posix::POSIX_EWOULDBLOCK,
|
||||||
|
"per-call nonblocking UDPP2P receive reports an actually empty queue");
|
||||||
|
Check(Net::Setsockopt(encrypted, 0xffff, 0x1200, &enabled, sizeof(enabled)) == 0 &&
|
||||||
|
Net::Setsockopt(encrypted, 0xffff, 0x20000, &enabled, sizeof(enabled)) == 0 &&
|
||||||
|
Net::Recvfrom(encrypted, &untouched, 1, 0, source.data(), &source_size) == -1 &&
|
||||||
|
*Libs::Posix::GetErrorAddr() == Libs::Posix::POSIX_EWOULDBLOCK &&
|
||||||
|
untouched == '!' && source == p2p_address && source_size == source.size(),
|
||||||
|
"empty encrypted nonblocking receive preserves all caller outputs");
|
||||||
|
const int raw_sender = Net::Socket(2, 2, 0);
|
||||||
|
Check(raw_sender >= 0 &&
|
||||||
|
Net::Sendto(raw_sender, "pending", 7, 0, p2p_address.data(), p2p_address.size()) == 7,
|
||||||
|
"queue a datagram requiring unsupported UDPP2P processing");
|
||||||
|
const auto pending_deadline = std::chrono::steady_clock::now() + std::chrono::seconds(2);
|
||||||
|
while (Net::Recv(encrypted, &untouched, 1, 0) == -1 &&
|
||||||
|
*Libs::Posix::GetErrorAddr() == Libs::Posix::POSIX_EWOULDBLOCK &&
|
||||||
|
std::chrono::steady_clock::now() < pending_deadline) {
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||||
|
}
|
||||||
|
Check(*Libs::Posix::GetErrorAddr() == Libs::Posix::POSIX_EOPNOTSUPP &&
|
||||||
|
Net::Recv(encrypted, &untouched, 1, 0) == -1 &&
|
||||||
|
*Libs::Posix::GetErrorAddr() == Libs::Posix::POSIX_EOPNOTSUPP && untouched == '!',
|
||||||
|
"queued packets remain queued and unsupported instead of masquerading as empty");
|
||||||
|
Check(Net::SocketClose(encrypted) == 0 && Net::SocketClose(raw_sender) == 0,
|
||||||
|
"close UDPP2P readiness fixtures");
|
||||||
Check(Net::SocketClose(writer) == 0, "close wake writer");
|
Check(Net::SocketClose(writer) == 0, "close wake writer");
|
||||||
*net_errno = Libs::Posix::POSIX_EINVAL;
|
*net_errno = Libs::Posix::POSIX_EINVAL;
|
||||||
Check(net_recv(reader, received.data(), received.size(), 0) == 0 &&
|
Check(net_recv(reader, received.data(), received.size(), 0) == 0 &&
|
||||||
|
|||||||
Reference in New Issue
Block a user