mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-08-15 21:19:47 +00:00
allow configure socket level
This commit is contained in:
@@ -274,14 +274,12 @@ void BSD::GetSockName(HLERequestContext& ctx) {
|
||||
void BSD::GetSockOpt(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const s32 fd = rp.Pop<s32>();
|
||||
const u32 level = rp.Pop<u32>();
|
||||
const auto optname = static_cast<Network::OptName>(rp.Pop<u32>());
|
||||
const auto level = Network::SocketLevel(rp.Pop<u32>());
|
||||
const auto optname = Network::OptName(rp.Pop<u32>());
|
||||
|
||||
std::vector<u8> optval(ctx.GetWriteBufferSize());
|
||||
|
||||
LOG_DEBUG(Service, "called. fd={} level={} optname={:#x} len={:#x}", fd, level, optname,
|
||||
optval.size());
|
||||
|
||||
LOG_DEBUG(Service, "called. fd={} level={} optname={:#x} len={:#x}", fd, level, optname, optval.size());
|
||||
const Network::Errno err = GetSockOptImpl(fd, level, optname, optval);
|
||||
|
||||
ctx.WriteBuffer(optval);
|
||||
@@ -323,7 +321,7 @@ void BSD::SetSockOpt(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
|
||||
const s32 fd = rp.Pop<s32>();
|
||||
const u32 level = rp.Pop<u32>();
|
||||
const Network::SocketLevel level = Network::SocketLevel(rp.Pop<u32>());
|
||||
const Network::OptName optname = Network::OptName(rp.Pop<u32>());
|
||||
const auto optval = ctx.ReadBuffer();
|
||||
|
||||
@@ -526,7 +524,7 @@ std::pair<s32, Network::Errno> BSD::SocketImpl(Network::Domain domain, Network::
|
||||
file_descriptors[fd].reset();
|
||||
return {-1, Network::Errno::NOTCONN};
|
||||
}
|
||||
if (descriptor.socket->fd < 0) {
|
||||
if (descriptor.socket->fd == Network::Socket::INVALID_SOCKET) {
|
||||
file_descriptors[fd].reset();
|
||||
return {-1, bsd_errno};
|
||||
}
|
||||
@@ -741,7 +739,7 @@ std::pair<s32, Network::Errno> BSD::FcntlImpl(s32 fd, Network::FcntlCmd cmd, s32
|
||||
}
|
||||
}
|
||||
|
||||
Network::Errno BSD::GetSockOptImpl(s32 fd, u32 level, Network::OptName optname, std::vector<u8>& optval) {
|
||||
Network::Errno BSD::GetSockOptImpl(s32 fd, Network::SocketLevel level, Network::OptName optname, std::vector<u8>& optval) {
|
||||
if (!IsFileDescriptorValid(fd)) {
|
||||
return Network::Errno::BADF;
|
||||
}
|
||||
@@ -750,9 +748,8 @@ Network::Errno BSD::GetSockOptImpl(s32 fd, u32 level, Network::OptName optname,
|
||||
return Network::Errno::BADF;
|
||||
}
|
||||
|
||||
if (level != static_cast<u32>(Network::SocketLevel::SOCKET)) {
|
||||
UNIMPLEMENTED_MSG("Unknown getsockopt level");
|
||||
return Network::Errno::SUCCESS;
|
||||
if (level != Network::SocketLevel::SOCKET) {
|
||||
LOG_WARNING(Service, "(stubbed) level fd={}, level={}, optname={}", fd, level, optname);
|
||||
}
|
||||
|
||||
Network::SocketBase* const socket = file_descriptors[fd]->socket.get();
|
||||
@@ -775,7 +772,8 @@ Network::Errno BSD::GetSockOptImpl(s32 fd, u32 level, Network::OptName optname,
|
||||
}
|
||||
}
|
||||
|
||||
Network::Errno BSD::SetSockOptImpl(s32 fd, u32 level, Network::OptName optname, std::span<const u8> optval) {
|
||||
Network::Errno BSD::SetSockOptImpl(s32 fd, Network::SocketLevel level, Network::OptName optname, std::span<const u8> optval) {
|
||||
LOG_DEBUG(Service, "fd={},level={},optname={}", fd, level, optname);
|
||||
if (!IsFileDescriptorValid(fd)) {
|
||||
return Network::Errno::BADF;
|
||||
}
|
||||
@@ -784,14 +782,11 @@ Network::Errno BSD::SetSockOptImpl(s32 fd, u32 level, Network::OptName optname,
|
||||
return Network::Errno::BADF;
|
||||
}
|
||||
|
||||
if (level != u32(Network::SocketLevel::SOCKET)) {
|
||||
LOG_WARNING(Service, "(STUBBED) setsockopt with level={}, optname={}", level, optname);
|
||||
return Network::Errno::SUCCESS;
|
||||
}
|
||||
|
||||
Network::SocketBase* const socket = file_descriptors[fd]->socket.get();
|
||||
ASSERT(optval.size() == sizeof(u32));
|
||||
return socket->SetSockOpt(fd, optname, optval);
|
||||
if (level != Network::SocketLevel::SOCKET) {
|
||||
LOG_WARNING(Service, "(stubbed) level fd={}, level={}, optname={}", fd, level, optname);
|
||||
}
|
||||
return socket->SetSockOpt(fd, level, optname, optval);
|
||||
}
|
||||
|
||||
Network::Errno BSD::ShutdownImpl(s32 fd, s32 how) {
|
||||
|
||||
@@ -164,8 +164,8 @@ private:
|
||||
Network::Errno GetSockNameImpl(s32 fd, std::vector<u8>& write_buffer);
|
||||
Network::Errno ListenImpl(s32 fd, s32 backlog);
|
||||
std::pair<s32, Network::Errno> FcntlImpl(s32 fd, Network::FcntlCmd cmd, s32 arg);
|
||||
Network::Errno GetSockOptImpl(s32 fd, u32 level, Network::OptName optname, std::vector<u8>& optval);
|
||||
Network::Errno SetSockOptImpl(s32 fd, u32 level, Network::OptName optname, std::span<const u8> optval);
|
||||
Network::Errno GetSockOptImpl(s32 fd, Network::SocketLevel level, Network::OptName optname, std::vector<u8>& optval);
|
||||
Network::Errno SetSockOptImpl(s32 fd, Network::SocketLevel level, Network::OptName optname, std::span<const u8> optval);
|
||||
Network::Errno ShutdownImpl(s32 fd, s32 how);
|
||||
std::pair<s32, Network::Errno> RecvImpl(s32 fd, u32 flags, std::vector<u8>& message);
|
||||
std::pair<s32, Network::Errno> RecvFromImpl(s32 fd, u32 flags, std::vector<u8>& message,
|
||||
|
||||
@@ -129,48 +129,30 @@ Errno TranslateNativeError(int e, CallType call_type = CallType::Other) {
|
||||
} else {
|
||||
return Errno::CONNABORTED;
|
||||
}
|
||||
case WSAEBADF:
|
||||
return Errno::BADF;
|
||||
case WSAEINVAL:
|
||||
return Errno::INVAL;
|
||||
case WSAEMFILE:
|
||||
return Errno::MFILE;
|
||||
case WSAENOTCONN:
|
||||
return Errno::NOTCONN;
|
||||
case WSAEWOULDBLOCK:
|
||||
return Errno::AGAIN;
|
||||
case WSAECONNREFUSED:
|
||||
return Errno::CONNREFUSED;
|
||||
case WSAECONNRESET:
|
||||
return Errno::CONNRESET;
|
||||
case WSAEHOSTUNREACH:
|
||||
return Errno::HOSTUNREACH;
|
||||
case WSAENETDOWN:
|
||||
return Errno::NETDOWN;
|
||||
case WSAENETUNREACH:
|
||||
return Errno::NETUNREACH;
|
||||
case WSAEMSGSIZE:
|
||||
return Errno::MSGSIZE;
|
||||
case WSAETIMEDOUT:
|
||||
return Errno::TIMEDOUT;
|
||||
case WSAEINPROGRESS:
|
||||
return Errno::INPROGRESS;
|
||||
case WSAEISCONN:
|
||||
return Errno::ISCONN;
|
||||
case WSAEADDRINUSE:
|
||||
return Errno::ADDRINUSE;
|
||||
case WSAEADDRNOTAVAIL:
|
||||
return Errno::ADDRNOTAVAIL;
|
||||
case WSAEPROTOTYPE:
|
||||
return Errno::PROTOTYPE;
|
||||
case WSAENOPROTOOPT:
|
||||
return Errno::NOPROTOOPT;
|
||||
case WSAEPROTONOSUPPORT:
|
||||
return Errno::PROTONOSUPPORT;
|
||||
case WSAESOCKTNOSUPPORT:
|
||||
return Errno::SOCKTNOSUPPORT;
|
||||
case WSAENOTSUP:
|
||||
return Errno::NOTSUP;
|
||||
case WSAEBADF: return Errno::BADF;
|
||||
case WSAEINVAL: return Errno::INVAL;
|
||||
case WSAEMFILE: return Errno::MFILE;
|
||||
case WSAENOTCONN: return Errno::NOTCONN;
|
||||
case WSAEWOULDBLOCK: return Errno::AGAIN;
|
||||
case WSAECONNREFUSED: return Errno::CONNREFUSED;
|
||||
case WSAECONNRESET: return Errno::CONNRESET;
|
||||
case WSAEHOSTUNREACH: return Errno::HOSTUNREACH;
|
||||
case WSAENETDOWN: return Errno::NETDOWN;
|
||||
case WSAENETUNREACH: return Errno::NETUNREACH;
|
||||
case WSAEMSGSIZE: return Errno::MSGSIZE;
|
||||
case WSAETIMEDOUT: return Errno::TIMEDOUT;
|
||||
case WSAEINPROGRESS: return Errno::INPROGRESS;
|
||||
case WSAEISCONN: return Errno::ISCONN;
|
||||
case WSAEADDRINUSE: return Errno::ADDRINUSE;
|
||||
case WSAEADDRNOTAVAIL: return Errno::ADDRNOTAVAIL;
|
||||
case WSAEPROTOTYPE: return Errno::PROTOTYPE;
|
||||
case WSAENOPROTOOPT: return Errno::NOPROTOOPT;
|
||||
case WSAEPROTONOSUPPORT: return Errno::PROTONOSUPPORT;
|
||||
case WSAESOCKTNOSUPPORT: return Errno::SOCKTNOSUPPORT;
|
||||
#ifdef WSAENOTSUP
|
||||
// Not defined by fucking MSVC because MSVC is stupid as shitfuckery
|
||||
case WSAENOTSUP: return Errno::NOTSUP;
|
||||
#endif
|
||||
default:
|
||||
UNIMPLEMENTED_MSG("Unimplemented errno={}", e);
|
||||
return Errno::OTHER;
|
||||
@@ -257,7 +239,7 @@ int closesocket(SOCKET fd) {
|
||||
}
|
||||
|
||||
linger MakeLinger(bool enable, u32 linger_value) {
|
||||
linger value;
|
||||
linger value{};
|
||||
value.l_onoff = enable ? 1 : 0;
|
||||
value.l_linger = linger_value;
|
||||
return value;
|
||||
@@ -302,7 +284,8 @@ Errno TranslateNativeError(int e, CallType call_type = CallType::Other) {
|
||||
NETWORK_ERROR_ELEM(SOCKTNOSUPPORT) \
|
||||
NETWORK_ERROR_ELEM(NOTSUP) \
|
||||
NETWORK_ERROR_ELEM(ADDRINUSE) \
|
||||
NETWORK_ERROR_ELEM(ADDRNOTAVAIL)
|
||||
NETWORK_ERROR_ELEM(ADDRNOTAVAIL) \
|
||||
NETWORK_ERROR_ELEM(NOTSOCK)
|
||||
#define NETWORK_ERROR_ELEM(name) case E##name: return Errno::name;
|
||||
NETWORK_ERROR_LIST
|
||||
#undef NETWORK_ERROR_ELEM
|
||||
@@ -946,35 +929,30 @@ std::pair<T, Errno> Socket::GetSockOpt(SOCKET fd_so, int option) {
|
||||
|
||||
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;
|
||||
// managarm doesn't like these
|
||||
#ifdef SO_DEBUG
|
||||
case Network::OptName::DEBUG: return SO_DEBUG;
|
||||
#endif
|
||||
#ifdef SO_ACCEPTCONN
|
||||
case Network::OptName::ACCEPTCONN: return SO_ACCEPTCONN;
|
||||
#endif
|
||||
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;
|
||||
case Network::OptName::REUSEPORT: return SO_REUSEPORT;
|
||||
#endif
|
||||
#ifdef SO_ACCEPTFILTER
|
||||
case Network::OptName::ACCEPTFILTER:
|
||||
return SO_ACCEPTFILTER;
|
||||
case Network::OptName::ACCEPTFILTER: return SO_ACCEPTFILTER;
|
||||
#endif
|
||||
#ifdef SO_TIMESTAMP
|
||||
case Network::OptName::TIMESTAMP:
|
||||
return SO_TIMESTAMP;
|
||||
case Network::OptName::TIMESTAMP: return SO_TIMESTAMP;
|
||||
#endif
|
||||
default:
|
||||
UNIMPLEMENTED_MSG("Unimplemented optname={}", optname);
|
||||
@@ -982,6 +960,30 @@ static s32 TranslateOptNameToNative(Network::OptName optname) {
|
||||
}
|
||||
}
|
||||
|
||||
static s32 TranslateSocketLevelToNative(Network::SocketLevel level) {
|
||||
switch (level) {
|
||||
case Network::SocketLevel::SOCKET: return SOL_SOCKET;
|
||||
// FreeBSD doesn't define below but Linux does :-(
|
||||
#ifdef SOL_IP
|
||||
case Network::SocketLevel::IP: return SOL_IP;
|
||||
#endif
|
||||
#ifdef SOL_ICMP
|
||||
case Network::SocketLevel::ICMP: return SOL_ICMP;
|
||||
#endif
|
||||
#ifdef SOL_TCP
|
||||
case Network::SocketLevel::TCP: return SOL_TCP;
|
||||
#endif
|
||||
#ifdef SOL_UDP
|
||||
case Network::SocketLevel::UDP: return SOL_UDP;
|
||||
#endif
|
||||
#ifdef SOL_CONFIG
|
||||
case Network::SocketLevel::CONFIG: return SOL_CONFIG;
|
||||
#endif
|
||||
default:
|
||||
UNIMPLEMENTED_MSG("Unimplemented level={}", level);
|
||||
return SOL_SOCKET;
|
||||
}
|
||||
}
|
||||
|
||||
Errno Socket::SetNonBlock(bool enable) {
|
||||
if (EnableNonBlock(fd, enable)) {
|
||||
@@ -991,29 +993,27 @@ Errno Socket::SetNonBlock(bool enable) {
|
||||
return GetAndLogLastError();
|
||||
}
|
||||
|
||||
Errno Socket::SetSockOpt(SOCKET fd_so, Network::OptName optname, std::span<const u8> optval) {
|
||||
Errno Socket::SetSockOpt(SOCKET fd_so, Network::SocketLevel level, Network::OptName optname, std::span<const u8> optval) {
|
||||
auto const native_level = TranslateSocketLevelToNative(level);
|
||||
auto const native_optname = TranslateOptNameToNative(optname);
|
||||
// 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
|
||||
auto const linger_optval = MakeLinger(bool(linger.onoff), linger.linger);
|
||||
return setsockopt(fd_so, native_level, native_optname, reinterpret_cast<const char*>(&linger_optval), sizeof(linger_optval)) != 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
|
||||
return setsockopt(fd_so, native_level, native_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;
|
||||
|
||||
@@ -52,7 +52,7 @@ Errno ProxySocket::SetNonBlock(bool enable) {
|
||||
return Errno::SUCCESS;
|
||||
}
|
||||
|
||||
Errno ProxySocket::SetSockOpt(SOCKET fd_, Network::OptName option, std::span<const u8> optval) {
|
||||
Errno ProxySocket::SetSockOpt(SOCKET fd_, Network::SocketLevel level, Network::OptName option, std::span<const u8> optval) {
|
||||
LOG_DEBUG(Network, "(stubbed) called");
|
||||
// numeric values?
|
||||
if (optval.size() >= sizeof(u32)) {
|
||||
|
||||
@@ -57,7 +57,7 @@ public:
|
||||
|
||||
Errno SetNonBlock(bool enable) override;
|
||||
|
||||
Errno SetSockOpt(SOCKET fd, Network::OptName option, std::span<const u8> value) override;
|
||||
Errno SetSockOpt(SOCKET fd, Network::SocketLevel level, Network::OptName option, std::span<const u8> value) override;
|
||||
|
||||
std::pair<Errno, Errno> GetPendingError() override;
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ enum class Errno : u32 {
|
||||
INVAL = 22,
|
||||
MFILE = 24,
|
||||
PIPE = 32,
|
||||
NOTSOCK = 88,
|
||||
MSGSIZE = 90,
|
||||
PROTOTYPE = 91,
|
||||
NOPROTOOPT = 92,
|
||||
@@ -234,7 +235,10 @@ enum class Protocol : u32 {
|
||||
|
||||
enum class SocketLevel : u32 {
|
||||
IP = 0,
|
||||
ICMP = 1,
|
||||
TCP = 6,
|
||||
UDP = 17,
|
||||
CONFIG = 0xfffe,
|
||||
SOCKET = 0xffff, // i.e. SOL_SOCKET
|
||||
};
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ public:
|
||||
|
||||
virtual Errno SetNonBlock(bool enable) = 0;
|
||||
|
||||
virtual Errno SetSockOpt(SOCKET fd, Network::OptName option, std::span<const u8> value) = 0;
|
||||
virtual Errno SetSockOpt(SOCKET fd, Network::SocketLevel level, Network::OptName option, std::span<const u8> value) = 0;
|
||||
|
||||
virtual std::pair<Errno, Errno> GetPendingError() = 0;
|
||||
|
||||
@@ -120,7 +120,7 @@ public:
|
||||
|
||||
Errno SetNonBlock(bool enable) override;
|
||||
|
||||
Errno SetSockOpt(SOCKET fd, Network::OptName option, std::span<const u8> value) override;
|
||||
Errno SetSockOpt(SOCKET fd, Network::SocketLevel level, Network::OptName option, std::span<const u8> value) override;
|
||||
|
||||
std::pair<Errno, Errno> GetPendingError() override;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user