mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-28 22:06:59 +01:00
net: export connect, getsockopt, sendto, and recvfrom
This commit is contained in:
committed by
nmzik
parent
fb7ff7ec03
commit
4852721005
+26
-2
@@ -89,6 +89,10 @@ int KYTY_SYSV_ABI NetBind(int s, const void* addr, uint32_t addrlen) {
|
|||||||
return FinishSocketCall(Net::Bind(s, addr, addrlen));
|
return FinishSocketCall(Net::Bind(s, addr, addrlen));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int KYTY_SYSV_ABI NetConnect(int s, const void* addr, uint32_t addrlen) {
|
||||||
|
return FinishSocketCall(Net::Connect(s, addr, addrlen));
|
||||||
|
}
|
||||||
|
|
||||||
int KYTY_SYSV_ABI NetListen(int s, int backlog) {
|
int KYTY_SYSV_ABI NetListen(int s, int backlog) {
|
||||||
return FinishSocketCall(Net::Listen(s, backlog));
|
return FinishSocketCall(Net::Listen(s, backlog));
|
||||||
}
|
}
|
||||||
@@ -170,14 +174,24 @@ int KYTY_SYSV_ABI NetSocketClose(int s) {
|
|||||||
return FinishNetCall(Net::SocketClose(s));
|
return FinishNetCall(Net::SocketClose(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int KYTY_SYSV_ABI NetGetsockopt(int s, int level, int optname, void* optval, uint32_t* optlen) {
|
||||||
|
return FinishSocketCall(Net::Getsockopt(s, level, optname, optval, optlen));
|
||||||
|
}
|
||||||
|
|
||||||
int KYTY_SYSV_ABI NetSetsockopt(int s, int level, int optname, const void* optval,
|
int KYTY_SYSV_ABI NetSetsockopt(int s, int level, int optname, const void* optval,
|
||||||
uint32_t optlen) {
|
uint32_t optlen) {
|
||||||
return FinishSocketCall(Net::Setsockopt(s, level, optname, optval, optlen));
|
return FinishSocketCall(Net::Setsockopt(s, level, optname, optval, optlen));
|
||||||
}
|
}
|
||||||
|
|
||||||
int KYTY_SYSV_ABI NetSend(int s, const void* buf, size_t len, int flags) {
|
int KYTY_SYSV_ABI NetSendto(int s, const void* buf, size_t len, int flags, const void* addr,
|
||||||
|
uint32_t addrlen) {
|
||||||
const auto size = std::min<size_t>(len, std::numeric_limits<int>::max());
|
const auto size = std::min<size_t>(len, std::numeric_limits<int>::max());
|
||||||
return FinishSocketCall(static_cast<int>(Net::Send(s, buf, size, flags | 0x20000)));
|
return FinishSocketCall(
|
||||||
|
static_cast<int>(Net::Sendto(s, buf, size, flags | 0x20000, addr, addrlen)));
|
||||||
|
}
|
||||||
|
|
||||||
|
int KYTY_SYSV_ABI NetSend(int s, const void* buf, size_t len, int flags) {
|
||||||
|
return NetSendto(s, buf, len, flags, nullptr, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int KYTY_SYSV_ABI NetRecv(int s, void* buf, size_t len, int flags) {
|
int KYTY_SYSV_ABI NetRecv(int s, void* buf, size_t len, int flags) {
|
||||||
@@ -185,6 +199,12 @@ int KYTY_SYSV_ABI NetRecv(int s, void* buf, size_t len, int flags) {
|
|||||||
return FinishSocketCall(static_cast<int>(Net::Recv(s, buf, size, flags)));
|
return FinishSocketCall(static_cast<int>(Net::Recv(s, buf, size, flags)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int KYTY_SYSV_ABI NetRecvfrom(int s, void* buf, size_t len, int flags, void* addr,
|
||||||
|
uint32_t* addrlen) {
|
||||||
|
const auto size = std::min<size_t>(len, std::numeric_limits<int>::max());
|
||||||
|
return FinishSocketCall(static_cast<int>(Net::Recvfrom(s, buf, size, flags, addr, addrlen)));
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t KYTY_SYSV_ABI NetHtonl(uint32_t host32) {
|
uint32_t KYTY_SYSV_ABI NetHtonl(uint32_t host32) {
|
||||||
return ((host32 & 0x000000ffu) << 24u) | ((host32 & 0x0000ff00u) << 8u) |
|
return ((host32 & 0x000000ffu) << 24u) | ((host32 & 0x0000ff00u) << 8u) |
|
||||||
((host32 & 0x00ff0000u) >> 8u) | ((host32 & 0xff000000u) >> 24u);
|
((host32 & 0x00ff0000u) >> 8u) | ((host32 & 0xff000000u) >> 24u);
|
||||||
@@ -209,6 +229,7 @@ LIB_DEFINE(InitNet_1_Net) {
|
|||||||
LIB_FUNC("HQOwnfMGipQ", LibNet::GetNetErrorAddr);
|
LIB_FUNC("HQOwnfMGipQ", LibNet::GetNetErrorAddr);
|
||||||
LIB_FUNC("PIWqhn9oSxc", LibNet::NetAccept);
|
LIB_FUNC("PIWqhn9oSxc", LibNet::NetAccept);
|
||||||
LIB_FUNC("bErx49PgxyY", LibNet::NetBind);
|
LIB_FUNC("bErx49PgxyY", LibNet::NetBind);
|
||||||
|
LIB_FUNC("OXXX4mUk3uk", LibNet::NetConnect);
|
||||||
LIB_FUNC("dgJBaeJnGpo", LibNet::NetPoolCreate);
|
LIB_FUNC("dgJBaeJnGpo", LibNet::NetPoolCreate);
|
||||||
LIB_FUNC("K7RlrTkI-mw", LibNet::NetPoolDestroy);
|
LIB_FUNC("K7RlrTkI-mw", LibNet::NetPoolDestroy);
|
||||||
LIB_FUNC("C4UgDHHPvdw", LibNet::NetResolverCreate);
|
LIB_FUNC("C4UgDHHPvdw", LibNet::NetResolverCreate);
|
||||||
@@ -229,9 +250,12 @@ LIB_DEFINE(InitNet_1_Net) {
|
|||||||
LIB_FUNC("TSM6whtekok", LibNet::NetShutdown);
|
LIB_FUNC("TSM6whtekok", LibNet::NetShutdown);
|
||||||
LIB_FUNC("Q4qBuN-c0ZM", LibNet::NetSocket);
|
LIB_FUNC("Q4qBuN-c0ZM", LibNet::NetSocket);
|
||||||
LIB_FUNC("45ggEzakPJQ", LibNet::NetSocketClose);
|
LIB_FUNC("45ggEzakPJQ", LibNet::NetSocketClose);
|
||||||
|
LIB_FUNC("xphrZusl78E", LibNet::NetGetsockopt);
|
||||||
LIB_FUNC("2mKX2Spso7I", LibNet::NetSetsockopt);
|
LIB_FUNC("2mKX2Spso7I", LibNet::NetSetsockopt);
|
||||||
LIB_FUNC("beRjXBn-z+o", LibNet::NetSend);
|
LIB_FUNC("beRjXBn-z+o", LibNet::NetSend);
|
||||||
|
LIB_FUNC("gvD1greCu0A", LibNet::NetSendto);
|
||||||
LIB_FUNC("9wO9XrMsNhc", LibNet::NetRecv);
|
LIB_FUNC("9wO9XrMsNhc", LibNet::NetRecv);
|
||||||
|
LIB_FUNC("304ooNZxWDY", LibNet::NetRecvfrom);
|
||||||
LIB_FUNC("9T2pDF2Ryqg", LibNet::NetHtonl);
|
LIB_FUNC("9T2pDF2Ryqg", LibNet::NetHtonl);
|
||||||
LIB_FUNC("iWQWrwiSt8A", LibNet::NetHtons);
|
LIB_FUNC("iWQWrwiSt8A", LibNet::NetHtons);
|
||||||
LIB_FUNC("pQGpHYopAIY", LibNet::NetNtohl);
|
LIB_FUNC("pQGpHYopAIY", LibNet::NetNtohl);
|
||||||
|
|||||||
@@ -1061,19 +1061,36 @@ void CheckSocketWakeup() {
|
|||||||
namespace Net = Libs::Network::Net;
|
namespace Net = Libs::Network::Net;
|
||||||
Loader::SymbolDatabase symbols;
|
Loader::SymbolDatabase symbols;
|
||||||
Libs::LibNet::InitNet_1_Net(&symbols);
|
Libs::LibNet::InitNet_1_Net(&symbols);
|
||||||
|
const auto *connect_symbol = symbols.Find(
|
||||||
|
{"OXXX4mUk3uk", "Net", 1, "Net", 1, 1, Loader::SymbolType::Func});
|
||||||
|
const auto *getsockopt_symbol = symbols.Find(
|
||||||
|
{"xphrZusl78E", "Net", 1, "Net", 1, 1, Loader::SymbolType::Func});
|
||||||
const auto *send_symbol = symbols.Find(
|
const auto *send_symbol = symbols.Find(
|
||||||
{"beRjXBn-z+o", "Net", 1, "Net", 1, 1, Loader::SymbolType::Func});
|
{"beRjXBn-z+o", "Net", 1, "Net", 1, 1, Loader::SymbolType::Func});
|
||||||
|
const auto *sendto_symbol = symbols.Find(
|
||||||
|
{"gvD1greCu0A", "Net", 1, "Net", 1, 1, Loader::SymbolType::Func});
|
||||||
const auto *recv_symbol = symbols.Find(
|
const auto *recv_symbol = symbols.Find(
|
||||||
{"9wO9XrMsNhc", "Net", 1, "Net", 1, 1, Loader::SymbolType::Func});
|
{"9wO9XrMsNhc", "Net", 1, "Net", 1, 1, Loader::SymbolType::Func});
|
||||||
|
const auto *recvfrom_symbol = symbols.Find(
|
||||||
|
{"304ooNZxWDY", "Net", 1, "Net", 1, 1, Loader::SymbolType::Func});
|
||||||
const auto *errno_symbol = symbols.Find(
|
const auto *errno_symbol = symbols.Find(
|
||||||
{"HQOwnfMGipQ", "Net", 1, "Net", 1, 1, Loader::SymbolType::Func});
|
{"HQOwnfMGipQ", "Net", 1, "Net", 1, 1, Loader::SymbolType::Func});
|
||||||
Check(send_symbol && recv_symbol && errno_symbol,
|
Check(connect_symbol && getsockopt_symbol && send_symbol && sendto_symbol &&
|
||||||
"Net send, receive and errno exports resolve with the guest ABI versions");
|
recv_symbol && recvfrom_symbol && errno_symbol,
|
||||||
|
"Net socket and errno exports resolve with the guest ABI versions");
|
||||||
|
using Connect = int (KYTY_SYSV_ABI *)(int, const void *, uint32_t);
|
||||||
|
using Getsockopt = int (KYTY_SYSV_ABI *)(int, int, int, void *, uint32_t *);
|
||||||
using Send = int (KYTY_SYSV_ABI *)(int, const void *, size_t, int);
|
using Send = int (KYTY_SYSV_ABI *)(int, const void *, size_t, int);
|
||||||
|
using Sendto = int (KYTY_SYSV_ABI *)(int, const void *, size_t, int, const void *, uint32_t);
|
||||||
using Recv = int (KYTY_SYSV_ABI *)(int, void *, size_t, int);
|
using Recv = int (KYTY_SYSV_ABI *)(int, void *, size_t, int);
|
||||||
|
using Recvfrom = int (KYTY_SYSV_ABI *)(int, void *, size_t, int, void *, uint32_t *);
|
||||||
using Errno = int *(KYTY_SYSV_ABI *)();
|
using Errno = int *(KYTY_SYSV_ABI *)();
|
||||||
|
const auto net_connect = reinterpret_cast<Connect>(connect_symbol->vaddr);
|
||||||
|
const auto net_getsockopt = reinterpret_cast<Getsockopt>(getsockopt_symbol->vaddr);
|
||||||
const auto net_send = reinterpret_cast<Send>(send_symbol->vaddr);
|
const auto net_send = reinterpret_cast<Send>(send_symbol->vaddr);
|
||||||
|
const auto net_sendto = reinterpret_cast<Sendto>(sendto_symbol->vaddr);
|
||||||
const auto net_recv = reinterpret_cast<Recv>(recv_symbol->vaddr);
|
const auto net_recv = reinterpret_cast<Recv>(recv_symbol->vaddr);
|
||||||
|
const auto net_recvfrom = reinterpret_cast<Recvfrom>(recvfrom_symbol->vaddr);
|
||||||
auto *net_errno = reinterpret_cast<Errno>(errno_symbol->vaddr)();
|
auto *net_errno = reinterpret_cast<Errno>(errno_symbol->vaddr)();
|
||||||
const auto [reader, writer] = CreateTcpPair();
|
const auto [reader, writer] = CreateTcpPair();
|
||||||
const int enabled = 1;
|
const int enabled = 1;
|
||||||
@@ -1082,10 +1099,15 @@ void CheckSocketWakeup() {
|
|||||||
int socket_error = -1;
|
int socket_error = -1;
|
||||||
uint32_t error_size = sizeof(socket_error);
|
uint32_t error_size = sizeof(socket_error);
|
||||||
*Libs::Posix::GetErrorAddr() = Libs::Posix::POSIX_EINVAL;
|
*Libs::Posix::GetErrorAddr() = Libs::Posix::POSIX_EINVAL;
|
||||||
Check(Net::Getsockopt(writer, 0xffff, 0x1007, &socket_error, &error_size) == 0 &&
|
*net_errno = Libs::Posix::POSIX_EINVAL;
|
||||||
|
Check(net_getsockopt(writer, 0xffff, 0x1007, &socket_error, &error_size) == 0 &&
|
||||||
socket_error == 0 && error_size == sizeof(socket_error) &&
|
socket_error == 0 && error_size == sizeof(socket_error) &&
|
||||||
|
*net_errno == Libs::Posix::POSIX_EINVAL &&
|
||||||
*Libs::Posix::GetErrorAddr() == Libs::Posix::POSIX_EINVAL,
|
*Libs::Posix::GetErrorAddr() == Libs::Posix::POSIX_EINVAL,
|
||||||
"SO_ERROR reports socket status without changing guest errno");
|
"Net SO_ERROR reports socket status without changing either guest errno");
|
||||||
|
Check(net_getsockopt(writer, 0xffff, 0x1007, nullptr, &error_size) ==
|
||||||
|
Libs::Network::NET_ERROR_EFAULT && *net_errno == Libs::Posix::POSIX_EFAULT,
|
||||||
|
"Net getsockopt translates an invalid output buffer");
|
||||||
|
|
||||||
std::array<uint64_t, 16> readable {};
|
std::array<uint64_t, 16> readable {};
|
||||||
const auto bit = uint64_t {1} << (reader % 64);
|
const auto bit = uint64_t {1} << (reader % 64);
|
||||||
@@ -1122,6 +1144,51 @@ void CheckSocketWakeup() {
|
|||||||
*net_errno == Libs::Posix::POSIX_EWOULDBLOCK,
|
*net_errno == Libs::Posix::POSIX_EWOULDBLOCK,
|
||||||
"Net nonblocking receive translates POSIX failure and Net errno");
|
"Net nonblocking receive translates POSIX failure and Net errno");
|
||||||
#endif
|
#endif
|
||||||
|
const int datagram = Net::Socket(2, 2, 0);
|
||||||
|
const int datagram_writer = Net::Socket(2, 2, 0);
|
||||||
|
std::array<uint8_t, 16> address {16, 2, 0, 0, 127, 0, 0, 1};
|
||||||
|
std::array<uint8_t, 16> peer {}, expected_peer {};
|
||||||
|
uint32_t address_size = address.size(), peer_size = peer.size();
|
||||||
|
uint32_t expected_peer_size = expected_peer.size();
|
||||||
|
Check(datagram >= 0 && datagram_writer >= 0 &&
|
||||||
|
Net::Bind(datagram, address.data(), address.size()) == 0 &&
|
||||||
|
Net::Bind(datagram_writer, address.data(), address.size()) == 0 &&
|
||||||
|
Net::Getsockname(datagram, address.data(), &address_size) == 0 &&
|
||||||
|
Net::Getsockname(datagram_writer, expected_peer.data(), &expected_peer_size) == 0 &&
|
||||||
|
Net::Setsockopt(datagram, 0xffff, 0x1200, &enabled, sizeof(enabled)) == 0,
|
||||||
|
"create nonblocking loopback datagrams for Net ABI verification");
|
||||||
|
received.fill(0);
|
||||||
|
*net_errno = Libs::Posix::POSIX_EINVAL;
|
||||||
|
Check(net_sendto(datagram_writer, payload, sizeof(payload), 0,
|
||||||
|
address.data(), address_size) == sizeof(payload) &&
|
||||||
|
*net_errno == Libs::Posix::POSIX_EINVAL,
|
||||||
|
"Net sendto delivers to a guest sockaddr and preserves errno on success");
|
||||||
|
Check(net_recvfrom(datagram, received.data(), received.size(), 0,
|
||||||
|
peer.data(), &peer_size) == sizeof(payload) &&
|
||||||
|
std::memcmp(received.data(), payload, sizeof(payload)) == 0 &&
|
||||||
|
peer_size == expected_peer_size && peer == expected_peer &&
|
||||||
|
*net_errno == Libs::Posix::POSIX_EINVAL,
|
||||||
|
"Net recvfrom returns datagram bytes and sender address while preserving errno");
|
||||||
|
Check(net_recvfrom(datagram, received.data(), received.size(), 0, nullptr, nullptr) ==
|
||||||
|
Libs::Network::NET_ERROR_EWOULDBLOCK &&
|
||||||
|
*net_errno == Libs::Posix::POSIX_EWOULDBLOCK,
|
||||||
|
"Net recvfrom translates nonblocking failure with an omitted sender address");
|
||||||
|
*net_errno = Libs::Posix::POSIX_EINVAL;
|
||||||
|
Check(net_connect(datagram_writer, address.data(), address_size) == 0 &&
|
||||||
|
*net_errno == Libs::Posix::POSIX_EINVAL &&
|
||||||
|
net_sendto(datagram_writer, payload, sizeof(payload), 0, nullptr, 0) ==
|
||||||
|
sizeof(payload) && *net_errno == Libs::Posix::POSIX_EINVAL &&
|
||||||
|
net_recvfrom(datagram, received.data(), received.size(), 0, nullptr, nullptr) ==
|
||||||
|
sizeof(payload) && std::memcmp(received.data(), payload, sizeof(payload)) == 0,
|
||||||
|
"Net connect selects the peer used by sendto with an omitted destination");
|
||||||
|
Check(net_connect(-1, address.data(), address_size) == Libs::Network::NET_ERROR_EBADF &&
|
||||||
|
*net_errno == Libs::Posix::POSIX_EBADF,
|
||||||
|
"Net connect translates an invalid socket");
|
||||||
|
Check(net_sendto(-1, payload, sizeof(payload), 0, address.data(), address_size) ==
|
||||||
|
Libs::Network::NET_ERROR_EBADF && *net_errno == Libs::Posix::POSIX_EBADF,
|
||||||
|
"Net sendto translates an invalid socket");
|
||||||
|
Check(Net::SocketClose(datagram) == 0 && Net::SocketClose(datagram_writer) == 0,
|
||||||
|
"close Net loopback datagrams");
|
||||||
Check(net_send(-1, payload, sizeof(payload), 0) == Libs::Network::NET_ERROR_EBADF &&
|
Check(net_send(-1, payload, sizeof(payload), 0) == Libs::Network::NET_ERROR_EBADF &&
|
||||||
*net_errno == Libs::Posix::POSIX_EBADF,
|
*net_errno == Libs::Posix::POSIX_EBADF,
|
||||||
"Net send translates an invalid socket instead of returning POSIX minus one");
|
"Net send translates an invalid socket instead of returning POSIX minus one");
|
||||||
@@ -1138,10 +1205,12 @@ void CheckSocketWakeup() {
|
|||||||
const auto previous_sigpipe = std::signal(SIGPIPE, SIG_DFL);
|
const auto previous_sigpipe = std::signal(SIGPIPE, SIG_DFL);
|
||||||
Check(previous_sigpipe != SIG_ERR, "set default SIGPIPE disposition for Net send");
|
Check(previous_sigpipe != SIG_ERR, "set default SIGPIPE disposition for Net send");
|
||||||
const auto broken_send = net_send(disconnected, payload, sizeof(payload), 0);
|
const auto broken_send = net_send(disconnected, payload, sizeof(payload), 0);
|
||||||
|
const auto broken_sendto = net_sendto(disconnected, payload, sizeof(payload), 0, nullptr, 0);
|
||||||
std::signal(SIGPIPE, previous_sigpipe);
|
std::signal(SIGPIPE, previous_sigpipe);
|
||||||
Check(broken_send == Libs::Network::NET_ERROR_EPIPE &&
|
Check(broken_send == Libs::Network::NET_ERROR_EPIPE &&
|
||||||
|
broken_sendto == Libs::Network::NET_ERROR_EPIPE &&
|
||||||
*net_errno == Libs::Posix::POSIX_EPIPE,
|
*net_errno == Libs::Posix::POSIX_EPIPE,
|
||||||
"Net send reports a broken pipe without raising host SIGPIPE");
|
"Net send and sendto report a broken pipe without raising host SIGPIPE");
|
||||||
Check(Net::SocketClose(disconnected) == 0, "close unconnected socket");
|
Check(Net::SocketClose(disconnected) == 0, "close unconnected socket");
|
||||||
#endif
|
#endif
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
|||||||
Reference in New Issue
Block a user