From a4c6d68410b58b1cddf2960b0c6c9115dccb872a Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 1 Jul 2026 20:42:24 +0000 Subject: [PATCH] coalesce the various sockopt --- src/core/hle/service/sockets/bsd.cpp | 43 +----- src/core/internal_network/network.cpp | 154 ++++++++++----------- src/core/internal_network/socket_proxy.cpp | 96 +++---------- src/core/internal_network/socket_proxy.h | 14 +- src/core/internal_network/socket_types.h | 2 + src/core/internal_network/sockets.h | 37 +---- 6 files changed, 102 insertions(+), 244 deletions(-) diff --git a/src/core/hle/service/sockets/bsd.cpp b/src/core/hle/service/sockets/bsd.cpp index 9b582fa5e5..1d10482098 100644 --- a/src/core/hle/service/sockets/bsd.cpp +++ b/src/core/hle/service/sockets/bsd.cpp @@ -790,49 +790,8 @@ Network::Errno BSD::SetSockOptImpl(s32 fd, u32 level, Network::OptName optname, } Network::SocketBase* const socket = file_descriptors[fd]->socket.get(); - - if (optname == Network::OptName::LINGER) { - ASSERT(optval.size() == sizeof(Network::Linger)); - auto linger = GetValue(optval); - ASSERT(linger.onoff == 0 || linger.onoff == 1); - return (socket->SetLinger(linger.onoff != 0, linger.linger)); - } else if (optname == Network::OptName::TIMESTAMP) { - ASSERT(optval.size() == 4); - auto value = GetValue(optval); - return socket->SetTimeStamp(value); - } - ASSERT(optval.size() == sizeof(u32)); - auto value = GetValue(optval); - switch (optname) { - case Network::OptName::REUSEADDR: - ASSERT(value == 0 || value == 1); - return (socket->SetReuseAddr(value != 0)); - case Network::OptName::KEEPALIVE: - ASSERT(value == 0 || value == 1); - return (socket->SetKeepAlive(value != 0)); - case Network::OptName::BROADCAST: - ASSERT(value == 0 || value == 1); - return (socket->SetBroadcast(value != 0)); - case Network::OptName::SNDBUF: - return socket->SetSndBuf(value); - case Network::OptName::RCVBUF: - return socket->SetRcvBuf(value); - case Network::OptName::SNDTIMEO: - return socket->SetSndTimeo(value); - case Network::OptName::RCVTIMEO: - return socket->SetRcvTimeo(value); - case Network::OptName::NOSIGPIPE: - LOG_WARNING(Service, "(STUBBED) setting NOSIGPIPE to {}", value); - return Network::Errno::SUCCESS; - case Network::OptName::REUSEPORT: - return socket->SetReusePort(value); - case Network::OptName::ACCEPTFILTER: - return socket->SetAcceptFilter(value); - default: - UNIMPLEMENTED_MSG("Unimplemented optname={}", optname); - return Network::Errno::SUCCESS; - } + return socket->SetSockOpt(fd, optname, optval); } Network::Errno BSD::ShutdownImpl(s32 fd, s32 how) { diff --git a/src/core/internal_network/network.cpp b/src/core/internal_network/network.cpp index 2b8620b82d..bb11ed5a2d 100644 --- a/src/core/internal_network/network.cpp +++ b/src/core/internal_network/network.cpp @@ -943,17 +943,76 @@ std::pair Socket::GetSockOpt(SOCKET fd_so, int option) { return {value, GetAndLogLastError()}; } -template -Errno Socket::SetSockOpt(SOCKET fd_so, int option, T value) { - const int result = - setsockopt(fd_so, SOL_SOCKET, option, reinterpret_cast(&value), sizeof(value)); - if (result != SOCKET_ERROR) { +static s32 TranslateOptNameToNative(Network::OptName optname) { + switch (optname) { + case Network::OptName::LINGER: + return SO_LINGER; + case Network::OptName::REUSEADDR: + return SO_REUSEADDR; + case Network::OptName::KEEPALIVE: + return SO_KEEPALIVE; + case Network::OptName::BROADCAST: + return SO_BROADCAST; + case Network::OptName::SNDBUF: + return SO_SNDBUF; + case Network::OptName::RCVBUF: + return SO_RCVBUF; + case Network::OptName::SNDTIMEO: + return SO_SNDTIMEO; + case Network::OptName::RCVTIMEO: + return SO_RCVTIMEO; + case Network::OptName::NOSIGPIPE: + return SO_NOSIGPIPE; +#ifdef SO_REUSEPORT + case Network::OptName::REUSEPORT: + return SO_REUSEPORT; +#endif +#ifdef SO_ACCEPTFILTER + case Network::OptName::ACCEPTFILTER: + return SO_ACCEPTFILTER; +#endif +#ifdef SO_TIMESTAMP + case Network::OptName::TIMESTAMP: + return SO_TIMESTAMP; +#endif + default: + UNIMPLEMENTED_MSG("Unimplemented optname={}", optname); + return 0; + } +} + + +Errno Socket::SetNonBlock(bool enable) { + if (EnableNonBlock(fd, enable)) { + is_non_blocking = enable; return Errno::SUCCESS; } return GetAndLogLastError(); } +Errno Socket::SetSockOpt(SOCKET fd_so, Network::OptName optname, std::span optval) { + // TODO: is it >= or ==? for sizes + if (optname == Network::OptName::LINGER) { + if (optval.size() >= sizeof(Network::Linger)) { + Network::Linger linger{}; + std::memcpy(&linger, optval.data(), sizeof(linger)); + auto const linkger_optval = MakeLinger(bool(linger.onoff), linger.linger); + return setsockopt(fd_so, SOL_SOCKET, TranslateOptNameToNative(optname), reinterpret_cast(linkger_optval.data()), socklen_t(linkger_optval.size())) != SOCKET_ERROR + ? Errno::SUCCESS + : GetAndLogLastError(); + } + return Errno::INVAL; + } + return setsockopt(fd_so, SOL_SOCKET, TranslateOptNameToNative(optname), reinterpret_cast(optval.data()), socklen_t(optval.size())) != SOCKET_ERROR + ? Errno::SUCCESS + : GetAndLogLastError(); +} + Errno Socket::Initialize(Domain domain, Type type, Protocol protocol) { + if (type == Type::STREAM && protocol == Protocol::UDP) { + LOG_WARNING(Network, "UDP used with STREAM"); + type = Type::DGRAM; + } fd = socket(TranslateDomainToNative(domain), TranslateTypeToNative(type), TranslateProtocolToNative(protocol)); if (fd != INVALID_SOCKET) return Errno::SUCCESS; @@ -1070,31 +1129,31 @@ Errno Socket::Shutdown(ShutdownHow how) { static s32 TranslateMsgOptToNative(s32 flags) { s32 r = 0; #ifdef MSG_OOB - if (flags & s32(MsgOpt::OOB)) r |= MSG_OOB; + if (0 != (flags & s32(MsgOpt::OOB))) r |= MSG_OOB; #endif #ifdef MSG_PEEK - if (flags & s32(MsgOpt::PEEK)) r |= MSG_PEEK; + if (0 != (flags & s32(MsgOpt::PEEK))) r |= MSG_PEEK; #endif #ifdef MSG_DONTROUTE - if (flags & s32(MsgOpt::DONTROUTE)) r |= MSG_DONTROUTE; + if (0 != (flags & s32(MsgOpt::DONTROUTE))) r |= MSG_DONTROUTE; #endif #ifdef MSG_EOR - if (flags & s32(MsgOpt::EOR_)) r |= MSG_EOR; + if (0 != (flags & s32(MsgOpt::EOR_))) r |= MSG_EOR; #endif #ifdef MSG_TRUNC - if (flags & s32(MsgOpt::TRUNC)) r |= MSG_TRUNC; + if (0 != (flags & s32(MsgOpt::TRUNC))) r |= MSG_TRUNC; #endif #ifdef MSG_CTRUNC - if (flags & s32(MsgOpt::CTRUNC)) r |= MSG_CTRUNC; + if (0 != (flags & s32(MsgOpt::CTRUNC))) r |= MSG_CTRUNC; #endif #ifdef MSG_WAITALL - if (flags & s32(MsgOpt::WAITALL)) r |= MSG_WAITALL; + if (0 != (flags & s32(MsgOpt::WAITALL))) r |= MSG_WAITALL; #endif #ifdef MSG_DONTWAIT - if (flags & s32(MsgOpt::DONTWAIT)) r |= MSG_DONTWAIT; + if (0 != (flags & s32(MsgOpt::DONTWAIT))) r |= MSG_DONTWAIT; #endif #ifdef MSG_EOF - if (flags & s32(MsgOpt::EOF_)) r |= MSG_EOF; + if (0 != (flags & s32(MsgOpt::EOF_))) r |= MSG_EOF; #endif return r; } @@ -1185,73 +1244,6 @@ std::pair Socket::GetPendingError() { return {TranslateNativeError(pending_err), getsockopt_err}; } -Errno Socket::SetLinger(bool enable, u32 linger) { - return SetSockOpt(fd, SO_LINGER, MakeLinger(enable, linger)); -} - -Errno Socket::SetReuseAddr(bool enable) { - return SetSockOpt(fd, SO_REUSEADDR, enable ? 1 : 0); -} - -Errno Socket::SetKeepAlive(bool enable) { - return SetSockOpt(fd, SO_KEEPALIVE, enable ? 1 : 0); -} - -Errno Socket::SetBroadcast(bool enable) { - return SetSockOpt(fd, SO_BROADCAST, enable ? 1 : 0); -} - -Errno Socket::SetSndBuf(u32 value) { - return SetSockOpt(fd, SO_SNDBUF, value); -} - -Errno Socket::SetRcvBuf(u32 value) { - return SetSockOpt(fd, SO_RCVBUF, value); -} - -Errno Socket::SetSndTimeo(u32 value) { - return SetSockOpt(fd, SO_SNDTIMEO, value); -} - -Errno Socket::SetRcvTimeo(u32 value) { - return SetSockOpt(fd, SO_RCVTIMEO, value); -} - -Errno Socket::SetReusePort(u32 value) { -#ifdef SO_REUSEPORT - return SetSockOpt(fd, SO_REUSEPORT, value); -#else - LOG_WARNING(Network, "(stubbed)"); - return Errno::SUCCESS; -#endif -} - -Errno Socket::SetTimeStamp(u32 value) { -#ifdef SO_TIMESTAMP - return SetSockOpt(fd, SO_TIMESTAMP, value); -#else - LOG_WARNING(Network, "(stubbed)"); - return Errno::SUCCESS; -#endif -} - -Errno Socket::SetAcceptFilter(u32 value) { -#ifdef SO_ACCEPTFILTER - return SetSockOpt(fd, SO_ACCEPTFILTER, value); -#else - LOG_WARNING(Network, "(stubbed)"); - return Errno::SUCCESS; -#endif -} - -Errno Socket::SetNonBlock(bool enable) { - if (EnableNonBlock(fd, enable)) { - is_non_blocking = enable; - return Errno::SUCCESS; - } - return GetAndLogLastError(); -} - bool Socket::IsOpened() const { return fd != INVALID_SOCKET; } diff --git a/src/core/internal_network/socket_proxy.cpp b/src/core/internal_network/socket_proxy.cpp index c5aeb2e99b..376148d28d 100644 --- a/src/core/internal_network/socket_proxy.cpp +++ b/src/core/internal_network/socket_proxy.cpp @@ -47,16 +47,29 @@ void ProxySocket::HandleProxyPacket(const ProxyPacket& packet) { received_packets.push(decompressed); } -template -Errno ProxySocket::SetSockOpt(SOCKET fd_, int option, T value) { - LOG_DEBUG(Network, "(STUBBED) called"); +Errno ProxySocket::SetNonBlock(bool enable) { + blocking = !enable; + return Errno::SUCCESS; +} + +Errno ProxySocket::SetSockOpt(SOCKET fd_, Network::OptName option, std::span optval) { + LOG_DEBUG(Network, "(stubbed) called"); + // numeric values? + if (optval.size() >= sizeof(u32)) { + u32 value; + std::memcpy(&value, optval.data(), sizeof(value)); + if (option == Network::OptName::BROADCAST) + broadcast = bool(value); + if (option == Network::OptName::SNDTIMEO) + send_timeout = value; + if (option == Network::OptName::RCVTIMEO) + receive_timeout = value; + } return Errno::SUCCESS; } Errno ProxySocket::Initialize(Domain domain, Type type, Protocol socket_protocol) { protocol = socket_protocol; - SetSockOpt(fd, SO_TYPE, type); - return Errno::SUCCESS; } @@ -246,79 +259,6 @@ Errno ProxySocket::Close() { return Errno::SUCCESS; } -Errno ProxySocket::SetLinger(bool enable, u32 linger) { - struct { - u16 linger_enable; - u16 linger_time; - } values; - values.linger_enable = enable ? 1 : 0; - values.linger_time = u16(linger); - return SetSockOpt(fd, SO_LINGER, values); -} - -Errno ProxySocket::SetReuseAddr(bool enable) { - return SetSockOpt(fd, SO_REUSEADDR, enable ? 1 : 0); -} - -Errno ProxySocket::SetBroadcast(bool enable) { - broadcast = enable; - return SetSockOpt(fd, SO_BROADCAST, enable ? 1 : 0); -} - -Errno ProxySocket::SetSndBuf(u32 value) { - return SetSockOpt(fd, SO_SNDBUF, value); -} - -Errno ProxySocket::SetKeepAlive(bool enable) { - return Errno::SUCCESS; -} - -Errno ProxySocket::SetRcvBuf(u32 value) { - return SetSockOpt(fd, SO_RCVBUF, value); -} - -Errno ProxySocket::SetSndTimeo(u32 value) { - send_timeout = value; - return SetSockOpt(fd, SO_SNDTIMEO, static_cast(value)); -} - -Errno ProxySocket::SetRcvTimeo(u32 value) { - receive_timeout = value; - return SetSockOpt(fd, SO_RCVTIMEO, static_cast(value)); -} - -Errno ProxySocket::SetReusePort(u32 value) { -#ifdef SO_REUSEPORT - return SetSockOpt(fd, SO_REUSEPORT, value); -#else - LOG_WARNING(Network, "(stubbed)"); - return Errno::SUCCESS; -#endif -} - -Errno ProxySocket::SetTimeStamp(u32 value) { -#ifdef SO_TIMESTAMP - return SetSockOpt(fd, SO_TIMESTAMP, value); -#else - LOG_WARNING(Network, "(stubbed)"); - return Errno::SUCCESS; -#endif -} - -Errno ProxySocket::SetAcceptFilter(u32 value) { -#ifdef SO_ACCEPTFILTER - return SetSockOpt(fd, SO_ACCEPTFILTER, value); -#else - LOG_WARNING(Network, "(stubbed)"); - return Errno::SUCCESS; -#endif -} - -Errno ProxySocket::SetNonBlock(bool enable) { - blocking = !enable; - return Errno::SUCCESS; -} - std::pair ProxySocket::GetPendingError() { LOG_DEBUG(Network, "(STUBBED) called"); return {Errno::SUCCESS, Errno::SUCCESS}; diff --git a/src/core/internal_network/socket_proxy.h b/src/core/internal_network/socket_proxy.h index 9b7c3fb4c9..9f00e1ad0e 100644 --- a/src/core/internal_network/socket_proxy.h +++ b/src/core/internal_network/socket_proxy.h @@ -55,21 +55,9 @@ public: std::pair SendTo(u32 flags, std::span message, const Network::SockAddrIn* addr) override; - Errno SetLinger(bool enable, u32 linger) override; - Errno SetReuseAddr(bool enable) override; - Errno SetBroadcast(bool enable) override; - Errno SetKeepAlive(bool enable) override; - Errno SetSndBuf(u32 value) override; - Errno SetRcvBuf(u32 value) override; - Errno SetSndTimeo(u32 value) override; - Errno SetRcvTimeo(u32 value) override; - Errno SetReusePort(u32 value) override; - Errno SetTimeStamp(u32 value) override; - Errno SetAcceptFilter(u32 value) override; Errno SetNonBlock(bool enable) override; - template - Errno SetSockOpt(SOCKET fd, int option, T value); + Errno SetSockOpt(SOCKET fd, Network::OptName option, std::span value) override; std::pair GetPendingError() override; diff --git a/src/core/internal_network/socket_types.h b/src/core/internal_network/socket_types.h index 1fbb2e4678..a973f48761 100644 --- a/src/core/internal_network/socket_types.h +++ b/src/core/internal_network/socket_types.h @@ -252,6 +252,8 @@ enum class MsgOpt : u32 { }; enum class OptName : u32 { + DEBUG = 0x0001, + ACCEPTCONN = 0x0002, REUSEADDR = 0x0004, KEEPALIVE = 0x0008, DONTROUTE = 0x0010, diff --git a/src/core/internal_network/sockets.h b/src/core/internal_network/sockets.h index 3aa9c29970..90c6f4947d 100644 --- a/src/core/internal_network/sockets.h +++ b/src/core/internal_network/sockets.h @@ -64,22 +64,12 @@ public: virtual std::pair Send(std::span message, int flags) = 0; - virtual std::pair SendTo(u32 flags, std::span message, - const Network::SockAddrIn* addr) = 0; - - virtual Errno SetLinger(bool enable, u32 linger) = 0; - virtual Errno SetReuseAddr(bool enable) = 0; - virtual Errno SetKeepAlive(bool enable) = 0; - virtual Errno SetBroadcast(bool enable) = 0; - virtual Errno SetSndBuf(u32 value) = 0; - virtual Errno SetRcvBuf(u32 value) = 0; - virtual Errno SetSndTimeo(u32 value) = 0; - virtual Errno SetRcvTimeo(u32 value) = 0; - virtual Errno SetReusePort(u32 value) = 0; - virtual Errno SetTimeStamp(u32 value) = 0; - virtual Errno SetAcceptFilter(u32 value) = 0; + virtual std::pair SendTo(u32 flags, std::span message, const Network::SockAddrIn* addr) = 0; + virtual Errno SetNonBlock(bool enable) = 0; + virtual Errno SetSockOpt(SOCKET fd, Network::OptName option, std::span value) = 0; + virtual std::pair GetPendingError() = 0; virtual bool IsOpened() const = 0; @@ -126,24 +116,11 @@ public: std::pair Send(std::span message, int flags) override; - std::pair SendTo(u32 flags, std::span message, - const Network::SockAddrIn* addr) override; - - Errno SetLinger(bool enable, u32 linger) override; - Errno SetReuseAddr(bool enable) override; - Errno SetKeepAlive(bool enable) override; - Errno SetBroadcast(bool enable) override; - Errno SetSndBuf(u32 value) override; - Errno SetRcvBuf(u32 value) override; - Errno SetSndTimeo(u32 value) override; - Errno SetRcvTimeo(u32 value) override; - Errno SetReusePort(u32 value) override; - Errno SetTimeStamp(u32 value) override; - Errno SetAcceptFilter(u32 value) override; + std::pair SendTo(u32 flags, std::span message, const Network::SockAddrIn* addr) override; + Errno SetNonBlock(bool enable) override; - template - Errno SetSockOpt(SOCKET fd, int option, T value); + Errno SetSockOpt(SOCKET fd, Network::OptName option, std::span value) override; std::pair GetPendingError() override;