network: implement POSIX socket shutdown on Linux

This commit is contained in:
nmzik
2026-10-17 10:10:16 +02:00
parent 5bf37f52ad
commit 3ecc6b7d1b
3 changed files with 37 additions and 7 deletions
+6
View File
@@ -2006,6 +2006,11 @@ int KYTY_SYSV_ABI listen(int s, int backlog) {
return Network::Net::Listen(s, backlog);
}
int KYTY_SYSV_ABI shutdown(int s, int how) {
PRINT_NAME();
return Network::Net::Shutdown(s, how);
}
int KYTY_SYSV_ABI accept(int s, void* addr, uint32_t* addrlen) {
PRINT_NAME();
return Network::Net::Accept(s, addr, addrlen);
@@ -2242,6 +2247,7 @@ LIB_DEFINE(InitLibKernel_1_Posix) {
LIB_FUNC("KuOmgKoqCdY", Posix::bind);
LIB_FUNC("XVL8So3QJUk", Posix::connect);
LIB_FUNC("pxnCmagrtao", Posix::listen);
LIB_FUNC("TUuiYS2kE8s", Posix::shutdown);
LIB_FUNC("3e+4Iv7IJ8U", Posix::accept);
LIB_FUNC("RenI1lL1WFk", Posix::getsockname);
LIB_FUNC("6O8EwYOgH9Y", Posix::getsockopt);
+3 -7
View File
@@ -2096,19 +2096,15 @@ int KYTY_SYSV_ABI Shutdown(int s, int how) {
return -1;
}
#if defined(_WIN32)
if (::shutdown(socket, how) == SOCKET_ERROR) {
if (::shutdown(socket, how) != 0) {
return SetHostSocketError();
}
#if defined(_WIN32)
if (how == SD_RECEIVE || how == SD_BOTH) {
transport->receive_shutdown.store(true, std::memory_order_relaxed);
}
return 0;
#else
*Posix::GetErrorAddr() = Posix::POSIX_ENOSYS;
return -1;
#endif
return 0;
}
int KYTY_SYSV_ABI Getsockname(int s, void* addr, uint32_t* addrlen) {
+28
View File
@@ -1905,6 +1905,11 @@ void CheckSocketWakeup() {
namespace Net = Libs::Network::Net;
Loader::SymbolDatabase symbols;
Libs::LibNet::InitNet_1_Net(&symbols);
Libs::InitLibKernel_1(&symbols);
const auto *shutdown_symbol = symbols.Find(
{"TUuiYS2kE8s", "Posix", 1, "libkernel", 1, 1, Loader::SymbolType::Func});
Check(shutdown_symbol != nullptr, "POSIX shutdown export resolves");
const auto shutdown = reinterpret_cast<int (KYTY_SYSV_ABI *)(int, int)>(shutdown_symbol->vaddr);
const auto *connect_symbol = symbols.Find(
{"OXXX4mUk3uk", "Net", 1, "Net", 1, 1, Loader::SymbolType::Func});
const auto *getsockopt_symbol = symbols.Find(
@@ -2145,6 +2150,29 @@ void CheckSocketWakeup() {
CheckSocketReceiveBuffer(reader, writer);
CheckSocketReceiveConcurrency();
#endif
const auto [shutdown_reader, shutdown_writer] = CreateTcpPair();
const auto ready_to_read = [](int fd) {
std::array<uint64_t, 16> readable {};
readable[fd / 64] = uint64_t {1} << (fd % 64);
const std::array<int64_t, 2> timeout {2, 0};
return Net::Select(fd + 1, readable.data(), nullptr, nullptr, timeout.data()) == 1;
};
Check(shutdown(-1, 1) == -1 &&
*Libs::Posix::GetErrorAddr() == Libs::Posix::POSIX_EBADF &&
shutdown(shutdown_writer, 3) == -1 &&
*Libs::Posix::GetErrorAddr() == Libs::Posix::POSIX_EINVAL,
"shutdown rejects invalid descriptors and directions");
Check(Net::Send(shutdown_writer, "x", 1, 0) == 1 && shutdown(shutdown_writer, 1) == 0 &&
ready_to_read(shutdown_reader) &&
Net::Recv(shutdown_reader, received.data(), 1, 0) == 1 && received[0] == 'x' &&
ready_to_read(shutdown_reader) &&
Net::Recv(shutdown_reader, received.data(), 1, 0) == 0 &&
Net::Send(shutdown_reader, "y", 1, 0) == 1 &&
ready_to_read(shutdown_writer) &&
Net::Recv(shutdown_writer, received.data(), 1, 0) == 1 && received[0] == 'y',
"write shutdown drains queued bytes, signals EOF, and preserves reverse traffic");
Check(Net::SocketClose(shutdown_reader) == 0 && Net::SocketClose(shutdown_writer) == 0,
"close half-shutdown sockets");
Check(Net::SocketClose(writer) == 0, "close wake writer");
*net_errno = Libs::Posix::POSIX_EINVAL;
Check(net_recv(reader, received.data(), received.size(), 0) == 0 &&