|
|
|
@@ -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;
|
|
|
|
|