diff --git a/.gitmodules b/.gitmodules index 940c0417d..4dfd47d01 100644 --- a/.gitmodules +++ b/.gitmodules @@ -113,3 +113,8 @@ path = externals/hwinfo url = https://github.com/shadps4-emu/ext-hwinfo shallow = true +[submodule "externals/ext-wepoll"] + path = externals/ext-wepoll + url = https://github.com/shadps4-emu/ext-wepoll.git + shallow = true + branch = dist diff --git a/CMakeLists.txt b/CMakeLists.txt index 171c9032c..89958f13e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -380,6 +380,8 @@ set(NETWORK_LIBS src/core/libraries/network/http.cpp src/core/libraries/network/net_ctl_codes.h src/core/libraries/network/net_util.cpp src/core/libraries/network/net_util.h + src/core/libraries/network/net_epoll.cpp + src/core/libraries/network/net_epoll.h src/core/libraries/network/net_error.h src/core/libraries/network/net.h src/core/libraries/network/ssl.cpp @@ -1222,7 +1224,7 @@ if (ENABLE_QT_GUI) endif() if (WIN32) - target_link_libraries(shadps4 PRIVATE mincore) + target_link_libraries(shadps4 PRIVATE mincore wepoll) if (MSVC) # MSVC likes putting opinions on what people can use, disable: diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index 1fc206259..686c05101 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -238,3 +238,8 @@ if (APPLE) add_subdirectory(epoll-shim) endif() endif() + +#windows only +if (WIN32) +add_subdirectory(ext-wepoll) +endif() diff --git a/externals/ext-wepoll b/externals/ext-wepoll new file mode 160000 index 000000000..d3bb81035 --- /dev/null +++ b/externals/ext-wepoll @@ -0,0 +1 @@ +Subproject commit d3bb81035304a0dc6a5ca48ebf0f8cee1fe269e4 diff --git a/src/core/libraries/network/net.cpp b/src/core/libraries/network/net.cpp index dc58015f8..378b6600b 100644 --- a/src/core/libraries/network/net.cpp +++ b/src/core/libraries/network/net.cpp @@ -11,12 +11,16 @@ #endif #include +#include #include "common/assert.h" +#include "common/error.h" #include "common/logging/log.h" #include "common/singleton.h" +#include "core/file_sys/fs.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" #include "core/libraries/network/net.h" +#include "net_epoll.h" #include "net_error.h" #include "net_util.h" #include "netctl.h" @@ -25,6 +29,8 @@ namespace Libraries::Net { +using FDTable = Common::Singleton; + static thread_local int32_t net_errno = 0; static bool g_isNetInitialized = true; // TODO init it properly @@ -613,28 +619,171 @@ int PS4_SYSV_ABI sceNetEpollAbort() { return ORBIS_OK; } -int PS4_SYSV_ABI sceNetEpollControl() { - LOG_ERROR(Lib_Net, "(STUBBED) called"); +int PS4_SYSV_ABI sceNetEpollControl(OrbisNetId epollid, OrbisNetEpollFlag op, OrbisNetId id, + OrbisNetEpollEvent* event) { + auto epoll = Common::Singleton::Instance()->GetEpoll(epollid); + if (!epoll) { + *sceNetErrnoLoc() = ORBIS_NET_EBADF; + return ORBIS_NET_ERROR_EBADF; + } + LOG_WARNING(Lib_Net, "called, epollid = {} ({}), op = {}, id = {}", epollid, epoll->name, + magic_enum::enum_name(op), id); + + auto find_id = [&](OrbisNetId id) { + return std::ranges::find_if(epoll->events, [&](const auto& el) { return el.first == id; }); + }; + + switch (op) { + case ORBIS_NET_EPOLL_CTL_ADD: { + if (event == nullptr) { + *sceNetErrnoLoc() = ORBIS_NET_EINVAL; + return ORBIS_NET_ERROR_EINVAL; + } + if (find_id(id) != epoll->events.end()) { + *sceNetErrnoLoc() = ORBIS_NET_EEXIST; + return ORBIS_NET_ERROR_EEXIST; + } + + auto file = FDTable::Instance()->GetSocket(id); + if (!file) { + *sceNetErrnoLoc() = ORBIS_NET_EBADF; + LOG_ERROR(Lib_Net, "socket id is invalid = {}", id); + return ORBIS_NET_ERROR_EBADF; + } + epoll_event native_event = {.events = ConvertEpollEventsIn(event->events), + .data = {.fd = id}}; + ASSERT(epoll_ctl(epoll->epoll_fd, EPOLL_CTL_ADD, *file->socket->Native(), &native_event) == + 0); + epoll->events.emplace_back(id, *event); + break; + } + case ORBIS_NET_EPOLL_CTL_MOD: { + if (event == nullptr) { + *sceNetErrnoLoc() = ORBIS_NET_EINVAL; + return ORBIS_NET_ERROR_EINVAL; + } + + UNREACHABLE(); + break; + } + case ORBIS_NET_EPOLL_CTL_DEL: { + if (event != nullptr) { + *sceNetErrnoLoc() = ORBIS_NET_EINVAL; + return ORBIS_NET_ERROR_EINVAL; + } + + auto it = find_id(id); + if (it == epoll->events.end()) { + *sceNetErrnoLoc() = ORBIS_NET_EBADF; + return ORBIS_NET_ERROR_EBADF; + } + + auto file = FDTable::Instance()->GetSocket(id); + if (!file) { + *sceNetErrnoLoc() = ORBIS_NET_EBADF; + LOG_ERROR(Lib_Net, "socket id is invalid = {}", id); + return ORBIS_NET_ERROR_EBADF; + } + ASSERT(epoll_ctl(epoll->epoll_fd, EPOLL_CTL_DEL, *file->socket->Native(), nullptr) == 0); + epoll->events.erase(it); + break; + } + default: + *sceNetErrnoLoc() = ORBIS_NET_EINVAL; + return ORBIS_NET_ERROR_EINVAL; + } + return ORBIS_OK; } -int PS4_SYSV_ABI sceNetEpollCreate() { - LOG_ERROR(Lib_Net, "(STUBBED) called"); +int PS4_SYSV_ABI sceNetEpollCreate(const char* name, int flags) { + LOG_INFO(Lib_Net, "called, name = {}, flags = {}", name, flags); + if (flags != 0) { + *sceNetErrnoLoc() = ORBIS_NET_EINVAL; + return ORBIS_NET_ERROR_EINVAL; + } + + auto epoll = Common::Singleton::Instance()->CreateHandle(name); + + return epoll; +} + +int PS4_SYSV_ABI sceNetEpollDestroy(OrbisNetId epollid) { + auto epoll = Common::Singleton::Instance()->GetEpoll(epollid); + if (!epoll) { + *sceNetErrnoLoc() = ORBIS_NET_EBADF; + return ORBIS_NET_ERROR_EBADF; + } + + LOG_INFO(Lib_Net, "called, epollid = {} ({})", epollid, epoll->name); + + epoll->Destroy(); + return ORBIS_OK; } -int PS4_SYSV_ABI sceNetEpollDestroy() { - LOG_ERROR(Lib_Net, "(STUBBED) called"); - return ORBIS_OK; -} +int PS4_SYSV_ABI sceNetEpollWait(OrbisNetId epollid, OrbisNetEpollEvent* events, int maxevents, + int timeout) { + auto epoll = Common::Singleton::Instance()->GetEpoll(epollid); + if (!epoll) { + *sceNetErrnoLoc() = ORBIS_NET_EBADF; + return ORBIS_NET_ERROR_EBADF; + } -int PS4_SYSV_ABI sceNetEpollWait() { - LOG_TRACE(Lib_Net, "(STUBBED) called"); - return ORBIS_OK; + LOG_INFO(Lib_Net, "called, epollid = {} ({}), maxevents = {}, timeout = {}", epollid, + epoll->name, maxevents, timeout); + + std::vector native_events{static_cast(maxevents)}; +#ifdef __linux__ + const timespec epoll_timeout{.tv_sec = timeout / 1000000, + .tv_nsec = (timeout % 1000000) * 1000}; + int result = epoll_pwait2(epoll->epoll_fd, native_events.data(), maxevents, + timeout < 0 ? nullptr : &epoll_timeout, nullptr); +#else + int result = epoll_wait(epoll->epoll_fd, native_events.data(), maxevents, + timeout < 0 ? timeout : timeout / 1000); +#endif + if (result < 0) { + LOG_ERROR(Lib_Net, "epoll_wait failed with {}", Common::GetLastErrorMsg()); + switch (errno) { + case EINTR: + *sceNetErrnoLoc() = ORBIS_NET_EINTR; + return ORBIS_NET_ERROR_EINTR; + case EINVAL: + *sceNetErrnoLoc() = ORBIS_NET_EINVAL; + return ORBIS_NET_ERROR_EINVAL; + case EBADF: + *sceNetErrnoLoc() = ORBIS_NET_EBADF; + return ORBIS_NET_ERROR_EBADF; + default: + *sceNetErrnoLoc() = ORBIS_NET_EINTERNAL; + return ORBIS_NET_ERROR_EINTERNAL; + } + } else if (result == 0) { + LOG_DEBUG(Lib_Net, "timed out"); + } else { + for (int i = 0; i < result; ++i) { + const auto& current_event = native_events[i]; + LOG_DEBUG(Lib_Net, "native_event[{}] = ( .events = {}, .data = {:#x} )", i, + current_event.events, current_event.data.u64); + const auto it = std::ranges::find_if( + epoll->events, [&](auto& el) { return el.first == current_event.data.fd; }); + ASSERT(it != epoll->events.end()); + events[i] = { + .events = ConvertEpollEventsOut(current_event.events), + .ident = static_cast(current_event.data.fd), + .data = it->second.data, + }; + LOG_DEBUG(Lib_Net, "event[{}] = ( .events = {:#x}, .ident = {}, .data = {:#x} )", i, + events[i].events, events[i].ident, events[i].data.data_u64); + } + } + + return result; } int* PS4_SYSV_ABI sceNetErrnoLoc() { - LOG_DEBUG(Lib_Net, "called"); + LOG_TRACE(Lib_Net, "called"); return &net_errno; } @@ -713,6 +862,8 @@ int PS4_SYSV_ABI sceNetGetMacAddress(Libraries::NetCtl::OrbisNetEtherAddr* addr, LOG_ERROR(Lib_Net, "addr is null!"); return ORBIS_NET_EINVAL; } + LOG_DEBUG(Lib_Net, "called"); + auto* netinfo = Common::Singleton::Instance(); netinfo->RetrieveEthernetAddr(); memcpy(addr->data, netinfo->GetEthernetAddr().data(), 6); @@ -767,7 +918,6 @@ int PS4_SYSV_ABI sceNetGetsockname(OrbisNetId s, OrbisNetSockaddr* addr, u32* pa } int PS4_SYSV_ABI sceNetGetsockopt(OrbisNetId s, int level, int optname, void* optval, u32* optlen) { - LOG_INFO(Lib_Net, "s={} level={} optname={}", s, level, optname); if (!g_isNetInitialized) { return ORBIS_NET_ERROR_ENOTINIT; } @@ -926,6 +1076,7 @@ const char* PS4_SYSV_ABI sceNetInetNtop(int af, const void* src, char* dst, u32 LOG_ERROR(Lib_Net, "returned ORBIS_NET_ENOSPC"); return nullptr; } + const char* returnvalue = nullptr; switch (af) { case ORBIS_NET_AF_INET: @@ -942,6 +1093,8 @@ const char* PS4_SYSV_ABI sceNetInetNtop(int af, const void* src, char* dst, u32 if (returnvalue == nullptr) { *sceNetErrnoLoc() = ORBIS_NET_ENOSPC; LOG_ERROR(Lib_Net, "returned ORBIS_NET_ENOSPC"); + } else { + LOG_DEBUG(Lib_Net, "{}: {}", magic_enum::enum_name((OrbisNetFamily)af), dst); } return returnvalue; } @@ -1241,7 +1394,6 @@ int PS4_SYSV_ABI sceNetSetDnsInfoToKernel() { int PS4_SYSV_ABI sceNetSetsockopt(OrbisNetId s, int level, int optname, const void* optval, u32 optlen) { - LOG_INFO(Lib_Net, "s={} level={} optname={} optlen={}", s, level, optname, optlen); if (!g_isNetInitialized) { return ORBIS_NET_ERROR_ENOTINIT; } diff --git a/src/core/libraries/network/net.h b/src/core/libraries/network/net.h index fe809579b..06f99800d 100644 --- a/src/core/libraries/network/net.h +++ b/src/core/libraries/network/net.h @@ -3,6 +3,7 @@ #pragma once +#include "common/assert.h" #include "common/types.h" #include "netctl.h" @@ -45,8 +46,28 @@ enum OrbisNetProtocol : u32 { ORBIS_NET_SOL_SOCKET = 0xFFFF }; -enum OrbisNetSocketOption : u32 { - /* IP */ +constexpr std::string_view NameOf(OrbisNetProtocol p) { + switch (p) { + case ORBIS_NET_IPPROTO_IP: + return "ORBIS_NET_IPPROTO_IP"; + case ORBIS_NET_IPPROTO_ICMP: + return "ORBIS_NET_IPPROTO_ICMP"; + case ORBIS_NET_IPPROTO_IGMP: + return "ORBIS_NET_IPPROTO_IGMP"; + case ORBIS_NET_IPPROTO_TCP: + return "ORBIS_NET_IPPROTO_TCP"; + case ORBIS_NET_IPPROTO_UDP: + return "ORBIS_NET_IPPROTO_UDP"; + case ORBIS_NET_IPPROTO_IPV6: + return "ORBIS_NET_IPPROTO_IPV6"; + case ORBIS_NET_SOL_SOCKET: + return "ORBIS_NET_SOL_SOCKET"; + default: + UNREACHABLE_MSG("{}", (u32)p); + } +} + +enum OrbisNetSocketIpOption : u32 { ORBIS_NET_IP_HDRINCL = 2, ORBIS_NET_IP_TOS = 3, ORBIS_NET_IP_TTL = 4, @@ -57,11 +78,15 @@ enum OrbisNetSocketOption : u32 { ORBIS_NET_IP_DROP_MEMBERSHIP = 13, ORBIS_NET_IP_TTLCHK = 23, ORBIS_NET_IP_MAXTTL = 24, - /* TCP */ +}; + +enum OrbisNetSocketTcpOption : u32 { ORBIS_NET_TCP_NODELAY = 1, ORBIS_NET_TCP_MAXSEG = 2, ORBIS_NET_TCP_MSS_TO_ADVERTISE = 3, - /* SOCKET */ +}; + +enum OrbisNetSocketSoOption : u32 { ORBIS_NET_SO_REUSEADDR = 0x00000004, ORBIS_NET_SO_KEEPALIVE = 0x00000008, ORBIS_NET_SO_BROADCAST = 0x00000020, @@ -85,6 +110,55 @@ enum OrbisNetSocketOption : u32 { ORBIS_NET_SO_PRIORITY = 0x1203 }; +constexpr std::string_view NameOf(OrbisNetSocketSoOption o) { + switch (o) { + case ORBIS_NET_SO_REUSEADDR: + return "ORBIS_NET_SO_REUSEADDR"; + case ORBIS_NET_SO_KEEPALIVE: + return "ORBIS_NET_SO_KEEPALIVE"; + case ORBIS_NET_SO_BROADCAST: + return "ORBIS_NET_SO_BROADCAST"; + case ORBIS_NET_SO_LINGER: + return "ORBIS_NET_SO_LINGER"; + case ORBIS_NET_SO_REUSEPORT: + return "ORBIS_NET_SO_REUSEPORT"; + case ORBIS_NET_SO_ONESBCAST: + return "ORBIS_NET_SO_ONESBCAST"; + case ORBIS_NET_SO_USECRYPTO: + return "ORBIS_NET_SO_USECRYPTO"; + case ORBIS_NET_SO_USESIGNATURE: + return "ORBIS_NET_SO_USESIGNATURE"; + case ORBIS_NET_SO_SNDBUF: + return "ORBIS_NET_SO_SNDBUF"; + case ORBIS_NET_SO_RCVBUF: + return "ORBIS_NET_SO_RCVBUF"; + case ORBIS_NET_SO_ERROR: + return "ORBIS_NET_SO_ERROR"; + case ORBIS_NET_SO_TYPE: + return "ORBIS_NET_SO_TYPE"; + case ORBIS_NET_SO_SNDTIMEO: + return "ORBIS_NET_SO_SNDTIMEO"; + case ORBIS_NET_SO_RCVTIMEO: + return "ORBIS_NET_SO_RCVTIMEO"; + case ORBIS_NET_SO_ERROR_EX: + return "ORBIS_NET_SO_ERROR_EX"; + case ORBIS_NET_SO_ACCEPTTIMEO: + return "ORBIS_NET_SO_ACCEPTTIMEO"; + case ORBIS_NET_SO_CONNECTTIMEO: + return "ORBIS_NET_SO_CONNECTTIMEO"; + case ORBIS_NET_SO_NBIO: + return "ORBIS_NET_SO_NBIO"; + case ORBIS_NET_SO_POLICY: + return "ORBIS_NET_SO_POLICY"; + case ORBIS_NET_SO_NAME: + return "ORBIS_NET_SO_NAME"; + case ORBIS_NET_SO_PRIORITY: + return "ORBIS_NET_SO_PRIORITY"; + default: + UNREACHABLE_MSG("{}", (u32)o); + } +} + enum OrbisNetEpollFlag : u32 { ORBIS_NET_EPOLL_CTL_ADD = 1, ORBIS_NET_EPOLL_CTL_MOD = 2, @@ -285,10 +359,12 @@ int PS4_SYSV_ABI sceNetDumpRead(); int PS4_SYSV_ABI sceNetDuplicateIpStart(); int PS4_SYSV_ABI sceNetDuplicateIpStop(); int PS4_SYSV_ABI sceNetEpollAbort(); -int PS4_SYSV_ABI sceNetEpollControl(); -int PS4_SYSV_ABI sceNetEpollCreate(); -int PS4_SYSV_ABI sceNetEpollDestroy(); -int PS4_SYSV_ABI sceNetEpollWait(); +int PS4_SYSV_ABI sceNetEpollControl(OrbisNetId epollid, OrbisNetEpollFlag op, OrbisNetId id, + OrbisNetEpollEvent* event); +int PS4_SYSV_ABI sceNetEpollCreate(const char* name, int flags); +int PS4_SYSV_ABI sceNetEpollDestroy(OrbisNetId epollid); +int PS4_SYSV_ABI sceNetEpollWait(OrbisNetId epollid, OrbisNetEpollEvent* events, int maxevents, + int timeout); int* PS4_SYSV_ABI sceNetErrnoLoc(); int PS4_SYSV_ABI sceNetEtherNtostr(); int PS4_SYSV_ABI sceNetEtherStrton(); diff --git a/src/core/libraries/network/net_epoll.cpp b/src/core/libraries/network/net_epoll.cpp new file mode 100644 index 000000000..e64c8ac64 --- /dev/null +++ b/src/core/libraries/network/net_epoll.cpp @@ -0,0 +1,72 @@ +// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/assert.h" +#include "common/types.h" +#include "net_epoll.h" + +namespace Libraries::Net { + +u32 ConvertEpollEventsIn(u32 orbis_events) { + u32 ret = 0; + + if ((orbis_events & ORBIS_NET_EPOLLIN) != 0) { + ret |= EPOLLIN; + } + if ((orbis_events & ORBIS_NET_EPOLLOUT) != 0) { + ret |= EPOLLOUT; + } + + return ret; +} + +u32 ConvertEpollEventsOut(u32 epoll_events) { + u32 ret = 0; + + if ((epoll_events & EPOLLIN) != 0) { + ret |= ORBIS_NET_EPOLLIN; + } + if ((epoll_events & EPOLLOUT) != 0) { + ret |= ORBIS_NET_EPOLLOUT; + } + if ((epoll_events & EPOLLERR) != 0) { + ret |= ORBIS_NET_EPOLLERR; + } + if ((epoll_events & EPOLLHUP) != 0) { + ret |= ORBIS_NET_EPOLLHUP; + } + + return ret; +} + +int EpollTable::CreateHandle(const char* name) { + std::scoped_lock lock{m_mutex}; + + if (auto it = std::ranges::find_if(epolls, [](const Epoll& e) { return e.Destroyed(); }); + it != epolls.end()) { + *it = Epoll(name); + const auto ret = std::distance(epolls.begin(), it); + LOG_DEBUG(Lib_Net, "epollid = {}", ret); + return ret; + } else { + epolls.emplace_back(name); + const auto ret = epolls.size() - 1; + LOG_DEBUG(Lib_Net, "epollid = {}", ret); + return ret; + } +} + +void EpollTable::DeleteHandle(int d) { + UNREACHABLE(); +} + +Epoll* EpollTable::GetEpoll(int epollid) { + std::scoped_lock lock{m_mutex}; + if (epollid >= epolls.size() || epolls[epollid].Destroyed()) { + return nullptr; + } + + return &epolls[epollid]; +} + +} // namespace Libraries::Net diff --git a/src/core/libraries/network/net_epoll.h b/src/core/libraries/network/net_epoll.h new file mode 100644 index 000000000..b4745fcab --- /dev/null +++ b/src/core/libraries/network/net_epoll.h @@ -0,0 +1,83 @@ +// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "common/types.h" +#include "core/libraries/network/net.h" + +#include +#include + +#ifdef _WIN32 +#include +#endif + +#if defined(__linux__) || defined(__APPLE__) +#include +#include +#endif + +namespace Libraries::Net { + +#ifdef _WIN32 +using epoll_handle = HANDLE; +#else +using epoll_handle = int; +#endif + +struct Epoll { + std::vector> events{}; + const char* name; + epoll_handle epoll_fd; + + explicit Epoll(const char* name_) : name(name_), epoll_fd(epoll_create1(0)) { +#ifdef _WIN32 + ASSERT(epoll_fd != nullptr); +#else + ASSERT(epoll_fd != -1); +#endif + if (name == nullptr) { + name = "anon"; + } + } + + bool Destroyed() const noexcept { + return destroyed; + } + + void Destroy() noexcept { + events.clear(); +#ifdef _WIN32 + epoll_fd = nullptr; + epoll_close(epoll_fd); +#else + epoll_fd = -1; + close(epoll_fd); +#endif + name = ""; + destroyed = true; + } + +private: + bool destroyed{}; +}; + +u32 ConvertEpollEventsIn(u32 orbis_events); +u32 ConvertEpollEventsOut(u32 epoll_events); + +class EpollTable { +public: + EpollTable() = default; + virtual ~EpollTable() = default; + + int CreateHandle(const char* name); + void DeleteHandle(int d); + Epoll* GetEpoll(int d); + +private: + std::vector epolls; + std::mutex m_mutex; +}; + +} // namespace Libraries::Net \ No newline at end of file diff --git a/src/core/libraries/network/posix_sockets.cpp b/src/core/libraries/network/posix_sockets.cpp index 87872b86c..3ffb42528 100644 --- a/src/core/libraries/network/posix_sockets.cpp +++ b/src/core/libraries/network/posix_sockets.cpp @@ -286,12 +286,9 @@ int PosixSocket::Connect(const OrbisNetSockaddr* addr, u32 namelen) { std::scoped_lock lock{m_mutex}; sockaddr addr2; convertOrbisNetSockaddrToPosix(addr, &addr2); - int result = 0; - do { - result = ::connect(sock, &addr2, sizeof(sockaddr_in)); - LOG_DEBUG(Lib_Net, "raw connect result = {}, errno = {}", result, - result == -1 ? Common::GetLastErrorMsg() : "none"); - } while (result == -1 && (errno == EINTR || errno == EINPROGRESS)); + int result = ::connect(sock, &addr2, sizeof(sockaddr_in)); + LOG_DEBUG(Lib_Net, "raw connect result = {}, errno = {}", result, + result == -1 ? Common::GetLastErrorMsg() : "none"); return ConvertReturnErrorCode(result); } @@ -526,7 +523,6 @@ int PosixSocket::GetSocketOptions(int level, int optname, void* optval, u32* opt int PosixSocket::GetPeerName(OrbisNetSockaddr* name, u32* namelen) { std::scoped_lock lock{m_mutex}; - LOG_DEBUG(Lib_Net, "called"); sockaddr addr; convertOrbisNetSockaddrToPosix(name, &addr); diff --git a/src/core/libraries/network/sys_net.cpp b/src/core/libraries/network/sys_net.cpp index eaa3a659f..6d7876c06 100644 --- a/src/core/libraries/network/sys_net.cpp +++ b/src/core/libraries/network/sys_net.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "common/error.h" #include "common/singleton.h" #include "core/file_sys/fs.h" @@ -22,11 +23,13 @@ int PS4_SYSV_ABI sys_connect(OrbisNetId s, const OrbisNetSockaddr* addr, u32 add LOG_ERROR(Lib_Net, "socket id is invalid = {}", s); return -1; } + LOG_DEBUG(Lib_Net, "s = {} ({})", s, file->m_guest_name); int returncode = file->socket->Connect(addr, addrlen); if (returncode >= 0) { return returncode; } - LOG_ERROR(Lib_Net, "error code returned: {}", (u32)*Libraries::Kernel::__Error()); + LOG_ERROR(Lib_Net, "s = {} ({}) returned error code: {}", s, file->m_guest_name, + (u32)*Libraries::Kernel::__Error()); return -1; } @@ -37,6 +40,7 @@ int PS4_SYSV_ABI sys_bind(OrbisNetId s, const OrbisNetSockaddr* addr, u32 addrle LOG_ERROR(Lib_Net, "socket id is invalid = {}", s); return -1; } + LOG_DEBUG(Lib_Net, "s = {} ({})", s, file->m_guest_name); int returncode = file->socket->Bind(addr, addrlen); if (returncode >= 0) { return returncode; @@ -52,10 +56,11 @@ int PS4_SYSV_ABI sys_accept(OrbisNetId s, OrbisNetSockaddr* addr, u32* paddrlen) LOG_ERROR(Lib_Net, "socket id is invalid = {}", s); return -1; } + LOG_DEBUG(Lib_Net, "s = {} ({})", s, file->m_guest_name); auto new_sock = file->socket->Accept(addr, paddrlen); if (!new_sock) { - LOG_ERROR(Lib_Net, "error creating new socket for accepting: {:#x}", - (u32)*Libraries::Kernel::__Error()); + LOG_ERROR(Lib_Net, "s = {} ({}) returned error code creating new socket for accepting: {}", + s, file->m_guest_name, (u32)*Libraries::Kernel::__Error()); return -1; } auto fd = FDTable::Instance()->CreateHandle(); @@ -67,14 +72,13 @@ int PS4_SYSV_ABI sys_accept(OrbisNetId s, OrbisNetSockaddr* addr, u32* paddrlen) } int PS4_SYSV_ABI sys_getpeername(OrbisNetId s, OrbisNetSockaddr* addr, u32* paddrlen) { - LOG_INFO(Lib_Net, "s = {}", s); - auto file = FDTable::Instance()->GetSocket(s); if (!file) { *Libraries::Kernel::__Error() = ORBIS_NET_EBADF; LOG_ERROR(Lib_Net, "socket id is invalid = {}", s); return -1; } + LOG_DEBUG(Lib_Net, "s = {} ({})", s, file->m_guest_name); int returncode = file->socket->GetPeerName(addr, paddrlen); if (returncode >= 0) { return returncode; @@ -90,6 +94,7 @@ int PS4_SYSV_ABI sys_getsockname(OrbisNetId s, OrbisNetSockaddr* addr, u32* padd LOG_ERROR(Lib_Net, "socket id is invalid = {}", s); return -1; } + LOG_DEBUG(Lib_Net, "s = {} ({})", s, file->m_guest_name); int returncode = file->socket->GetSocketAddress(addr, paddrlen); if (returncode >= 0) { return returncode; @@ -105,8 +110,25 @@ int PS4_SYSV_ABI sys_getsockopt(OrbisNetId s, int level, int optname, void* optv LOG_ERROR(Lib_Net, "socket id is invalid = {}", s); return -1; } + auto name = [&] -> std::string_view { + switch (level) { + case ORBIS_NET_SOL_SOCKET: + return NameOf((OrbisNetSocketSoOption)optname); + case ORBIS_NET_IPPROTO_IP: + return magic_enum::enum_name((OrbisNetSocketIpOption)optname); + case ORBIS_NET_IPPROTO_TCP: + return magic_enum::enum_name((OrbisNetSocketTcpOption)optname); + default: + return std::string_view{"unknown"}; + } + }(); + LOG_DEBUG(Lib_Net, "s = {} ({}), level = {}, optname = {}", s, file->m_guest_name, + NameOf((OrbisNetProtocol)level), name); int returncode = file->socket->GetSocketOptions(level, optname, optval, optlen); if (returncode >= 0) { + if (optname == ORBIS_NET_SO_ERROR) { + LOG_DEBUG(Lib_Net, "so_error = {}", *reinterpret_cast(optval)); + } return returncode; } LOG_ERROR(Lib_Net, "error code returned: {}", (u32)*Libraries::Kernel::__Error()); @@ -120,6 +142,7 @@ int PS4_SYSV_ABI sys_listen(OrbisNetId s, int backlog) { LOG_ERROR(Lib_Net, "socket id is invalid = {}", s); return -1; } + LOG_DEBUG(Lib_Net, "s = {} ({}), backlog = {}", s, file->m_guest_name, backlog); int returncode = file->socket->Listen(backlog); if (returncode >= 0) { return returncode; @@ -136,6 +159,20 @@ int PS4_SYSV_ABI sys_setsockopt(OrbisNetId s, int level, int optname, const void LOG_ERROR(Lib_Net, "socket id is invalid = {}", s); return -1; } + auto name = [&] -> std::string_view { + switch (level) { + case ORBIS_NET_SOL_SOCKET: + return NameOf((OrbisNetSocketSoOption)optname); + case ORBIS_NET_IPPROTO_IP: + return magic_enum::enum_name((OrbisNetSocketIpOption)optname); + case ORBIS_NET_IPPROTO_TCP: + return magic_enum::enum_name((OrbisNetSocketTcpOption)optname); + default: + return std::string_view{"unknown"}; + } + }(); + LOG_DEBUG(Lib_Net, "s = {} ({}), level = {}, optname = {}", s, file->m_guest_name, + NameOf((OrbisNetProtocol)level), name); int returncode = file->socket->SetSocketOptions(level, optname, optval, optlen); if (returncode >= 0) { return returncode; @@ -149,13 +186,10 @@ int PS4_SYSV_ABI sys_shutdown(OrbisNetId s, int how) { } int PS4_SYSV_ABI sys_socketex(const char* name, int family, int type, int protocol) { - if (name == nullptr) { - LOG_INFO(Lib_Net, "name = no-named family = {} type = {} protocol = {}", family, type, - protocol); - } else { - LOG_INFO(Lib_Net, "name = {} family = {} type = {} protocol = {}", std::string(name), - family, type, protocol); - } + auto sname = name ? name : "anon"; + LOG_INFO(Lib_Net, "name = {} family = {} type = {} protocol = {}", std::string(sname), + magic_enum::enum_name((OrbisNetFamily)family), + magic_enum::enum_name((OrbisNetSocketType)type), protocol); SocketPtr socket; switch (type) { case ORBIS_NET_SOCK_STREAM: @@ -185,7 +219,7 @@ int PS4_SYSV_ABI sys_socketex(const char* name, int family, int type, int protoc sock->is_opened = true; sock->type = Core::FileSys::FileType::Socket; sock->socket = socket; - sock->m_guest_name = name ? name : "anon_sock"; + sock->m_guest_name = sname; return fd; } @@ -298,6 +332,7 @@ int PS4_SYSV_ABI sys_socketclose(OrbisNetId s) { LOG_ERROR(Lib_Net, "socket id is invalid = {}", s); return -1; } + LOG_DEBUG(Lib_Net, "s = {} ({})", s, file->m_guest_name); int returncode = file->socket->Close(); if (returncode >= 0) { return returncode; @@ -318,6 +353,7 @@ int PS4_SYSV_ABI sys_sendto(OrbisNetId s, const void* buf, u64 len, int flags, LOG_ERROR(Lib_Net, "socket id is invalid = {}", s); return -1; } + LOG_DEBUG(Lib_Net, "s = {} ({}), len = {}, flags = {:#x}", s, file->m_guest_name, len, flags); int returncode = file->socket->SendPacket(buf, len, flags, addr, addrlen); if (returncode >= 0) { return returncode; @@ -354,11 +390,13 @@ s64 PS4_SYSV_ABI sys_recvfrom(OrbisNetId s, void* buf, u64 len, int flags, Orbis LOG_ERROR(Lib_Net, "socket id is invalid = {}", s); return -1; } + LOG_DEBUG(Lib_Net, "s = {} ({}), len = {}, flags = {:#x}", s, file->m_guest_name, len, flags); int returncode = file->socket->ReceivePacket(buf, len, flags, addr, paddrlen); if (returncode >= 0) { return returncode; } - LOG_ERROR(Lib_Net, "error code returned: {}", (u32)*Libraries::Kernel::__Error()); + LOG_ERROR(Lib_Net, "s = {} ({}) returned error code: {}", s, file->m_guest_name, + (u32)*Libraries::Kernel::__Error()); return -1; }