Browse Source

coalesce the various sockopt

lizzie/refactor-networking-12
lizzie 1 month ago
parent
commit
a4c6d68410
  1. 43
      src/core/hle/service/sockets/bsd.cpp
  2. 154
      src/core/internal_network/network.cpp
  3. 96
      src/core/internal_network/socket_proxy.cpp
  4. 14
      src/core/internal_network/socket_proxy.h
  5. 2
      src/core/internal_network/socket_types.h
  6. 37
      src/core/internal_network/sockets.h

43
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<Network::Linger>(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<u32>(optval);
return socket->SetTimeStamp(value);
}
ASSERT(optval.size() == sizeof(u32));
auto value = GetValue<u32>(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) {

154
src/core/internal_network/network.cpp

@ -943,17 +943,76 @@ std::pair<T, Errno> Socket::GetSockOpt(SOCKET fd_so, int option) {
return {value, GetAndLogLastError()};
}
template <typename T>
Errno Socket::SetSockOpt(SOCKET fd_so, int option, T value) {
const int result =
setsockopt(fd_so, SOL_SOCKET, option, reinterpret_cast<const char*>(&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<const u8> 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<const char*>(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<const char*>(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<Errno, Errno> 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<u32>(fd, SO_REUSEADDR, enable ? 1 : 0);
}
Errno Socket::SetKeepAlive(bool enable) {
return SetSockOpt<u32>(fd, SO_KEEPALIVE, enable ? 1 : 0);
}
Errno Socket::SetBroadcast(bool enable) {
return SetSockOpt<u32>(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;
}

96
src/core/internal_network/socket_proxy.cpp

@ -47,16 +47,29 @@ void ProxySocket::HandleProxyPacket(const ProxyPacket& packet) {
received_packets.push(decompressed);
}
template <typename T>
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<const u8> 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<u32>(fd, SO_REUSEADDR, enable ? 1 : 0);
}
Errno ProxySocket::SetBroadcast(bool enable) {
broadcast = enable;
return SetSockOpt<u32>(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<int>(value));
}
Errno ProxySocket::SetRcvTimeo(u32 value) {
receive_timeout = value;
return SetSockOpt(fd, SO_RCVTIMEO, static_cast<int>(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<Errno, Errno> ProxySocket::GetPendingError() {
LOG_DEBUG(Network, "(STUBBED) called");
return {Errno::SUCCESS, Errno::SUCCESS};

14
src/core/internal_network/socket_proxy.h

@ -55,21 +55,9 @@ public:
std::pair<s32, Errno> SendTo(u32 flags, std::span<const u8> 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 <typename T>
Errno SetSockOpt(SOCKET fd, int option, T value);
Errno SetSockOpt(SOCKET fd, Network::OptName option, std::span<const u8> value) override;
std::pair<Errno, Errno> GetPendingError() override;

2
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,

37
src/core/internal_network/sockets.h

@ -64,22 +64,12 @@ public:
virtual std::pair<s32, Errno> Send(std::span<const u8> message, int flags) = 0;
virtual std::pair<s32, Errno> SendTo(u32 flags, std::span<const u8> 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<s32, Errno> SendTo(u32 flags, std::span<const u8> message, const Network::SockAddrIn* addr) = 0;
virtual Errno SetNonBlock(bool enable) = 0;
virtual Errno SetSockOpt(SOCKET fd, Network::OptName option, std::span<const u8> value) = 0;
virtual std::pair<Errno, Errno> GetPendingError() = 0;
virtual bool IsOpened() const = 0;
@ -126,24 +116,11 @@ public:
std::pair<s32, Errno> Send(std::span<const u8> message, int flags) override;
std::pair<s32, Errno> SendTo(u32 flags, std::span<const u8> 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<s32, Errno> SendTo(u32 flags, std::span<const u8> message, const Network::SockAddrIn* addr) override;
Errno SetNonBlock(bool enable) override;
template <typename T>
Errno SetSockOpt(SOCKET fd, int option, T value);
Errno SetSockOpt(SOCKET fd, Network::OptName option, std::span<const u8> value) override;
std::pair<Errno, Errno> GetPendingError() override;

Loading…
Cancel
Save