diff --git a/src/core/libraries/network/net.cpp b/src/core/libraries/network/net.cpp index baf45b64f..d5d74c1a3 100644 --- a/src/core/libraries/network/net.cpp +++ b/src/core/libraries/network/net.cpp @@ -34,7 +34,7 @@ using FDTable = Common::Singleton; static thread_local int32_t net_errno = 0; -static bool g_isNetInitialized = true; // TODO init it properly +static bool g_isNetInitialized = false; static int ConvertFamilies(int family) { switch (family) { @@ -127,6 +127,8 @@ int PS4_SYSV_ABI sce_net_in6addr_nodelocal_allnodes() { } OrbisNetId PS4_SYSV_ABI sceNetAccept(OrbisNetId s, OrbisNetSockaddr* addr, u32* paddrlen) { + LOG_DEBUG(Lib_Net, "called, s = {}, addr = {}, paddrlen = {}", s, fmt::ptr(addr), + fmt::ptr(paddrlen)); if (!g_isNetInitialized) { return ORBIS_NET_ERROR_ENOTINIT; } @@ -657,8 +659,7 @@ int PS4_SYSV_ABI sceNetEpollControl(OrbisNetId epollid, OrbisNetEpollFlag op, Or case Core::FileSys::FileType::Socket: { auto native_handle = file->socket->Native(); if (!native_handle) { - // P2P socket, cannot be added to epoll - LOG_ERROR(Lib_Net, "P2P socket cannot be added to epoll (unimplemented)"); + LOG_ERROR(Lib_Net, "socket {} has no native handle", id); *sceNetErrnoLoc() = ORBIS_NET_EBADF; return ORBIS_NET_ERROR_EBADF; } @@ -666,9 +667,10 @@ int PS4_SYSV_ABI sceNetEpollControl(OrbisNetId epollid, OrbisNetEpollFlag op, Or #ifndef __FreeBSD__ epoll_event native_event = {.events = ConvertEpollEventsIn(event->events), .data = {.fd = id}}; - ASSERT(epoll_ctl(epoll->epoll_fd, EPOLL_CTL_ADD, *native_handle, &native_event) == 0); - epoll->events.emplace_back(id, *event); + ASSERT(epoll_ctl(epoll->epoll_fd, EPOLL_CTL_ADD, *native_handle, + &native_event) == 0); #endif + epoll->events.emplace_back(id, *event); break; } case Core::FileSys::FileType::Resolver: { @@ -707,8 +709,7 @@ int PS4_SYSV_ABI sceNetEpollControl(OrbisNetId epollid, OrbisNetEpollFlag op, Or case Core::FileSys::FileType::Socket: { auto native_handle = file->socket->Native(); if (!native_handle) { - // P2P socket, cannot be modified in epoll - LOG_ERROR(Lib_Net, "P2P socket cannot be modified in epoll (unimplemented)"); + LOG_ERROR(Lib_Net, "socket {} has no native handle", id); *sceNetErrnoLoc() = ORBIS_NET_EBADF; return ORBIS_NET_ERROR_EBADF; } @@ -716,9 +717,10 @@ int PS4_SYSV_ABI sceNetEpollControl(OrbisNetId epollid, OrbisNetEpollFlag op, Or #ifndef __FreeBSD__ epoll_event native_event = {.events = ConvertEpollEventsIn(event->events), .data = {.fd = id}}; - ASSERT(epoll_ctl(epoll->epoll_fd, EPOLL_CTL_MOD, *native_handle, &native_event) == 0); - *it = {id, *event}; + ASSERT(epoll_ctl(epoll->epoll_fd, EPOLL_CTL_MOD, *native_handle, + &native_event) == 0); #endif + *it = {id, *event}; break; } default: @@ -751,15 +753,15 @@ int PS4_SYSV_ABI sceNetEpollControl(OrbisNetId epollid, OrbisNetEpollFlag op, Or case Core::FileSys::FileType::Socket: { auto native_handle = file->socket->Native(); if (!native_handle) { - // P2P socket, cannot be removed from epoll - LOG_ERROR(Lib_Net, "P2P socket cannot be removed from epoll (unimplemented)"); + LOG_ERROR(Lib_Net, "socket {} has no native handle", id); *sceNetErrnoLoc() = ORBIS_NET_EBADF; return ORBIS_NET_ERROR_EBADF; } + #ifndef __FreeBSD__ ASSERT(epoll_ctl(epoll->epoll_fd, EPOLL_CTL_DEL, *native_handle, nullptr) == 0); - epoll->events.erase(it); #endif + epoll->events.erase(it); break; } case Core::FileSys::FileType::Resolver: { @@ -1700,7 +1702,8 @@ int PS4_SYSV_ABI sceNetSysctl() { } int PS4_SYSV_ABI sceNetTerm() { - LOG_ERROR(Lib_Net, "(STUBBED) called"); + LOG_DEBUG(Lib_Net, "called"); + g_isNetInitialized = false; return ORBIS_OK; } diff --git a/src/core/libraries/network/p2p_sockets.cpp b/src/core/libraries/network/p2p_sockets.cpp index cfdd1bda7..6ef21852e 100644 --- a/src/core/libraries/network/p2p_sockets.cpp +++ b/src/core/libraries/network/p2p_sockets.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-FileCopyrightText: Copyright 2024-2026 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include @@ -7,82 +7,308 @@ #include "net_error.h" #include "sockets.h" +#ifndef _WIN32 +#include +#include +#endif + namespace Libraries::Net { +P2PSocket::P2PSocket(int domain, int type, int protocol) : Socket(domain, type, protocol) { + socket_type = type; + // Map P2P socket types to real OS socket types + int os_type; + int os_protocol; + if (type == ORBIS_NET_SOCK_DGRAM_P2P) { + os_type = SOCK_DGRAM; + os_protocol = IPPROTO_UDP; + } else { + // ORBIS_NET_SOCK_STREAM_P2P + os_type = SOCK_STREAM; + os_protocol = IPPROTO_TCP; + } + sock = ::socket(AF_INET, os_type, os_protocol); + LOG_INFO(Lib_Net, "P2P socket created: type={} (os_type={}), fd={}", type, os_type, sock); +} + +P2PSocket::~P2PSocket() { +#ifdef _WIN32 + if (sock != INVALID_SOCKET) { + closesocket(sock); + } +#else + if (sock != -1) { + ::close(sock); + } +#endif +} + +bool P2PSocket::IsValid() const { +#ifdef _WIN32 + return sock != INVALID_SOCKET; +#else + return sock != -1; +#endif +} + int P2PSocket::Close() { - LOG_ERROR(Lib_Net, "(STUBBED) called"); - return 0; + std::scoped_lock lock{m_mutex}; +#ifdef _WIN32 + auto out = closesocket(sock); + sock = INVALID_SOCKET; +#else + auto out = ::close(sock); + sock = -1; +#endif + return ConvertReturnErrorCode(out); } int P2PSocket::SetSocketOptions(int level, int optname, const void* optval, u32 optlen) { - LOG_ERROR(Lib_Net, "(STUBBED) called"); - return 0; + std::scoped_lock lock{m_mutex}; + int native_level = ConvertLevels(level); + + // Handle PS4-specific options that have no OS equivalent + if (native_level == SOL_SOCKET) { + switch (optname) { + case ORBIS_NET_SO_NBIO: { + sockopt_so_nbio = *(int*)optval; + int val = sockopt_so_nbio; +#ifdef _WIN32 + u_long mode = val; + return ConvertReturnErrorCode(ioctlsocket(sock, FIONBIO, &mode)); +#else + return ConvertReturnErrorCode(ioctl(sock, FIONBIO, &val)); +#endif + } + case ORBIS_NET_SO_USECRYPTO: + case ORBIS_NET_SO_USESIGNATURE: + case ORBIS_NET_SO_REUSEPORT: + LOG_DEBUG(Lib_Net, "P2P setsockopt: storing PS4-specific option {}", optname); + return 0; + case ORBIS_NET_SO_SNDTIMEO: + case ORBIS_NET_SO_RCVTIMEO: { + int us = *(int*)optval; +#ifdef _WIN32 + DWORD timeout_ms = us / 1000; + int native_opt = (optname == ORBIS_NET_SO_SNDTIMEO) ? SO_SNDTIMEO : SO_RCVTIMEO; + return ConvertReturnErrorCode( + ::setsockopt(sock, SOL_SOCKET, native_opt, (char*)&timeout_ms, sizeof(timeout_ms))); +#else + timeval tv{.tv_sec = us / 1000000, .tv_usec = us % 1000000}; + int native_opt = (optname == ORBIS_NET_SO_SNDTIMEO) ? SO_SNDTIMEO : SO_RCVTIMEO; + return ConvertReturnErrorCode( + ::setsockopt(sock, SOL_SOCKET, native_opt, &tv, sizeof(tv))); +#endif + } + default: + break; + } + } + + if (native_level < 0) { + LOG_WARNING(Lib_Net, "P2P setsockopt: unknown level {}", level); + return 0; + } + + return ConvertReturnErrorCode( + ::setsockopt(sock, native_level, optname, (const char*)optval, optlen)); } int P2PSocket::GetSocketOptions(int level, int optname, void* optval, u32* optlen) { - LOG_ERROR(Lib_Net, "(STUBBED) called"); - return 0; + std::scoped_lock lock{m_mutex}; + int native_level = ConvertLevels(level); + + if (native_level == SOL_SOCKET) { + switch (optname) { + case ORBIS_NET_SO_NBIO: + *(int*)optval = sockopt_so_nbio; + *optlen = sizeof(int); + return 0; + case ORBIS_NET_SO_TYPE: + *(int*)optval = socket_type; + *optlen = sizeof(int); + return 0; + default: + break; + } + } + + if (native_level < 0) { + LOG_WARNING(Lib_Net, "P2P getsockopt: unknown level {}", level); + return 0; + } + + socklen_t native_optlen = *optlen; + int ret = ::getsockopt(sock, native_level, optname, (char*)optval, &native_optlen); + *optlen = native_optlen; + return ConvertReturnErrorCode(ret); } int P2PSocket::Bind(const OrbisNetSockaddr* addr, u32 addrlen) { - LOG_ERROR(Lib_Net, "(STUBBED) called"); - return 0; + std::scoped_lock lock{m_mutex}; + const auto* orbis_addr = reinterpret_cast(addr); + if (orbis_addr) { + vport = orbis_addr->sin_vport; + LOG_INFO(Lib_Net, "P2P bind: port={}, vport={}", ntohs(orbis_addr->sin_port), vport); + } + sockaddr native_addr; + convertOrbisNetSockaddrToPosix(addr, &native_addr); + return ConvertReturnErrorCode(::bind(sock, &native_addr, sizeof(sockaddr_in))); } int P2PSocket::Listen(int backlog) { - LOG_ERROR(Lib_Net, "(STUBBED) called"); - return 0; + std::scoped_lock lock{m_mutex}; + return ConvertReturnErrorCode(::listen(sock, backlog)); } int P2PSocket::SendMessage(const OrbisNetMsghdr* msg, int flags) { - LOG_ERROR(Lib_Net, "(STUBBED) called"); - *Libraries::Kernel::__Error() = ORBIS_NET_EAGAIN; - return -1; + std::scoped_lock lock{m_mutex}; + int native_flags = convertOrbisFlagsToPosix(socket_type, flags); +#ifdef _WIN32 + // Windows: loop through buffers with send() + int total_sent = 0; + for (int i = 0; i < msg->msg_iovlen; i++) { + auto& iov = msg->msg_iov[i]; + int sent = ::send(sock, (const char*)iov.iov_base, iov.iov_len, native_flags); + if (sent < 0) { + return total_sent > 0 ? total_sent : ConvertReturnErrorCode(sent); + } + total_sent += sent; + } + return total_sent; +#else + return ConvertReturnErrorCode( + ::sendmsg(sock, reinterpret_cast(msg), native_flags)); +#endif } int P2PSocket::SendPacket(const void* msg, u32 len, int flags, const OrbisNetSockaddr* to, u32 tolen) { - LOG_ERROR(Lib_Net, "(STUBBED) called"); - *Libraries::Kernel::__Error() = ORBIS_NET_EAGAIN; - return -1; + std::scoped_lock lock{m_mutex}; + int native_flags = convertOrbisFlagsToPosix(socket_type, flags); + if (to == nullptr) { + return ConvertReturnErrorCode(::send(sock, (const char*)msg, len, native_flags)); + } + sockaddr native_addr; + convertOrbisNetSockaddrToPosix(to, &native_addr); + return ConvertReturnErrorCode( + ::sendto(sock, (const char*)msg, len, native_flags, &native_addr, sizeof(sockaddr_in))); } int P2PSocket::ReceiveMessage(OrbisNetMsghdr* msg, int flags) { - LOG_ERROR(Lib_Net, "(STUBBED) called"); - *Libraries::Kernel::__Error() = ORBIS_NET_EAGAIN; - return -1; + std::scoped_lock lock{receive_mutex}; + int native_flags = convertOrbisFlagsToPosix(socket_type, flags); +#ifdef _WIN32 + // Windows: loop through buffers with recv() + int total_recv = 0; + for (int i = 0; i < msg->msg_iovlen; i++) { + auto& iov = msg->msg_iov[i]; + int recvd = ::recv(sock, (char*)iov.iov_base, iov.iov_len, native_flags); + if (recvd < 0) { + return total_recv > 0 ? total_recv : ConvertReturnErrorCode(recvd); + } + total_recv += recvd; + if (recvd < (int)iov.iov_len) { + break; + } + } + return total_recv; +#else + return ConvertReturnErrorCode( + ::recvmsg(sock, reinterpret_cast(msg), native_flags)); +#endif } -int P2PSocket::ReceivePacket(void* buf, u32 len, int flags, OrbisNetSockaddr* from, u32* fromlen) { - LOG_ERROR(Lib_Net, "(STUBBED) called"); - *Libraries::Kernel::__Error() = ORBIS_NET_EAGAIN; - return -1; +int P2PSocket::ReceivePacket(void* buf, u32 len, int flags, OrbisNetSockaddr* from, + u32* fromlen) { + std::scoped_lock lock{receive_mutex}; + int native_flags = convertOrbisFlagsToPosix(socket_type, flags); + if (from == nullptr) { + return ConvertReturnErrorCode(::recv(sock, (char*)buf, len, native_flags)); + } + sockaddr native_addr; + socklen_t native_addrlen = sizeof(native_addr); + int ret = ::recvfrom(sock, (char*)buf, len, native_flags, &native_addr, &native_addrlen); + if (ret >= 0) { + convertPosixSockaddrToOrbis(&native_addr, from); + if (fromlen) { + *fromlen = sizeof(OrbisNetSockaddrIn); + } + } + return ConvertReturnErrorCode(ret); } SocketPtr P2PSocket::Accept(OrbisNetSockaddr* addr, u32* addrlen) { - LOG_ERROR(Lib_Net, "(STUBBED) called"); - *Libraries::Kernel::__Error() = ORBIS_NET_EAGAIN; - return nullptr; + std::scoped_lock lock{m_mutex}; + sockaddr native_addr; + socklen_t len = sizeof(native_addr); + auto new_sock = ::accept(sock, &native_addr, &len); +#ifdef _WIN32 + if (new_sock == INVALID_SOCKET) { +#else + if (new_sock < 0) { +#endif + ConvertReturnErrorCode(-1); + return nullptr; + } + if (addr) { + convertPosixSockaddrToOrbis(&native_addr, addr); + if (addrlen) { + *addrlen = sizeof(OrbisNetSockaddrIn); + } + } + return std::make_shared(new_sock); } int P2PSocket::Connect(const OrbisNetSockaddr* addr, u32 namelen) { - LOG_ERROR(Lib_Net, "(STUBBED) called"); - return 0; + std::scoped_lock lock{m_mutex}; + const auto* orbis_addr = reinterpret_cast(addr); + if (orbis_addr) { + vport = orbis_addr->sin_vport; + LOG_INFO(Lib_Net, "P2P connect: vport={}", vport); + } + sockaddr native_addr; + convertOrbisNetSockaddrToPosix(addr, &native_addr); + int ret = ::connect(sock, &native_addr, sizeof(sockaddr_in)); +#ifdef _WIN32 + if (ret < 0 && WSAGetLastError() == WSAEWOULDBLOCK) { + WSASetLastError(WSAEINPROGRESS); + } +#endif + return ConvertReturnErrorCode(ret); } int P2PSocket::GetSocketAddress(OrbisNetSockaddr* name, u32* namelen) { - LOG_ERROR(Lib_Net, "(STUBBED) called"); - return 0; + std::scoped_lock lock{m_mutex}; + sockaddr native_addr; + socklen_t len = sizeof(native_addr); + int ret = ::getsockname(sock, &native_addr, &len); + if (ret == 0) { + convertPosixSockaddrToOrbis(&native_addr, name); + if (namelen) { + *namelen = sizeof(OrbisNetSockaddrIn); + } + } + return ConvertReturnErrorCode(ret); } int P2PSocket::GetPeerName(OrbisNetSockaddr* addr, u32* namelen) { - LOG_ERROR(Lib_Net, "(STUBBED) called"); - return 0; + std::scoped_lock lock{m_mutex}; + sockaddr native_addr; + socklen_t len = sizeof(native_addr); + int ret = ::getpeername(sock, &native_addr, &len); + if (ret == 0) { + convertPosixSockaddrToOrbis(&native_addr, addr); + if (namelen) { + *namelen = sizeof(OrbisNetSockaddrIn); + } + } + return ConvertReturnErrorCode(ret); } int P2PSocket::fstat(Libraries::Kernel::OrbisKernelStat* stat) { - LOG_ERROR(Lib_Net, "(STUBBED) called"); + LOG_DEBUG(Lib_Net, "(STUBBED) called"); return 0; } -} // namespace Libraries::Net \ No newline at end of file +} // namespace Libraries::Net diff --git a/src/core/libraries/network/posix_sockets.cpp b/src/core/libraries/network/posix_sockets.cpp index 164d85896..8171cf589 100644 --- a/src/core/libraries/network/posix_sockets.cpp +++ b/src/core/libraries/network/posix_sockets.cpp @@ -27,7 +27,7 @@ namespace Libraries::Net { return -1; #endif -static int ConvertReturnErrorCode(int retval) { +int ConvertReturnErrorCode(int retval) { if (retval < 0) { #ifdef _WIN32 switch (WSAGetLastError()) { @@ -118,7 +118,7 @@ static int ConvertReturnErrorCode(int retval) { return retval; } -static int ConvertLevels(int level) { +int ConvertLevels(int level) { switch (level) { case ORBIS_NET_SOL_SOCKET: return SOL_SOCKET; @@ -132,7 +132,7 @@ static int ConvertLevels(int level) { return -1; } -static void convertOrbisNetSockaddrToPosix(const OrbisNetSockaddr* src, sockaddr* dst) { +void convertOrbisNetSockaddrToPosix(const OrbisNetSockaddr* src, sockaddr* dst) { if (src == nullptr || dst == nullptr) return; memset(dst, 0, sizeof(sockaddr)); @@ -143,7 +143,7 @@ static void convertOrbisNetSockaddrToPosix(const OrbisNetSockaddr* src, sockaddr memcpy(&dst_in->sin_addr, &src_in->sin_addr, 4); } -static void convertPosixSockaddrToOrbis(sockaddr* src, OrbisNetSockaddr* dst) { +void convertPosixSockaddrToOrbis(sockaddr* src, OrbisNetSockaddr* dst) { if (src == nullptr || dst == nullptr) return; memset(dst, 0, sizeof(OrbisNetSockaddr)); @@ -184,7 +184,7 @@ int PosixSocket::Listen(int backlog) { return ConvertReturnErrorCode(::listen(sock, backlog)); } -static int convertOrbisFlagsToPosix(int sock_type, int sce_flags) { +int convertOrbisFlagsToPosix(int sock_type, int sce_flags) { int posix_flags = 0; if (sce_flags & ORBIS_NET_MSG_PEEK) diff --git a/src/core/libraries/network/sockets.h b/src/core/libraries/network/sockets.h index 86661c71c..74600f792 100644 --- a/src/core/libraries/network/sockets.h +++ b/src/core/libraries/network/sockets.h @@ -57,6 +57,13 @@ struct Socket; typedef std::shared_ptr SocketPtr; +// Shared socket helper functions defined in posix_sockets.cpp +int ConvertReturnErrorCode(int retval); +int ConvertLevels(int level); +void convertOrbisNetSockaddrToPosix(const OrbisNetSockaddr* src, sockaddr* dst); +void convertPosixSockaddrToOrbis(sockaddr* src, OrbisNetSockaddr* dst); +int convertOrbisFlagsToPosix(int sock_type, int sce_flags); + struct OrbisNetLinger { s32 l_onoff; s32 l_linger; @@ -126,10 +133,14 @@ struct PosixSocket : public Socket { }; struct P2PSocket : public Socket { - explicit P2PSocket(int domain, int type, int protocol) : Socket(domain, type, protocol) {} - bool IsValid() const override { - return true; - } + net_socket sock; + int sockopt_so_nbio = 0; + int socket_type; + u16 vport = 0; // PS4 virtual port + + explicit P2PSocket(int domain, int type, int protocol); + ~P2PSocket() override; + bool IsValid() const override; int Close() override; int SetSocketOptions(int level, int optname, const void* optval, u32 optlen) override; int GetSocketOptions(int level, int optname, void* optval, u32* optlen) override; @@ -146,7 +157,7 @@ struct P2PSocket : public Socket { int GetPeerName(OrbisNetSockaddr* addr, u32* namelen) override; int fstat(Libraries::Kernel::OrbisKernelStat* stat) override; std::optional Native() override { - return {}; + return sock; } }; diff --git a/src/core/libraries/network/unix_sockets.cpp b/src/core/libraries/network/unix_sockets.cpp index 29bbc5f16..0914384f3 100644 --- a/src/core/libraries/network/unix_sockets.cpp +++ b/src/core/libraries/network/unix_sockets.cpp @@ -15,123 +15,6 @@ namespace Libraries::Net { -#ifdef _WIN32 -#define ERROR_CASE(errname) \ - case (WSA##errname): \ - *Libraries::Kernel::__Error() = ORBIS_NET_##errname; \ - return -1; -#else -#define ERROR_CASE(errname) \ - case (errname): \ - *Libraries::Kernel::__Error() = ORBIS_NET_##errname; \ - return -1; -#endif - -static int ConvertReturnErrorCode(int retval) { - if (retval < 0) { -#ifdef _WIN32 - switch (WSAGetLastError()) { -#else - switch (errno) { -#endif -#ifndef _WIN32 // These errorcodes don't exist in WinSock - ERROR_CASE(EPERM) - ERROR_CASE(ENOENT) - // ERROR_CASE(ESRCH) - // ERROR_CASE(EIO) - // ERROR_CASE(ENXIO) - // ERROR_CASE(E2BIG) - // ERROR_CASE(ENOEXEC) - // ERROR_CASE(EDEADLK) - ERROR_CASE(ENOMEM) - // ERROR_CASE(ECHILD) - // ERROR_CASE(EBUSY) - ERROR_CASE(EEXIST) - // ERROR_CASE(EXDEV) - ERROR_CASE(ENODEV) - // ERROR_CASE(ENOTDIR) - // ERROR_CASE(EISDIR) - ERROR_CASE(ENFILE) - // ERROR_CASE(ENOTTY) - // ERROR_CASE(ETXTBSY) - // ERROR_CASE(EFBIG) - ERROR_CASE(ENOSPC) - // ERROR_CASE(ESPIPE) - // ERROR_CASE(EROFS) - // ERROR_CASE(EMLINK) - ERROR_CASE(EPIPE) - // ERROR_CASE(EDOM) - // ERROR_CASE(ERANGE) - // ERROR_CASE(ENOLCK) - // ERROR_CASE(ENOSYS) - // ERROR_CASE(EIDRM) - // ERROR_CASE(EOVERFLOW) - // ERROR_CASE(EILSEQ) - // ERROR_CASE(ENOTSUP) - ERROR_CASE(ECANCELED) - // ERROR_CASE(EBADMSG) - ERROR_CASE(ENODATA) - // ERROR_CASE(ENOSR) - // ERROR_CASE(ENOSTR) - // ERROR_CASE(ETIME) -#endif - ERROR_CASE(EINTR) - ERROR_CASE(EBADF) - ERROR_CASE(EACCES) - ERROR_CASE(EFAULT) - ERROR_CASE(EINVAL) - ERROR_CASE(EMFILE) - ERROR_CASE(EWOULDBLOCK) - ERROR_CASE(EINPROGRESS) - ERROR_CASE(EALREADY) - ERROR_CASE(ENOTSOCK) - ERROR_CASE(EDESTADDRREQ) - ERROR_CASE(EMSGSIZE) - ERROR_CASE(EPROTOTYPE) - ERROR_CASE(ENOPROTOOPT) - ERROR_CASE(EPROTONOSUPPORT) -#if defined(__APPLE__) || defined(_WIN32) - ERROR_CASE(EOPNOTSUPP) -#endif - ERROR_CASE(EAFNOSUPPORT) - ERROR_CASE(EADDRINUSE) - ERROR_CASE(EADDRNOTAVAIL) - ERROR_CASE(ENETDOWN) - ERROR_CASE(ENETUNREACH) - ERROR_CASE(ENETRESET) - ERROR_CASE(ECONNABORTED) - ERROR_CASE(ECONNRESET) - ERROR_CASE(ENOBUFS) - ERROR_CASE(EISCONN) - ERROR_CASE(ENOTCONN) - ERROR_CASE(ETIMEDOUT) - ERROR_CASE(ECONNREFUSED) - ERROR_CASE(ELOOP) - ERROR_CASE(ENAMETOOLONG) - ERROR_CASE(EHOSTUNREACH) - ERROR_CASE(ENOTEMPTY) - } - *Libraries::Kernel::__Error() = ORBIS_NET_EINTERNAL; - return -1; - } - // if it is 0 or positive return it as it is - return retval; -} - -static int ConvertLevels(int level) { - switch (level) { - case ORBIS_NET_SOL_SOCKET: - return SOL_SOCKET; - case ORBIS_NET_IPPROTO_IP: - return IPPROTO_IP; - case ORBIS_NET_IPPROTO_TCP: - return IPPROTO_TCP; - case ORBIS_NET_IPPROTO_IPV6: - return IPPROTO_IPV6; - } - return -1; -} - static void convertOrbisNetSockaddrToUnix(const OrbisNetSockaddr* src, sockaddr_un* dst) { if (src == nullptr || dst == nullptr) return;